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

    0xD34F
    @0xD34F Куратор тега JavaScript
    О каких элементах идёт речь: const selector = '.box';.

    Вместо назначения индивидуальных обработчиков каждому элементу можно сделать один делегированный:

    document.addEventListener('click', ({ target: t }) => {
      if (t = t.closest(selector)) {
        for (const n of document.querySelectorAll(selector)) {
          n.style.background = n === t ? 'red' : 'black';
        }
      }
    });

    или

    .box        { background: black; }
    .box.active { background:   red; }

    document.addEventListener('click', function({ target: t }) {
      if (t = this.find(n => n.contains(t))) {
        this.forEach(n => n.classList.toggle('active', n === t));
      }
    }.bind([...document.querySelectorAll(selector)]));

    ИЛИ

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

    document.querySelectorAll(selector).forEach(function(n) {
      n.addEventListener('click', this);
    }, function() {
      document.querySelector(`${selector}.active`)?.classList.remove('active');
      this.classList.add('active');
    });
    Ответ написан
    5 комментариев
  • Как получить объект с числами и именами дней недели, зная месяц и год?

    0xD34F
    @0xD34F Куратор тега JavaScript
    function getDatesGroupedByWeekday(year, month) {
      const d = new Date(`${month} 1, ${year}`);
      const iMonth = d.getMonth();
      const result = {};
    
      while (d.getMonth() === iMonth) {
        const date = d.getDate();
        const weekday = d.toLocaleString('en-US', { weekday: 'long' });
        (result[weekday] = result[weekday] ?? []).push(date);
        d.setDate(date + 1);
      }
    
      return result;
    }
    Ответ написан
  • Как обернуть все что идет после div?

    0xD34F
    @0xD34F Куратор тега JavaScript
    После кого и во что надо оборачивать:

    const block = document.querySelector('.block');
    const wrapper = document.createElement('div');
    wrapper.classList.add('another__block');

    Вариант раз - вычисляем индекс блока внутри родителя, вырезаем из родителя подмассив вложенных узлов, начиная с индекс плюс один, вставляем в обёртку:

    const parent = block.parentNode;
    const childNodes = [...parent.childNodes];
    wrapper.append(...childNodes.slice(-~childNodes.indexOf(block)));
    parent.append(wrapper);

    Вариант два - пока у блока есть следующий узел, добавляем его в обёртку:

    for (let n; n = block.nextSibling; wrapper.appendChild(n)) ;
    block.after(wrapper);
    Ответ написан
    1 комментарий
  • Как вывести на страницу полученные данные?

    0xD34F
    @0xD34F Куратор тега JavaScript
    fetch('https://jsonplaceholder.typicode.com/albums')
      .then(r => r.json())
      .then(r => {
        const keys = [ 'userId', 'id', 'title' ];
    
        // собираем разметку
        document.body.insertAdjacentHTML('beforeend', `
          <div class="wrapper">${r.map(n => `
            <div class="item">${keys.map(k => `
              <div>${k}: ${n[k]}</div>`).join('')}
            </div>`).join('')}
          </div>
        `);
    
        // или, создаём элементы напрямую
        function createElement(tag, className, children) {
          const el = document.createElement(tag);
          el.className = className;
          el.append(...children);
          return el;
        }
    
        document.body.append(
          createElement('div', 'wrapper', r.map(n =>
            createElement('div', 'item', keys.map(k =>
              createElement('div', '', [ `${k}: ${n[k]}` ])
            ))
          ))
        );
      });

    .wrapper {
      border: 3px solid black;
      padding: 10px;
      margin: 10px;
    }
    
    .item {
      border: 1px solid silver;
      padding: 5px;
      margin: 5px;
    }
    Ответ написан
    Комментировать
  • Как вызывать функцию только по отношению к дочернему общему блоку кнопки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Класс лучше переключайте не у .img-block, а у их самых дальних не общих предков, т.е., у .documents_block. В этом случае не придётся переписывать js-код, если вдруг потребуется стилизовать ещё-что то, кроме .img-block, или если решите изменить внутреннюю структуру .documents_block. Вместо .класс дополнительные стили надо будет прописывать у .класс .img-block.

    const itemSelector = '.documents_block';
    const buttonSelector = `${itemSelector} .open-doc-list`;
    const contentSelector = '.documents-content';
    const activeClass = 'active';
    const toggleEffect = 'slideToggle'; // или fadeToggle, или toggle
    const onClick = e => $(e.currentTarget)
      .closest(itemSelector)
      .toggleClass(activeClass)
      .find(contentSelector)
      [toggleEffect]();
    
    
    // обработчик клика подключаем к кнопкам
    $(buttonSelector).click(onClick);
    
    // или, если предполагается добавление новых блоков уже после подключения
    // обработчика, то лучше будет повесить его на документ, тогда всё будет
    // работать как надо без каких-либо дополнительных действий
    $(document).on('click', buttonSelector, onClick);
    Ответ написан
    1 комментарий
  • Как сравнить два массива и найти вхождения?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const fourValues = four.map(Object.values);
    
    const result = three.map(n => {
      const values = Object.values(n);
      const intersections = fourValues.filter(m => values.every(v => m.includes(v)));
      return `${values} - ${intersections.length
        ? `входит в / ${intersections.map(m => `${m}`).join(' / ')} /`
        : 'нет вхождений'}`;
    });
    Ответ написан
    Комментировать
  • Как сделать независимую нумерацию слайдов в различных слайдерах?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Кого надо пронумеровать:

    const containerSelector = '.bakeries-slider';
    const itemSelector = '.bakeries-slider__span';

    Как пронумеровать (зависимость текста от индекса элемента):

    const getNumber = i => (i + 1) + '.';
    // или
    const getNumber = i => `${-~i}.`;
    // или
    const getNumber = i => ''.concat(++i, '.');

    Если использовать jquery, то индекс элемента принимает коллбек метода text:

    $(containerSelector).each(function() {
      $(itemSelector, this).text((i, text) => text + getNumber(i));
    });

    В противном случае, есть варианты:

    document.querySelectorAll(containerSelector).forEach(container => {
      const items = container.querySelectorAll(itemSelector);
    
      // индекс передаётся в коллбек forEach'а
      items.forEach((n, i) => n.textContent += getNumber(i));
    
      // или, отдаётся итератором entries
      for (const [ i, n ] of items.entries()) {
        n.appendChild(document.createTextNode(getNumber(i)));
      }
    
      // или, можно самостоятельно обновлять переменную с индексом
      for (let i = 0; i < items.length; i++) {
        items[i].insertBefore(new Text(getNumber(i)), null);
      }
    
      // причём цикл для этого не обязателен
      (function next(i, n = items.item(i)) {
        n && (n.append(getNumber(i)), next(-~i));
      })(0);
    });
    Ответ написан
    Комментировать
  • Jquery modal image нормально работает только первый раз, как решить?

    0xD34F
    @0xD34F Куратор тега JavaScript
    При каждом клике по картинкам вы добавляете обработчики клика кнопкам. В результате, сколько раз открыли окно - столько обработчиков на кнопках будет висеть. И при клике все они будут выполняться, и каждый сделает +/- 1 к текущему индексу.

    Выносите $('#m_prev').click и $('#m_next').click за пределы $('.norutyun img').click.
    Ответ написан
    1 комментарий
  • Как отфильтровать объекты в массиве по слову в строчке ключа?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Чего не надо:

    const key = 'status';
    const value = 'maybe';

    Фильтруем:

    const newArr = arr.filter(n => !n[key].includes(value));

    Если же и правда слово, тогда регулярные выражения используйте или предварительно режьте строку на куски:

    const reg = RegExp(`\\b${value}\\b`);
    const newArr = arr.filter(n => !reg.test(n[key]));
    
    // или
    
    const newArr = arr.filter(function(n) {
      return !n[key].match(this);
    }, RegExp(`(^| )${value}( |$)`));
    
    // или
    
    const newArr = arr.filter(n => !n[key].split(' ').includes(value));
    Ответ написан
    Комментировать
  • Как получить отсортированный массив в jquery?

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

    $('#sortable').sortable({
      stop() {
        const values = $('input[name="slider-id"]', this).get().map(n => n.value);
      },
    });
    Ответ написан
    Комментировать
  • Почему target.closest не выбирает элемент по классу?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Очевидно, потому что среди предков target нет элемента с указанным классом. Смотрите внимательнее, где находится target, а где то, что вы пытаетесь получить.
    Ответ написан
    3 комментария
  • Как из массива достать объекты, у которых одно из свойств имеет определённые значения?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Какое свойство смотрим, какие значения хотим увидеть:

    const key = 'workplace';
    const values = [ 'office', 'hotel' ];

    Достаём объекты:

    const result = arr.filter(function(n) {
      return this.has(n[key]);
    }, new Set(values));
    
    // или
    
    const result = values.flatMap(((grouped, n) => grouped[n] ?? []).bind(
      null,
      arr.reduce((acc, n) => ((acc[n[key]] = acc[n[key]] ?? []).push(n), acc), {})
    ));
    
    // или
    
    const result = [];
    for (const n of arr) {
      for (const m of values) {
        if (m === n[key]) {
          result.push(n);
          break;
        }
      }
    }
    
    // или
    
    const result = [];
    for (let i = 0; i < arr.length; i++) {
      if (~values.indexOf(arr[i][key])) {
        result[result.length] = arr[i];
      }
    }
    
    // или
    
    const result = (function get(i, n = arr[i]) {
      return n
        ? [].concat(values.includes(n[key]) ? n : [], get(-~i))
        : [];
    })(0);
    Ответ написан
    Комментировать
  • JavaScript - как получить время от инициализации страницы до первого клика юзера?

    0xD34F
    @0xD34F Куратор тега JavaScript
    document.addEventListener('click', () => {
      console.log(performance.now());
    }, { once: true });

    или

    const t = new Date;
    document.addEventListener('click', function onClick() {
      console.log(new Date - t);
      document.removeEventListener('click', onClick);
    });
    Ответ написан
    Комментировать
  • Почему не работает "скрыть" на не первых элементах?

    0xD34F
    @0xD34F Куратор тега JavaScript
    При каждом добавлении нового элемента в #list-case вы назначаете обработчики клика всем существующим .img и .show, а не только свежесозданным. Если срабатывает два (или четыре, или шесть, или...) обработчика, которые выполняют toggleClass, то конечное состояние от начального отличаться не будет. Отсюда ваше кажущееся "не работает".

    Не надо назначать никаких обработчиков при добавлении .case, делайте это один раз, используя делегирование:

    $('#list-case')
      .on('click', '.img', function() {
        $(this).closest('.case').remove();
      })
      .on('click', '.show', function() {
        $(this).toggleClass('none').closest('.case').find('.case-bottom').toggleClass('invise');
      });
    Ответ написан
    1 комментарий
  • Как сделать смену placeholder через n секунд?

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

    const placeholders = [ 'hello, world!!', 'fuck the world', 'fuck everything' ];
    const delay = 200;
    const input = document.querySelector('input');

    Назначаем:

    function interval(arr, delay, callback) {
      let i = -1;
    
      return arr.length
        ? setInterval(() => callback(arr[i = -~i % arr.length]), delay)
        : null;
    }
    
    
    const intervalId = interval(placeholders, delay, n => input.placeholder = n);
    // хотим остановить, делаем так: 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(
      placeholders,
      delay,
      Element.prototype.setAttribute.bind(input, 'placeholder')
    );
    // хотим остановить, делаем так: stop();
    Ответ написан
    Комментировать
  • Почему не ставится атрибут checked?

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

    return false;

    Возврат false из обработчика события, устанавливаемого посредством jquery, приводит к отмене действия по умолчанию. В данном случае - клика по input'у.

    toggle дважды начинает срабатывать

    Потому что клик по label'у вызывает клик по input'у, это событие всплывает, и обработчик, привязанный к label'у, срабатывает повторно.

    Вешайте обработчик на input вместо label и слушайте change вместо click.
    Ответ написан
    Комментировать
  • Как разбить строку по пробелам?

    0xD34F
    @0xD34F Куратор тега JavaScript
    str.trim().split(/\s+/)

    или

    str.match(/\S+/g) ?? []
    Ответ написан
    Комментировать
  • Как сделать фильтрацию массива с объектами?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const comparators = [
      [ 'city', (itemVal, filterVal) => itemVal === filterVal ],
      [ 'title', (itemVal, filterVal) => itemVal.includes(filterVal) ],
      [ 'type', (itemVal, filterVal) => itemVal.includes(filterVal) ],
    ];
    
    
    const filteredArr = arr.filter(n => comparators.every(([ k, f ]) => f(n[k], filter[k])));
    Ответ написан
    Комментировать