Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как задать события в классах 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 комментарий
  • Как проверить, что картинка существует?

    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, ибо мало ли, Вам нужна поддержка старья, а сборкой Вы явно не пользуетесь...
    Ответ написан
  • Как воспользоваться 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)
    });
    Ответ написан
    Комментировать
  • Как добавить/удалить элемент в блок?

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

    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 из запроса
    Ответ написан
    Комментировать
  • Как вырезать строку начинающего с определённого символа?

    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 Куратор тега JavaScript
    Crazy on performance...
    const SHORTCUT_SUFFIXES = ['K', 'M', 'B', 'T', 'Q', 'P'];
    function shortcutNumber(num) {
      const normalized = Number(num).toFixed(0);
      const expPosition = normalized.indexOf('e');
      const dotPosition = normalized.indexOf('.');
      const hasExponent = expPosition !== -1;
      const exponent = parseInt(normalized.slice(expPosition + 2));
      const len = hasExponent ? expPosition + exponent : normalized.length;
      if(len < 4) return String(num);
      const suffixNumber = Math.floor((len - 1)  / 3);
      const suffix = SHORTCUT_SUFFIXES[suffixNumber - 1];
      const fullNumber = (hasExponent
        ? normalized.slice(0, expPosition).replace('.', '')
          + '0'.repeat(exponent - (dotPosition === -1 ? 0 : expPosition + dotPosition + 1))
        : normalized
      );
      if(!suffix) {
        // число о-о-очень большое, больше чем мы суффиксов задали...
        return fullNumber.slice(0, -(SHORTCUT_SUFFIXES.length * 3))
          + SHORTCUT_SUFFIXES[SHORTCUT_SUFFIXES.length - 1];
      }
      return fullNumber.slice(0, -(suffixNumber * 3)) + suffix;
    }
    Ответ написан
    Комментировать
  • Как сортировать обьекты по дате ( по возрастанию )?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    array.sort((a, b) => {
      if(a.var !== true || b.var !== true) return 0;
      return a.date - b.date;
    });
    Ответ написан
    Комментировать
  • Какую спецификацию EcmaScript учить?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Все, они не заменяют, а дополняют друг друга
    Ответ написан
    Комментировать
  • Как с технической точки зрения сделаны сервисы генерирующие виджеты?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Поделюсь как это сделано у нас, надеюсь поможет
    во-первых, сайт заводится в нашей БД и ему присваивается id
    во-вторых, сайт вставляет к себе наш код, он небольшой, но делает две вещи:
    1. создает временную функцию в window - которая совпадает по имени с нашей функцией запуска, но просто сохраняет себе в массив все вызовы и их аргументы
    2. начинает загрузку js-кода нашего виджета
    в-третьих, сайт вызывает нашу функцию запуска, куда передает свой id из нашей БД и некоторые параметры

    когда наш основной js загрузился, он делает следующее:
    1. переписывает в window временную функцию собирающую аргументы на настоящую, которая запускает вставку виджета
    2. если собранны запуски до этого момента - запускает их в настоящей функции запуска
    3. функция запуска дергает сервер и запрашивает данные по id сайта
    4. вставляем на страницу iframe и в нем рисуем виджет

    на деле все чуть сложнее, но общий принцип такой
    Ответ написан
    2 комментария
  • Как получить статус отправки сообщения через WebSocket?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    вообще websocket в конечном итоге работает поверх tcp, который сам уведомляет другую сторону о доставке пакета, а если уведомление не получено - через время шлет пакет повторно
    у самого websocket нет такого встроенного механизма, но никто не мешает реализовать такое самостоятельно
    Ответ написан
  • Как получить дату на английском?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    new Date().toLocaleString('en', {timeZoneName: 'long'})

    https://developer.mozilla.org/ru/docs/Web/JavaScri...
    Ответ написан
    Комментировать
  • Как разбивать параграф построчно?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    разбиваем в HTML-строку:
    function text2HTML(text) {
      return text.split('\n').map(line => `<div>${line}</div>`).join('');
    }


    разбиваем в DOM фрагмент, который потом можно будет вставить на страницу через appendChild:
    function text2DOMFragment(text) {
      return text.split('\n').reduce((frag, line) => (frag
        .appendChild(document.createElement('div'))
        .appendChild(document.createTextNode(line)),
      frag), document.createDocumentFragment());
    }
    Ответ написан
  • По какой версии учебника Кантора по JS учиться - русской или английской?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    ИМХО, но не стоит учится по учебнику Кантора, все что научитесь - быдлокодить. Лучше Дэвида Флэнагана почитайте.

    Ну а по сабжу, у Кантора русская версия - оригинал, а английская - перевод
    Ответ написан
    3 комментария
  • Как получить случайный элемент массива без повторений при вызове функции?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    function makeGetRandomElement(initialArray) {
      var arr;
      function randomIndex() {
        return Math.floor(Math.random() * arr.length);
      }
      function reinitArray() {
        arr = initialArray.slice();
      }
      reinitArray();
      return function getRandomElement() {
        if(arr.length === 0) reinitArray();
        return arr.splice(randomIndex(), 1)[0];
      }
    }
    
    
    // использование
    var getRandomElement = makeGetRandomElement([1, 2, 3, 4, 5, 6, 7]);
    console.log(getRandomElement());
    console.log(getRandomElement());
    console.log(getRandomElement());
    console.log(getRandomElement());
    console.log(getRandomElement());
    Ответ написан
    Комментировать