Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как правильно оформить несколько одинаковых canvas на одной странице?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const images = [
      {
        src: 'https://i.imgur.com/GigS3KR.png',
        translate: [ 50, 50, 500, 20 ],
        rotate: [ 340, 200 ],
        draw: [ 0, 0, 0.95 ],
      },
      {
        src: 'https://i.imgur.com/y3JAe69.png',
        translate: [ 5, 0, 382, 2 ],
        rotate: [ 630, 40 ],
        draw: [ 150, 100, 0.84 ],
      },
      {
        src: 'https://i.imgur.com/v30JIWp.png',
        translate: [ 8, 150, 198, 3 ],
        rotate: [ 500, 450 ],
        draw: [ 0, 0, 0.7 ],
      },
    ].map(n => {
      n.draw.unshift(new Image);
      n.draw[0].src = n.src;
      return n;
    });
    
    const canvases = document.querySelectorAll('.canvas');
    const canvasSize = document.documentElement.clientWidth;
    
    for (const n of canvases) {
      n.setAttribute('width', canvasSize);
      n.setAttribute('height', canvasSize);
    }
    
    let ts0;
    window.requestAnimationFrame(function draw(ts) {
      for (const n of canvases) {
        ts0 = ts0 || ts;
        const dt = ts - ts0;
    
        const ctx = n.getContext('2d');
        ctx.clearRect(0, 0, canvasSize, canvasSize);
    
        for (const { translate: t, rotate: r, draw: d } of images) {
          ctx.save();
          ctx.translate(t[0], t[1] + Math.sin(dt / t[2]) / t[3]);
          ctx.rotate(Math.sin(dt / r[0]) / r[1]);
          ctx.drawImage(d[0], d[1], d[2], canvasSize * d[3], canvasSize * d[3]);
          ctx.restore();
        }
      }
    
      window.requestAnimationFrame(draw);
    });
    Ответ написан
    1 комментарий
  • Зачем использовать >>> над десятичными числами?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вообще-то, нет гарантии, что операция выполняется над числом. Это может быть что угодно. Собственно, потому тут и применяется побитовый оператор - чтобы гарантировать, что len будет целым числом. А почему применяется именно >>>, а не | или >> - число должно быть не только целым, но и положительным (или, если быть более точным, неотрицательным - 0 тоже окей).
    Ответ написан
    2 комментария
  • Как достать текст label, у чекнутой радиокнопки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    О каких радиокнопках идёт речь:

    const radioSelector = '.radio_wrap input[type="radio"]';

    Как, имея радиокнопку, можно получить содержимое её label'а:

    const getLabel = el => document.querySelector(`[for="${el.id}"]`).textContent;
    // или
    const getLabel = el => el.nextElementSibling.innerText;
    // или
    const getLabel = el => el.labels[0].innerHTML;

    Получаем, по событию change:

    // назначаем обработчик события каждой радиокнопке индивидуально
    document.querySelectorAll(radioSelector).forEach(function(n) {
      n.addEventListener('change', this);
    }, e => console.log(getLabel(e.target)));
    
    // или, можно сделать делегированный обработчик, где будет проверка, откуда пришло событие
    document.addEventListener('change', ({ target: t }) => {
      if (t.matches(radioSelector)) {
        console.log(getLabel(t));
      }
    });
    Ответ написан
    Комментировать
  • Как правильно задать $(this) в настройках плагина?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Попробуйте заменить

    '.catalog__scrollbarLine'

    на

    $(this).find('.catalog__scrollbarLine')

    или

    $(this).find('.catalog__scrollbarLine')[0]
    Ответ написан
  • Почему мои значения не определены?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Если вы внутри функции определяете переменную с таким же именем, как и у переменной из внешней области видимости, то последняя окажется недоступной. Строка 57 - уберите ключевое слово var.
    Ответ написан
    Комментировать
  • Почему setTimeout не изменяет время в цикле?

    0xD34F
    @0xD34F Куратор тега JavaScript
    setTimeout(show(i), i * 300);

    Вместо того, чтобы передать в setTimeout функцию, вы её вызываете.

    Какие есть варианты исправить косяк:

    1. Оберните вызов своей функции в другую функцию, которая будет передана в setTimeout:

      setTimeout(() => show(i), i * 300);

    2. Выполните привязку параметра:

      setTimeout(show.bind(null, i), i * 300);

    3. Передавайте свою функцию в setTimeout, а параметры, с которыми она должны быть вызвана, укажите отдельно:

      setTimeout(show, i * 300, i);

    4. Перепишите свою функцию так, чтобы она возвращала другую функцию:

      function show(x) {
        return function() {
          // сюда помещаете то, что находится у вас в show сейчас
        };
      }

    Ответ написан
    3 комментария
  • Почему этот код не работает в IE?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Не работающая часть
    class NewsLoader {

    https://caniuse.com/#feat=es6-class
    Ответ написан
    2 комментария
  • Как удалить дальнего родителя при клике на потомке?

    0xD34F
    @0xD34F Куратор тега JavaScript
    О каких элементах идёт речь:

    const ancestorSelector = 'селектор_предка';
    const descendantSelector = `${ancestorSelector} селектор_потомка`;

    Если цеплять обработчик клика непосредственно на потомков - от элемента, на котором висит обработчик, поднимаемся к предку и удаляем его:

    document.querySelectorAll(descendantSelector).forEach(function(n) {
      n.addEventListener('click', this);
    }, e => e.currentTarget.closest(ancestorSelector).replaceWith());

    Если применять делегирование - пробуем подняться от целевого элемента к потомку, если таковой нашёлся, поднимаемся к предку и удаляем его:

    document.addEventListener('click', e => {
      const descendant = e.target.closest(descendantSelector);
      if (descendant) {
        descendant.closest(ancestorSelector).outerHTML = '';
      }
    });
    
    // или
    
    document.addEventListener('click', ({ target: t }) =>
      (t = t.closest(descendantSelector)) && t.closest(ancestorSelector).remove()
    );

    UPD. Наконец-то дождались, теперь сокращённой версии делегированного обработчика можно придать более пристойный вид:

    document.addEventListener('click', e => {
      e.target.closest(descendantSelector)?.closest(ancestorSelector).remove();
    });
    Ответ написан
    Комментировать
  • Как остановить/поставить на паузу typed.js?

    0xD34F
    @0xD34F Куратор тега JavaScript
    <span id="typed"></span>
    <div id="actions">
      <button data-action="start">play</button>
      <button data-action="stop">pause</button>
    </div>

    const typed = new Typed('#typed', {
      typeSpeed: 100,
      loop: true,
      strings: [
        'hello, world!!',
        'fuck the world',
        'fuck everything',
      ],
    });
    
    document.querySelector('#actions').addEventListener('click', e => {
      const { action } = e.target.dataset;
      if (action) {
        typed[action]();
      }
    });
    Ответ написан
    1 комментарий
  • Как правильно задать анимацию небольшого вращения-"покачивания" в canvas?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Ну как бы так:

    const cloud = new Image();
    cloud.src = 'https://avatanplus.com/files/resources/mid/56dc1ba4ba1b81534bcbfb9a.png';
    
    (function draw() {
      const ctx = document.getElementById('canvas').getContext('2d');
    
      ctx.globalCompositeOperation = 'destination-over';
      ctx.clearRect(0, 0, canvas.width, canvas.height);
    
      ctx.fillStyle = 'rgba(0,0,0,0.4)';
      ctx.strokeStyle = 'rgba(0,153,255,0.4)';
      ctx.save();
      ctx.translate(300, 200);
    
      const time = new Date();
      ctx.rotate(Math.sin(time / 500) / 10);
    
      ctx.drawImage(cloud, -300, -200);
      ctx.restore();
    
      window.requestAnimationFrame(draw);
    })();

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

    0xD34F
    @0xD34F Куратор тега JavaScript
    100 * arr.reduce((sum, n) => sum + +n.no_apply, 0) / arr.reduce((sum, n) => sum + +n.count, 0)
    Ответ написан
    Комментировать
  • Почему localStorage передает active только из первого списка, а из последующих игнорирует?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Проблема не localStorage, а в том, что вы не до конца понимаете, как работает метод index. Если вызывать его без аргументов, то будет возвращён индекс элемента относительно его соседей. А вовсе не на странице в целом, как вам сейчас кажется.

    Какие есть варианты решения вашей проблемы:
    • Собирать индексы на всех уровнях вложенности, вместо одного числа будете хранить массив
    • Вместо индексов использовать id (лично мне это видится наиболее предпочтительным вариантом - при изменении структуры меню информация о выбранном пункте останется корректной)
    • Ну и наконец, самый лёгкий и простой способ - воспользоваться методом index соответственно вашей задумке, замените $(this).index() на $('.sub3').index(this) (за подробностями - в документацию)
    Ответ написан
  • Js считает сумму цифр всех блоков а не раздельно, как исправить?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Во-первых - обходите не те блоки. Вместо .counter-block (он же у вас всего один) должно быть .product-count.

    Во-вторых - работая с конкретным блоком, вместо поиска элементов только внутри него, вы обшариваете всю страницу.
    Ответ написан
    Комментировать
  • Как зациклить таймер countdown?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Документацию-то открывать пробовали? Там пишут, что будто бы для задания новой конечной даты достаточно просто выполнить инициализацию ещё раз. Соответственно, внутрь if (event.elapsed) {} вставляете $(this).countdown(а здесь новая дата);.
    Ответ написан
    4 комментария
  • Как вывести значения в textarea?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Ну, поскольку стили вы назначаете с помощью метода css, они попадают в атрибут style. А значит - достаточно просто получить его значение, типа так. Или, можно не переприсваивать объект со стилями, а дополнять его - тогда можно воспользоваться JSON.stringify, типа так.
    Ответ написан
  • Как задать проверку в цикле?

    0xD34F
    @0xD34F Куратор тега JavaScript
    if( slideIndex > sliderItem.length ) {

    Да ну? Вы что, действительно не знаете, что массивы индексируются начиная с нуля? Не будет sliderItem.length корректным значением, элемента с таким индексом уже нет. Замените > на ===.
    Ответ написан
    7 комментариев
  • Почему синхронный forkJoin работает некорректно?

    0xD34F
    @0xD34F Куратор тега JavaScript
    в консоль выводится два значения, причём непонятно каким образом сформированные

    Я вижу правильное выполнение так: <бла-бла-бла>

    Вместо того, чтобы фантазировать, как оно там должно быть - следует читать документацию.

    Открываем, читаем:

    When all observables complete, emit the last emitted value from each.

    Последнее значение из каждого. Ну и всё.
    Ответ написан
    2 комментария
  • Как взять первые символы из массива слов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const result = arr.map(n => n.charAt());
    
    // или
    
    const result = [];
    for (const [ n = '' ] of arr) {
      result.push(n);
    }
    
    // или
    
    const result = Array(arr.length);
    for (let i = 0; i < arr.length; i++) {
      result[i] = arr[i][0] || '';
    }
    
    // или
    
    const result = [];
    for (let i, n; (n = arr[i = result.length]) != null;) {
      result.splice(i, 0, n.replace(/(.).+/, '$1'));
    }
    
    // или
    
    const result = (function get(i, n = arr[i]) {
      return n != null ? [ n.slice(0, 1), ...get(-~i) ] : [];
    })(0);
    Ответ написан
    Комментировать
  • Как вытащить for у label?

    0xD34F
    @0xD34F Куратор тега JavaScript
    О каких label'ах и каком select'е идёт речь:

    const labels = document.querySelectorAll('#price_block .change_model_iphone .item label');
    const select = document.querySelector('#select_model');

    Как получить for:

    const getFor = el => el.getAttribute('for');
    // или
    const getFor = el => el.attributes.for.value;
    // или
    const getFor = el => el.htmlFor;

    Заполняем select option'ами:

    // можно перезаписать разметку
    select.innerHTML = Array
      .from(labels, n => `<option value="${getFor(n)}">iPhone ${n.innerText}</option>`)
      .join('');
    
    // или, напрямую создавать новые элементы
    select.append(...Array.prototype.map.call(
      labels,
      n => new Option(`iPhone ${n.textContent}`, getFor(n))
    ));
    Ответ написан
    1 комментарий
  • Как по value в селекте, найти такой же текст в селекторе, и добавить селектору класс?

    0xD34F
    @0xD34F Куратор тега JavaScript
    <div class="text">hello, world!!</div>
    <div class="text">fuck the world</div>
    <div class="text">fuck everything</div>
    
    <select></select>

    const texts = document.querySelectorAll('.text');
    const select = document.querySelector('select');
    
    select.append(...Array.from(texts, n => new Option(n.textContent)));
    select.value = null;
    
    select.addEventListener('change', ({ target: { selectedIndex } }) => {
      texts.forEach((n, i) => n.classList.toggle('active', i === selectedIndex));
    });
    Ответ написан
    1 комментарий