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

    0xD34F
    @0xD34F Куратор тега JavaScript
    function compoundMatch(words, target) {
      const pairs = [];
    
      for (let i = 1; i < target.length; i++) {
        pairs.push([ target.slice(0, i), target.slice(i) ]);
      }
    
      for (const [ a, b ] of pairs) {
        const ia = words.indexOf(a);
        const ib = words.indexOf(b);
    
        if (ia !== -1 && ib !== -1) {
          return ia < ib ? [ a, b, [ ia, ib ] ] : [ b, a, [ ia, ib ] ];
        }
      }
    
      return null;
    }

    или

    function compoundMatch(words, target) {
      const indices = {};
    
      for (let i = 0; i < words.length; i++) {
        const a = words[i];
        if (!indices.hasOwnProperty(a)) {
          indices[a] = i;
    
          const b = target.replace(a, '');
          if (indices.hasOwnProperty(b)) {
            return [ b, a, a + b === target ? [ i, indices[b] ] : [ indices[b], i ] ];
          }
        }
      }
    
      return null;
    }

    или

    function compoundMatch(words, target) {
      const indices = {};
    
      for (let i = 0; i < words.length; i++) {
        indices[words[i]] = i;
      }
    
      for (const a in indices) {
        for (const b in indices) {
          if (a + b === target) {
            return indices[a] < indices[b]
              ? [ a, b, [ indices[a], indices[b] ] ]
              : [ b, a, [ indices[a], indices[b] ] ];
          }
        }
      }
    
      return null;
    }
    Ответ написан
    Комментировать
  • Как при зажатой кнопке мыши выделять кликать по элементу?

    0xD34F
    @0xD34F Куратор тега JavaScript
    .active {
      background: black;
      color: white;
    }

    const handler = e =>
      (e.type === 'click' || e.buttons === 1) &&
      e.target.classList.contains('but') &&
      e.target.classList.add('active');
    
    document.addEventListener('click', handler);
    document.addEventListener('mousemove', handler);
    Ответ написан
    Комментировать
  • Как дописать цикл jquery с поиском по тексту в строке таблицы?

    0xD34F
    @0xD34F Куратор тега JavaScript
    В каком столбце значение смотрим, в какой столбец значение пишем:

    const iKey = 0;
    const iTarget = 2;

    Возможные содержимые одного столбца (ключи объекта) и что надо записывать в другой (значения):

    const values = {
      'если есть такое значение': 'подставляем это',
      'а при наличие такого': 'ну вы поняли, что здесь должно быть',
      // ну и так далее
    };

    Подставляем значения, если ключ совпадает с содержимым столбца:

    $('.table tbody tr').each(function() {
      const $td = $('td', this);
      const key = $td.eq(iKey).text();
    
      if (values.hasOwnProperty(key)) {
        $td.eq(iTarget).text(values[key]);
      }
    });
    
    // или
    
    for (const { rows } of document.querySelector('.table').tBodies) {
      for (const { cells: { [iKey]: k, [iTarget]: t } } of rows) {
        t.textContent = values[k.textContent] ?? t.textContent;
      }
    }
    Ответ написан
    Комментировать
  • Как найти последний div, а все остальные удалить?

    0xD34F
    @0xD34F Куратор тега JavaScript
    найти последний div

    const last = document.querySelector('#container').lastElementChild;

    остальные удалить

    Array.prototype.reduceRight.call(
      document.getElementById('container').children,
      (_, n) => n?.nextElementSibling && n.replaceWith(),
      null
    );

    Оба действия сразу:

    const last = Array
      .from(document.querySelectorAll('[id="container"] > *'))
      .reduce((_, n, i, a) => i === ~-a.length ? n : n.remove(), null);
    Ответ написан
    Комментировать
  • Как в таблице подсветить колонки в зависимости от thead?

    0xD34F
    @0xD34F Куратор тега JavaScript
    О какой таблице речь и что за класс отвечает за выделение ячеек:

    const table = document.querySelector('table');
    const className = 'red';

    Сперва собираем индексы столбцов, заголовки которых имеют класс:

    const indices = Array.from(
      table.querySelectorAll(`thead .${className}`),
      n => n.cellIndex
    );

    Затем можно добавить класс ячейкам в теле таблицы:

    table.querySelectorAll('tbody tr').forEach(n => {
      indices.forEach(i => n.cells[i].classList.add(className));
    });

    Или, кроме добавления, можно класс ещё и убирать (если вдруг есть) в тех столбцах, заголовок которого не подсвечен:

    for (const { rows } of table.tBodies) {
      for (const { cells } of rows) {
        for (let i = 0, j = 0; i < cells.length; i++) {
          j += cells[i].classList.toggle(className, i === indices[j]);
        }
      }
    }
    Ответ написан
    Комментировать
  • Как написать это с одним циклом?

    0xD34F
    @0xD34F Куратор тега JavaScript
    О каких элементах идёт речь: const selector = '.box';.

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

    document.addEventListener('click', ({ target: t }) => {
      if (t = t.closest(selector)) {
        for (const n of document.querySelectorAll(selector)) {
          n.style.background = n === t ? 'red' : 'black';
        }
      }
    });

    или

    .box        { background: black; }
    .box.active { background:   red; }

    document.addEventListener('click', function({ target: t }) {
      if (t = this.find(n => n.contains(t))) {
        this.forEach(n => n.classList.toggle('active', n === t));
      }
    }.bind([...document.querySelectorAll(selector)]));

    ИЛИ

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

    document.querySelectorAll(selector).forEach(function(n) {
      n.addEventListener('click', this);
    }, function() {
      document.querySelector(`${selector}.active`)?.classList.remove('active');
      this.classList.add('active');
    });
    Ответ написан
    5 комментариев
  • Как получить объект с числами и именами дней недели, зная месяц и год?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function getDatesGroupedByWeekday(year, month) {
      const d = new Date(`${month} 1, ${year}`);
      const iMonth = d.getMonth();
      const result = {};
    
      while (d.getMonth() === iMonth) {
        const date = d.getDate();
        const weekday = d.toLocaleString('en-US', { weekday: 'long' });
        (result[weekday] = result[weekday] ?? []).push(date);
        d.setDate(date + 1);
      }
    
      return result;
    }
    Ответ написан
  • Как обернуть все что идет после div?

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

    const block = document.querySelector('.block');
    const wrapper = document.createElement('div');
    wrapper.classList.add('another__block');

    Вариант раз - вычисляем индекс блока внутри родителя, вырезаем из родителя подмассив вложенных узлов, начиная с индекс плюс один, вставляем в обёртку:

    const parent = block.parentNode;
    const childNodes = [...parent.childNodes];
    wrapper.append(...childNodes.slice(-~childNodes.indexOf(block)));
    parent.append(wrapper);

    Вариант два - пока у блока есть следующий узел, добавляем его в обёртку:

    for (let n; n = block.nextSibling; wrapper.appendChild(n)) ;
    block.after(wrapper);
    Ответ написан
    1 комментарий
  • Как вывести на страницу полученные данные?

    0xD34F
    @0xD34F Куратор тега JavaScript
    fetch('https://jsonplaceholder.typicode.com/albums')
      .then(r => r.json())
      .then(r => {
        const keys = [ 'userId', 'id', 'title' ];
    
        // собираем разметку
        document.body.insertAdjacentHTML('beforeend', `
          <div class="wrapper">${r.map(n => `
            <div class="item">${keys.map(k => `
              <div>${k}: ${n[k]}</div>`).join('')}
            </div>`).join('')}
          </div>
        `);
    
        // или, создаём элементы напрямую
        function createElement(tag, className, children) {
          const el = document.createElement(tag);
          el.className = className;
          el.append(...children);
          return el;
        }
    
        document.body.append(
          createElement('div', 'wrapper', r.map(n =>
            createElement('div', 'item', keys.map(k =>
              createElement('div', '', [ `${k}: ${n[k]}` ])
            ))
          ))
        );
      });

    .wrapper {
      border: 3px solid black;
      padding: 10px;
      margin: 10px;
    }
    
    .item {
      border: 1px solid silver;
      padding: 5px;
      margin: 5px;
    }
    Ответ написан
    Комментировать
  • Как вызывать функцию только по отношению к дочернему общему блоку кнопки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Класс лучше переключайте не у .img-block, а у их самых дальних не общих предков, т.е., у .documents_block. В этом случае не придётся переписывать js-код, если вдруг потребуется стилизовать ещё-что то, кроме .img-block, или если решите изменить внутреннюю структуру .documents_block. Вместо .класс дополнительные стили надо будет прописывать у .класс .img-block.

    const itemSelector = '.documents_block';
    const buttonSelector = `${itemSelector} .open-doc-list`;
    const contentSelector = '.documents-content';
    const activeClass = 'active';
    const toggleEffect = 'slideToggle'; // или fadeToggle, или toggle
    const onClick = e => $(e.currentTarget)
      .closest(itemSelector)
      .toggleClass(activeClass)
      .find(contentSelector)
      [toggleEffect]();
    
    
    // обработчик клика подключаем к кнопкам
    $(buttonSelector).click(onClick);
    
    // или, если предполагается добавление новых блоков уже после подключения
    // обработчика, то лучше будет повесить его на документ, тогда всё будет
    // работать как надо без каких-либо дополнительных действий
    $(document).on('click', buttonSelector, onClick);
    Ответ написан
    1 комментарий
  • Как сравнить два массива и найти вхождения?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const fourValues = four.map(Object.values);
    
    const result = three.map(n => {
      const values = Object.values(n);
      const intersections = fourValues.filter(m => values.every(v => m.includes(v)));
      return `${values} - ${intersections.length
        ? `входит в / ${intersections.map(m => `${m}`).join(' / ')} /`
        : 'нет вхождений'}`;
    });
    Ответ написан
    Комментировать
  • Как сделать независимую нумерацию слайдов в различных слайдерах?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Кого надо пронумеровать:

    const containerSelector = '.bakeries-slider';
    const itemSelector = '.bakeries-slider__span';

    Как пронумеровать (зависимость текста от индекса элемента):

    const getNumber = i => (i + 1) + '.';
    // или
    const getNumber = i => `${-~i}.`;
    // или
    const getNumber = i => ''.concat(++i, '.');

    Если использовать jquery, то индекс элемента принимает коллбек метода text:

    $(containerSelector).each(function() {
      $(itemSelector, this).text((i, text) => text + getNumber(i));
    });

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

    document.querySelectorAll(containerSelector).forEach(container => {
      const items = container.querySelectorAll(itemSelector);
    
      // индекс передаётся в коллбек forEach'а
      items.forEach((n, i) => n.textContent += getNumber(i));
    
      // или, отдаётся итератором entries
      for (const [ i, n ] of items.entries()) {
        n.appendChild(document.createTextNode(getNumber(i)));
      }
    
      // или, можно самостоятельно обновлять переменную с индексом
      for (let i = 0; i < items.length; i++) {
        items[i].insertBefore(new Text(getNumber(i)), null);
      }
    
      // причём цикл для этого не обязателен
      (function next(i, n = items.item(i)) {
        n && (n.append(getNumber(i)), next(-~i));
      })(0);
    });
    Ответ написан
    Комментировать
  • Jquery modal image нормально работает только первый раз, как решить?

    0xD34F
    @0xD34F Куратор тега JavaScript
    При каждом клике по картинкам вы добавляете обработчики клика кнопкам. В результате, сколько раз открыли окно - столько обработчиков на кнопках будет висеть. И при клике все они будут выполняться, и каждый сделает +/- 1 к текущему индексу.

    Выносите $('#m_prev').click и $('#m_next').click за пределы $('.norutyun img').click.
    Ответ написан
    1 комментарий
  • Как отфильтровать объекты в массиве по слову в строчке ключа?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Чего не надо:

    const key = 'status';
    const value = 'maybe';

    Фильтруем:

    const newArr = arr.filter(n => !n[key].includes(value));

    Если же и правда слово, тогда регулярные выражения используйте или предварительно режьте строку на куски:

    const reg = RegExp(`\\b${value}\\b`);
    const newArr = arr.filter(n => !reg.test(n[key]));
    
    // или
    
    const newArr = arr.filter(function(n) {
      return !n[key].match(this);
    }, RegExp(`(^| )${value}( |$)`));
    
    // или
    
    const newArr = arr.filter(n => !n[key].split(' ').includes(value));
    Ответ написан
    Комментировать
  • Как получить отсортированный массив в jquery?

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

    $('#sortable').sortable({
      stop() {
        const values = $('input[name="slider-id"]', this).get().map(n => n.value);
      },
    });
    Ответ написан
    Комментировать
  • Почему target.closest не выбирает элемент по классу?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Очевидно, потому что среди предков target нет элемента с указанным классом. Смотрите внимательнее, где находится target, а где то, что вы пытаетесь получить.
    Ответ написан
    3 комментария
  • Как из массива достать объекты, у которых одно из свойств имеет определённые значения?

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

    const key = 'workplace';
    const values = [ 'office', 'hotel' ];

    Достаём объекты:

    const result = arr.filter(function(n) {
      return this.has(n[key]);
    }, new Set(values));
    
    // или
    
    const result = values.flatMap(((grouped, n) => grouped[n] ?? []).bind(
      null,
      arr.reduce((acc, n) => ((acc[n[key]] = acc[n[key]] ?? []).push(n), acc), {})
    ));
    
    // или
    
    const result = [];
    for (const n of arr) {
      for (const m of values) {
        if (m === n[key]) {
          result.push(n);
          break;
        }
      }
    }
    
    // или
    
    const result = [];
    for (let i = 0; i < arr.length; i++) {
      if (~values.indexOf(arr[i][key])) {
        result[result.length] = arr[i];
      }
    }
    
    // или
    
    const result = (function get(i, n = arr[i]) {
      return n
        ? [].concat(values.includes(n[key]) ? n : [], get(-~i))
        : [];
    })(0);
    Ответ написан
    Комментировать