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

    0xD34F
    @0xD34F Куратор тега JavaScript
    document.querySelectorAll('.row').forEach(addClass);
    
    // или
    
    for (const n of document.getElementsByClassName('row')) {
      addClass(n);
    }

    Как выглядит функция addClass? Зависит от того, что вам нужно. Есть разные варианты:

    • Если добавляемый класс всегда содержит количество дочерних элементов:

      const addClass = el => el.classList.add(`row-${el.children.length}`);

    • Если добавлять класс надо не всегда и имя может быть произвольным, тогда можно сделать объект, где ключами будут количества дочерних элементов, а значениями - соответствующие классы:

      const classes = {
        3: 'row-3',
        5: 'row-5',
        7: 'row-xxx',
      };
      
      function addClass(el) {
        const className = classes[el.children.length];
        if (className) {
          el.classList.add(className);
        }
      }

    • Если класс должен добавляться когда количество дочерних элементов попадает в некоторый интервал, то складываем в массив пары из классов и верхних границ соответствующих интервалов:

      const classes = [
        { max:        3, name: 'row-0-3' },
        { max:        5, name:        '' }, // если дочерних элементов 4 или 5, класс не добавляется
        { max:        7, name: 'row-6-7' },
        { max: Infinity, name: 'row-7-x' },
      ];
      
      function addClass(el) {
        const { name } = classes.find(n => n.max >= el.children.length) ?? {};
        if (name) {
          el.classList.add(name);
        }
      }

    • В случае, когда классов может быть несколько, делаем массив, содержащий пары из классов и функций, принимающих количество элементов и определяющих, надо ли данные классы добавлять:

      const classes = [
        [ c => c < 5,          'row-0-4' ],
        [ c => c % 2,          'row-odd' ],
        [ c => 6 < c && c < 9, 'row-7-8' ],
      ];
      
      const addClass = ({ classList, children: { length } }) =>
        classList.add(...classes.reduce((acc, n) => (
          n[0](length) && acc.push(n[1]),
          acc
        ), []));

    Ответ написан
    Комментировать
  • Что изменить в переключателях времени?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.entry__arrow--increment, .entry__arrow--decrement').click(function() {
      const $this = $(this);
    
      $this.closest('.entry__box').find('.entry__data').text(function(i, text) {
        const { step, max, min } = this.dataset;
    
        let newVal = +text + step * ($this.hasClass('entry__arrow--increment') ? 1 : -1);
        if (newVal > max) {
          newVal = min;
        } else if (newVal < min) {
          newVal = max;
        }
    
        return `${newVal}`.padStart(2, 0);
      });
    });
    Ответ написан
    7 комментариев
  • Как кликая на ссылку присвоить class пункту меню?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const li = document.querySelectorAll('li');
    li.forEach(n => n.addEventListener('click', onClick));
    
    function onClick(e) {
      e.preventDefault();
      li.forEach(n => n.classList.toggle('active', n === this));
      const href = this.querySelector('a').getAttribute('href');
      document.querySelector(href).scrollIntoView({
        behavior: 'smooth',
      });
    }
    Ответ написан
    3 комментария
  • Как на JQUERY обернуть каждые два элемента списка в тег?

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

    const parent = document.querySelector('.team');
    const wrapperTag = 'div';
    const wrapperClass = 'new';
    const wrapSize = 2;

    Оборачиваем:

    parent.querySelectorAll(':scope > *').forEach((n, i) => {
      if (!(i % wrapSize)) {
        parent.appendChild(document.createElement(wrapperTag));
        parent.lastChild.classList.add(wrapperClass);
      }
    
      parent.lastChild.appendChild(n);
    });

    или

    parent.append(...Array.from(
      { length: Math.ceil(parent.children.length / wrapSize) },
      () => {
        const wrapper = document.createElement(wrapperTag);
        wrapper.className = wrapperClass;
        wrapper.append(...Array.prototype.slice.call(parent.children, 0, wrapSize));
        return wrapper;
      }
    ));
    Ответ написан
    Комментировать
  • Как вставить текст после родителя определённого кол-ва символов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    О каких элементах идёт речь, какое количество символов у них внутри должно оказаться, и какой текст надо вставить:

    const elements = document.querySelectorAll('p');
    const max = 20;
    const text = 'hello, world!!';

    Перебираем элементы, суммируем длины их содержимого, по достижении заданного значения вставляем текст:

    let len = 0;
    
    for (const n of elements) {
      len += n.innerText.length;
      if (len >= max) {
        n.parentNode.insertBefore(new Text(text), n.nextSibling);
        // или
        n.outerHTML += text;
    
        break;
      }
    }

    или

    const el = Array.prototype.find.call(elements, function(n) {
      return (this[0] += n.textContent.length) >= max;
    }, [ 0 ]);
    
    el?.after(text);
    // или
    el && el.insertAdjacentText('afterend', text);
    Ответ написан
    1 комментарий
  • Как понять на какое время приходят эти данные из OpenWeatherApp?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Очевидно же - свойство dt. Умножаете на 1000, засовываете в конструктор Date - получаете дату.
    Ответ написан
    Комментировать
  • Как вывести массив строк по колонкам?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function tableString(arr, numCols, colSpacing = 3) {
      const numRows = Math.ceil(arr.length / numCols);
      const rows = Array.from(
        { length: numRows },
        (n, i) => arr.slice(i * numCols, (i + 1) * numCols)
      );
      const widths = Array.from(
        { length: numCols },
        (n, i) => Math.max(...rows.map(m => (m[i] ?? '').length))
      );
    
      return rows
        .map(n => n.map((m, i) => m.padEnd(colSpacing + widths[i], ' ')).join(''))
        .join('\n');
    }
    
    
    const arr = [
      '11111', '22222222', '33333333', '444', '11', '222', '3333',
      '4444444', '11111111', '222222', '33333333', '4', '1',
      '2222222222', '3', '44444444444444',
    ];
    
    console.log(tableString(arr, 4));
    console.log(tableString(arr, 3));
    console.log(tableString(arr, 3, 8));
    Ответ написан
    1 комментарий
  • Как по всему документу скрыть значения которые имеют undefined?

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

    Умно, ничего не скажешь.

    А главное - это будет ни разу не костыль.
    /*
     * надеюсь, хотя бы вместо "по всему документу" вы сумеете подобрать
     * какой-нибудь вменяемый селектор, чтобы не проверять реально всё,
     * а только те элементы, где ваш "undefined" действительно может случиться
     */
    document.querySelectorAll('*').forEach(n => {
      const text = n.innerText?.trim();
      if (text === 'undefined') {
        n.hidden = true;
      }
    });
    Ответ написан
    4 комментария
  • Как привести русский URL в нормальный вид средствами PHP или JS?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Ответ написан
    Комментировать
  • Как разбить слова на подгруппы?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const arr = str.split(/(?<=[A-Z]), /);
    
    // или
    
    const arr = str.match(/[^,\s][^,]*, [^,]+/g) ?? [];
    
    // или
    
    const arr = str
      .split(', ')
      .reduce((acc, n, i) => (
        (i & 1) || acc.push([]),
        acc[acc.length - 1].push(n),
        acc
      ), [])
      .map(n => n.join(', '));
    Ответ написан
    1 комментарий
  • Как реализовать фильтр товаров на checkbox?

    0xD34F
    @0xD34F Куратор тега JavaScript
    .hidden {
      display: none;
    }

    const filter = document.querySelector('.filter');
    
    filter.addEventListener('change', function() {
      document.querySelectorAll('.cart-product').forEach(function(n) {
        n.classList.toggle('hidden', this.length && !this.includes(n.dataset.category));
      }, Array.from(this.querySelectorAll(':checked'), n => n.dataset.filter));
    });
    
    filter.dispatchEvent(new Event('change'));
    Ответ написан
    3 комментария
  • Как посчитать точки, которые попадают в полигон?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Обходите массив с точками, считаете количество положительных результатов вызовов containsLocation:

    function showDotsCountInPolygon(e) {
      const dotsCountInPolygon = dots
        .filter(n => google.maps.geometry.poly.containsLocation(new google.maps.LatLng(n), this))
        .length;
    
      infoWindow.setContent(`Точек в полигоне: ${dotsCountInPolygon}`);
      infoWindow.setPosition(e.latLng);
      infoWindow.open(map);
    }

    polygon.addListener('click', showDotsCountInPolygon);

    https://jsfiddle.net/awcu8de9/
    Ответ написан
    Комментировать
  • Как можно сформировать дерево категорий в javascript?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сперва превращаем плоский массив во вложенный:

    function createTreeData(arr, idKey, parentKey) {
      const tree = Object.fromEntries(arr.map(n => [ n[idKey], { ...n, children: [] } ]));
      return Object.values(tree).filter(n => !tree[n[parentKey]]?.children.push(n));
    }
    
    
    const treeData = createTreeData(data, 'id', 'parent_id');

    Затем можно собрать разметку дерева:

    const createTreeHTML = data =>
      Array.isArray(data) && data.length
        ? `<ul>${data.map(n => `
             <li>
               ${n.name}
               ${createTreeHTML(n.children)}
             </li>`).join('')}
           </ul>`
        : '';
    
    
    document.body.insertAdjacentHTML('beforeend', createTreeHTML(treeData));

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

    const createTreeElement = data =>
      data instanceof Array && data.length
        ? data.reduce((ul, n) => (
            ul.append(document.createElement('li')),
            ul.lastChild.append(n.name, createTreeElement(n.children)),
            ul
          ), document.createElement('ul'))
        : '';
    
    
    document.body.append(createTreeElement(treeData));

    ИЛИ

    Без создания промежуточного вложенного массива:

    function createTreeElement(arr, idKey, parentKey) {
      const tree = arr.reduce((acc, { [parentKey]: n }) => (
        acc[n] = acc[n] ?? document.createElement('ul'),
        acc
      ), {});
    
      arr.forEach(n => (
        tree[n[parentKey]].append(document.createElement('li')),
        tree[n[parentKey]].lastChild.append(n.name, tree[n[idKey]] ?? '')
      ));
    
      return Object.values(tree).reduce((ul, n) => (
        n.parentNode || ul.append(...n.children),
        ul
      ), document.createElement('ul'));
      // или, если не надо объединять в общий список элементы, у которых разные корневые parent_id
      // return Object.values(tree).filter(n => !n.parentNode);
    }
    
    
    document.body.append(createTreeElement(data, 'id', 'parent_id'));
    Ответ написан
    Комментировать
  • Как преобразовать массив с 3 индекса?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Собираем новый массив:

    const newArr = [...Array(num)].reduce((acc, n, i) => (
      acc[(index + i) % acc.length]++,
      acc
    ), [...arr]);
    
    // или
    
    const newArr = arr.map(function(n, i, a) {
      return n + this[0] + (((i - index) % a.length + a.length) % a.length < this[1]);
    }, [ num / arr.length | 0, num % arr.length ]);

    Обновляем существующий:

    for (let i = num; i-- > 0; arr[(index + i) % arr.length]++) ;
    
    // или
    
    (function xxx(i) {
      if (--i >= 0) {
        arr[(index + i) % arr.length]++;
        xxx(i);
      }
    })(num);
    Ответ написан
  • Как найти сумму всех элементов многомерного объекта?

    0xD34F
    @0xD34F Куратор тега JavaScript
    В чем моя ошибка?

    В неприменении рекурсии:

    const sum = val =>
      val instanceof Object
        ? Object.values(val).reduce((acc, n) => acc + sum(n), 0)
        : typeof val === 'number'
          ? val
          : 0;
    
    
    console.log(sum(obj));

    Но, конечно, можно и без неё:

    function sum(val) {
      let result = 0;
    
      for (const stack = [ val ]; stack.length;) {
        const n = stack.pop();
        if (n instanceof Object) {
          stack.push(...Object.values(n));
        } else if (n === +n) {
          result += n;
        }
      }
    
      return result;
    }
    Ответ написан
    4 комментария
  • Как сделать, чтобы при появлении ответа на один вопрос другие вопросы скрывались?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Чтобы ставший видимым .faq__answer не растягивал родительский элемент и, соответственно, не перемещал лежащие ниже .faq__question, надо задать ему position: absolute. И ещё z-index побольше, чем у .faq__quest, чтобы не прятался за ними.

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

    https://jsfiddle.net/jsogh73b/
    Ответ написан
    Комментировать
  • Как в yandex api узнать id полигона в который попала метка?

    0xD34F
    @0xD34F Куратор тега JavaScript
    перебираете полигоны, смотрите результат contains
    Ответ написан
  • Почему пустой массив равен нулю?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Открываете спецификацию и смотрите, как выполняется сравнение.
    Ответ написан
    Комментировать
  • Как отфильтровать массив, вернуть, то, что не совпало?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function diff(data1, data2, key = n => n) {
      const getKey = key instanceof Function ? key : n => n[key];
      const keys = new Set(Array.from(data2, getKey));
      const result = [];
    
      for (const n of data1) {
        if (!keys.has(getKey(n))) {
          result.push(n);
        }
      }
    
      return result;
    }

    // ваш случай
    const result = diff(arr1, arr2, 'id');
    
    // есть и другие варианты использования
    diff(Array(10).keys(), Array(7).keys()) // [ 7, 8, 9 ]
    diff('ABCDE', 'ace', n => n.toLowerCase()) // [ 'B', 'D' ]
    Ответ написан
    Комментировать
  • Как перевести jquery код на чистый javascript?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function onChange() {
      document.querySelector('селектор элемента для вывода результата проверки').innerText = [
        // здесь массив селекторов вида
        // input[имя_атрибута1="значение1"][имя_атрибута2="значение2"]:checked
      ].every(n => document.querySelector(n))
        ? 'какой-то текст'
        : 'какой-то другой текст';
    }
    
    onChange();
    document.addEventListener('change', e => {
      if (e.target.matches('input[type="radio"]')) {
        onChange();
      }
    });

    https://jsfiddle.net/j1s2uatm/
    Ответ написан
    Комментировать