Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как создать динамически маркеры на Google Maps API из массива после обработки GeoCoder?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Объявление функции codeAddress - уберите цикл; в саму функцию передавайте адрес в качестве параметра:

    function codeAddress(address, geocoder, map) {
      geocoder.geocode({ address }, function(results, status) {
        if (status === 'OK') {
          new google.maps.Marker({
            map: map,
            position: results[0].geometry.location,
          });
        } else {
          alert('Geocode was not successful for the following reason: ' + status);
        }
      });
    }

    В initMap перебирайте массив адресов, для каждого вызывайте codeAddress:

    address.forEach(n => codeAddress(n, geocoder, map));
    Ответ написан
    4 комментария
  • Как добавить элемент родителю?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Перед кем и что надо добавить:

    const elements = document.querySelectorAll('li > ul');
    const tag = 'span';
    const text = 'hello, world!!';

    Добавляем:

    elements.forEach(n => {
      n.before(document.createElement(tag));
      n.previousSibling.textContent = text;
    });

    или

    for (const n of elements) {
      const el = document.createElement(tag);
      el.innerText = text;
      n.parentNode.insertBefore(el, n);
    }

    или

    for (let i = 0; i < elements.length; i++) {
      elements[i].insertAdjacentHTML('beforebegin', `<${tag}>${text}</${tag}>`);
    }

    или

    (function insert(i, n = elements.item(i)) {
      if (n) {
        const el = document.createElement(tag);
        el.appendChild(new Text(text));
        n.insertAdjacentElement('beforebegin', el);
        insert(-~i);
      }
    })(0);
    Ответ написан
  • Как скрывать элементы при несовпадении data-атрибутов?

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

    const selector = '.list-item';
    const key1 = 'pagereview';
    const key2 = 'pageslug';
    const attr1 = `data-${key1}`;
    const attr2 = `data-${key2}`;

    Получаем элементы:

    const $elements = $(selector);
    
    // или
    
    const elements = document.querySelectorAll(selector);

    Переключаем их видимость:

    $elements.show().filter((i, n) => $(n).data(key1) !== $(n).data(key2)).hide();
    
    // или
    
    $elements.each(function() {
      const $this = $(this);
      $this.toggle($this.attr(attr1) === $this.attr(attr2));
    });
    
    // или
    
    elements.forEach(n => {
      n.hidden = n.getAttribute(attr1) !== n.getAttribute(attr2);
    });
    
    // или
    
    for (const { style, dataset } of elements) {
      style.display = dataset[key1] === dataset[key2] ? 'block' : 'none';
    }
    
    // или (в стили надо будет добавить .hidden { display: none; })
    
    for (let i = 0; i < elements.length; i++) {
      const { classList: c, attributes: a } = elements[i];
      c.toggle('hidden', a[attr1].value !== a[attr2].value);
    }
    Ответ написан
    Комментировать
  • Как сделать так чтобы jquery фильтр искал по нескольким значениям?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Делаете общую функцию фильтрации, где получаете данные из всех фильтров и сравниваете их с элементами. Подключаете эту функцию ко всем фильтрам в качестве обработчика событий, возникающих при взаимодействии с ними пользователя. Например.
    Ответ написан
    1 комментарий
  • Как преобразовать данные?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const widgetsTransform = Object
      .values(widgets.reduce((acc, n) => ((acc[n.type] = acc[n.type] || []).push(n), acc), {}))
      .map(n => n.length > 1 ? ({ type: `Section${n[0].type}`, children: n }) : n[0]);
    Ответ написан
    Комментировать
  • Из-за чего тут ошибка с фильтрацией по цене?

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

    $('.price_min_max_btn').click(function() {
      const min = +$('.price_min').val() || 0;
      const max = +$('.price_max').val() || Infinity;
    
      $('.item_block_filter')
        .hide()
        .filter(function() {
          const price = +this.dataset.price;
          return min <= price && price <= max;
        })
        .show();
    });
    Ответ написан
    1 комментарий
  • Как получить позицию элемента относительно родителя?

    0xD34F
    @0xD34F Куратор тега JavaScript
    document.querySelector('table').addEventListener('click', e => {
      const td = e.target.closest('td');
      if (td) {
        // поскольку речь идёт о ячейках таблицы, то нет причин использовать что-то иное
        const index = td.cellIndex;
    
        // но вообще, можно и метод массива припахать
        const index = Array.prototype.indexOf.call(td.parentNode.children, td);
    
        // или вручную посчитать, как далеко удастся уйти по ссылкам на предыдущие элементы
        let index = 0;
        for (let el = td; el = el.previousElementSibling; index++) ;
      }
    });
    Ответ написан
    Комментировать
  • Как реализовать рекурсивную генерацию объекта по строке?

    0xD34F
    @0xD34F Куратор тега JavaScript
    А почему строка? Могли бы и сами догадаться её в массив порезать:

    const arr = str.split('-');
    const end = 'final';

    Использовать рекурсию не нужно, перебираем массив от конца к началу, на каждом шаге создаём объект с единственным свойством, в качестве ключа используется текущий элемент, значение - объект, полученный на предыдущем шаге:

    const obj = arr.reduceRight((acc, n) => ({ [n]: acc }), end);

    Но, конечно, если очень хочется, то рекурсия возможна:

    const obj = (function createObj(i) {
      return i < arr.length
        ? { [arr[i]]: createObj(i + 1) }
        : end;
    })(0);
    Ответ написан
    1 комментарий
  • Как объединить массивы?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const result = graphData.map((n, i) => ({ ...n, color: palette[i % palette.length] }));

    или, в более общем виде:

    const combine = (arr, keys, values) =>
      arr.map(({ ...n }, i) => (
        values.forEach((m, j) => n[keys[j]] = m[i % m.length]),
        n
      ));
    
    const result = combine(graphData, [ 'color' ], [ palette ]);
    Ответ написан
    1 комментарий
  • Как найти и заменить несколько вхождений в тексте одним скриптом?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const replacements = [
      [ 'вот это надо заменить', 'вот на это' ],
      [ 'а это заменить', 'на вот это' ],
    ];
    
    $elements.html((i, html) => {
      return replacements.reduce((acc, n) => acc.replace(RegExp(n[0], 'g'), n[1]), html);
    });
    Ответ написан
    Комментировать
  • Как заменить в строке точку или тире на "-"?

    0xD34F
    @0xD34F Куратор тега JavaScript
    str.replace(/\.? /g, '-')
    Ответ написан
    Комментировать
  • Как реализовать лайк на чистом js?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Делегирование, назначаем обработчик клика один раз:

    // при клике по кнопке определяем её индекс и хватаем .photos__like-count с таким же индексом
    document.addEventListener('click', ({ target: t }) => {
      if (t.classList.contains('photos__like-icon')) {
        const index = [...document.querySelectorAll('.photos__like-icon')].indexOf(t);
        const counter = document.querySelectorAll('.photos__like-count')[index];
        const count = counter.textContent;
        counter.textContent = t.classList.toggle('active') ? -~count : ~-count;
      }
    });
    
    // но если у каждой пары icon-count если отдельный общий предок, то можно и попроще сделать
    document.addEventListener('click', ({ target: t }) => {
      if (t.matches('.photos__like-icon')) {
        t
          .closest('селектор общего предка кнопки и элемента с количеством')
          .querySelector('.photos__like-count')
          .textContent -= t.classList.toggle('active') ? -1 : 1;
      }
    });

    Назначаем обработчик клика каждой кнопке индивидуально:

    const toggleLike = function({ target: t }) {
      this[t.dataset.index].innerText -= [ 1, -1 ][+t.classList.toggle('active')];
    }.bind(document.querySelectorAll('.photos__like-count'));
    
    document.querySelectorAll('.photos__like-icon').forEach((n, i) => {
      n.dataset.index = i;
      n.addEventListener('click', toggleLike);
    });
    
    // или, при наличии отдельных общих предков у каждой пары .photos__like-icon и .photos__like-count
    const toggleLike = ({ target: t }) => t
      .closest('селектор общего предка кнопки и элемента с количеством')
      .querySelector('.photos__like-count')
      .innerText -= t.classList.toggle('active') ? -1 : 1;
    
    for (const n of document.querySelectorAll('.photos__like-icon')) {
      n.addEventListener('click', toggleLike);
    }
    Ответ написан
    Комментировать
  • Как сделать что бы при наведении мышкой на картинку она двигалась в противоположную сторону от мыши?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Слушать событие mousemove, в зависимости от event.movementX задавать transform: translateX. Например.
    Ответ написан
    Комментировать
  • Можно ли сделать код проще на jQuery?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Уберите цифры из классов кнопок, чтобы они, классы, стали одинаковыми.
    Соответственно, const buttonSelector = '.arrowopen';.

    Сокращаем код:

    $(buttonSelector).click(e => $(e.currentTarget).prev().toggle());

    Или, от jquery можно вообще избавиться:

    document.addEventListener('click', ({ target: t }) =>
      (t = t.closest(buttonSelector)) &&
      (t.previousElementSibling.hidden ^= 1)
    );

    или

    .hidden {
      display: none;
    }

    document.querySelectorAll(buttonSelector).forEach(function(n) {
      n.addEventListener('click', this);
    }, e => e.currentTarget.previousElementSibling.classList.toggle('hidden'));
    Ответ написан
    Комментировать
  • Как динамически менять длительность анимации?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function setAnimation(el) {
      $(el).css('animation', `shadow-pulse ${1 + Math.random() * 3}s`);
    }
    
    $('.mr-2').on('animationend', function() {
      $(this).css('animation', '');
      setTimeout(setAnimation, 0, this);
    }).get().forEach(setAnimation);
    Ответ написан
  • Как сделать, чтобы при поиске блок скрывался полностью?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.search').on('input', function() {
      const search = $(this).val().trim().toLowerCase();
    
      $('.metro-line__item')
        .hide()
        .filter((i, n) => $('.metro__name', n).text().toLowerCase().includes(search))
        .show();
    
      $('.metro-line')
        .show()
        .not(':has(.metro-line__item:visible)')
        .hide();
    });

    или

    .hidden {
      display: none;
    }

    document.querySelector('.search').addEventListener('input', e => {
      const search = e.target.value.trim().toLowerCase();
    
      document.querySelectorAll('.metro-line__item').forEach(n => {
        const name = n.querySelector('.metro__name').textContent.toLowerCase();
        n.classList.toggle('hidden', !name.includes(search));
      });
    
      document.querySelectorAll('.metro-line').forEach(n => {
        n.classList.toggle('hidden', !n.querySelector('.metro-line__item:not(.hidden)'));
      });
    });
    Ответ написан
    Комментировать
  • Как удалить все классы, кроме одного?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const className = 'класс, который не надо удалять';
    
    
    // Если известно, что класс присутствует или должен быть добавлен в случае отсутствия:
    element.className = className;
    
    // Если известно, что класс отсутствует и не должен быть добавлен:
    element.className = '';
    
    // Если неизвестно, присутствует ли класс и в случае отсутствия он не должен быть добавлен:
    element.className = element.classList.contains(className) ? className : '';
    // или
    element.classList.remove(...[...element.classList].filter(n => n !== className));
    Ответ написан
    Комментировать
  • Как правильно составить массив с данными?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function createTree(arr, structure) {
      const tree = Object.fromEntries(arr.map(n => [ n.id, { ...n } ]));
      const nonRootIds = structure.flatMap(n => n.children);
    
      structure.forEach(n => tree[n.id].elements = n.children.map(m => tree[m]));
    
      return Object.values(tree).filter(n => !nonRootIds.includes(n.id));
    }
    Ответ написан
    3 комментария
  • Как избавиться от повторяющихся цифр в строке?

    0xD34F
    @0xD34F Куратор тега JavaScript
    str.replace(/(\d)\1+/g, '$1')
    
    // или
    
    ''.concat(...str.split(/(\d)\1+/))
    
    // или
    
    Array.from(str).filter((n, i, a) => Number.isNaN(+n) || a[i - 1] !== n).join('')
    
    // или
    
    [...str.matchAll(/(\D+)|(?:(\d)\2*)/g)].reduce((acc, n) => acc + (n[1] ?? n[2]), '')
    Ответ написан
    2 комментария
  • Как поместить в конец массива элементы, удовлетворяющие определённому условию?

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

    const checkItem = item => item.status === 'выполнено';

    Изменяем существующий массив:

    arr.sort((a, b) => +checkItem(a) || -checkItem(b));
    
    // или
    
    arr.reduceRight((_, n, i, a) => checkItem(n) && a.push(a.splice(i, 1)[0]), null);
    
    // или
    
    arr
      .reduce((acc, n, i) => (
        arr[i - acc.length] = n,
        checkItem(n) && acc.push(n),
        acc
      ), [])
      .forEach((n, i, a) => arr[arr.length - a.length + i] = n);

    Создаём новый:

    const newArr = arr
      .reduce((acc, n) => (
        acc[+checkItem(n)].push(n),
        acc
      ), [ [], [] ])
      .flat();
    
    // или
    
    const newArr = arr.reduce((acc, n) => (
      acc[checkItem(n) ? 'push' : 'unshift'](n),
      acc
    ), []);
    
    // или
    
    const newArr = [
      ...arr.filter(n => !checkItem(n)),
      ...arr.filter(checkItem),
    ];
    Ответ написан
    1 комментарий