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

    0xD34F
    @0xD34F Куратор тега JavaScript
    div.classList.remove(...[...div.classList].filter(n => n.indexOf('_key-word') !== -1))
    Ответ написан
    5 комментариев
  • Есть ли способ обходить ошибки типа "Cannot read property 'trim' of null"?

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

    (item._Name || '').trim()

    UPD. Наконец-то дождались, и трёх лет не прошло:

    item._Name?.trim?.() ?? ''
    Ответ написан
    2 комментария
  • Как прибавить к текущему времени 7 часов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Владивосток - плюс 7 часов к текущему.

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

    Вычислить время в заданном часовом поясе можно так, например:

    function getTimeInTimezone(zone) {
      const
        d = new Date(),
        utc = d.getTime() + d.getTimezoneOffset() * 60000;
    
      return new Date(utc + zone * 3600000);
    }

    Владивосток - это UTC+10, соответственно, вместо new Date(), делаем так: getTimeInTimezone(10).
    Ответ написан
    Комментировать
  • Как исправить ошибку Uncaught ReferenceError?

    0xD34F
    @0xD34F Куратор тега JavaScript
    (function(w) {
      'use strict';
      w.Test = function(hello) {
        console.log(hello);
      };
    }(window));

    или

    var Test = (function() {
      'use strict';
      return function(hello) {
        console.log(hello);
      };
    }());

    или

    (function() {
      Test = function(hello) {
        console.log(hello);
      };
    }());
    Ответ написан
    Комментировать
  • Какие есть способы сократить данную строку?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сложить допустимые значения в массив, с помощью метода узнать, содержится ли в массиве проверяемое значение:

    if (![ 'search', 'search_input', 'cancel_btn' ].includes(target.className)) {

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

    const t = target.className;
    if (t !== 'search' && t !== 'search_input' && t !== 'cancel_btn') {

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

    if (!target.matches('.search, .search_input, .cancel_btn')) {
    Ответ написан
    Комментировать
  • Как вернуться к началу событий (jQuery)?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Так:

    <div class="block">hello, world!!</div>
    <div class="block">fuck the world</div>
    <div class="block">fuck everything</div>

    .block {
      display: inline-block;
      width: 500px;
      height: 150px;
      padding: 20px;
      background: red;
      color: white;
    }

    const $blocks = $('.block').hide();
    let i = -1;
    
    (function showNext() {
      $blocks
        .eq(i = (i + 1) % $blocks.length)
        .dequeue()
        .fadeIn(1000)
        .delay(500)
        .fadeOut(1000)
        .queue(showNext);
    })();

    ??
    Ответ написан
    1 комментарий
  • Как сделать распределение слов по ячейкам таблицы?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Закрутите слова спиралью от краёв к центру. Типа так:

    |о|д|и|н|
    |е|т|ы|д|
    |ч|е|р|в|
    |и|р|т|а|

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

    Как это может выглядеть:

    function makeTable(data) {
      data = data.join('').split('');
    
      let width = Math.sqrt(data.length) | 0;
      let height = (data.length / width) | 0;
    
      while (width * height !== data.length) {
        width--;
        height = (data.length / width) | 0;
      }
    
      const position = [ 0, 0 ];
      const directions = [
        [  1,  0 ],
        [  0,  1 ],
        [ -1,  0 ],
        [  0, -1 ],
      ];
      let direction = 0;
    
      const result = Array.from({ length: height }, n => Array(width).fill(null));
    
      for (const n of data) {
        result[position[1]][position[0]] = n;
    
        if (null !== (result[position[1] + directions[direction][1]] || {})[position[0] + directions[direction][0]]) {
          direction = (direction + 1) % directions.length;
        }
    
        position[0] += directions[direction][0];
        position[1] += directions[direction][1];
      }
    
      return result.map(n => n.join(' ')).join('\n');
    }

    Примеры использования:

    console.log(makeTable([ 'раз', 'два', 'три' ])); /*
    р а з
    р и д
    т а в
    */
    console.log(makeTable([ 'один', 'два', 'три', 'четыре' ])); /*
    о д и н
    е т ы д
    ч е р в
    и р т а
    */
    console.log(makeTable([ 'hello', ',', ' ', 'world', '!!' ])); /*
    h e
    ! l
    ! l
    d o
    l ,
    r  
    o w
    */

    Ответ написан
    Комментировать
  • Как остановить выполнение функции после алерта во всех элементах?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Можно вынести создание обработчика клика из цикла:

    const elems = document.querySelectorAll('div');
    
    function handler() {
      alert(123);
      elems.forEach(n => n.removeEventListener('click', handler));
    }
    
    elems.forEach(n => n.addEventListener('click', handler));

    Или применить делегирование:

    const elems = [...document.querySelectorAll('div')];
    
    document.addEventListener('click', function handler(e) {
      if (elems.some(n => n.contains(e.target))) {
        alert(123);
        document.removeEventListener('click', handler);
      }
    });
    Ответ написан
    Комментировать
  • Как убрать баг с множественными повторениями при ресайзе окна?

    0xD34F
    @0xD34F Куратор тега JavaScript
    У вас при каждом ресайзе >= 768 вешается обработчик клика. Было 600, стало 800 - повесили обработчик, ОК. Затем из 800 сделали 1000 - добавился ещё один обработчик. 1000 -> 900 -> 1000 -> 900 -> 1000 - добавили ещё четыре обработчика. Разумеется, все они вызываются при клике - отсюда и многократное открывание/закрывание.

    Как исправить? Решение в лоб: при каждом ресайзе снимать обработчик клика. То есть, делаете .off('click') не в else, а перед if (winW >= 768).
    Ответ написан
    1 комментарий
  • Как на js или jq кликнуть на первые 100 элементов HTML (начиная с верха страницы) id которых начинается на "oOR"?

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

    const selector = '[id^="oOR"]';
    const clickCount = 100;

    Кликаем:

    $(selector).slice(0, clickCount).click();
    
    // или
    
    [...document.querySelectorAll(selector)].slice(0, clickCount).forEach(n => n.click());

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

    из-за "одновременного" клика все виснет

    Может подскажете конструкцию с .delay() (или чем то аналогичным)

    Функция, с помощью которой можно обрабатывать массивоподобные объекты по частям с задержкой:

    function chunkedAndDelayed(data, delay, chunkSize, onChunk) {
      const getChunk = (data.slice || Array.prototype.slice).bind(data);
    
      (function nextChunk(i) {
        if (i < data.length) {
          onChunk(getChunk(i, i + chunkSize));
          setTimeout(nextChunk, delay, i + chunkSize);
        }
      })(0);
    }

    C каким интервалом и по сколько за раз надо кликать:

    const delay = 500;
    const clickChunkSize = 5;

    Кликаем:

    chunkedAndDelayed(
      $(`${selector}:lt(${clickCount})`),
      delay,
      clickChunkSize,
      $elems => $elems.click()
    );
    
    // или
    
    chunkedAndDelayed(
      Array.prototype.slice.call(document.querySelectorAll(selector), 0, clickCount),
      delay,
      clickChunkSize,
      elems => elems.forEach(n => n.click())
    );
    Ответ написан
    2 комментария
  • Как разбить ссылку на название файла и адрес?

    0xD34F
    @0xD34F Куратор тега JavaScript
    1. Можно порезать регулярными выражениями. JS, например:

    [
      'https://toster.ru/foto/cool/432rejfio23.jpg',
      'https://toster.ru/foto/f923jiwe.gif',
      'https://toster.ru/foto/new/1423.png',
      'https://toster.ru/foto/123a.jpg'
    ].map(function(n) {
      const [ , path, file ] = /(.+\/)([^\/]+)$/.exec(n);
      return { file, path };
    });

    2. Можно резать строку по позиции последнего "/":

    [
      'https://toster.ru/foto/cool/432rejfio23.jpg',
      'https://toster.ru/foto/f923jiwe.gif',
      'https://toster.ru/foto/new/1423.png',
      'https://toster.ru/foto/123a.jpg'
    ].map(function(n) {
      const lastSlash = n.lastIndexOf('/') + 1;
      return {
        file: n.slice(lastSlash),
        path: n.slice(0, lastSlash)
      };
    });

    На PHP будет примерно то же самое.
    Ответ написан
    Комментировать
  • Задача с селектором, как решить?

    0xD34F
    @0xD34F Куратор тега JavaScript
    <select id="country"></select>
    <select id="сity"></select>
    <p></p>

    const data = {
      'Франция': [ 'Париж', 'Марсель', 'Лион' ],
      'США': [ 'Вашингтон', 'Чикаго', 'Фарго' ],
      'Италия': [ 'Рим', 'Милан', 'Неаполь' ],
    };
    
    const country = document.querySelector('#country');
    const city = document.querySelector('#сity');
    const p = document.querySelector('p');
    
    country.addEventListener('change', e => {
      setSelectOptions(city, data[e.target.value]);
    });
    
    city.addEventListener('change', () => {
      p.innerText = [ country.value, city.value ].join(', ');
    });
    
    setSelectOptions(country, Object.keys(data));
    
    
    function setSelectOptions(selectEl, optionsData) {
      selectEl.innerHTML = optionsData.map(n => `<option>${n}</option>`).join('');
      selectEl.dispatchEvent(new Event('change'));
    }
    Ответ написан
    1 комментарий
  • Как сделать один обработчик для всех менюшек?

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

    1. Если клик был за пределами какого-либо выпадающего меню - закрываем их все
    2. Если клик был по кнопке открытия - открываем соответствующее ей меню

    const cardSelector = '.post';
    const buttonSelector = '.post > img';
    const menuSelector = '.post-info';
    const activeClass = 'active';
    
    document.addEventListener('click', ({ target: t }) => {
      if (!t.closest(menuSelector)) {
        document.querySelectorAll(menuSelector).forEach(n => n.classList.remove(activeClass));
      }
    
      if (t.matches(buttonSelector)) {
        t.closest(cardSelector).querySelector(menuSelector).classList.add(activeClass);
      }
    });
    Ответ написан
    2 комментария
  • В To-Do приложении таски отмечаются через один. Почему?

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

    UPD. Обработчики кликов на .goal и .delete надо вешать один раз, применяя делегирование:

    $('.todo-task').on('click', '.delete', function() {
      $(this).parent().remove();   
    });
    
    $('.todo-task').on('click', '.goal', function() {
      $(this).toggleClass('goal-check');
    });
    Ответ написан
    3 комментария
  • Как не обрабатывать клик по некоторым из вложенных элементов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Чьи клики не нужны:

    const selector = '.tr-class input[type="checkbox"]';

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

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

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

    for (const n of document.querySelectorAll('.tr-class')) {
      n.addEventListener('click', onClick);
    }
    
    function onClick(e) {
      if (e.target.matches(selector)) {
        return;
      }
    
      // ...
    }
    Ответ написан
    1 комментарий
  • Как можно короче записать тернарное условие?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Можно короче без тернарного оператора:

    myVariable && (myVariable - 35)

    Проверяем, действительно ли будем получать одно и то же:

    [100, 0, null, '', true, false, 'gdfsg'].map(n => [n ? n - 35 : n, n && (n - 35)]);
    /*
    0:(2) [65, 65]
    1:(2) [0, 0]
    2:(2) [null, null]
    3:(2) ["", ""]
    4:(2) [-34, -34]
    5:(2) [false, false]
    6:(2) [NaN, NaN]
    */

    Вроде похоже на правду.

    UPD. Можно с функцией, так длинное имя переменной будет использовано всего один раз:

    (n => n && (n - 35))(myVariable)
    Ответ написан
    Комментировать
  • Как решить проблему с датой для datepicker при чтении параметра из URL?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Как решить эту проблему?

    А что за проблема-то? День и месяц перепутаны - должно быть 6 сентября? Используйте moment.js. Можно задавать произвольный формат:

    moment('06.09.2017 16:16', 'DD-MM-YYYY HH:mm')

    Ну или вручную меняйте их местами, например:

    new Date('06.09.2017 16:16'.replace(/(\d+)\.(\d+)\.(\d+)/, '$3-$2-$1'))
    Ответ написан
    Комментировать
  • Почему не срабатывает триггер?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Не срабатывает потому, что обработчик события установлен не через jQuery. Отсюда и решение - создавать и отправлять событие вручную.

    Вместо $('select').val('ru').trigger('click'); пишем так:

    $('select').val('ru')[0].dispatchEvent(new Event('change'));
    Ответ написан
    1 комментарий