Задать вопрос
  • Как отфильтровать определенные div с классами, совпадающие с дата-атрибутами ссылки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Во-первых, get-age - это не data-атрибут. Меняйте на data-age.

    Во-вторых, сделайте значения селекторами, т.е. вместо age_3_6 будет .age_3_6, вместо age_7_10 будет .age_7_10 и т.д., ну а у элемента "все" будет data-age="*".

    const itemSelector = '.ped_holder .ped';
    const buttonSelector = '.ages a';
    const activeButtonClass = 'active';
    const selectorAttr = 'age';

    const $buttons = $(buttonSelector).click(function() {
      const selector = $buttons
        .removeClass(activeButtonClass)
        .filter(this)
        .addClass(activeButtonClass)
        .data(selectorAttr);
    
      $(itemSelector).hide().filter(selector).show();
    });
    
    // или, к чёрту jquery
    
    const buttons = document.querySelectorAll(buttonSelector);
    const items = document.querySelectorAll(itemSelector);
    
    buttons.forEach(n => n.addEventListener('click', onClick));
    
    function onClick({ target: t }) {
      const selector = t.dataset[selectorAttr];
      buttons.forEach(n => n.classList.toggle(activeButtonClass, n === t));
      items.forEach(n => n.style.display = n.matches(selector) ? '' : 'none');
    }
    Ответ написан
    Комментировать
  • Возврат переменной из axios.get?

    0xD34F
    @0xD34F Куратор тега React
    getMyIP() {    
      return axios.get('https://httpbin.org/get').then(response => response.data.origin)
    }
      
    handleClick() {
      this.getMyIP().then(ip => console.log(`ip: ${ip}`))
    }
    Ответ написан
    Комментировать
  • Как сортировать даты только по дню и месяцу?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сортируем существующий массив:

    arr.sort((a, b) => {
      a = a.split('.', 2);
      b = b.split('.', 2);
      return (a[1] - b[1]) || (a[0] - b[0]);
    });

    Или, собираем отсортированный новый:

    const sortedArr = arr
      .map(n => n.split('.'))
      .sort((a, b) => (a[1] - b[1]) || (a[0] - b[0]))
      .map(n => n.join('.'));
    Ответ написан
    Комментировать
  • Почему событие onBlur в react-contenteditable срабатывает всегда, когда в метод передаётся аргумент?

    0xD34F
    @0xD34F Куратор тега React
    передаю метод без аргумента onBlur={this.handleChange}

    стоит мне изменить на onBlur={this.handleChange('title')}

    Т-а-а-а-к, ясно. Осознаёте ли вы, что в первом случае вы назначаете в качестве обработчика onBlur метод handleChange, а во втором - результат его выполнения? Вы вообще понимаете, что функция и вызов функции - не одно и то же?

    Хотите передавать параметр, делайте так: onBlur={() => this.handleChange('title')}. Или вместо передачи значения в качестве параметра добавляйте его элементу как атрибут, а в обработчике события считывайте:

    onBlur={this.handleChange} data-change-param="title"

    handleChange = (e) => {
      const changeParam = e.target.getAttribute('data-change-param');
      ...
    Ответ написан
    1 комментарий
  • Возможно ли решить задачу без циклов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Рекурсия:

    const sum = (val, index = 0) =>
      val instanceof Array
        ? val.length > index
          ? sum(val[index]) + sum(val, index + 1)
          : 0
        : val;
    Ответ написан
    Комментировать
  • Как проверить не пустой ли файл?

    0xD34F
    @0xD34F
    fs.stat(filename, function(err, stats) {
      if (stats.size) {
        console.log('not empty');
      } else {
        console.log('empty');
      }
    });
    Ответ написан
    Комментировать
  • Зачем в кастомный валидатор формы ещё раз передавать this?

    0xD34F
    @0xD34F
    Не надо ничего передавать. И вызывать валидатор при передаче в конструктор FormControl тоже не надо (вы что, действительно до сих пор не понимаете разницы между функцией и её вызовом?).

    Что вы забыли - так это вернуть из валидатора какой-нибудь результат. Например.
    Ответ написан
    Комментировать
  • Как правильно клонировать input[type=radio]?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Хотите, чтобы суффиксы у атрибутов name были правильные - оператор + вам в помощь, добавляйте сколько надо.

    Хотите, чтобы клонирование происходило не только по клику на кнопку, что существует изначально, но и по новым - клонируйте элементы вместе с обработчиками событий или делегируйте обработку клика контейнеру.

    // исправляем ваш код
    $('.add-attr').on('click', function() {
      const index = $('.radios').length + 1;
    
      const $lastRow = $(this).closest('.container').find('.item').last();
      const $newRow = $lastRow.clone(true).insertAfter($lastRow);
    
      $newRow.find('input[type="radio"]').prop('name', 'name-' + index);
    });
    
    // или переписываем его без использования jquery
    document.querySelector('.container').addEventListener('click', e => {
      if (e.target.classList.contains('add-attr')) {
        const row = e.currentTarget.firstElementChild.cloneNode(true);
        const name = `name-${e.currentTarget.children.length + 1}`;
        e.currentTarget.appendChild(row);
        row.querySelectorAll('[type="radio"]').forEach(n => n.name = name);
      }
    });
    Ответ написан
    6 комментариев
  • Как подсчитать количество блоков в блоке?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const count = document.querySelectorAll('.ablock [class*="bblock_"]').length;

    Если кроме .bblock_* других элементов внутри .ablock нет, то

    const count = document.querySelector('.ablock').children.length;
    Ответ написан
    Комментировать
  • Как клонировать селект с изменением id?

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

    Странный способ получать новые значения id - единица в качестве начального значения и постфиксный инкремент. В результате последовательность идентификаторов получается такая: 1, 2, 3,... Элементы с 1 и 2 уже есть. Начальным значением должно быть максимальное существующее значение плюс единица. Или просто максимум, но инкремент тогда префиксный.

    const $row = $('.b-items').clone();
    let ID = +$row.find('select').last().attr('id').split('-').pop();
    
    function selectize($el) {
      $el.selectize({
        allowEmptyOption: true,
        create: true,
      });
    }
    
    selectize($('select'));
    
    $('.btn-clone').on('click', function() {
      selectize($row
        .clone()
        .insertBefore(this)
        .find('select')
        .attr('id', () => `select-${++ID}`)
      );
    });
    Ответ написан
    3 комментария
  • Как получить аттрибут ссылки во vue?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Пробовал указать и a.href и a.getAttribute('href') и т.д.

    Лучше бы попробовали документацию почитать.

    @click.prevent="toPage"

    toPage(e) {
      console.log(e.target.href)
    }
    Ответ написан
    Комментировать
  • Как "красиво" в методе компонента заменять надпись на каком-либо элементе?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Каким самым правильным способом можно это сделать?

    "Самых правильных" способов нет.

    Создавать еще один элемент в data()?

    Да.
    Ответ написан
    2 комментария
  • Выдает ошибку при переборе .children. Что делать?

    0xD34F
    @0xD34F Куратор тега JavaScript
    У последнего элемента следующего нет, так что в качестве nextElementSibling вы получаете null, а у null нельзя читать свойства. Как победить возникающую ошибку? - проще всего будет вообще не трогать последний элемент, пусть цикл делает на одну итерацию меньше, для этого замените i < children.length на i < children.length - 1. Другой вариант - прежде чем пытаться читать свойства у следующего элемента, проверять, существует ли он, или не является ли текущий последним, или подсовывать вместо отсутствующего элемента пустой объект - актуально в том случае, если перебор элементов организован не через цикл со счётчиком, а с помощью for...of или методов.

    Ещё стоит разобраться, чем присваивание отличается от проверки на равенство (nodeName = 'P', ну да, ну да).

    Как может выглядеть исправленная (и переписанная) функция:

    function findAllPSiblings(el) {
      const result = [];
    
      for (const n of el.children) {
        if ((n.nextElementSibling || {}).tagName === 'P') {
          result.push(n);
        }
      }
    
      return result;
    }

    А вообще, зачем ограничиваться одними лишь p? Давайте решим задачу в чуть более общем виде - пусть функция кроме родительского элемента принимает ещё и селектор, которому должны соответствовать соседи справа:

    const getChildrenWithNext = (el, selector) =>
      Array.prototype.filter.call(
        el.children,
        ({ nextElementSibling: n }) => n && n.matches(selector)
      );
    Ответ написан
    Комментировать
  • Как группировать каждые 3 элемента массива в foreach?

    0xD34F
    @0xD34F
    $arr = array_chunk(range(1, 12), 3);
    foreach ($arr as $chunk) {
      echo "<div>";
      foreach ($chunk as $value) {
        echo "<div>$value</div>";
      }
      echo "</div>";
    }
    Ответ написан
    1 комментарий
  • Как подсветить элементы, содержащие заданную подстроку, игнорируя регистр?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.intro')
      .filter((i, n) => $(n).text().toLowerCase().includes(t))
      .css('background-color', 'silver');

    или

    for (const n of document.getElementsByClassName('intro')) {
      if (n.textContent.toLowerCase().indexOf(t) !== -1) {
        n.style.backgroundColor = 'silver';
      }
    }

    или

    .highlight {
      background-color: silver;
    }

    document.querySelectorAll('.intro').forEach(function(n) {
      n.classList.toggle('highlight', ~n.innerText.search(this));
    }, RegExp(t, 'i'));
    Ответ написан
    1 комментарий
  • VueJs: не изменяются реактивные переменные на лету?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Если я правильно понял, должно быть так (в смысле - наблюдаемое поведение, а не код - тут уж вы сами думайте, как правильно надо). Реактивность тут не при чём, проблема в том, что вы сначала используете значение, а потом его меняете, предполагая при этом, что использовано будет изменённое значение.
    Ответ написан
  • При нажатии на плюс значение прибавляется, при нажатии на минус убавляется. Как сделать?

    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.matches('.style-count-plus') || -t.matches('.style-count-minus');
      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 комментария