Задать вопрос
  • При нажатии на плюс значение прибавляется, при нажатии на минус убавляется. Как сделать?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сколько предполагается таких элементов - один или несколько? Будем считать, что несколько.

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

    Вариант раз - назначаем обработчики клика каждой кнопке индивидуально:

    function setOnClick(selector, change) {
      function onClick({ target: t }) {
        const el = t.closest('.style-item_count').querySelector('.style-count-number');
        el.innerText = el.innerText.replace(/\d+/, m => Math.max(0, +m + change));
      }
    
      document.querySelectorAll(selector).forEach(n => n.addEventListener('click', onClick));
    }
    
    setOnClick('.style-count-plus', 1);
    setOnClick('.style-count-minus', -1);
    
    // или
    
    function setOnClick(selector, change) {
      $(selector).on('click', e => {
        $(e.target)
          .closest('.style-item_count')
          .find('.style-count-number')
          .text((i, text) => `${Math.max(0, parseInt(text) + change)} шт`);
      });
    }

    Вариант два - делегирование, один обработчик на всех. Если не менять разметку, то

    document.addEventListener('click', ({ target: t }) => {
      const change =
        t.classList.contains('style-count-plus')  ? +1 :
        t.classList.contains('style-count-minus') ? -1 :
                                                     0;
      if (change) {
        const el = t.closest('.style-item_count').querySelector('.style-count-number');
        el.innerText = `${Math.max(0, parseInt(el.innerText) + change)} шт`;
      }
    });
    
    // или
    
    $(document).on('click', '.style-count-plus, .style-count-minus', e => {
      const $target = $(e.target);
      const change = $target.hasClass('style-count-plus') ? 1 : -1;
    
      $target
        .closest('.style-item_count')
        .find('.style-count-number')
        .text((i, text) => text.replace(/\d+/, m => Math.max(0, +m + change)));
    });

    Но если кнопкам добавить data-атрибуты, которые будут указывать, на сколько надо изменить значение, а самому значению добавить обёртку (чтобы отделить его от единиц измерения), то код можно немного упростить:

    <div class="style-item_count">
      <div class="style-count-minus" data-change="-1">-</div>
      <div class="style-count-number"><span>1</span> шт</div>
      <div class="style-count-plus" data-change="+1">+</div>
    </div>

    document.addEventListener('click', ({ target: t }) => {
      const change = +t.dataset.change;
      if (change) {
        const el = t.closest('.style-item_count').querySelector('.style-count-number span');
        el.textContent = Math.max(0, +el.textContent + change);
      }
    });
    
    // или
    
    $(document).on('click', '[data-change]', function() {
      $(this)
        .closest('.style-item_count')
        .find('.style-count-number span')
        .text((i, text) => Math.max(0, +text + +this.dataset.change));
    });
    Ответ написан
    1 комментарий
  • Vue lodash.shuffle для списка?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Использовать индекс в качестве key не надо никогда. Чтоб вот такого, как у вас сейчас, не было.

    Делаем нормальный key - всё окей.
    Ответ написан
    Комментировать
  • Как случайным образом добавлять элемент?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Почему у блоков отсутствует общий класс? - добавьте.

    const banners = [...document.querySelectorAll('.banner')];
    
    for (let i = banners.length; --i > 0;) {
      const j = Math.random() * (i + 1) | 0;
      [ banners[i], banners[j] ] = [ banners[j], banners[i] ];
    }
    
    document.querySelectorAll('.products--container').forEach((n, i) => n.append(banners[i]));
    Ответ написан
    Комментировать
  • Как объекты, состоящие из нескольких свойств, разделить на несколько объектов из одного свойства?

    0xD34F
    @0xD34F Куратор тега JavaScript
    arr.map(n => Object
      .entries(n)
      .reduce((acc, [ k, v ]) => (
        acc[k] = v
          .flatMap(Object.entries)
          .map(([ k, v ]) => ({ [k]: v })),
        acc
      ), {})
    )
    Ответ написан
    3 комментария
  • Chart with Axios?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Как можно с помощью axios подставить данные в массив chart?

    Это в принципе невозможно, axios - для выполнения запросов, а не работы с массивами.

    Разумеется, вы имели в виду кое-что другое, и даже понятно, что именно. Но учитывая фантастически ублюдочную формулировку вопроса, иного ответа вы не заслуживаете. Под ублюдочной формулировкой я имею в виду не только непонимание, о чём вы сами же и спрашиваете, но также и почти полное отсутствие какой-либо конкретики. А именно:

    Не сказано ни слова о графике, что он отображает.

    Получение данных для графика осуществляется будто бы с помощью axios - но единственный показанный запрос про другое, там идёт получение данных для выпадающего списка. То есть, должен быть ещё какой-то запрос. Какой? - url, параметры, структура ответа - ничего не известно.

    Далее, "подставить данные" вы планируете в "массив chart" - но как следует из показанного огрызка кода, такого массива нет. Есть chartData. Это он? Или какой-то другой массив? Не знаю что и думать. Что до собственно "подставить" - у массивов есть метод push, неужели вы про него не слышали? Если не слышали - разговаривать тут не о чем, идите учить язык. А где-нибудь через полгодика, не раньше, можно будет и в сторону vue попробовать посмотреть. Если слышали - очевидно, сам по себе push проблемой быть не может, придётся констатировать, что о сути своих затруднений вы решили попросту умолчать.

    Компонент line-chart, который, надо полагать, ответственен за построение графика - что это такое? Едва ли вы его написали сами - это или сторонний компонент, или обёртка над сторонним компонентом. Почему нет ссылки на документацию/github/...? - насколько я понял, график успешно строится, но надо динамически докидывать в него данные, так что сведения о компоненте графика пришлись бы очень кстати. Отслеживает ли он изменения своих параметров? Или может у него есть метод, позволяющий принудительно обновить свой внешний вид? Но нет - и тут никакой информации.

    Вот так.

    UPD. Вынесено из комментариев:

    График строится библиотекой chartkick.js

    есть запрос <...> необходимо подставить значения получаемых менеджеров в имена chartData. То есть в chartData:[{name:[сюда]}]

    Понятно.

    Не надо ничего "подставлять". Делаем отдельные свойства name и data, а chartData будет вычисляемым, причём собирать массив надо только в том случае, когда и name и data будут получены:

    computed: {
      chartData() {
        const { names, data } = this;
        return names && data && data.map((n, i) => ({
          name: names[i],
          data: n,
        }));
      },
    },

    Соответственно, график создаётся только в том случае, если удалось собрать chartData:

    <line-chart v-if="chartData" :data="chartData"></line-chart>

    https://jsfiddle.net/t5dovxL4/
    Ответ написан
    1 комментарий
  • Как узнать, что ul список состоит из ссылок?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const isLinks = Array
      .from(ul.querySelectorAll(':scope > li'))
      .every(n => n.childNodes.length === 1 && n.childNodes[0] instanceof HTMLAnchorElement);

    или

    const isLinks = Array.prototype.every.call(
      ul.children,
      ({ childNodes: [ a, b ] }) => a.tagName === 'A' && !b,
    );
    Ответ написан
    2 комментария
  • Как сравнить массив с объектами и если значение у этих объектов разные, то взять его id?

    0xD34F
    @0xD34F Куратор тега JavaScript
    arr1.filter((n, i) => arr2[i].num !== n.num).map(n => n.id)

    или

    arr1.reduce((acc, n, i) => (arr2[i].num === n.num || acc.push(n.id), acc), [])
    Ответ написан
    Комментировать
  • Почему перезагружается страница после отправки формы?

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

    0xD34F
    @0xD34F Куратор тега React
    Мне нужно чтобы валидация происходила только после нажатии на кнопку Submit.

    Я так понимаю, вы считаете чтение документации излишним. Это зря - там есть пример того, что вам надо.
    Ответ написан
    Комментировать
  • Где ошибка в маленьком компоненте React. Почему он не работает как в примере?

    0xD34F
    @0xD34F Куратор тега React
    Всё работает как надо. Просто у вас, в отличие от примера из документации, различаются значения полей key и title, поэтому при поиске вы проверяете не те значения, которые отображаете. Замените в методе generateList

    dataList.push({ key, title: key });

    на

    dataList.push({ key, title: node.title });
    Ответ написан
  • Почему не выполняется 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();
    });
    Ответ написан
  • Как webpack'ом минифицировать не-модульный JS?

    0xD34F
    @0xD34F
    Всё так же, как и с остальными файлами - то, что код "не-модульный", не значит, что нельзя выполнять импорт. Просто пишите что-то вроде:

    import './local_copies/xd_connection.js';
    import './local_copies/rbadman-html5.min.js';
    // ну и т.д.

    Это так называемый импорт ради побочных эффектов.

    Можно сократить, избавившись от необходимости указывать конкретные файлы, используя require.context:

    const context = require.context('./local_copies', false, /\.js$/);
    context.keys().forEach(key => context(key));

    Так они все окажутся в общем бандле.
    Ответ написан
    2 комментария
  • Можно ли в одну строчку найти все элементы, которые содержат другие?

    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
    Ответ написан
    Комментировать
  • Как добавить class в див по клику?

    0xD34F
    @0xD34F Куратор тега React
    Зачем onClick? - при повторном клике на инпут класс удалится, а клик снаружи инпута вы так не обработаете. Наверное, стоит использовать onFocus и onBlur:

    class App extends React.Component {
      state = {
        classes: [ 'bullshit' ],
      }
    
      onFocus = () => {
        this.setState(({ classes }) => ({
          classes: [ ...classes, 'focus' ],
        }));
      }
    
      onBlur = () => {
        this.setState(({ classes }) => ({
          classes: classes.filter(n => n !== 'focus'),
        }));
      }
    
      render() {
        return (
          <div className={this.state.classes.join(' ')}>
            <input onFocus={this.onFocus} onBlur={this.onBlur} />
          </div>
        );
      }
    }
    Ответ написан
    4 комментария
  • 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 комментариев