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

    0xD34F
    @0xD34F Куратор тега JavaScript
    62b0f00f35c0f358713719.png

    "Добавить"? Понятно, почему ничего не получается - формы добавляются динамически, так что обработчики событий вы пытаетесь назначать элементам, которых ещё нет. Применим делегирование - обработчик добавляем один раз, выше форм, проверяем целевой элемент, если это оказался интересующий нас input, то поднимаемся от него к элементу формы, ищем внутри неё все input'ы и элемент, в который надо записать результат вычислений.

    document.addEventListener('input', e => {
      if (e.target.classList.contains('form-control')) {
        const form = e.target.closest('селектор формы');
        form.querySelector('span').innerText = Array
          .from(form.querySelectorAll('input.form-control'))
          .reduce((acc, n) => acc * (+n.value || 0), 1);
      }
    });
    Ответ написан
    Комментировать
  • Как правильно распарсить такой массив со строками?

    0xD34F
    @0xD34F Куратор тега JavaScript
    arr.reduce((acc, n) => (
      n = n.match(/(\S+) = (.*)/),
      n && (acc[n[1]] = n[2]),
      acc
    ), {})

    или

    Object.fromEntries(arr
      .map(n => n.split(': ').pop().split(' = '))
      .filter(n => n.length === 2)
    )
    Ответ написан
    2 комментария
  • Как реализовать несколько независимых степперов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Как опознать кнопки +/-, как обновить значение:

    const plusSelector = '.count-plus';
    const minusSelector = '.count-minus';
    
    function updateCount(el, change) {
      const counterEl = el.closest('.count-wrapper').querySelector('.counter');
      counterEl.innerText = Math.max(0, +counterEl.innerText + change);
    }

    Назначаем один делегированный обработчик:

    document.addEventListener('click', ({ target: t }) => {
      const change = +t.matches(plusSelector) || -t.matches(minusSelector);
      if (change) {
        updateCount(t, change);
      }
    });

    Или, каждой кнопке индивидуально:

    function setClickHandler(selector, change) {
      document.querySelectorAll(selector).forEach(function(n) {
        n.addEventListener('click', this);
      }, e => updateCount(e.target, change));
    }
    
    setClickHandler(plusSelector, 1);
    setClickHandler(minusSelector, -1);
    Ответ написан
    Комментировать
  • Почему функция ничего не возвращает?

    0xD34F
    @0xD34F Куратор тега JavaScript
    return arr.forEach((fn) => {

    Понятно.

    Вот дураки вроде вас: раз дурак, два дурак, три дурак, четыре, пять.
    Ответ написан
    1 комментарий
  • Как с помощью JQUERY перебрать и сложить значение нескольких select?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Функция суммирования:

    function sum(data, key = n => n) {
      const getVal = key instanceof Function ? key : n => n[key];
      let result = 0;
    
      for (const n of data) {
        result += +getVal(n) || 0;
      }
    
      return result;
    }

    Элементы могут быть представлены как jquery-объект, NodeList или HTMLCollection (ну и разумеется, обычный массив, если что, тоже будет обсчитан как надо):

    const $form = $('form').on('change', 'select', () => {
      $('#result').val(sum($form.find('select'), n => $(n).val()));
    });

    const input = document.querySelector('#result');
    const selects = document.querySelectorAll('form select');
    const onChange = () => input.value = sum(selects, 'value');
    selects.forEach(n => n.addEventListener('change', onChange));

    document.forms[0].addEventListener('change', function(e) {
      if (e.target.tagName === 'SELECT') {
        document.getElementById('result').value = sum(
          this.getElementsByTagName('select'),
          n => n.selectedOptions[0].getAttribute('value')
        );
      }
    });
    Ответ написан
    1 комментарий
  • Как убрать checked с input radio при клике на него?

    0xD34F
    @0xD34F Куратор тега JavaScript
    А что за задача-то решается? Нужен гибрид радиокнопки и чекбокса?

    Вариант раз, радиокнопки:

    let checked = null;
    
    $('input').click(function() {
      checked = checked === this.value ? null : this.value;
      this.checked = !!checked;
    });
    
    // или
    
    document.querySelectorAll('input').forEach(function(n) {
      n.addEventListener('click', this);
    }, function({ target: t }) {
      t.checked = !!(this[0] = this[0] === t ? null : t);
    }.bind([]));

    Вариант два, с заменой радиокнопок чекбоксами:

    const $checkboxes = $('input').change(function() {
      if (this.checked) {
        $checkboxes.not(this).prop('checked', false);
      }
    });
    
    // или
    
    const checkboxes = document.querySelectorAll('input');
    const onChange = e => checkboxes.forEach(n => n.checked &&= n === e.target);
    checkboxes.forEach(n => n.addEventListener('change', onChange));

    Вариант три - вместо того, чтобы изменять значение свойства checked вручную, добавьте ещё одну радиокнопку, которая будет обозначать отсутствие выбора.
    Ответ написан
    1 комментарий
  • Как передать в аргументы функции карирования старые аргумент + новые?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const sum5 = (...args) =>
      args.length > 4
        ? args.slice(0, 5).reduce((acc, n) => acc + n, 0)
        : sum5.bind(null, ...args);
    //  или
    //  : (...args2) => sum5(...args, ...args2);
    Ответ написан
    1 комментарий
  • Как сделать, чтобы при выборе значения в одном select'е оно пропадало в других?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const selects = [...document.querySelectorAll('select')];
    const onChange = () =>
      selects.forEach(function({ value, options: [...n] }) {
        n.forEach(m => m.hidden = this(m.value) && value !== m.value);
      }, Set.prototype.has.bind(new Set(selects.map(n => n.value))));
    
    selects.forEach(n => n.addEventListener('change', onChange));
    Ответ написан
    1 комментарий
  • Как "развернуть" таблицу, превратив строки в столбцы?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function transposeTable(table) {
      const headerCol = table.rows[0]?.cells[1]?.tagName === 'TH';
      const content = Array.from(
        table.rows,
        tr => Array.from(tr.cells, td => td.innerHTML)
      );
    
      table.innerHTML = content[0]?.map((n, i) => `
        <tr>${content.map((m, j) => (j = (headerCol ? j : i) ? 'td' : 'th', `
          <${j}>${m[i]}</${j}>`)).join('')}
        </tr>
      `).join('') ?? '';
    }

    или

    function transposeTable(table) {
      const cells = Array
        .from(table.rows, tr => [...tr.cells])
        .reduce((acc, n) => (
          n.forEach((m, j) => (acc[j] ??= []).push(m)),
          acc
        ), []);
    
      Array.prototype.forEach.call(table.children, n => n.remove());
      cells.forEach(n => table.insertRow().append(...n));
    }

    https://jsfiddle.net/mqjna81x/
    Ответ написан
    Комментировать
  • Как проверить, что набор карт образует покерную комбинацию "стрит"?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сделать вспомогательный объект, где для нечисловых карт будут указываться их числовые эквиваленты. Массив карт превратить в массив соответствующих им чисел (карты используется как ключ для извлечения значения из объекта, если ничего не найдено, то карта приводится к числу); отсортировать массив; убедиться, что разность соседних значений всегда составляет единицу.

    const weights = {
      j: 11,
      q: 12,
      k: 13,
      a: 14,
    };
    
    const isStraight = hand => hand
      .map(n => weights[n] ?? +n)
      .sort((a, b) => a - b)
      .every((n, i, a) => !i || (n - a[i - 1] === 1));
    Ответ написан
    Комментировать
  • Как убрать disabled при повторном нажатии на чекбокс?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Не надо отслеживать никаких "повторных" "нажатий".
    Достаточно поставить состояние кнопки в зависимость от состояния чекбокса:

    чекбокс.addEventListener('change', e => кнопка.disabled = !e.target.checked);
    Ответ написан
    1 комментарий
  • Как отобразить блок "Нет элементов"?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.elem_block').on('click', '.dell', function() {
      $(this).closest('.block').addClass('fx_none');
      $('.no-res').toggleClass('fx_none', !!$('.block:not(.fx_none)').length);
    });

    или

    document.addEventListener('click', e => {
      const btn = e.target.closest('.dell');
      if (btn) {
        btn.closest('.block').classList.add('fx_none');
        document.querySelector('.no-res').classList.toggle(
          'fx_none',
          !!document.querySelector('.block:not(.fx_none)')
        );
      }
    });

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

    • Класс fx_none вырезаем
    • Элементам .no-res и .elem_block добавляем общую обёртку, какой-нибудь <div class="container">
    • По кликам на .dell вместо добавления класса, скрывающего элементы, удаляем их по-настоящему:

      document.querySelectorAll('.dell').forEach(function(n) {
        n.addEventListener('click', this);
      }, e => e.target.closest('.block').remove());
    • Прячем .no-res, если в .elem_block что-то есть:

      .container:has(.elem_block *) .no-res {
        display: none;
      }

      Если же удаление элементов не вариант, то прятать .no-res надо в том случае, если существует .block без класса, которые его скрывает:

      .container:has(.block:not(.fx_none)) .no-res {
        display: none;
      }


    Ответ написан
    Комментировать
  • Как переделать код для множества segmented control?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const controls = document.querySelectorAll('.segmented-control');
    controls.forEach(n => n.addEventListener('change', updatePillPosition));
    window.addEventListener('resize', () => controls.forEach(n => updatePillPosition.call(n)));
    
    function updatePillPosition() {
      const inputs = [...this.querySelectorAll('.option input')];
      const x = this.offsetWidth / inputs.length * inputs.findIndex(n => n.checked);
      this.querySelector('.selection').style.transform = `translateX(${x}px)`;
    }
    Ответ написан
    Комментировать
  • Как показать определённое количество блоков по клику?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const SHOW_ON_LOAD = 3;
    const SHOW_MORE = 2;
    
    const items = [...document.querySelectorAll('.box-list__item')];
    const button = document.querySelector('.show-more');
    
    showItems(SHOW_ON_LOAD);
    button.addEventListener('click', () => showItems(SHOW_MORE));
    
    function showItems(count) {
      items.splice(0, count).forEach(n => n.classList.add('ui-box-active'));
      button.classList.toggle('ui-button-hidden', !items.length);
    }
    Ответ написан
    1 комментарий
  • Когда применять arr.reduce?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Когда сочтёте нужным. Типа, подумали, и решили - здесь reduce нужен. Или не нужен. Да, подумали. Для этого у вас есть особый инструмент - голова называется.
    Ответ написан
    Комментировать
  • Как превратить данные input в массив js?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const data = Array.prototype.reduce.call(
      document.querySelectorAll('input'),
      (acc, n) => {
        const keys = n.name.match(/\w+/g);
        const key = keys.pop();
        keys.reduce((p, c) => p[c] ??= {}, acc)[key] = n.value;
        return acc;
      },
      {}
    );
    Ответ написан
    Комментировать
  • Как сделать кастомный выпадающий список?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вместо назначения индивидуальных обработчиков клика элементам списка (которых в момент назначения ещё нет, openItems оказывается пуст, так что обработчики никому не назначаются) сделайте один делегированный, надо

    openItems.forEach(function (formItem) {
      formItem.addEventListener('click', function () {
        openBtn.innerText = this.innerText;
        openList.classList.remove('open');
        hiddenInput.value = this.dataset.value;
      });
    });

    заменить на

    openList.addEventListener('click', function(e) {
      const item = e.target.closest('li.form-item');
      if (item) {
        openBtn.innerText = item.innerText;
        openList.classList.remove('open');
        hiddenInput.value = item.dataset.value;
      }
    });
    Ответ написан
    1 комментарий
  • Как получить последовательно разницу значений в массиве?

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

    const newData = data.map((n, i, a) => ({
      ...n,
      newSick: n.sick - (i < ~-a.length && a[-~i].sick),
    }));

    Добавить свойство элементам существующего массива:

    data.forEach((n, i, a) => n.newSick = n.sick - (a[i + 1]?.sick ?? 0));
    // или
    data.reduceRight((prev, n) => (n.newSick = n.sick - prev, n.sick), 0);
    Ответ написан
    Комментировать
  • Как отсортировать массив пар [ключ, значение]?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const sorted = (arr, key) => arr
      .map(n => [ key(n), n ])
      .sort(([a], [b]) => a < b ? -1 : +(a > b))
      .map(n => n[1]);

    Так как сортировка сбивается из-за наличия нечисловых символов в начале некоторых строк, просто вырежем их:

    const sortedArr = sorted(arr, n => n[0].replace(/^\D+/, ''));

    Если же значения могут быть не только двухзначными, то сравнивать их как строки уже нельзя. Делаем из них настоящие числа, считаем сумму; если второе слагаемое отсутствует, используем первое повторно:

    const sortedArr = sorted(arr, n => {
      const d = n[0].match(/\d+/g);
      return +d[0] + +d.at(-1);
    });
    Ответ написан
    Комментировать
  • Как добавить или отнять 1 по клику на кнопки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    let count = 0;
    const countEl = document.querySelector('.text');
    const buttons = [...document.querySelectorAll('.click')];
    const onClick = e => updateCount(e.target.classList.toggle('clicked') ? 1 : -1);
    const updateCount = change => countEl.innerText = count += change;
    buttons.forEach(n => n.addEventListener('click', onClick));
    updateCount(buttons.reduce((acc, n) => acc + n.classList.contains('clicked'), 0));
    Ответ написан
    1 комментарий