Задать вопрос
  • Как найти наибольшее значение по полю в объекте и вернуть его?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function max(data, key = n => n) {
      const getVal = key instanceof Function ? key : n => n[key];
      let result = null;
    
      for (const n of data) {
        const val = getVal(n);
        result = (!result || result[1] < val) ? [ n, val ] : result;
      }
    
      return result?.[0];
    }

    const { text } = max(arr, n => n.text.length);
    const oldest = max(arr, 'age');
    Ответ написан
    Комментировать
  • Как удалить лишние столбцы в table с помощью jquery?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Где и кого надо удалить:

    const tableSelector = 'здесь селектор вашей таблицы';
    const columnIndices = [ 8, 9, 10 ];
    
    const $rows = $(`${tableSelector} tr`);
    // или
    const { rows } = document.querySelector(tableSelector);

    Удаляем:

    $rows.each((_, n) =>
      $('> *', n)
        .filter(i => ~columnIndices.indexOf(i))
        .remove()
    );

    или

    $rows
      .children(`${columnIndices.map(n => `:nth-child(${-~n})`)}`)
      .detach();

    или

    Array.prototype.forEach.call(rows, function(n) {
      for (let i = n.cells.length; i--; this.has(i) && n.deleteCell(i)) ;
    }, new Set(columnIndices));

    или

    for (const { cells } of rows) {
      columnIndices.map(n => cells[n]).forEach(n => n?.remove());
    }

    или

    for (const n of rows) {
      n.replaceChildren(...Array.prototype.filter.call(
        n.cells,
        (_, i) => !columnIndices.includes(i)
      ));
    }
    Ответ написан
    Комментировать
  • Как получить массив чисел месяца вместе с днями недели?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function getWeekdaysOfMonth(year, month) {
      const date = new Date(year, --month, 1);
      const result = [];
    
      while (date.getMonth() === month) {
        result.push(date.toLocaleString('ru-RU', {
          month: 'long',
          day: 'numeric',
          weekday: 'long',
        }));
        date.setDate(date.getDate() + 1);
      }
    
      return result;
    }
    
    
    const weekdaysOfDecember2020 = getWeekdaysOfMonth(2020, 12);

    UPD. Вынесено из комментариев:

    но как поступить если я не хочу забирать дни недели из стандартного объекта. а взять из их своего массива?

    const weekdays = [
      'воскресенье',
      'это понедельник',
      'а это вторник',
      'конечно же среда',
      'четверг',
      'пятница - прямо после четверга',
      'суббота, рабочая неделя окончена',
    ];
    
    const getWeekdaysOfMonth = (year, month) => Array.from(
      { length: new Date(year, month--, 0).getDate() },
      (n, i) => {
        const d = new Date(year, month, i + 1);
        return d.toLocaleString('ru-RU', {
          month: 'long',
          day: 'numeric',
        }) + ', ' + weekdays[d.getDay()];
      });
    
    
    const weekdaysOfFebruary2021 = getWeekdaysOfMonth(2021, 2);
    Ответ написан
  • Как из массива сделать вложенный объект?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const result = arr.reduceRight((acc, n) => ({ [n]: acc }), {});

    или

    let result = {};
    for (let i = arr.length; i--;) {
      result = { [arr[i]]: result };
    }

    или

    const result = (function createObj(i) {
      return i < arr.length
        ? { [arr[i]]: createObj(-~i) }
        : {};
    })(0);
    Ответ написан
    Комментировать
  • Как получить src из тега picture?

    0xD34F
    @0xD34F Куратор тега JavaScript
    document.querySelector('.products__body').addEventListener('click', e => {
      const item = e.target.closest('.card-preview__item');
      if (item) {
        e.preventDefault();
        const { srcset } = item.querySelector('source');
        item.closest('.card').querySelector('.card-head__image source').srcset = srcset;
      }
    });
    Ответ написан
    1 комментарий
  • Как сложить значения массивов по ключам?

    0xD34F
    @0xD34F
    function merge(...$arrays) {
      $result = [];
    
      foreach ($arrays as $arr) {
        foreach ($arr as $key => $values) {
          if (!isset($result[$key])) {
            $result[$key] = [];
          }
    
          for ($i = 0; $i < count($values); $i++) {
            $result[$key][$i] = ($result[$key][$i] ?? 0) + $values[$i];
          }
        }
      }
    
      return $result;
    }
    
    
    $arr = merge($arr1, $arr2);
    Ответ написан
    1 комментарий
  • Как создать тег на хабр Q & A?

    0xD34F
    @0xD34F
    Открываете форму обратной связи. В выпадающем списке "тема" выбираете пункт "гениальная идея". В текстовом поле "текст сообщения" излагаете суть - что за тэг, и почему его следует добавить. Подсказка: "почему следует добавить" - это, как минимум, наличие уже существующих вопросов, к которым новый тэг можно будет прицепить, и, наверное, не в количестве 3-5-10 штук, а побольше. Так что прежде чем предлагать добавление тэга, стоит воспользоваться поиском - убедитесь, что оно того стоит.
    Ответ написан
    Комментировать
  • Как правильно доработать логику слайдера?

    0xD34F
    @0xD34F
    нужно отлавливать дата атрибуты и если эти дата атрибуты совпадают с дата атрибутами других блоков то вешать класс на блоки

    Может, не надо никакие атрибуты трогать - учитывая, что порядок значений атрибутов идентичен для слайдов и блоков? Смотрите на индекс:

    on: {
      slideChange() {
        const index = this.realIndex;
        document.querySelectorAll('.lol').forEach((n, i) => n.classList.toggle('active', i === index));
      },
    },

    А вообще, всё это похоже на попытку соорудить собственную пагинацию. Для этого у swiper'а предусмотрены отдельные настройки. Вырезаете из .clients__picture все .lol, вырезаете обработчик slideChange, добавляете

    pagination: {
      el: '.clients__picture',
      bulletClass: 'lol',
      bulletActiveClass: 'active',
      renderBullet: (index, className) => `<div class="${className}">${index + 1}</div>`,
    },
    Ответ написан
    1 комментарий
  • Почему не отрабатывает событие?

    0xD34F
    @0xD34F Куратор тега JavaScript
    • tagName:

      For DOM trees which represent HTML documents, the returned tag name is always in the canonical upper-case form.

      А теперь посмотрите, что вы у себя написали:

      if(str.tagName == 'ul') {

      } else if (str.tagName == 'li') {

      Кстати, а почему str, что за странный выбор имени? Там же элемент, а не строка.

    • Вместо элемента добавляется строка:

      elem.append('li');

    • Крайне странное назначение обработчика клика:

      for (let el of strLi) {
          el.addEventListener('click',func);
      };

      Во-первых - зачем каждый раз добавлять всем? Хорошо, что хоть объявление func вынесено за пределы текущей функции, иначе бы при каждом клике всем существующим li добавлялся новый обработчик.

      Во-вторых - пока не кликните по li, на свежесозданных li клик обрабатываться не будет (касается и тех, что изначально существуют).

      В-третьих - а на хрена оно надо? Вы же уже обрабатываете клик по li - так зачем назначать отдельный обработчик клика? То, что делаете в func, вполне можно делать прямо тут.


    А вообще, исправлять существующий код я бы не стал. Лучше его вырезать полностью и написать другой, получится гораздо проще и короче:

    document.querySelector('ul').addEventListener('click', e => {
      const t = e.target;
      const ct = e.currentTarget;
      t.insertAdjacentHTML('beforeend', ct === t ? '<li>text</li>' : '!');
    });
    Ответ написан
    Комментировать
  • Как из списка строк удалить элементы, кроме заданных?

    0xD34F
    @0xD34F
    [ ''.join(m for m in n if m in punct) for n in arr ]
    Ответ написан
    Комментировать
  • JS Promise Memoize как правильно описать функцию?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function memoize(f, timeout) {
      const memo = {};
    
      return () => (new Date() < memo.time + timeout)
        ? Promise.resolve(memo.result)
        : f().then(r => (memo.time = +new Date(), memo.result = r));
    }
    Ответ написан
    Комментировать
  • Как отсортировать DOM элементы в обратную сторону на чистом js?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Где надо развернуть элементы: const parent = document.querySelector('ul');.

    Разворачиваем:

    parent.querySelectorAll(':scope > *').forEach(n => parent.prepend(n));
    
    // или
    
    Element.prototype.append.apply(parent, [...parent.children].reverse());
    
    // или
    
    const [ first, ...rest ] = parent.children;
    first?.before(...rest.reverse());
    
    // или
    
    for (const n of parent.children) {
      parent.insertBefore(n, parent.firstElementChild);
    }
    
    // или
    
    for (let i = parent.children.length; i--;) {
      parent.insertAdjacentElement('beforeend', parent.children[i]);
    }
    
    // или
    
    const elems = Array.from(parent.children);
    while (elems.length) {
      parent.appendChild(elems.pop());
    }
    Ответ написан
    7 комментариев
  • Как определить первые цифры чисел массива?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Если исправлять/дополнять существующий код, то, во-первых, определять первую цифру надо для каждого из элементов массива отдельно, т.е. let first = вам следовало разместить внутри цикла, а не перед ним; во-вторых, проще всего получить цифру старшего разряда можно превратив число в строку и взяв нулевой символ. Т.е., вы пытались изобразить нечто подобное:

    for (const n of arr) {
      const [ first ] = String(n);
      if (first == 1 || first == 2 || first == 5) {
        console.log(n);
      }
    }

    Но вообще, можно сделать и иначе.

    Вместо трёх проверок достаточно одной, если допустимые первые цифры представлены в подходящем виде, например, будут являться...

    // ...строкой
    const first = '125';
    const startsWithFirst = n => !!~first.indexOf(`${n}`[0]);
    
    // ...массивом чисел
    const first = [ 1, 2, 5 ];
    const startsWithFirst = n => first.includes(n / (10 ** (Math.log10(n) | 0)) | 0);
    
    // ...числом
    const first = 0b100110;
    const startsWithFirst = n => ((first >> ('' + n).charAt()) & 1) === 1;
    
    // ...регулярным выражением
    const first = /^[125]/;
    const startsWithFirst = n => first.test(n);

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

    // все сразу
    console.log(arr.filter(startsWithFirst));
    
    // или по одному
    arr.forEach(n => startsWithFirst(n) && console.log(n));
    Ответ написан
    Комментировать
  • Как ограничить выход элемента за другой?

    0xD34F
    @0xD34F Куратор тега JavaScript
    новая_координата = Math.max(
      минимальное_допустимое_значение,
      Math.min(
        максимальное_допустимое_значение,
        текущая_координата + изменение_координаты
      )
    );

    https://jsfiddle.net/03mh1q78/
    Ответ написан
    Комментировать
  • Регулярное выражение для замены img на picture?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Как получить src:

    const getSrc = img => img.getAttribute('src');
    // или
    const getSrc = img => img.attributes.src.value;

    Чтобы дальше два раза одно и то же не писать, небольшой декоратор:

    const relativeOnly = f => img => {
      const src = getSrc(img);
      if (!/^https?:\/\//.test(src)) {
        f(img, src);
      }
    };

    Можно перезаписывать разметку:

    document.querySelectorAll('img').forEach(relativeOnly((img, src) =>
      img.outerHTML = `
        <picture>
          <source srcset="${src}" type="image/svg+xml">
          ${img.outerHTML}
        </picture>`
    ));

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

    const wrapImages = relativeOnly((img, src) => {
      const picture = document.createElement('picture');
      const source = document.createElement('source');
      source.srcset = src;
      source.type = 'image/svg+xml';
      img.replaceWith(picture);
      picture.append(source, img);
    });

    for (const n of document.getElementsByTagName('img')) {
      wrapImages(n);
    }
    
    // или
    
    Array.prototype.forEach.call(document.images, wrapImages);
    Ответ написан
  • Как разделить значения массива через запятую и обернуть их в кавычки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    О каком количестве значений идёт речь: const count = 10;.

    const result = Array
      .from({ length: count }, (n, i) => `"${-~i}"`)
      .join(', ');
    
    // или
    
    const result = [...Array(count).keys()].reduce((acc, n) => {
      return acc.concat(acc && ', ', '"', ++n, '"');
    }, '');
    
    // или
    
    const result = (function xxx(n) {
      return n > 0 ? xxx(n - 1) + (n === 1 ? '' : ', ') + '"' + n + '"' : '';
    })(count);
    
    // или
    
    const result = Array(count)
      .fill()
      .map((n, i) => JSON.stringify((i + 1).toString()))
      .toString()
      .replace(/,/g, '$& ');
    Ответ написан
    Комментировать
  • Как повесить события на динамический дочерний класс?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Куда надо нажимать и какие классы переключать:

    const buttonSelector = '.class2';
    const classesToToggle = [ 'class3', 'class4' ];

    Переключаем:

    $(buttonSelector).click(e => {
      $(e.currentTarget).next().toggleClass(classesToToggle.join(' '));
    });

    или

    document.querySelectorAll(buttonSelector).forEach(n => {
      n.addEventListener('click', onClick);
    });
    
    function onClick() {
      classesToToggle.forEach(n => this.nextElementSibling.classList.toggle(n));
    }

    или

    document.addEventListener('click', e => {
      const button = e.target.closest(buttonSelector);
      if (button) {
        for (const n of classesToToggle) {
          button.parentNode.lastElementChild.classList.toggle(n);
        }
      }
    });
    Ответ написан
    2 комментария
  • Как сделать циклическую смену 3х цветов фона div при наведении и отведении мыши?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const el = document.querySelector('#box');
    const colors = [ 'red', 'green', 'blue' ];
    let index = -1;
    
    el.addEventListener('mouseenter', function() {
      index = (index + 1) % colors.length;
      this.style.backgroundColor = colors[index];
    });
    el.addEventListener('mouseleave', function() {
      this.style.backgroundColor = '';
    });
    Ответ написан
    Комментировать