Задать вопрос
  • Как объединить два массива в один у которых ключи id и user_id с одинаковыми значениями?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const result = arr2.map(function(n) {
      return { ...n, ...this[n.id] };
    }, arr1.reduce((acc, { user_id: id, ...n }) => {
      const obj = acc[id] = acc[id] ?? {};
      Object.keys(n).forEach(k => obj[k] = (obj[k] ?? 0) + n[k]);
      return acc;
    }, {}));
    Ответ написан
    Комментировать
  • Как сделать рекурсию в таком случае?

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

    const getReversedPaths = (arr, path = []) =>
      arr.reduce((acc, { childItems, ...item }) => {
        path.push(item);
    
        if (childItems) {
          acc.push(...getReversedPaths(childItems, path));
        } else {
          acc.push(path.length > 1
            ? path.map(({ packingLevel }, i, a) => ({ ...a[a.length - i - 1], packingLevel }))
            : [ path[0] ]
          );
        }
    
        path.pop();
    
        return acc;
      }, []);

    Туда:

    const reverseThere = arr =>
      getReversedPaths(arr).map(n =>
        n.reduceRight((child, parent) => ({ ...parent, childItems: [ child ] }))
      );

    Обратно:

    const reverseBackAgain = arr =>
      (function createTree(arr) {
        return Object.values(arr.reduce((acc, [ head, ...tail ]) => {
          if (tail.length) {
            (acc[head.name] = acc[head.name] || { ...head, childItems: [] }).childItems.push(tail);
          } else {
            acc[head.name] = head;
          }
    
          return acc;
        }, {})).map(n => (n.childItems && (n.childItems = createTree(n.childItems)), n));
      })(getReversedPaths(arr));
    Ответ написан
    3 комментария
  • Kогда состояние в дочернем компоненте изменилось, как отправить эти значения родительскому компоненту?

    0xD34F
    @0xD34F Куратор тега React
    Если отвечать ровно на то, что было спрошено - из родительского компонента в дочерний передавайте функцию, которая будет вызываться в эффекте, зависящем от отслеживаемого значения.

    В родительском компоненте:

    <Child onChange={onChange} />

    В дочернем:

    useEffect(() => props.onChange(val), [ val ]);

    https://jsfiddle.net/su2az6of/

    Но вообще, это странно. Обычно, если надо отправлять изменения какого-то значения родителю, то само значение хранится там же, в родителе, и передаётся через props (вместе с функцией, которая его обновляет).

    https://jsfiddle.net/su2az6of/1/
    Ответ написан
    Комментировать
  • Как в массиве объектов оставить только то, что есть в другом массиве?

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

    const newArr2 = arr2.filter(n => arr1.some(m => m === n.name));
    
    // или
    
    const obj2 = arr2.reduce((acc, n) => (
      (acc[n.name] = acc[n.name] ?? []).push(n),
      acc
    ), {});
    const newArr2 = arr1.flatMap(n => obj2[n] ?? []);
    
    // или
    
    const newArr2 = [];
    for (const n of arr2) {
      for (const m of arr1) {
        if (m === n.name) {
          newArr2.push(n);
          break;
        }
      }
    }

    Удалить элементы существующего:

    arr2.reduceRight((_, n, i, a) => ~arr1.indexOf(n.name) || a.splice(i, 1), null);
    
    // или
    
    arr2.splice(0, arr2.length, ...arr2.filter(function(n) {
      return this.has(n.name);
    }, new Set(arr1)));
    
    // или
    
    arr2.length -= arr2.reduce((acc, n, i, a) => (
      a[i - acc] = n,
      acc + !arr1.includes(n.name)
    ), 0);
    Ответ написан
    Комментировать
  • Как добавить описание select?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Добавьте в начало скрытый option:

    <select>
      <option value="" hidden>здесь ваше описание</option>
      ...

    UPD. А зачем тэг "javascript"? Собираетесь добавлять "описания" динамически? Если так, есть следующие варианты:

    select.innerHTML = '<option value="" hidden>...</option>' + select.innerHTML;

    select.insertAdjacentHTML('afterbegin', '<option value="" hidden>...</option>');

    const option = document.createElement('option');
    option.value = '';
    option.hidden = true;
    option.innerText = '...';
    select.prepend(option);

    const option = new Option('...', '');
    option.style.display = 'none';
    select.insertBefore(option, select.firstElementChild);

    https://jsfiddle.net/bkdcexhw/
    Ответ написан
    Комментировать
  • Как преобразовать строку в число?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Раз у вас там vue, используйте модификатор:

    <input type="number" v-model.number="Current.amount">
    Ответ написан
    Комментировать
  • Как сделать фильтрацию элементов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    <div id="items"></div>

    document.querySelector('.map__filters').addEventListener('change', function() {
      const values = Array.from(
        this.querySelectorAll('.map__checkbox:checked'),
        n => n.value
      );
    
      const filtered = values.length
        ? data.filter(n => values.every(m => n.features.includes(m)))
        : [];
    
      document.querySelector('#items').innerHTML = filtered
        .map(n => `<div>${JSON.stringify(n, null, 2)}</div>`)
        .join('');
    });
    Ответ написан
    Комментировать
  • Как сравнить две даты на vuejs?

    0xD34F
    @0xD34F Куратор тега Vue.js
    data: () => ({
      now: Date.now(),
      ...
    }),
    computed: {
      filteredList() {
        return this.list.filter(n => this.parseDate(n.dateend) < this.now);
      },
      ...
    },
    methods: {
      parseDate: str => new Date(str.split('.').reverse().join('-')),
      ...
    },
    Ответ написан
    Комментировать
  • Как на определенной итерации v-for обнулить индекс?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Можно сделать...

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

      computed: {
        itemsWithBullshitCounter() {
          let counter = -1; /* или 0, если хотите, чтобы нулевой элемент массива получил ненулевой индекс
                               в том случае, если для него не выполняется условие обнуления */
          return this.items.map((n, i) => ({
            ...n,
            counter: counter = (здесь проверяете, надо ли обнулить счётчик
              ? 0
              : counter + 1
            ),
          }));
        },
      },

      <div v-for="n in itemsWithBullshitCounter">
        вместо индекса используете значение добавленного свойства: {{ n.counter }}
      </div>

      https://jsfiddle.net/hk93q6gf/

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

      computed: {
        chunkedItems() {
          return this.items.reduce((acc, n, i) => {
            if (!i || на текущем элементе надо сбросить индексацию) {
              acc.push([]);
            }
      
            acc[acc.length - 1].push(n);
      
            return acc;
          }, []);
        },
      },

      <template v-for="chunk in chunkedItems">
        у каждого куска индексация независимая:
        <div v-for="(n, i) in chunk">{{ i }}</div>
      </template>

      https://jsfiddle.net/hk93q6gf/1/

    • ...метод, который будет вычислять нужный индекс (плохо - вычисления выполняются при каждом рендеринге):

      methods: {
        createStrangeIndex(arr, baseIndex) {
          let index = 0;
      
          while (baseIndex > 0 && на элементе arr[baseIndex--] сбрасывать индексацию не надо) {
            index++;
          }
      
          return index;
        },
      },

      <div v-for="(n, i) in items">{{ createStrangeIndex(items, i) }}</div>

      https://jsfiddle.net/hk93q6gf/2/
    Ответ написан
    2 комментария
  • Как в Vue сделать так, чтобы объект видел новые обработчики событий v-on?

    0xD34F
    @0xD34F Куратор тега Vue.js
    есть метод orgajax - он тянет данные с сервера, в том числе и HTML код

    А должен - просто данные, на основе которых разметка будет создаваться уже на клиенте. Переделывайте.

    Ну или можете путём говнокодера пойти - компилируйте получаемые шаблоны.
    Ответ написан
  • Как выбрать информацию из двух массивов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function filter(obj, key, f) {
      const keys = Object.keys(obj);
    
      return (obj[key] || []).reduce((acc, n, i) => (
        f(n) && keys.forEach(k => acc[k].push(obj[k][i])),
        acc
      ), keys.reduce((acc, k) => (acc[k] = [], acc), {}));
    }
    
    const result = filter(obj, 'years', n => 2012 <= n && n <= 2014);

    или

    function filter(obj, f) {
      const keys = Object.keys(obj);
      const length = keys.length && obj[keys[0]].length;
      const result = Object.fromEntries(keys.map(k => [ k, [] ]));
    
      for (let i = 0; i < length; i++) {
        if (f(i, obj)) {
          keys.forEach(k => result[k].push(obj[k][i]));
        }
      }
    
      return result;
    }
    
    const result = filter(obj, (i, { years: { [i]: n } }) => 2012 <= n && n <= 2014);
    Ответ написан
    1 комментарий
  • Как переключать классы у input в зависимости от длины его значения?

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

    const selector = '[type="tel"]';
    const event = 'input';
    const minLength = 10;
    const classNames = [ 'какой-то класс', 'какой-то другой класс' ];

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

    $(selector).on(event, function() {
      const isLengthOK = $(this).val().length >= minLength;
      $(this)
        .toggleClass(classNames[0], !isLengthOK)
        .toggleClass(classNames[1], isLengthOK);
    });

    или

    document.querySelectorAll(selector).forEach(function(n) {
      n.addEventListener(event, this);
    }, ({ target: t }) => {
      const isLengthOK = +(t.value.length >= minLength);
      classNames.forEach((n, i) => t.classList.toggle(n, isLengthOK === i));
    });
    Ответ написан
    Комментировать
  • PHP preg_match - как вытащить вхождение?

    0xD34F
    @0xD34F Куратор тега Регулярные выражения
    /(?<=21).*?(?=91)/
    Ответ написан
    Комментировать
  • Почему в функциональном компоненте vuejs this == undefined?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Потому что они так устроены:

    we can mark components as functional, which means that they’re stateless (no reactive data) and instanceless (no this context)
    Ответ написан
  • Как закрыть 2 одинаковых попапа?

    0xD34F
    @0xD34F Куратор тега JavaScript
    - .dropdown__block.open {
    + .dropdown.open .dropdown__block {

    const containerSelector = '.dropdown';
    const buttonSelector = `${containerSelector} .dropdown__toggler`;
    const activeClass = 'open';
    
    
    // jquery, как вы и хотели
    $(document).on('click', ({ target: t }) => {
      const $container = $(t).closest(containerSelector);
      const $button = $(t).closest(buttonSelector);
    
      if ($button.length) {
        $container.toggleClass(activeClass);
      }
    
      $(containerSelector).not($container).removeClass(activeClass);
    });
    
    // или, к чёрту jquery
    document.addEventListener('click', ({ target: t }) => {
      const container = t.closest(containerSelector);
      const button = t.closest(buttonSelector);
    
      if (button) {
        container.classList.toggle(activeClass);
      }
    
      document.querySelectorAll(containerSelector).forEach(n => {
        if (n !== container) {
          n.classList.remove(activeClass);
        }
      });
    });
    Ответ написан
    3 комментария
  • Как скрыть элементы между элементами с определённым классом?

    0xD34F
    @0xD34F Куратор тега JavaScript
    По кому кликаем: const itemSelector = '.item-service';.

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

    function toggleUntilNextItem(el) {
      while ((el = el.nextElementSibling) && !el.matches(itemSelector)) {
        el.hidden ^= 1;
        // или (в стили надо будет добавить .hidden { display: none; })
        el.classList.toggle('hidden');
      }
    }

    Клики слушать можно непосредственно на интересующих нас элементах:

    document.querySelectorAll(itemSelector).forEach(function(n) {
      n.addEventListener('click', this);
    }, e => toggleUntilNextItem(e.currentTarget));

    Или на каком-нибудь из их общих предков:

    document.addEventListener('click', ({ target: t }) =>
      (t = t.closest(itemSelector)) && toggleUntilNextItem(t)
    );
    Ответ написан
    1 комментарий
  • Как взять values из объекта?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Object.entries(obj).filter(n => Number.isInteger(+n[0])).map(n => n[1]).join(';')
    
    // или
    
    Object.keys(obj).reduce((acc, n) => (`${+n}` === n && acc.push(obj[n]), acc), []).join(';')
    
    // или
    
    Array.from(obj).join(';')
    
    // или
    
    JSON.stringify(obj).match(/(?<="\d+":").*?(?=")/g).join(';')
    Ответ написан
    Комментировать
  • Как поменять src картинки с помощью скрипта?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.links').on('mouseover', 'a', function() {
      $(this).closest('.block').find('img').attr('src', $(this).data('src'));
    });

    или

    document.addEventListener('mouseover', ({ target: t }) => {
      const { src } = t.dataset;
      if (src) {
        t.closest('.block').querySelector('img').src = src;
      }
    });

    или

    document.querySelectorAll('[data-src]').forEach(function(n) {
      n.addEventListener('mouseenter', this);
    }, ({ target: t }) => t
      .parentNode
      .parentNode
      .nextElementSibling
      .setAttribute('src', t.getAttribute('data-src'))
    );
    Ответ написан
    2 комментария
  • Как связать элементы с помощью data-атрибута?

    0xD34F
    @0xD34F Куратор тега JavaScript
    О каком data-атрибуте идёт речь:

    const key = 'id';
    const attr = `data-${key}`;

    Как из элемента достать значение data-атрибута:

    const getVal = el => $(el).data(key);
    // или
    const getVal = el => $(el).attr(attr);
    // или
    const getVal = el => el.dataset[key];
    // или
    const getVal = el => el.getAttribute(attr);
    // или
    const getVal = el => el.attributes[attr].value;

    По кому кликаем, кому и какой класс надо переключать:

    const buttonSelector = '.open-category';
    const contentSelector = button => `.d-none[${attr}="${getVal(button)}"]`;
    const activeClass = 'active';

    Как переключить класс:

    const toggle = button => $(contentSelector(button)).toggleClass(activeClass);
    
    // или
    
    const toggle = button => document
      .querySelector(contentSelector(button))
      .classList
      .toggle(activeClass);

    Клики можно слушать непосредственно на кнопках:

    $(buttonSelector).click(function() {
      toggle(this);
    });
    
    // или
    
    document.querySelectorAll(buttonSelector).forEach(function(n) {
      n.addEventListener('click', this);
    }, e => toggle(e.currentTarget));

    Или на ком-нибудь из их общих предков:

    $(document).on('click', buttonSelector, e => toggle(e.currentTarget));
    
    // или
    
    document.addEventListener('click', ({ target: t }) =>
      (t = t.closest(buttonSelector)) && toggle(t)
    );
    Ответ написан
    6 комментариев