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

    0xD34F
    @0xD34F Куратор тега JavaScript
    Имитация клика по кнопке происходит до подключения обработчика submit.
    Ответ написан
  • Почему не выполняется reduce, если выполняется map?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Есть map, и есть map. Вы их явно путаете. А reduce'а в jquery нет. Хотите применить reduce - сначала надо сделать массив из набора элементов, для этого используйте get или toArray.
    Ответ написан
  • При стилизации 2х select в каждом выводятся сразу два первых option?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Давайте не будем копипастить, а сделаем нормальный плагин:

    $.fn.customSelect = function() {
      return this.each(function() {
        const $this = $(this).hide();
        const $wrapper = $this.wrap('<div class="select_wrapper"></div>').parent();
    
        $wrapper.append(`
          <span>${$this.find(':selected').text()}</span>
          <ul class="select_inner">${$this.children().get().map(n => `
            <li data-value="${n.value}">${n.innerText}</li>`).join('')}
          </ul>
        `);
        $wrapper.on('click', 'li', function() {
          $wrapper.children('span').text(this.innerText);
          $this.val(this.dataset.value).trigger('change');
        });
        $wrapper.on('click', function() {
          $('ul', this).slideToggle('fast');
        });
      });
    };
    
    
    $('#materialColor, #kantcolor').customSelect().change(function() {
      console.log(`#${this.id}: "${this.value}"`);
    });
    Ответ написан
    2 комментария
  • Почему при изменении полей с одинаковым классом меняется только первое поле?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.datepicker-input').datepicker({
      minDate: 0,
      onClose(dateText, inst) {
        $(this).parent().next('.date').text([
          inst.selectedDay,
          inst.selectedMonth + 1,
          inst.selectedYear
        ].join('-'));
      }
    });
    
    $('.date').click(function() {
      $(this).prev('div').find('.datepicker-input').focus();
    });
    Ответ написан
  • Можно ли в одну строчку найти все элементы, которые содержат другие?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const ancestor = 'селектор элементов, которые надо получить';
    const descendant = 'селектор вложенных элементов';

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

    Array.prototype.filter.call(
      document.querySelectorAll(ancestor),
      n => n.querySelector(descendant)
    )

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

    Array.from(
      document.querySelectorAll(`${ancestor} ${descendant}`),
      n => n.closest(ancestor)
    )

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

    [...document.querySelectorAll(descendant)].reduce(
      (acc, n) => ((n = n.closest(ancestor)) && acc.push(n), acc),
      []
    )

    UPD. Наконец-то дождались (ну, почти):

    document.querySelectorAll(`${ancestor}:has(${descendant})`)
    Ответ написан
    Комментировать
  • Как конвертировать дату в Unix time?

    0xD34F
    @0xD34F Куратор тега JavaScript
    new Date('Fri Oct 05 2018 00:00:00 GMT+0300 (Саудовская Аравия, стандартное время)') / 1000
    Ответ написан
    Комментировать
  • JSON - есть ли разница между {'num': 1} и {num: 1}? Как лучше писать?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Нет разницы - оба варианта некорректные, таких JSON'ов не бывает.

    Конечно, на самом деле вы имели в виду кое-что другое, но... учитесь задавать вопросы.
    Ответ написан
    10 комментариев
  • Как отрефакторить такой код?

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

    [
      [   'region_id',   'regionName' ],
      [ 'district_id', 'districtName' ],
      [     'area_id',     'areaName' ],
      [     'city_id',     'cityName' ],
      [    'place_id',     'cityName' ],
      [        'name',   'streetName' ],
    ].forEach(([ del, search ]) => {
      if (this.tableParam[del]) {
        delete this.tableParam[del];
        this.searchForm.get(search).patchValue(null);
      }
    });
    Ответ написан
    5 комментариев
  • Почему this выбирает родителя?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const containerSelector = '#menu_left';
    const itemSelector = `${containerSelector} li`;
    const className = 'active';

    Останавливайте всплытие событий:

    $(itemSelector).click(function(e) {
      e.stopPropagation();
      $(this).addClass(className);
    });
    
    // или
    
    document.querySelectorAll(itemSelector).forEach(function(n) {
      n.addEventListener('click', this);
    }, e => {
      e.stopPropagation();
      e.currentTarget.classList.add(className);
    });

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

    $(containerSelector).click(e => {
      $(e.target).closest(itemSelector).addClass(className);
    });
    
    // или
    
    document.querySelector(containerSelector).addEventListener('click', e => {
      const li = e.target.closest(itemSelector);
      if (li) {
        li.classList.add(className);
      }
    });
    Ответ написан
    1 комментарий
  • Как сделать обертку?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Где элементы находятся (родительский элемент), кого из них (минимальный и максимальный индексы в коллекции вложенных элементов родителя) и куда надо переместить:

    const parent = document.querySelector('.box').parentNode;
    
    const iMin = 2;
    const iMax = 5;
    
    const wrapper = document.createElement('div');
    wrapper.classList.add('wrapper');

    Получаем элементы, перемещаем:

    if (parent.children[iMin]) {
      const elems = Array.prototype.slice.call(parent.children, iMin, iMax);
      elems[0].before(wrapper);
      wrapper.append(...elems);
    }
    
    // или
    
    const elems = parent.querySelectorAll(`:nth-child(n + ${-~iMin}):not(:nth-child(n + ${-~iMax}))`);
    if (elems.length) {
      parent.insertBefore(wrapper, elems[0]);
      elems.forEach(n => wrapper.appendChild(n));
    }
    
    // или
    
    if (parent.children.length > iMin) {
      parent.children[iMin].insertAdjacentElement('beforebegin', wrapper);
      for (let i = iMax - iMin, n = null; i-- && (n = wrapper.nextElementSibling);) {
        wrapper.insertAdjacentElement('beforeend', n);
      }
    }
    Ответ написан
    Комментировать
  • Как использовать map с async/await?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Что значит "не промисы, а async/await"? - async/await это тоже промисы.

    Используйте await Promise.all, например:

    const result = await Promise.all([ 1, 2, 3 ].map((n, i) => {
      return new Promise(resolve => {
        setTimeout(() => {
          console.log(`timeout #${i}`);
          resolve(n * 10);
        }, Math.random() * 3000 | 0);
      });
    }));
    
    console.log('result:', result);
    Ответ написан
    2 комментария
  • Как задать цикл в массиве?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Какого размера нужен массив и как создавать его элементы:

    const length = 25;
    const createItem = i => ({
      url: `photos/${i}.jpg`,
      // ещё какие-то свойства
    });

    Создаём:

    const items = Array.from({ length }, (_, i) => createItem(i + 1));
    
    // или
    
    const items = [];
    for (let i = 1; i <= length; i++) {
      items.push(createItem(i));
    }
    
    // или
    
    const items = [];
    while (items.length < length) {
      items[items.length] = createItem(-~items.length);
    }
    
    // или
    
    const items = (function createItems(i) {
      return i > 0 ? [ ...createItems(i - 1), createItem(i) ] : [];
    })(length);

    И самое главное, мне нужно потом взять значение этих массивов.
    descriptionImage.url - Как-то так

    Не так.

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

    Во-вторых - пропущено обращение к элементу массива: descriptionImage[индекс элемента].url.
    Ответ написан
    Комментировать
  • Как обернуть три элемента в блок?

    0xD34F
    @0xD34F Куратор тега JavaScript
    не оборачиваются

    Вообще-то, оборачиваются. Только после вы ничего с этими элементами не делаете. Ну и вместо wrap следует использовать wrapAll, чтобы у элементов оказался общий родитель, а не отдельный для каждого.
    Ответ написан
  • Как скрыть элементы начиная с четвёртого в нескольких списках?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.list').find('li:gt(2)').hide();
    // или
    $('li:gt(2)', '.list').hide();
    // или
    $('.list li:nth-child(3)').nextAll().hide();
    // или
    $('.list li:nth-child(n + 4)').hide();
    // или
    $('.list li').next().next().next().hide();
    // или
    $('.list > + + +').hide();

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

    Array
      .from(document.querySelectorAll('.list'))
      .flatMap(n => [...n.children].slice(3))
      .forEach(n => n.hidden = true);
    
    // или (тут надо будет стиль добавить: .hidden { display: none; })
    
    [].forEach.call(document.getElementsByClassName('list'), n => {
      [].forEach.call(n.getElementsByTagName('li'), (m, i) => {
        m.classList.toggle('hidden', i > 2);
      });
    });

    Если подобное надо выполнять неоднократно, а селекторы и количество элементов, оставляемых видимыми, разнятся, то можно и функцию сообразить (чтобы можно было делать так, например: hide('.list', 'li', 3);):

    function hide(containerSelector, elementSelector, hideFrom) {
      $(containerSelector).each((i, n) => {
        $(elementSelector, n).slice(hideFrom).hide();
      });
    }
    
    // или
    
    function hide(containerSelector, elementSelector, hideFrom) {
      for (const n of document.querySelectorAll(containerSelector)) {
        const elements = n.querySelectorAll(elementSelector);
        for (let i = hideFrom; i < elements.length; i++) {
          elements[i].style.display = 'none';
        }
      }
    }
    Ответ написан
    Комментировать
  • Как вставить клонированный блок несколько раз?

    0xD34F
    @0xD34F Куратор тега JavaScript
    add() {
      const clone = this.clone.cloneNode(true);
      clone.dataset.index = this.index++;
      this.beforeInsert.before(clone);
    }
    Ответ написан
    1 комментарий
  • Как закрывать всплывающее окно по повторному клику?

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

    Так что стили немного поправим:

    - .material-block .filter-values.open {
    + .material-block.open .filter-values {

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

    const containerSelector = '.material-block';
    const buttonSelector = `${containerSelector} .catalog-filter-block-title`;
    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);
        }
      });
    });
    Ответ написан
    Комментировать
  • Как правильно реализовать события по клику?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Во-первых - вы пытаетесь работать с элементами, которых нет (это я про .expanded). Гуглите "делегирование".

    Во-вторых - поскольку в разные моменты времени поведение должно быть разным, click(false) не годится в качестве отмены действия по умолчанию - надо сделать нормальный обработчик, в котором выполнять preventDefault. Типа так (ну или тоже через делегирование, но это как-то глупо будет выглядеть - два обработчика одного события, хотя мог бы быть и один).
    Ответ написан
    Комментировать