Задать вопрос
  • Вопрос о новых веяниях и требованиях во фронтенде?

    bingo347
    @bingo347
    Crazy on performance...
    Для начала скажу об Html academy, что знаю.
    В начале года звали преподавать у них js + разрабатывать по нему курсы. Сразу скажу, что у меня впервые сложилось положительное впечатление от такого предложения, а не пошел я к ним по причинам не зависящим от них. Во-первых они дают базис, основы без которых Вы просто не сможете нормально разрабатывать, а освоить с этим базисом фреймворк большого труда не составит (про фреймворки ниже напишу).
    Во-вторых, хорошее впечатление у них составили люди, с кем удалось пообщаться, которые занимаются там составлением курсов и преподаванием - все как один не академики-теоретики, а практикующие разработчики с хорошим уровнем (а набирала в преподаватели Html academy в тот момент не ниже сеньера, предлагая соответствующую рынку зп).
    Ну и в-третьих, один раз собеседовал кандидата, имеющего за плечами только Html academy, обычно я негативно отношусь к кандидатом имеющим только курсы за плечами, но тут собеседуемый показал хороший уровень владения js.

    Теперь по фреймворкам.
    Не одному адекватному работодателю не нужен тупой фреймворкописатель без знания языка и нативного api, на которых этот фреймворк основан. В то же время, при знании js и DOM Api - Vue и React осваиваются за неделю, Angular за месяц. А без знания основ, может формочки ваять и сможете, но не больше. Так что учите сначала основы - js и нативное api браузера (DOM, CSSOM, ajax и т.д.), а уже потом беритесь за фреймворк.
    Ответ написан
    Комментировать
  • Как выделить все :focus в css с помощью регулярного выражения?

    bingo347
    @bingo347
    Crazy on performance...
    С регулярками на весь файл скорее всего будут проблемы, много чего может поломаться.
    Я бы сделал так:
    1. поставил бы модуль https://www.npmjs.com/package/css
    2. спарсил бы этим модулем css файл в AST дерево
    3.1. пробежался бы по всем селекторам в AST дереве в поисках селектора с :focus
    3.2. при нахождении нужного селектора, сделал бы что-то с ним (изменил, вырезал (если последний селектор в правиле, нужно вырезать все правило), что-то еще по вкусу)
    4. собрал модулем css AST дерево обратно в css код и записал бы в файл
    Ответ написан
    Комментировать
  • Как задать события в классах ES6?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    // мне кажется, что ждать полной загрузки страницы тут незачем
    document.addEventListener('DOMContentLoaded', () => {
        new Slider({
            images: ".slider__galary img",
            btnPrev: ".btnPrev",
            btnNext: ".btnNext",
            rate: false
        });
    });
    
    // хелпер для прослушивания событий
    class EventListener {
        constructor(ctx, handlers, target) {
            this.ctx = ctx;
            this.handlers = handlers;
            Object.keys(handlers).forEach(event => target.addEventListener(event, this));
        }
    
        handleEvent(event) {
            const {handlers, ctx} = this;
            const {type} = event;
            if(typeof handlers[type] !== 'function') return;
            handlers[type].call(ctx, event);
        }
    }
    
    class Slider {
      construnctor({images, btnPrev, btnNext, rate, time = 1000}) {
            this.images = document.querySelectorAll(images);
            this.i = 0;
            new EventListener(this, {
                click: this.prev
            }, document.querySelector(btnPrev));
            new EventListener(this, {
                click: this.next
            }, document.querySelector(btnNext));
            if(rate) {
                setInterval(() => this.next(), time);
            }
        }
        
        prev() {
            this.images[i].classList.remove("showed");
            this.i--;
            if(this.i < 0){
                this.i = this.images.length - 1;
            }
            this.images[i].classList.add("showed");
        }
    
        next() {
            this.images[i].classList.remove("showed");
            this.i++;
            if(this.i >= this.images.length){
                this.i = 0;
            }
            this.images[i].classList.add("showed");
        }
    }
    Ответ написан
    2 комментария
  • Как впустить в поток, поток получаемый из другого сервиса?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    без знания, что за либа предоставляет youtubeApi сделать адекватно проблематично, но можно сделать универсально:
    const {PassThrough} = require('stream');
    
    const youtubeStream = new PassThrough();
    youtubeApi.downloadVideo(
      'v=4P1-JwZF0Vo&t=4519s',
      chunk => youtubeStream.write(chunk),
      () => youtubeStream.end()
    );
    youtubeStream.pipe(res); // где res - выходной поток к клиенту
    Ответ написан
    1 комментарий
  • Не могу добавить папку в $PATH. Пишет Нет такого файла или каталога. В чем дело?

    bingo347
    @bingo347
    Crazy on performance...
    export PATH="$PATH:/bin/customscripts"
    Ответ написан
    Комментировать
  • Как проверить, что картинка существует?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Ну во-первых, присваивание функции в img.load не даст никакого результата, если хотите повесить обработчик события, то нужно присваивать в img.onload

    Во-вторых, данный обработчик работает асинхронно, когда Вы делаете проверку, он еще не выполнился, а выполнится он только тогда, когда картинка загрузится

    Ну и наконец в-третьих, если картинки нет, то событие load не произойдет никогда, нужно проверять еще событие error, чтоб отследить ошибку загрузки, а заодно вешать таймаут, дабы не ждать загрузки вечность

    Проще всего это реализовать с промисами (если нужна поддержка старых браузеров - то добавьте полифил):
    // для начала я вынесу массив с разрешениями из функции, чтоб не создавать его для каждого вызова:
    var resolutions = ['maxresdefault', 'hqdefault', 'mqdefault'];
    function fetch_highest_res(videoid) {
      // сама функция будет возвращать промис, полученный сверткой массива resolutions
      return resolutions.reduce(
        function(promise, resolution) {
          // перехватываем только ошибку загрузки, если была успешная загрузка - просто отдаем ее дальше
          return promise.catch(function() {
            return new Promise(function(resolve, reject) {
              var img = new Image();
              // повесим таймаут в 3 секунды (если надо, поставьте больше), генерирующий ошибку
              setTimeout(reject, 3000);
              // отследим ошибку загрузки
              img.onerror = reject;
              // а в случае успешной загрузки отдадим результат
              img.onload = function() {
                resolve(resolution);
              };
              // и только когда навесили обработчики начинаем загрузку
              img.src = 'https://i.ytimg.com/vi/' + videoid + '/' + resolution + '.jpg';
            });
          });
        },
        // в качестве инициализирующего значения отдаем отклоненный промис
        // так как следующая картинка должна пробоваться только если не получилось загрузить предыдущую
        // а отслеживать мы это будем по ошибке загрузки
        Promise.reject()
      // ну и перехватим случай, если ничего не удалось загрузить
      ).catch(function() { return null; });
    }
    
    // ну и функция теперь у нас возвращает асинхронный результат в виде промиса
    // поэтому и получать его надо соответствующе
    fetch_highest_res('eei-soH5Gx8').then(function(resolution) {
      console.log(resolution); // hqdefault
    });


    P.S. сделал все в es5, ибо мало ли, Вам нужна поддержка старья, а сборкой Вы явно не пользуетесь...
    Ответ написан
  • Правильно ли изучать все и сразу?

    bingo347
    @bingo347
    Crazy on performance...
    учить что-то бесполезно, нужна практика а не зубрежка.
    выкиньте вообще все учебники пылится на полку, они не эффективны, придумайте себе проект и начните его делать, а там где уже попали в ступор - идите в справочники и учебники, так профит будет в разы больше

    ну и насчет распылятся сразу на несколько ЯП, тоже не стоит, в голове каша будет. лучше натренироваться досконально в чем то одном, а остальное уже после смотреть для общего развития
    иначе в голове возникнет каша, Вы ведь не изучаете в раз английский, немецкий и французкий? ну и с языками программирования так же
    Ответ написан
    Комментировать
  • Как воспользоваться callback для обработчика?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    function handleClick() {
        $('.photo').removeClass('active-element');
        $(this).addClass('active-element');
        $('.point li').removeClass('active-point').
        filter((index, item) => $(this).data('id') == $(item).data('id')).addClass('active-point');
        $('.about-text p').text($(this).data('text'));
        $('.about-site p').text($(this).data('info'));
        $('.about-site a').text($(this).data('website')).attr("href", "#");
    }
    
    $('.photo').click(handleClick);
    $('.point li').click(function() {
        $('.point li').removeClass('active-point');
        $(this).addClass('active-point');
        handleClick.call(this)
    });
    Ответ написан
    Комментировать
  • Кроссбраузерность Safari?

    bingo347
    @bingo347
    Crazy on performance...
    Кто нибудь знает бесплатные способы посмотреть свою верстку в Safari, если сижу на винде?
    Из бесплатных - только воткнуть хакинтош в виртуалку, но нормально работает только на процессорах от intel (и то не на всех), имеющих аппаратную виртуализацию
    Из бюджетных - взять б/у макбук эир или мак мини

    И стоит ли вообще запариваться по этому поводу
    стоит... сафари на сегодня самый проблемный браузер.

    кроме того еще есть мобильный сафари, с которым проблем еще больше, распространен он тоже больше чем десктопный брат (на iOS по факту нет других браузеров), дебажить его можно только с мака (ну или хака), и Вам по любому понадобится iPhone (опять же подойдет б/у)
    Ответ написан
    Комментировать
  • Как добавить/удалить элемент в блок?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    замените
    if (optionList) {
        $('.total-review-list').append(optionList);
      }
    на$('.total-review-list').html(optionList);
    Ответ написан
    1 комментарий
  • Настроить импорт из window в webpack?

    bingo347
    @bingo347
    Crazy on performance...
    Комментировать
  • Как должна организовываться модульная система?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    модули имеют изолированную область видимости, на то они и модули
    Вам нужно явно поместить chartModule в глобальный объект:
    //module.js
    import  chartModule from '/static/scripts/myScripts/chartModule/myChart.js'; // импортирует функцию для создания графиков
    
    // помещаем chartModule в window, чтоб он был доступен глобально
    window.chartModule = chartModule;
    Ответ написан
  • Как добавить JavaScript после тега?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Я так понимаю, у Вас js-код в виде строки в другом js-коде получается, тут есть несколько вариантов:

    вариант 1, самый простой, создать из строки функцию и выполнить ее:
    const CODE = 'console.log("good");'; // ваш код
    
    (new Function(CODE))(); // создаем из него функцию и сразу вызываем

    вариант 2, подходит только для этапа загрузки страницы, работает только до события DOMContentLoaded у document, просто пишем в поток html кода тег script с нужным кодом. Подойдет так же для выполнения кода в iframe
    const CODE = 'console.log("good");'; // ваш код
    
    document.write('<script>' + CODE + '</' + 'script>');


    вариант 3, тоже с генерацией тега script, но уже работает в любое время, подставляем код как url в src тега script
    const CODE = 'console.log("good");'; // ваш код
    
    const scriptTag = document.createElement('script');
    scriptTag.type = 'application/javascript';
    scriptTag.src = URL.createObjectURL(new Blob([CODE]));
    document.head.appendChild(scriptTag);
    Ответ написан
  • Как проверить что объект существует?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    player1 = new YT.Player('player1', {
      // your config
      events: {
        onReady() {
          // плеер создан
        },
        onError(err) {
          // что-то пошло не так
        }
      }
    }
    Ответ написан
  • Почему не работает крос доменный запрос?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    у Вас стоит опция withCredentials: true - которая говорит браузеру, что Вы хотите отправлять куки стороннему ресурсу. В этом плане более строгая политика CORS:
    1. заголовок ответа Access-Control-Allow-Origin не может быть вилдкард (*), сервер должен отвечать точным origin
    2. должен присутствовать заголовок ответа Access-Control-Allow-Credentials: true

    по итогу сервер должен ответить следующими заголовками:
    Access-Control-Allow-Origin: {request.headers.Origin}
    Access-Control-Allow-Methods: GET, OPTIONS, HEAD
    Access-Control-Allow-Credentials: true

    где {request.headers.Origin} - заголовок Origin из запроса
    Ответ написан
    Комментировать
  • Как свойство экземпляра в VUE сделать реактивным?

    bingo347
    @bingo347
    Crazy on performance...
    Хм, на ум приходит нечто такое:
    const box = new Vue({data: {groups: []}});
    Object.defineProperty(Vue.prototype, '$dataGroups', {
      configurable: true,
      get() { return box.groups; },
      set(value) { box.groups = value; }
    });


    P.S. у Вас разные свойства $dataGroups и $dataGroupsActive
    P.S.S. иметь в прототипе объекты/массивы не очень хорошая практика, лучше сделать подобно тому, как Vuex кидает $store в инстансы, через миксин: https://github.com/vuejs/vuex/blob/dev/src/mixin.js#L22

    UPD: пример с миксином:
    Vue.mixin({
      beforeCreate() {
        const {$options} = this;
        const {parent} = $options;
        if($options.dataGroups) {
          const groups = typeof $options.dataGroups === 'function' ? $options.dataGroups() : $options.dataGroups;
          const box = new Vue({data: {groups}});
          Object.defineProperty(this, '$dataGroups', {
            configurable: true,
            get() { return box.groups; },
            set(value) { box.groups = value; }
          });
          return;
        }
        if(!parent) { return; }
        const descriptor = Object.getOwnPropertyDescriptor(parent, '$dataGroups');
        if(!descriptor) { return; }
        Object.defineProperty(this, '$dataGroups', descriptor);
      }
    });
    Ответ написан
  • Как вырезать строку начинающего с определённого символа?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    если правильно понял:
    console.log(`
    Текст
    # текст 2
    # текст "текст с #" 3
    # текст 4
    # текст 5
    `.match(/^#.*$/gm));
    Ответ написан
    1 комментарий
  • Каким образом можно кешировать изображения?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    О ,я как раз собирался уточнить это) Суть в том ,что на сайте есть достаточно много картинок ,и про проверке сайта на скорость загрузки ,мне посоветовало "кэшировать изображения" ,я начитался в интернете ,что можно начать загрузку всех изображений сразу ,до их открытия пользователем ,путем кэширования. Т.е. страницы открылась ,пользователь еще на самом верху ,а изображения в других местах страницы уже грузятся и когда он до них доходит ,они уже загружены ,как то так )

    Насчет проверки на скорость загрузки - имеется в виду как раз отдавать правильные заголовки для кэширования с сервера, что Вам уже подсказали в комментариях к вопросу.

    Ну а насчет предварительной загрузки изображений до показа их пользователю, понадобится список таких изображений, которые нужно предзагрузить. Сразу скажу, что грузить таким образом изображения, которые уже есть на странице смысла нет, но вот изображения для всяких модалок таким образом грузить вполне себе резонно:
    // сделаем функцию, ждущую загрузку основной страницы,
    // чтоб не мешать ей при загрузке дополнительных картинок:
    function waitWindowLoad() {
      if(document.readyState === 'complete') {
        return Promise.resolve();
      }
      return new Promise(resolve => {
        const listener = () => {
          window.removeEventListener('load', listener);
          resolve();
        };
        window.addEventListener('load', listener);
      });
    }
    
    // массив url подгружаемых картинок
    [
      '/images/1.png',
      '/images/2.png',
      '/images/3.png'
    ].reduce((promise, url) => promise.then(() => new Promise(resolve => {
      // грузим картинки по очереди
      const img = new Image();
      img.onload = img.onerror = resolve;
      img.src = url;
    })), waitWindowLoad());
    Ответ написан
  • Почему у меня данные не меняются?

    bingo347
    @bingo347
    Crazy on performance...
    Во-первых, selected у Вас явно объект, а не массив, поэтому в data меняем строку
    selected: []
    на
    selected: {}

    Во-вторых, vue не умеет отслеживать данные, которых изначально нет в data и нужно явно указывать, что мы их меняем, поэтому в методе onSelect меняем строку
    this.selected[day] = !this.selected[day];
    на
    this.$set(this.selected, day, !this.selected[day]);

    https://ru.vuejs.org/v2/api/#vm-set
    Ответ написан
  • Веб студии просто не выставляют многие работы в портфолио или в свободное время на стройке работают?

    bingo347
    @bingo347
    Crazy on performance...
    Когда я на старте своей карьеры работал в веб-студии (давно было, но не думаю, что что-то кардинально поменялось), сайты клепались пачками, по несколько штук в день. Естественно 90% из них были как под копирку, отличаясь лишь контентом. Смысла выставлять 100500 однотипных сайтов в портфолио просто нет
    Ответ написан
    Комментировать