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

    0xD34F
    @0xD34F Куратор тега JavaScript
    str.replace(/(p17)\/\w+/, '$1').replace('/index.m3u8', '.mp3')
    Ответ написан
    Комментировать
  • Как применить e.preventDefault только к определенным ссылкам, а не ко всем?

    0xD34F
    @0xD34F Куратор тега JavaScript
    О каких ссылках идёт речь: const selector = 'li.my_class a[href="#"]';.

    Обработчик клика можно назначать каждой ссылке индивидуально:

    document.querySelectorAll(selector).forEach(function(n) {
      n.addEventListener('click', this);
    }, e => e.preventDefault());

    Или один раз для всех:

    document.addEventListener('click', e => {
      const link = e.target.closest(selector);
      if (link) {
        e.preventDefault();
      }
    });
    Ответ написан
    Комментировать
  • Вместо массива получаю строку в коде?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Не могу понять, что в моём коде не так.

    Да в общем-то, всё не так:

    1. function getIndexOfWarmestDay(data){

      Козлиное имя функции - не соответствует тому, что она должна делать.

    2. let max = 0;

      Каким будет результат, если все элементы массива отрицательные? Начальное максимальное значение должно быть максимально минимальным - минус бесконечность.

    3. resultArr += max;

      Это как вообще родилось? Надо было погуглить, как выполняется добавление значения в массив, вместо того, чтобы высасывать из пальца подобную чушь.

    4. max = 0;

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

    5. console.log(resultArr);

      Функция должна заниматься чем-то одним. Не надо смешивать вычисления и вывод результатов. Вместо console.log тут надо делать return.

    6. Слишком многословно, зачем-то написано десять строк вместо одной: data.map(n => Math.max(...n)).
    Ответ написан
    Комментировать
  • Как вызвать функцию несколько раз?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function scrollTracking() {
      const wt = $(window).scrollTop();
      const wh = $(window).height();
    
      $('#console').html($('.active').get().find(n => {
        const et = $(n).offset().top;
        const eh = $(n).outerHeight();
        return wt > et && wt + wh - eh * 2 <= et + (wh - eh);
      }) ? 'Работает' : 'Не работает');
    }
    Ответ написан
  • Как вам такое решение задачки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Что меня здесь бесит:

    1. Мутирование переданного массива
    2. Для массивов нулевой и единичной длины результат не строка
    3. Многовато if'ов, слишком сложно

    UPD. Ну и ещё результаты кривоваты. Посмотрите [ 1, 2 ], например. Или [ 5, 6, 8, 9 ].
    Т.е., задача по сути не решена.

    UPD. Варианты решения.

    const range = ([...arr]) => arr
      .sort((a, b) => a - b)
      .reduce((acc, n, i, a) => (
        (n === a[i - 1] + 1) || acc.push([ n ]),
        acc[acc.length - 1][1] = n,
        acc
      ), [])
      .map(([ a, b ]) => a === b ? a : `${a}-${b}`)
      .join(', ');

    const range = arr => ''.concat(...arr
      .slice()
      .sort((a, b) => a - b)
      .reduce((acc, n, i, a) => (
        n !== a[i - 1] + 1 && acc.push(i ? `, ${n}` : n),
        n === a[i - 1] + 1 && n !== a[i + 1] - 1 && acc.push(`-${n}`),
        acc
      ), [])
    );

    Ответ написан
    6 комментариев
  • Как каждые несколько секунд убирать класс у одного блока и добавлять другому с таким же классом?

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

    function interval(arr, delay, callback) {
      let i = ~-arr.length;
    
      return arr.length
        ? setInterval(() => callback(arr[i], arr[i = -~i % arr.length]), delay)
        : null;
    }
    
    // или
    
    function interval(arr, delay, callback) {
      let timeoutId = null;
    
      arr.length && (function step(i) {
        timeoutId = setTimeout(() => {
          callback(arr[i++], arr[i %= arr.length]);
          step(i);
        }, delay);
      })(arr.length - 1);
    
      return () => clearTimeout(timeoutId);
    }

    Перебираем элементы, удаляем/добавляем класс:

    interval(
      document.querySelectorAll('.banner-block'),
      300,
      (prev, curr) => {
        prev.classList.remove('active');
        curr.classList.add('active');
      }
    );

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

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.num').each(function() {
      $({ value: 0 }).animate({ value: +$(this).text() }, {
        duration: 1000,
        easing: 'linear',
        step: val => $(this).text(val.toFixed(2)),
      });
    });
    Ответ написан
    1 комментарий
  • Как реализовать различные стратегии выбора элементов, в зависимости от блоков, в которых они находятся?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Элементам .item добавить data-атрибуты, указывающие, выбор какого типа осуществляется с помощью кнопок внутри (only - выбран может быть только один вариант вообще, one - выбран может быть только один вариант внутри данного .item, multiple - можно выбирать произвольное количество вариантов внутри данного .item):

    <div class="item" data-type="only">
      <h2>Выбрать все категории</h2>
      ...
    </div>
    <div class="item" data-type="one">
      <h2>Выбрать пол</h2>
      ...
    </div>
    <div class="item" data-type="multiple">
      <h2>Выбрать тип одежды</h2>
      ...
    </div>

    const containerSelector = '.filter';
    const itemSelector = `${containerSelector} .item`;
    const baseBtnSelector = 'button';
    const btnSelector = `${itemSelector} ${baseBtnSelector}`;
    const btnOnlySelector = `${itemSelector}[data-type="only"] ${baseBtnSelector}`;
    const activeClass = 'active';
    
    document.addEventListener('click', ({ target: t }) => {
      const button = t.closest(btnSelector);
      if (button) {
        const toggle = n => n.classList.toggle(activeClass, n === button);
        const item = button.closest(itemSelector);
        const { type } = item.dataset;
    
        item
          .closest(containerSelector)
          .querySelectorAll(type === 'only' ? btnSelector : btnOnlySelector)
          .forEach(toggle);
    
        if (type === 'multiple') {
          button.classList.toggle(activeClass);
        } else if (type === 'one') {
          item.querySelectorAll(btnSelector).forEach(toggle);
        }
      }
    });
    Ответ написан
    1 комментарий
  • Как объединить отсортированные массивы так, чтобы элементы итогового массива остались отсортированными?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function merge(nums1, m, nums2, n) {
      for (let i = m + n, i1 = m - 1, i2 = n - 1; i--;) {
        nums1[i] = i2 < 0 || nums1[i1] > nums2[i2] ? nums1[i1--] : nums2[i2--];
      }
    }
    Ответ написан
    2 комментария
  • Как вызывать случайную функцию с заданной вероятностью?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function randomCall(items) {
      const max = items.reduce((acc, n) => acc + n.ratio, 0);
    
      return function(...args) {
        const val = Math.random() * max;
        for (let sum = 0, i = 0; i < items.length; i++) {
          sum += items[i].ratio;
          if (sum > val) {
            return items[i].func.apply(this, args);
          }
        }
      };
    }
    
    
    const func = randomCall([
      { func: func1, ratio: 1 },
      { func: func2, ratio: 2 },
      { func: func3, ratio: 3 },
      { func: func4, ratio: 4 },
    ]);

    https://jsfiddle.net/pgnL6at1/
    Ответ написан
    Комментировать
  • Как в структуре с неизвестной вложенностью найти объект со свойством, имеющим определённое значение?

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

    function find(data, val) {
      const values = data instanceof Object ? Object.values(data) : [];
      return values.includes(val)
        ? data
        : values.reduce((found, n) => found || find(n, val), null);
    }
    
    
    const obj = find(arrayData, 'myValue');

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

    function find(data, val) {
      for (const stack = [ data ]; stack.length;) {
        const n = stack.pop();
        if (n instanceof Object) {
          const values = Object.values(n);
          if (values.includes(val)) {
            return n;
          }
    
          stack.push(...values);
        }
      }
    
      return null;
    }
    Ответ написан
    Комментировать
  • Как рандомить сразу все блоки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Классы замените data-атрибутом, в зависимости от значения которого будет стилизоваться сам .item, а не вложенные в него элементы:

    .item[data-xxx="1"]::before { background: #444; }
    .item[data-xxx="2"]::before { background: #555; }
    .item[data-xxx="3"]::before { background: #666; }
    .item[data-xxx="4"]::before { background: #777; }
    .item[data-xxx="5"]::before { background: #888; }
    .item[data-xxx="6"]::before { background: #999; }

    Соответственно, засовывать шесть div'ов в каждый .item не надо:

    $('#counter').on('input', e => {
      $('#results').html('<div class="item"></div>'.repeat(e.target.value));
    }).trigger('input');
    
    // или
    
    const results = document.querySelector('#results');
    const counter = document.querySelector('#counter');
    
    counter.addEventListener('input', ({ target: { value } }) => {
      results.innerHTML = Array(++value).join('<div class="item"></div>');
    });
    counter.dispatchEvent(new Event('input'));

    Нет div'ов - не надо ни у кого переключать видимость. Достаточно выставить атрибуту случайное значение:

    $('#view').on('click', () => $('.item').attr('data-xxx', () => 1 + Math.random() * 6 | 0));
    
    // или
    
    document.querySelector('#view').addEventListener('click', () => {
      document.querySelectorAll('.item').forEach(n => n.dataset.xxx = -~(Math.random() * 6));
    });

    https://jsfiddle.net/L76mav3t/
    Ответ написан
    Комментировать
  • Как обратиться к соседнему объекту DOM, если объект и его сосед - в разных?

    0xD34F
    @0xD34F Куратор тега JavaScript
    document.querySelector('table').addEventListener('click', ({ target: t }) => {
      const next = t.matches('input[type="button"]') && t.parentNode.nextElementSibling;
      const input = next && next.querySelector('input');
      input && (input.type = 'text');
    });
    Ответ написан
    1 комментарий
  • Как получить utm-метки из url?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Object.fromEntries((url.match(/(?<=utm_).+?=[^&]*/g) || []).map(n => n.split('=')))

    или

    [...url.matchAll(/utm_([^=]+)=([^&]*)/g)].reduce((acc, [ , k, v ]) => (acc[k] = v, acc), {})

    или

    Array
      .from(new URL(url).searchParams)
      .filter(n => n[0].startsWith('utm_'))
      .reduce((acc, n) => ({ ...acc, [n[0].slice(4)]: n[1] }), {})
    Ответ написан
  • Как вернуть исходное состояние select в динамичном режиме?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Что можно сделать:
    1. Установить значение select'а: select.value = '0';
    2. Установить индекс выбранного option'а: select.selectedIndex = 0;
    3. Назначить true в качестве значения свойства selected тому option'у, на который хотите переключиться:

      select[0].selected = true;
      // или
      select.options[0].selected = true;
      // или
      select.children[0].selected = true;
      // или
      select.firstElementChild.selected = true;
      // или
      select.querySelector('[selected]').selected = true;

    4. Перезаписать внутреннюю разметку select'а: select.innerHTML += '';
    Ответ написан
    Комментировать
  • Как удалить пустые значение в объекте исключая boolean?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const entries = Object.entries(obj);
    const mustBeRemoved = v =>
      (v instanceof Object && !Object.keys(v).length) ||
      (!v && typeof v !== 'boolean');

    Собираем новый объект:

    const newObj = Object.fromEntries(entries.filter(n => !mustBeRemoved(n[1])));

    Удаляем из существующего:

    entries.forEach(n => mustBeRemoved(n[1]) && delete obj[n[0]]);
    Ответ написан
    Комментировать
  • Как скопировать элемент и изменить его содержимое?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Что и куда будем копировать:

    const source = document.querySelector('.box1').children;
    const target = document.querySelector('.box2');

    Копируем:

    target.firstElementChild.insertAdjacentHTML('afterend', Array
      .from(source, ({ innerText: n }) => `<p><a href="#${n}">${n}</a></p>`)
      .join('')
    );

    или

    target.children[0].after(...Array.prototype.map.call(source, ({ textContent: n }) => {
      const p = document.createElement('p');
      const a = document.createElement('a');
      a.href = '#' + n;
      a.textContent = n;
      p.append(a);
      return p;
    }));
    Ответ написан
  • Как реализовать переключение вида карточек?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Так что надо-то - задавать карточкам различные стили (а это и есть "переключение вида"), или переключаться между разными наборами карточек (которые вы показали в песочнице)?

    Первое.
    <div class="wrapper">
      <button data-view="horizontal">Горизонтально</button>
      <button data-view="vertical">Вертикально</button>
      <div class="card-wrapper" data-view="horizontal">
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
      </div>
    </div>

    .card-wrapper {
      display: flex;
    }
    .card-wrapper[data-view="horizontal"] {
      flex-direction: row;
    }
    .card-wrapper[data-view="vertical"] {
      flex-direction: column;
    }

    document.querySelector('.wrapper').addEventListener('click', function(e) {
      const view = e.target.dataset.view;
      if (view && e.target.tagName === 'BUTTON') {
        this.querySelector('.card-wrapper').dataset.view = view;
      }
    });

    https://jsfiddle.net/7Leb60y9/

    Второе.
    <div class="wrapper">
      <button data-view="horizontal">Горизонтально</button>
      <button data-view="vertical">Вертикально</button>
      <div class="card-wrapper active" data-view="horizontal">
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
      </div>
      <div class="card-wrapper" data-view="vertical">
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
        <div class="card"></div>
      </div>
    </div>

    .card-wrapper {
      display: none;
    }
    .card-wrapper.active {
      display: flex;
    }
    .card-wrapper[data-view="horizontal"] {
      flex-direction: row;
    }
    .card-wrapper[data-view="vertical"] {
      flex-direction: column;
    }

    document.querySelector('.wrapper').addEventListener('click', function(e) {
      const view = e.target.dataset.view;
      if (view && e.target.tagName === 'BUTTON') {
        document.querySelectorAll('.card-wrapper').forEach(n => {
          n.classList.toggle('active', n.dataset.view === view);
        });
      }
    });

    https://jsfiddle.net/dq2hpfzj/
    Ответ написан
  • Почему не работает сумма?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Потому что

    data('.nights')

    data('.guests')

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

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

    $('div > span').click(e => e.stopPropagation());

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

    $('div').click(function(e) {
      if ($(e.target).is('span')) {
        return;
      }
    
      ...
    });
    Ответ написан
    Комментировать