Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как вытащить стили конкретного класса DOM?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Можно попробовать обшарить document.styleSheets:

    const getClassStyles = className =>
      [...document.styleSheets].reduce((styles, { cssRules }) => {
        return [...cssRules]
          .filter(n => n.selectorText === `.${className}`)
          .reduce((styles, { cssText }) => {
            return (cssText
              .match(/[\w\-]+: [^;]+/g) || [])
              .map(n => n.split(': '))
              .reduce((styles, [ k, v ]) => (styles[k] = v, styles), styles);
          }, styles);
      }, {});
    
    
    const styles = getClassStyles('class-name');
    Ответ написан
    Комментировать
  • Как построить html дерево по массиву объектов с дочерними элементами?

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

    Рекурсия. Если в элементе есть непустой массив children, то делаете рекурсивный вызов функции, передавая ей этот массив.

    Можно напрямую создавать элементы:

    const createTreeElement = data =>
      Array.isArray(data) && data.length
        ? data.reduce((ul, n) => {
            const li = document.createElement('li');
            const div = document.createElement('div');
            div.textContent = n.name;
            li.append(div, createTreeElement(n.children));
            ul.append(li);
            return ul;
          }, document.createElement('ul'))
        : '';
    
    
    document.body.append(createTreeElement(data));

    Или собрать соответствующую разметку:

    const createTreeHTML = data =>
      data instanceof Array && data.length
        ? `<ul>${data.map(n => `
             <li>
               <div>${n.name}</div>
               ${createTreeHTML(n.children)}
             </li>`).join('')}
           </ul>`
        : '';
    
    
    document.body.insertAdjacentHTML('beforeend', createTreeHTML(data));
    Ответ написан
    Комментировать
  • Как правильно оформить несколько одинаковых 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 = 'селектор потомка';

    Если клики по вложенным элементам "потомка" учитывать не надо:

    document.addEventListener('click', ({ target: t }) => {
      if (t.matches(descendantSelector)) {
        const ancestor = t.closest(ancestorSelector);
        if (ancestor) {
          ancestor.remove();
        }
      }
    });

    Если интересуют все клики внутри "потомка", в том числе и по его потомкам:

    document.addEventListener('click', e => {
      const descendant = e.target.closest(descendantSelector);
      if (descendant) {
        const ancestor = descendant.closest(ancestorSelector);
        if (ancestor) {
          ancestor.remove();
        }
      }
    });

    UPD. Наконец-то дождались:

    document.addEventListener('click', ({ target: t }) =>
      t.matches(descendantSelector) &&
      t.closest(ancestorSelector)?.remove()
    );

    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 = Array(arr.length);
    for (let i = 0; i < arr.length; i++) {
      result[i] = arr[i][0] || '';
    }
    
    // или
    
    const result = [];
    for (const [ n = '' ] of arr) {
      result.push(n);
    }
    
    // или
    
    const result = [];
    while (result.length < arr.length) {
      result[result.length] = arr[result.length].slice(0, 1);
    }
    
    // или
    
    const result = arr.map(n => n.charAt(0));
    Ответ написан
    Комментировать