Задать вопрос
  • Как регуляркой взять символ процента?

    0xD34F
    @0xD34F Куратор тега Регулярные выражения
    (?<=\n)%(?=\n)
    Ответ написан
    Комментировать
  • Как сгруппировать данные списка?

    0xD34F
    @0xD34F
    grouped = {}
    
    for n in products:
      category = n['category']['name']
      group = grouped.setdefault(category, {})
      group[n['productId']] = { 'name': n['name'] }
    Ответ написан
    1 комментарий
  • Как получить самую давнюю дату, хранящуюся в массиве?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const [ date = null ] = arr.map(n => n.date).sort();

    или

    const date = arr.reduce((min, { date: n }) => min !== null && min < n ? min : n, null);

    или

    const date = arr.length
      ? new Date(Math.min(...arr.map(n => new Date(n.date)))).toISOString()
      : null;
    Ответ написан
    Комментировать
  • Как удалить из массива даты с определенным месяцем?

    0xD34F
    @0xD34F
    Собрать новый массив:

    $newArr = array_filter($arr, fn($n) => explode('.', $n)[1] !== '08');

    Изменить существующий:

    for ($i = 0, $j = 0; $i < count($arr); $i++) {
      if (explode('.', $arr[$i])[1] === '08') {
        $j++;
      } else if ($j) {
        $arr[$i - $j] = $arr[$i];
      }
    }
    
    array_splice($arr, -$j, $j);
    Ответ написан
    2 комментария
  • Как сделать кнопку больше-меньше на React чтобы скрыть или показать li?

    0xD34F
    @0xD34F Куратор тега React
    const [ showAll, setShowAll ] = useState(false);
    const defaultShow = 2;
    const showAllByDefault = ingredients.length <= defaultShow;
    const ingredientsToShow = (showAll || showAllByDefault)
      ? ingredients
      : ingredients.slice(0, defaultShow);

    {showAllByDefault
      ? null
      : <button onClick={() => setShowAll(val => !val)}>{showAll ? 'hide' : 'show'}</button>
    }
    <ul>
      {ingredientsToShow.map(n => <li>{n}</li>)}
    </ul>
    Ответ написан
    1 комментарий
  • Как запустить computed в VUE3?

    0xD34F
    @0xD34F Куратор тега Vue.js
    Ключевое слово в качестве имени переменной - что за бред?
    Как достучаться до параметров из script setup - читаем документацию.
    У вычисляемого свойства нет сеттера - так пусть будет функцией, объект не нужен.

    Исправляем:

    const props = defineProps({
      showBgBlue: {
        type: Boolean,
        default: true,
      },
    });
    
    const mainClass = computed(() => props.showBgBlue ? 'bg-blueGray-50 py-12' : 'bg-white');
    Ответ написан
    5 комментариев
  • Как найти сумму элементов вложенных массивов?

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

    const sum = data =>
      Array.isArray(data)
        ? data.reduce((acc, n) => acc + sum(n), 0)
        : (+data || 0);

    Рекурсии нет:

    function sum(data) {
      const stack = [];
      let result = 0;
    
      for (let i = 0, arr = [ data ]; i < arr.length || stack.length; i++) {
        if (i === arr.length) {
          [ i, arr ] = stack.pop();
        } else if (arr[i] instanceof Array) {
          stack.push([ i, arr ]);
          [ i, arr ] = [ -1, arr[i] ];
        } else {
          result += +arr[i] || 0;
        }
      }
    
      return result;
    }

    Здесь, конечно, будет складываться всё, что можно сложить. Т.е., не только собственно числа, но и всё, что может быть сведено к числу, например true, '0xBB', { valueOf: () => 666 } и т.д.

    Если нужно складывать только числа - предлагаю подумать самостоятельно, как изменить представленный код.
    Ответ написан
    1 комментарий
  • Как вывести элементы массива в разные блоки по ID?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Странно, но все работает, несмотря на ошибку:

    TypeError: Cannot read properties of null (reading 'insertAdjacentHTML').

    Ничего странного, id существующих блоков совпадают с id первых объектов в массиве, т.е., сначала заполняются все существующие блоки, а уже потом случается ошибка, когда пытаетесь дёрнуть метод у отсутствующего блока.

    Какие есть способы победить ошибку:

    • Проверка наличия элемента перед тем как попытаться что-то в него добавить.

      Можно делать это явно:

      arr.forEach(n => {
        const el = document.getElementById(n.id);
        if (el) {
          el.innerHTML = `
            <h2>Id: ${n.id}</h2>
            <h3>${n.title}</h3>
            <p>${n.body}</p>
          `;
        }
      });

      Или не очень:

      for (const { id, title, body } of arr) {
        document.querySelector(`[id="${id}"]`)?.insertAdjacentHTML('beforeend', `
          <h2>Id: ${id}</h2>
          <h3>${title}</h3>
          <p>${body}</p>
        `);
      }

    • Создание элементов под все полученные объекты (в этом случае пусть section изначально будет пустым):

      document.querySelector('section').innerHTML = arr
        .map(n => `
          <div id="post-${n.id}">
            <h2>Id: ${n.id}</h2>
            <h3>${n.title}</h3>
            <p>${n.body}</p>
          </div>`)
        .join('');

    • Ограничение объёма получаемых данных.

      Если id элементов действительно имеют показанный вами вид (начинаются с 1 и идут по возрастанию), то просто запрашиваем столько объектов, сколько есть элементов:

      const limit = document.querySelector('section').children.length;
      const requestURL = `https://jsonplaceholder.typicode.com/posts?_limit=${limit}`;

      Или, можно запросить объекты с id как у элементов:

      const requestURL = 'https://jsonplaceholder.typicode.com/posts?' + Array
        .from(document.querySelector('section').children, n => `id=${n.id}`)
        .join('&');


    Какой из способов следует предпочесть? 2 + 3. Только, конечно, количество объектов или их id надо брать не из DOM.
    Ответ написан
  • Как можно улучшить модерирование?

    0xD34F
    @0xD34F
    Через форму обратной связи изложить администрации свои гениальные идеи (нет, это не насмешка, не сарказм - там такой пункт есть в выпадающем списке "тема"). Дальше надеяться, что администрация вас услышит, согласиться с услышанным и укажет модераторам на необходимость смены поведенческих паттернов.
    Ответ написан
    2 комментария
  • Почему при обновлении блока на нем перестает работать mouseover?

    0xD34F
    @0xD34F Куратор тега Vue.js
    new Vue({

    loaves: [

    this.loaves[idx] =

    Этих кусков кода достаточно, чтобы понять, какой именно раздел документации вы решили не читать.

    Перезапись элемента массива не отслежена => его свойства не стали реактивными => их изменения не приводят к обновлению DOM. Всё.
    Ответ написан
    Комментировать
  • Как сложить значения input'ов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Кого складываем:

    const elements = document.querySelectorAll('[name^=AR_AMOUNT]');

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

    const sum = Array.prototype.reduce.call(
      elements,
      (acc, n) => acc + +n.value,
      0
    );
    
    // или
    
    let sum = 0;
    for (const { value } of elements) {
      sum += Number(value);
    }
    
    // или
    
    let sum = 0;
    for (let i = 0; i < elements.length; i++) {
      sum = sum + elements.item(i).value * 1;
    }

    Ненормальный способ - рекурсия. Функция получает индекс, если элемент с таким индексом существует, возвращаем его значение плюс результат рекурсивного вызова с индексом, увеличенным на единицу; если элемента нет - возвращаем 0:

    const sum = (function sum(i, n = elements[i]) {
      return n ? parseFloat(n.value) + sum(i + 1) : 0;
    })(0);

    Дикий способ - сами ничего считать не будем. Выдёргиваем из коллекции элементов значения; склеиваем их, используя в качестве разделителя символ +, в строку; строку отдаём в eval; всё, сумма получена (ну, почти, если исходная коллекция элементов была пуста, то строка тоже будет пустой, так что надо не забыть подставить 0 вместо возможного undefined, который является результатом выполнения пустой строки):

    const sum = eval(Array.from(elements, n => n.value).join('+')) ?? 0;
    Ответ написан
    Комментировать
  • Как реализовать анимацию набора текста?

    0xD34F
    @0xD34F Куратор тега React
    function Typewriter({ text }) {
      const [ length, setLength ] = useState(0);
    
      useEffect(() => {
        setLength(0);
    
        const interval = setInterval(setLength, 100, length => {
          if (++length >= text.length) {
            clearInterval(interval);
          }
    
          return length;
        });
    
        return () => clearInterval(interval);
      }, [ text ]);
    
      return <div>{text.slice(0, length)}</div>;
    }
    Ответ написан
    Комментировать
  • Как через цикл вложить элементы DOM один в другой?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Собираем и вставляем разметку:

    // заменяем содержимое элемента main
    main.innerHTML = arr.reduceRight(
      (content, tag) => `<${tag}>${content}</${tag}>`,
      ''
    );
    
    // или, дополняем его
    main.insertAdjacentHTML(
      'beforeend',
      (function next(i, tag = arr[i] ?? '') {
        return tag && `<${tag}>${next(-~i)}</${tag}>`;
      })(0)
    );

    Или создаём элементы напрямую:

    // замена контента
    main.replaceChildren(...arr.reduceRight((content, tag) => {
      const el = document.createElement(tag);
      el.append(...content);
      return [ el ];
    }, []));
    
    // или, добавление
    arr.reduce((el, tag) => (
      el.appendChild(document.createElement(tag)),
      el.lastChild
    ), main);
    Ответ написан
    Комментировать
  • Как объединить несколько объектов в один?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const merge = (target, ...sources) =>
      sources.reduce((acc, n) => (
        Object.entries(n).forEach(([ k, v ]) =>
          acc[k] = v instanceof Object
            ? merge(acc[k] instanceof Object ? acc[k] : {}, v)
            : v
        ),
        acc
      ), target);
    
    
    const result = merge({}, ...arrayObj);
    Ответ написан
    3 комментария
  • Как заранее знать уровень подготовки спрашивающего?

    0xD34F
    @0xD34F
    Считайте спрашивающего конченым дебилом. В девяти случаях из десяти окажетесь правы. Может даже в девятнадцати из двадцати. Нет, серьёзно, кем ещё надо быть, чтобы спрашивать то, что можно загуглить?
    Ответ написан
  • Как сделать сортировку HTML объектов в зависимости от чисел внутри элемента?

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

    const sorted = (data, key) => Array
      .from(data, n => [ key(n), n ])
      .sort(([a], [b]) => a < b ? -1 : +(a > b))
      .map(n => n[1]);

    Как отсортировать содержимое DOM-элемента - да просто добавить ему это содержимое в отсортированном виде:

    const sortChildren = (el, key) =>
      el.append(...sorted(el.children, key));

    Направление сортировки будем указывать с помощью data-атрибута:

    <button data-order="-1">От большего к меньшему</button>
    <button data-order="+1">От меньшего к большему</button>

    Кнопкам назначаем общий обработчик клика, где сортируем содержимое .catalog-items (вес элемента - число внутри, умноженное на направление сортировки), кликнутой кнопке класс добавляем, у остальных убираем:

    const wrapper = document.querySelector('.catalog-items');
    const buttons = document.querySelectorAll('[data-order]');
    
    buttons.forEach(n => n.addEventListener('click', onClick));
    
    function onClick({ target: t }) {
      const order = +t.dataset.order;
      sortChildren(wrapper, el => parseInt(el.innerText) * order);
      buttons.forEach(n => n.classList.toggle('active', n === t));
    }
    Ответ написан
    3 комментария
  • Как поменять действие по нажатию на label dataset'а?

    0xD34F
    @0xD34F
    В документации не нашёл явных примеров.

    плохо искали

    options: {
      plugins: {
        legend: {
          onClick(e, legendItem, { chart }) {
            this.legendItems.forEach((n, i) => {
              chart.getDatasetMeta(i).hidden = n !== legendItem && (legendItem.hidden || !n.hidden);
            });
    
            chart.update();
          },
        },
      },
    },

    https://jsfiddle.net/79Lfjor6/
    Ответ написан
    Комментировать
  • Как заставить работать кастомную навигацию Swiper в React?

    0xD34F
    @0xD34F Куратор тега React
    nextEl: prevRef.current

    Суть проблемы - current имеет значение null при первом рендеринге. Так что придётся заставить компонент отрендериться ещё раз. Например, можно это сделать путём сохранения ссылки на экземпляр swiper'а в стейт (да, с одной стороны костыль, с другой - наверняка пригодится в будущем):

    const [ swiper, setSwiper ] = useState();

    <Swiper
      onSwiper={setSwiper}
      ...

    https://codesandbox.io/s/for-https-qna-habr-com-q-...

    Или, так же получаете экземпляр swiper'а, но вырезаете к чёрту navigation, вместо того, чтобы передавать ref'ы в экземпляр компонента Swiper, добавьте элементам, которые должны выступать в роли кнопок, обработчики клика, где будут дёргаться методы slidePrev/slideNext:

    - ref={prevRef}
    + onClick={() => swiper.slidePrev()}

    https://stackblitz.com/edit/stackblitz-starters-rr...
    Ответ написан
  • Как вывести ключи и значения ассоциативного массива?

    0xD34F
    @0xD34F
    $arrToStr = fn($arr) => implode(', ', array_map(fn($v, $k) => "$k: $v", $arr, array_keys($arr)));
    echo implode("\n", array_map($arrToStr, $users));
    Ответ написан
  • Jquery, как получить значение атрибута после его изминения?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Надо заменить:

    - $('.play').attr('data-play', video);
    + $('.play').data('play', video);

    или

    - video = $(this).data('video');
    + video = $(this).attr('data-video');
    
    - atplay = $(this).data('play');
    + atplay = $(this).attr('data-play');

    То есть, работайте всегда через data, или всегда через attr. Потому что при использовании метода data обращение к data-атрибутам выполняется только один раз:

    data-* attributes are used to initialize jQuery data. An element's data-* attributes are retrieved the first time the data() method is invoked upon it, and then are no longer accessed or mutated

    А вообще, можно и отказаться от jquery:

    const play = document.querySelector('.play');
    
    document.querySelectorAll('.paskal').forEach(function(n) {
      n.addEventListener('click', this);
    }, e => play.dataset.play = e.currentTarget.dataset.video);
    
    play.addEventListener('click', e => {
      console.log(e.currentTarget.dataset.play);
    });
    Ответ написан