Задать вопрос
  • Как в select выставить первое значение по событию?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('button').click(() => $('select').prop('selectedIndex', 0));

    или, к чёрту jquery:

    document.querySelector('button').addEventListener('click', () => {
      document.querySelectorAll('select').forEach(n => {
        // Какие тут есть варианты:
    
        // 1. Установить индекс выбранного option'а
        n.selectedIndex = 0;
    
        // 2. Установить select'у значение option'а, который должен быть выбран
        //    (чтобы заработало, надо будет добавить value="" option'ам)
        n.value = '';
    
        // 3. Назначить true свойству selected того option'а, на который надо переключиться
        n[0].selected = true;
        // или
        // n.options[0].selected = true;
        // n.children[0].selected = true;
        // n.firstElementChild.selected = true;
        // n.querySelector('option').selected = true;
      });
    });
    Ответ написан
    Комментировать
  • Как объединить массив массивов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Массивы сложить в массив (const arrs = [ arr1, arr2 ];), дальше есть варианты:

    const result = arrs[0].map((_, i) => arrs.flatMap(arr => arr[i]));

    или

    const result = arrs.reduce((acc, arr) => (
      arr.forEach((n, i) => (acc[i] ??= []).push(...n)),
      acc
    ), []);

    или

    const result = [];
    
    for (const arr of arrs) {
      for (const [ i, n ] of arr.entries()) {
        if (!result[i]) {
          result[i] = [];
        }
    
        for (const m of n) {
          result[i][result[i].length] = m;
        }
      }
    }

    или

    function* zip(data, defaultValue = null) {
      const iterators = Array.from(data, n => n[Symbol.iterator]());
    
      for (let doneAll = false; doneAll = !doneAll;) {
        const values = [];
    
        for (const n of iterators) {
          const { value, done } = n.next();
          values.push(done ? defaultValue : value);
          doneAll &&= done;
        }
    
        if (!doneAll) {
          yield values;
        }
      }
    }
    
    const result = Array.from(zip(arrs), n => n.flat());
    Ответ написан
    1 комментарий
  • Как сделать валидацию инпута c типом number Vue.js?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Что такое product?

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

    watch: {
      'product.qty'(val) {
        this.product.qty = Math.max(1, Math.min(99, val | 0));
      },
    },

    Если у вас там v-for и это элемент массива, то можно установить глубокое наблюдение за всем массивом:

    watch: {
      products: {
        deep: true,
        handler: val => val.forEach(n => n.qty = Math.max(1, Math.min(99, n.qty | 0))),
      },
    },

    Если не нравится watch - исправляйте непосредственно пользовательский ввод:

    methods: {
      onInput(e) {
        if (e.isTrusted) {
          e.target.value = Math.max(1, Math.min(99, e.target.value | 0));
          e.target.dispatchEvent(new Event('input'));
        }
      },
    },

    <input
      @input="onInput"
      ...

    Можно даже это дело оформить в виде директивы:

    function onInput({ isTrusted, target: t }) {
      if (isTrusted) {
        t.value = Math.max(t.min, Math.min(t.max, t.value | 0));
        t.dispatchEvent(new Event('input'));
      }
    }
    
    const minmaxDirective = {
      mounted: el => el.addEventListener('input', onInput),
      unbind: el => el.removeEventListener('input', onInput),
    };

    app.directive('minmax', minmaxDirective);

    <input
      v-minmax
      min="1"
      max="99"
      ...
    Ответ написан
  • Как можно менять у элемента атрибут приоритета при drag'n'drop?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Добавить в обработчик dragend:

    box.querySelectorAll('.item').forEach((n, i) => n.dataset.priority = -~i);
    
    // или
    
    for (const [ i, n ] of box.querySelectorAll('.item').entries()) {
      n.setAttribute('data-priority', i + 1);
    }
    
    // или
    
    for (let i = box.children.length; i;) {
      const attr = document.createAttribute('data-priority');
      attr.value = i;
      box.children[--i].attributes.setNamedItem(attr);
    }
    
    // или
    
    (function next(i, n) {
      n && next(n.attributes['data-priority'].value = ++i, n.nextElementSibling);
    })(0, box.firstElementChild);
    Ответ написан
    Комментировать
  • Как получать значение data-атрибута при клике на кастомные placemark'и?

    0xD34F
    @0xD34F Куратор тега Яндекс.Карты
    Не надо никаких data-атрибутов. Передавайте эти id в properties (второй параметр конструктора) placemark'ов, при клике получайте:

    e.get('target').properties.get('имяСвойстваСодержащегоId')


    Ну а что до показанного вами кода...

    • Почему в шаблоны placemark'ов зашивается id? Неужели вы до сих пор не в курсе, что id должны быть уникальны? Кстати, поэтому у вас и "выводит всегда 1" - ищите элемент по id, вот и получаете всегда первый из созданных.
    • Зачем вообще понадобилось искать элемент и читать data-атрибут, значение которого вам и так доступно внутри обработчика (shop.id)?
    • Создавать отдельный layout под каждый placemark не надо. Вынесите создание layout'а за пределы цикла. Если надо передавать в шаблон какие-то уникальные значения, то их опять же можно подтянуть из свойств. Как бы это выглядело для вашего data-атрибута:

      <div data-id="{{ properties.имяСвойстваСодержащегоId }}">

      Также не надо создавать отдельные функции, назначаемые в качестве обработчиков клика - создайте один обработчик за пределами цикла (да, достать id из shop после этого уже не получится, как было сказано в начале - передавайте его через properties).
    Ответ написан
    1 комментарий
  • Как вывести длину самого большого вложенного массива?

    0xD34F
    @0xD34F Куратор тега JavaScript
    где ошибка?

    Скобки пересчитайте. Фигурные. Сколько закрывающих, сколько открывающих.

    Ну и конечно не надо никаких циклов в явном виде:

    const maxlen = Math.max(...arr.map(n => n.length));
    
    // или
    
    const maxlen = arr.reduce((max, { length: n }) => max > n ? max : n, -Infinity);
    Ответ написан
    Комментировать
  • Как в ссылки добавить значения title?

    0xD34F
    @0xD34F Куратор тега JavaScript
    fetch('https://gorest.co.in/public/v1/posts')
      .then(r => r.json())
      .then(r => {
    
       // собираем разметку
        document.body.insertAdjacentHTML('beforeend', `
          <ul>${r.data.map(n => `
            <li>
              <a>${n.title}</a>
            </li>`).join('')}
          </ul>
        `);
    
        // или, создаём элементы напрямую
        const ul = document.createElement('ul');
        ul.append(...r.data.map(n => {
          const li = document.createElement('li');
          const a = document.createElement('a');
          a.textContent = n.title;
          li.append(a);
          return li;
        }));
        document.body.append(ul);
      });
    Ответ написан
    1 комментарий
  • Как узнать что экземпляр конкретного класса а не его прародителя?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Получаем тип данных (конструктор или само значение, если оно nullish):

    const type = x => x == null ? x : x.constructor;
    
    type() === undefined // true
    type(null) === null // true
    type(/./) === RegExp // true
    type(187) === Number // true
    type(type) === Function // true

    Получаем имя типа:

    const typename = x => x?.constructor.name ?? `${x}`;
    
    typename() // 'undefined'
    typename(null) // 'null'
    typename(false) // 'Boolean'
    typename('hello, world!!') // 'String'
    typename({}) // 'Object'
    typename([]) // 'Array'
    typename(document.body) // 'HTMLBodyElement'
    typename(document.getElementsByClassName('xxx')) // 'HTMLCollection'
    typename(new class XXX {}) // 'XXX'
    typename((c => new class YYY extends c {})(class XXX {})) // 'YYY'
    typename(typename) // 'Function'
    Ответ написан
    Комментировать
  • Как изменить цвет активного чипа v-chip vuetify?

    0xD34F
    @0xD34F Куратор тега Vue.js
    .xxx {
      background: red;
    }
    
    .xxx:hover {
      background: orange;
    }
    
    .xxx .v-chip__content {
      color: white;
      font-weight: bold;
    }

    <v-chip-group active-class="xxx">
    Ответ написан
  • Почему не работает vue-select?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Версия vue какая? 3? - показанную вами ошибку можно получить, попытавшись использовать vue-select внутри vue3-приложения. Поддержка vue3 пока отсутствует, но обещают, что скоро появится.
    Ответ написан
  • Как переместить слова задом наперед?

    0xD34F
    @0xD34F
    implode(', ', array_reverse(explode(', ', $str)))
    Ответ написан
    Комментировать
  • Как лучше организовать передачу данных во Vue?

    0xD34F
    @0xD34F Куратор тега Vue.js
    промежуточных компонентов может быть много

    provide / inject
    Ответ написан
    3 комментария
  • Как менять радиус круга при изменении ползунка?

    0xD34F
    @0xD34F Куратор тега Яндекс.Карты
    Кладёте ссылку на круг в компонент:

    this.circle = new ymaps.Circle(
      ...

    И устанавливаете наблюдение за свойством, которое представляет радиус:

    watch: {
      радиусКруга(val) {
        this.circle.geometry.setRadius(val);
      },
      ...

    https://jsfiddle.net/5qmrxez0/

    Или, если этот круг нигде больше не понадобиться, то можно не делать его свойством компонента, а прямо по месту его создания установить наблюдение за радиусом:

    const circle = new ymaps.Circle(
      ...
    );
    
    this.$watch('радиусКруга', val => circle.geometry.setRadius(val));

    https://jsfiddle.net/5qmrxez0/1/
    Ответ написан
    4 комментария
  • Как сделать, чтобы одновременно был открыт только один элемент аккордеона?

    0xD34F
    @0xD34F Куратор тега React
    const AccordionItem = ({ title, opened, toggle, children }) => (
      <div>
        <button onClick={toggle}>{title}</button>
        {opened && children}
      </div>
    );
    
    const Accordion = ({ items }) => {
      const [ opened, setOpened ] = useState(null);
    
      return (
        <div>
          {items.map((n, i) => (
            <AccordionItem
              title={n.title}
              opened={i === opened}
              toggle={setOpened.bind(null, i === opened ? null : i)}
            >
              <p>{n.text}</p>
            </AccordionItem>
          ))}
        </div>
      );
    };
    Ответ написан
    Комментировать
  • Как найти элементы, встречающиеся только в одном из двух массивов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Уникализируем массивы; объединяем в один; перебираем, отмечая, встречался ли текущий элемент ранее - если элемент встречен впервые, будет false, повторно (т.е., представлен в более чем одном из исходных массивов) будет true; хватаем элементы, которые false:

    const diff = (...arrs) => Array
      .from(arrs
        .flatMap(arr => [...new Set(arr)])
        .reduce((acc, n) => acc.set(n, acc.has(n)), new Map))
      .reduce((acc, n) => (n[1] || acc.push(n[0]), acc), []);

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

    const diff = (...arrs) => Array
      .from(arrs.reduce((acc, arr) => (
        arr.forEach(n => acc.set(n, acc.get(n) ?? new Set).get(n).add(arr)),
        acc
      ), new Map))
      .reduce((acc, n) => (n[1].size === 1 && acc.push(n[0]), acc), []);

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

    const diff = (...arrs) =>
      arrs.reduce((acc, arr) => (
        arr.forEach(n =>
          arrs.every(m => m === arr || !m.includes(n)) &&
          !acc.includes(n) &&
          acc.push(n)
        ),
        acc
      ), []);
    Ответ написан
    1 комментарий
  • Как работать во Vue в computed со сеттерами?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Сеттер должен изменить данные, которые используются в геттере.

    Давайте рассмотрим на конкретном примере. Пусть есть массив объектов, на основе которых создаются чекбоксы:

    data: () => ({
      items: [
        { checked: false, label: '...' },
        { checked: false, label: '...' },
        ...
      ],
    }),

    <label v-for="n in items">
      <input type="checkbox" v-model="n.checked">
      {{ n.label }}
    </label>

    И мы хотим сделать чекбокс, который позволял бы устанавливать или снимать все чекбоксы сразу. Его состояние будет описываться вычисляемым свойством. Геттер - очевидно, будет содержать проверку, что все чекбоксы установлены. А сеттер будет устанавливать переданное ему значение всем чекбоксам. Как-то так:

    computed: {
      get() {
        return this.items.every(n => n.checked);
      },
      set(val) {
        this.items.forEach(n => n.checked = val);
      },
    },

    <label>
      <input type="checkbox" v-model="all">
      ALL
    </label>

    https://jsfiddle.net/j7hr68t4/
    Ответ написан
    4 комментария
  • Как заполнить TextArea через JS (калькулятор)?

    0xD34F
    @0xD34F Куратор тега JavaScript
    document.querySelector('.calc_container').addEventListener('input', e => {
      const block = e.target.closest('.calc_block');
      const price = +block.querySelector('.price span').innerText;
      const count = +e.target.value;
      block.querySelector('.summ span').innerText = price * count;
    
      const orderData = Array
        .from(e.currentTarget.querySelectorAll('.calc_block'), n => ({
          name: n.querySelector('label').innerText,
          count: +n.querySelector('.count').value,
          sum: +n.querySelector('.summ span').innerText,
        }))
        .filter(n => n.count);
    
      document.querySelector('.total_block span').innerText = orderData
        .reduce((acc, n) => acc + n.sum, 0);
    
      document.querySelector('textarea').value = orderData
        .map(n => `Название: ${n.name} | Количество: ${n.count}`)
        .join('\n');
    });
    Ответ написан
  • Как двумерный массив порезать на куски и превратить строки в столбцы?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const chunkedAndTransposed = ([ headers, ...arr ], chunkSize) =>
      arr.reduce((acc, n, i) => (
        (i % chunkSize) || acc.push(headers.map(m => [ m ])),
        n.forEach((m, j) => acc.at(-1)[j].push(m)),
        acc
      ), []);
    
    const result = chunkedAndTransposed(arr, 2);

    или, если на последний кусок данных не хватает, а размеры вложенных массивов должны быть одинаковыми, можно добавить null'ов или чего-нибудь ещё:

    const chunkedAndTransposed = (arr, chunkSize, defautlValue = null) =>
      Array.from({ length: Math.ceil((arr.length - 1) / chunkSize) }, (_, iChunk) =>
        Array.from({ length: arr[0].length }, (_, iCol) =>
          Array.from({ length: chunkSize + 1 }, (_, iRow) =>
            iRow ? arr[iChunk * chunkSize + iRow]?.[iCol] ?? defautlValue : arr[0][iCol]
          )
        )
      );
    
    const result = chunkedAndTransposed(arr, 5);
    Ответ написан
    4 комментария