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

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

    const options = [
      [ 'hello, world!!', 'fuck the world', 'fuck everything' ],
      500,
      console.log,
    ];

    Можно установить интервал:

    function interval(arr, delay, callback) {
      let i = -1;
    
      return arr.length
        ? setInterval(() => callback(arr[i = -~i % arr.length]), delay)
        : null;
    }
    
    const intervalId = interval(...options);
    // надо остановить хождение по кругу, делаем так: clearInterval(intervalId);

    Или воспользоваться рекурсивными таймаутами:

    function interval(arr, delay, callback) {
      let timeoutId = null;
    
      arr.length && (function next(i) {
        timeoutId = setTimeout(() => {
          callback(arr[i]);
          next((i + 1) % arr.length);
        }, delay);
      })(0);
    
      return () => clearTimeout(timeoutId);
    }
    
    const stop = interval.apply(null, options);
    // надо остановить, делаем так: stop();
    Ответ написан
    Комментировать
  • Как получить содержимое navigator.plugins в виде строки?

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

    Array.from(navigator.plugins, n => n.name).join(', ')
    Ответ написан
    Комментировать
  • Почему когда я вешаю событие клика на кнопку, то при загрузке она сразу срабатывает?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Потому что кто-то не понимает разницы между собственно функцией и результатом её вызова. Вот же позорище.

    Оборачивайте вызов функции в другую функцию. Или bind используйте. Или разберитесь, что принимают обработчики событий в качестве параметра, и перепишите функцию так, чтобы не надо было ей передавать элементы btnNextLevel.
    Ответ написан
    8 комментариев
  • Как сделать правильно рекурсию?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function xxx(key) {
      let val = entityTree[key];
      const nextKey = Array.isArray(val) && (val = [...val], val.pop());
      return val ? [].concat(key, val, xxx(nextKey)) : [];
    }
    Ответ написан
    3 комментария
  • Как сделать регулярку с отсутствием кириллицы и пробелов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Так чего надо-то? Как-то противоречиво выглядят ваши слова:

    Нужно сделать обычную регулярку, которая бы проверяла наличие кириллицы и пробелов.

    // проверяем, что строка содержит и первое, и второе
    /(?=.*[А-ЯЁ])(?=.* )/i.test(str)
    
    // проверяем, что ничего другого в строке нет
    /^[А-ЯЁ ]*$/i.test(str)

    Нужно полностью исключить кирилицу и пробелы.

    // проверяем отсутствие
    /^[^А-ЯЁ ]*$/i.test(str)
    
    // удаляем
    str.replace(/[А-ЯЁ ]/gi, '')
    Ответ написан
    Комментировать
  • Как не заменять значение свойства на другие, а добавить ещё одно?

    0xD34F
    @0xD34F Куратор тега JavaScript
    if (obj.hasOwnProperty(key)) {
      if (!Array.isArray(obj[key])) {
        obj[key] = [ obj[key] ];
      }
    
      obj[key].push(val);
    } else {
      obj[key] = val;
    }

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

    это для массива, а у меня объект

    И что? Самостоятельно одно на другое заменить - нет, никак? Вместо Array.isArray проверяйте instanceof Object. А ключ нового свойства - это количество уже существующих свойств:

    if (obj.hasOwnProperty(key)) {
      if (!(obj[key] instanceof Object)) {
        obj[key] = { 0: obj[key] };
      }
    
      obj[key][Object.keys(obj[key]).length] = val;
    } else {
      obj[key] = val;
    }
    Ответ написан
    6 комментариев
  • Как выделить текущий промежуток времени и следующий?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Во-первых, два класса не нужны, заменяем .next на .active + *.

    Во-вторых,

    // назначаем класс после создания элементов
    for (let i = times.length; i--;) {
      if (new Date(times[i]) <= date) {
        result.children[i].classList.add('active');
        break;
      }
    }
    
    // или, параллельно
    result.append(...times.map((n, i, { [-~i]: m = +date + 1 }) => {
      const p = document.createElement('p');
      p.textContent = n;
      p.classList.toggle('active', new Date(n) <= date && date < new Date(m));
      return p;
    }));
    Ответ написан
    1 комментарий
  • Как отфильтровать данный объект?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Непонятно, что конкретно надо. Варианты-то разные есть. Например:

    1. Один из элементов services должен содержать все категории, указанные в filterBy:

      users.filter(u => u.services.some(s => filterBy.every(f => s.categories.includes(f))))

    2. Должны присутствовать все категории, указанные в filterBy, но распределены по элементам services они могут быть произвольным образом:

      users.filter(u => filterBy.every(f => u.services.some(s => s.categories.includes(f))))

    3. Достаточно присутствия любой из категорий, указанных в filterBy, в любом из элементов services:

      users.filter(u => filterBy.some(f => u.services.some(s => s.categories.includes(f))))

    и т.д.
    Ответ написан
    Комментировать
  • Как правильно организовать вывод вложенного списка?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.products').append(data.uslugi.map(item => `
      <div class="item p-2">
        <img src="${item.img}" alt="" class="p-2 h-64 mx-auto">
        <h2 class="text-lg text-center font-semibold p-1 pb-0">${item.title}</h2>
        <div class="flex flex-wrap w-56 mx-auto py-2 pt-0 text-lg sizes">
          ${item.size.map(size => `
            <div class="p-1 flex size">
              <span class="px-2 rounded-full size active">${size}</span>
            </div>
          `).join('')}
        </div>
      </div>
    `).join(''))
    Ответ написан
    Комментировать
  • Как оптимизировать данный код?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const form = document.querySelector('.form');
    const items = [...form.querySelectorAll('.form__item')];
    
    form.addEventListener('change', function(e) {
      const index = items.indexOf(e.target.closest('.form__item'));
      form.querySelector('.form__progress-line').style.width = (index + 2) * 100 / items.length + '%';
    
      setTimeout(() => {
        items[index]?.classList.remove('form__item--active');
        items[index + 1]?.classList.add('form__item--active');
    
        if (index + 1 === items.length) {
          form.style.display = 'none';
          document.querySelector('.result').classList.add('result--active');
        }
      }, 1000);
    });
    
    form.dispatchEvent(new Event('change'));
    Ответ написан
    Комментировать
  • Как сократить скрипт, если возможно?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Заменить id на классы:

    const values = Array.from(document.querySelectorAll('.l'), n => n.value);
    document.querySelectorAll('.lt').forEach((n, i) => n.value = values[i]);
    document.querySelector('.block').style.borderRadius = values.map(n => `${n}px`).join(' ');
    Ответ написан
    Комментировать
  • Как при помощи moment.js вывести само время и единицу времени?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Никак. То, чего вы хотите, moment делать не умеет. Есть fromNow - но там не всё гладко (например, секунды отображаются неточно - вместо количества пишет "несколько" или округляет до минуты). Может, есть какой плагин, но это не точно и надо искать.

    Ваш вариант - это вот что.

    Или так можно:

    const pr = new Intl.PluralRules('ru');
    const rules = [
      { one:  'минута', few:  'минуты', many:  'минут' },
      { one: 'секунда', few: 'секунды', many: 'секунд' },
    ];
    
    function getTimeStr(minutes, seconds) {
      const t = minutes || seconds;
      return `Осталось ${t} ${rules[+!minutes][pr.select(t)]}`;
    }

    <div className={s.container}>{getTimeStr(+minutes, +seconds)}</div>
    Ответ написан
    1 комментарий
  • Как сделать, чтобы прилипающий блок в сайдбаре исчезал при достижении другого блока?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $(window).scroll(function() {
      const $banner = $('.banner');
      const bannerHeight = $banner.outerHeight(true);
      const bannerTop = parseInt($banner.css('top'), 10);
      const windowTop = $(this).scrollTop();
    
      $banner.toggleClass('hide', $('.fullwidth').get().some(n => {
        const $n = $(n);
        const nTop = $n.offset().top - bannerTop;
        const minTop = nTop - bannerHeight;
        const maxTop = nTop + $n.outerHeight(true);
    
        return windowTop > minTop && windowTop < maxTop;
      }));
    });
    Ответ написан
    1 комментарий
  • Как слить элементы вложенных массивов в одну строку?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Максимально простое решение, превращаем вложенный массив в плоский с помощью встроенного метода:

    const join = val =>
      Array.isArray(val)
        ? val.flat(Infinity).join('')
        : `${val}`;

    Чуть посложнее, применяем рекурсию:

    const join = val =>
      val instanceof Array
        ? val.reduce((acc, n) => acc + join(n), '')
        : val + '';

    Ещё сложнее, рекурсии нет:

    function join(val) {
      const result = [];
      const stack = [];
    
      for (let i = -1, arr = [ val ]; ++i < arr.length || stack.length;) {
        if (i === arr.length) {
          [ i, arr ] = stack.pop();
        } else if (arr[i]?.constructor === Array) {
          stack.push([ i, arr ]);
          [ i, arr ] = [ -1, arr[i] ];
        } else {
          result.push(arr[i]);
        }
      }
    
      return ''.concat(...result);
    }
    Ответ написан
    Комментировать
  • Как сделать кнопку disabled, пока не нажат checkbox?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('form').on('input', function() {
      $('#submit-about').prop('disabled', ![
        $('#name-about').val().length !== 0,
        $('#phone-about').val().length === 16,
        $('#personaldata-about').prop('checked'),
      ].every(Boolean));
    });
    Ответ написан
  • Почему переписывается последующий массив в 0?

    0xD34F
    @0xD34F Куратор тега JavaScript
    1. Метод splice изменяет массив.

    2. Массивы (как и прочие объекты) не копируются при использовании их в качестве аргументов функций.
    Ответ написан
    1 комментарий
  • Как сделать закрытие блока при 2м клилке на ссылку которая его показывает?

    0xD34F
    @0xD34F Куратор тега JavaScript
    .dropdown {
      display: none;
    }
    
    .dropdown.show {
      display: block;
    }

    const headerSelector = '.tabs__head';
    const contentSelector = '.dropdown';
    const activeClass = 'show';

    // делегирование, назначаем обработчик клика один раз для всех хедеров;
    // контент, соответствующий нажатому хедеру, находим через значение атрибута href
    document.addEventListener('click', ({ target: t }) => {
      const header = t.closest(headerSelector);
      if (header) {
        document.querySelectorAll(contentSelector).forEach(function(n, i) {
          n.classList[n === this ? 'toggle' : 'remove'](activeClass);
        }, document.querySelector(header.attributes.href.value));
      }
    });
    
    // или, назначаем обработчик клика каждому хедеру индивидуально;
    // контент, соответствующий нажатому хедеру, определяем по равенству индексов
    const headers = document.querySelectorAll(headerSelector);
    const contents = document.querySelectorAll(contentSelector);
    
    headers.forEach(n => n.addEventListener('click', onClick));
    
    function onClick() {
      const index = Array.prototype.indexOf.call(headers, this);
      contents.forEach((n, i) => n.classList[i === index ? 'toggle' : 'remove'](activeClass));
    }
    Ответ написан
    3 комментария
  • При запросе сonsole.log(options); пишет сonsole is not defined. Что я делаю не так?

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

    'console' === 'сonsole' // false
    Ответ написан
    Комментировать
  • Как изменить текст кнопки по клику?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сохранять исходный текст каждой кнопки отдельно:

    $('.price_tabs-content button').click(function() {
      const $this = $(this);
      const on = $this.siblings('p').toggleClass('on').hasClass('on');
      $this.text(on ? 'Закрыть' : $this.data('text'));
    }).each((i, n) => $(n).data('text', $(n).text()));

    https://jsfiddle.net/vs6m5hL0/

    Или, можно не менять надпись на кнопке, а добавить вторую кнопку, и переключать видимость обеих:

    $('.price_tabs-content button').click(function() {
      $(this).hide().next().show().end().prev().addClass('on');
    }).after('<button>Закрыть</button>').next().hide().click(function() {
      $(this).hide().prev().show().prev().removeClass('on');
    });

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

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вспомогательная функция - выбор случайного элемента массивоподобного объекта, дальше она нам понадобится:

    const random = arr => arr[Math.random() * arr.length | 0];

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

    const check = count === random([
      count1 + count2,
      count1 - count2,
      count1 * count2,
      count1 / count2,
    ]);

    Или, заранее подготавливаем функции, выполняющие различные действия над переданными аргументами, выбираем случайную, вызываем:

    const operations = [
      (a, b) => a + b,
      (a, b) => a - b,
      (a, b) => a * b,
      (a, b) => a / b,
    ];
    
    const check = count === random(operations)(count1, count2);

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

    const check = count === eval(count1 + random('+-*/') + count2);
    Ответ написан
    Комментировать