Задать вопрос
Ответы пользователя по тегу JavaScript
  • Tetris Series #1 — Scoring System?

    0xD34F
    @0xD34F Куратор тега JavaScript
    if (counting >= 10) {
       level++;
       counting = 0;

    Разница между 10 и counting (кроме 10, может принимать значения 11, 12 или 13) теряется - поэтому ваши результаты меньше ожидаемых. Может, не стоит считать каждую десятку отдельно? - сложновато как-то. Сделайте общую сумму, а на каждой итерации делите её на 10:

    function getScore(arr) {
      const points = [ 0, 40, 100, 300, 1200 ];
    
      let score = 0;
      let lines = 0;
    
      for (const n of arr) {
        score += points[n] * (1 + (lines / 10 | 0));
        lines += n;
      }
    
      return score;
    }
    Ответ написан
    Комментировать
  • Как найти и заменить в строке?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.away-players').text(function(i, text) {
      return $('.subs-players td:even')
        .get()
        .map(n => $(n).text().split(', '))
        .reduce((text, n) => text.replace(n[1], `(${n.join(' ')})`), text);
    });
    Ответ написан
    6 комментариев
  • Как на jQuery выполнить функцию после нескольких AJAX запросов?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Количество LI элементов заранее не известно, поэтому выполнять функцию WHEN с определенным количеством аргументов нет возможности.

    Согласиться с подобным утверждением - вот с чем нет возможности:

    $.when(...$('li').get().map(n => $.ajax())).then(/* выполняйте, чо там вам надо */);
    Ответ написан
    9 комментариев
  • Как с помощью proxy обратиться к несуществующему свойству объекта, созданного через class?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вместо this.data = new Proxy(... сделайте

    return new Proxy(this, {
      get(target, name) {
        return name in target
          ? target[name]
          : `Свойства ${name} нет`
      },
    });
    Ответ написан
  • Как правильно парсить URL параметры и вставить их в hidden inputs?

    0xD34F
    @0xD34F Куратор тега JavaScript
    for (const [ k, v ] of new URLSearchParams(url.replace(/.*\?/, ''))) {
      document.querySelector(`#${k}`).value = v;
    }

    или

    url
      .slice(url.indexOf('?') + 1)
      .split('&')
      .map(n => n.split('='))
      .forEach(n => document.getElementById(n[0]).value = n[1]);

    или

    const data = [...url.split('?').pop().matchAll(/([^&]+)=([^&]*)/g)];
    for (let i = 0; i < data.length; i++) {
      document.querySelector(`[id="${data[i][1]}"]`).value = data[i][2];
    }
    Ответ написан
    Комментировать
  • Регулярное выражение: цифры до любого символа. Как составить?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const id = /\d+(?=\?|$)/.exec(str)[0];
    
    // или
    
    const id = str.replace(/\?.*/, '').replace(/.*\D/, '');
    
    // или
    
    const id = str.split('?', 1).shift().split('-').pop();
    
    // или
    
    const [ id ] = new URL(str).pathname.match(/\d+/g).slice(-1);
    Ответ написан
    Комментировать
  • Как изменить элемент при наведении, не трогая остальные?

    0xD34F
    @0xD34F Куратор тега JavaScript
    .hover {
      opacity: 0.5;
    }

    const map = document.querySelector('.map svg');
    map.addEventListener('mouseover', onHover);
    map.addEventListener('mouseout', onHover);
    
    function onHover({ target: t }) {
      this.querySelectorAll('.hover-effect').forEach(n => {
        n.classList.toggle('hover', n !== t && this !== t);
      });
    }

    или, без js:

    .map:hover .hover-effect {
      opacity: 0.5;
    }
    
    .map:hover .hover-effect:hover {
      opacity: 1;
    }
    Ответ написан
    Комментировать
  • В чем отличие document.querySelectorAll() от document.getElementsByClassName()?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Если выводить в консоль то коллекции не чем не отличаются.

    Это не так. В первом случае HTMLCollection, во втором NodeList. Отличие первой от второго состоит в том, что

    HTMLCollection, хранящая элементы DOM, является динамической. При изменении документа она моментально отражает все произведённые изменения.

    То есть, обходите коллекцию, и одновременно модифицируете её. Удалили нулевой элемент - на его место встал первый, а индексу сделали ++. На следующей итерации удалять будете первый, и новый нулевой / бывший первый уже никуда не денется. Как и остальные элементы, изначально имевшие нечётные индексы.

    Как удалять элементы динамической коллекции без пропусков:

    // вариант раз - меняем направление обхода, от конца к началу:
    for (let i = elements.length; i--;) {
      elements.item(i).replaceWith();
    }
    
    // вариант два - удаляем нулевой элемент коллекции, пока он существует:
    for (let n; n = elements[0]; n.remove()) ;
    Ответ написан
    4 комментария
  • Как правильно создать 2 новых объекта из одного существующего?

    0xD34F
    @0xD34F Куратор тега JavaScript
    О каких свойствах идёт речь: const keys = [ 'a', 'd', 'e', 'f' ];.

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

    const obj1 = {};
    const obj2 = {};
    
    for (const k in obj) {
      if (obj.hasOwnProperty(k)) {
        (keys.indexOf(k) > -1 ? obj2 : obj1)[k] = obj[k];
      }
    }

    или

    const partition = (data, f) =>
      Array.prototype.reduce.call(
        data,
        (acc, n, i, a) => (
          acc[+!!f(n, i, a)].push(n),
          acc
        ),
        [ [], [] ]
      );
    
    const [ obj1, obj2 ] = partition(
      Object.entries(obj),
      n => keys.includes(n[0])
    ).map(Object.fromEntries);
    Ответ написан
    Комментировать
  • Как сделать всплывающее окно при клике на polygon?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.scheme-wrap polygon').click(function() {
      $(`.scheme-wrap__item[data-id="${this.dataset.id}"] .scheme-wrap__popup`).show();
    });

    или

    .scheme-wrap__popup.visible {
      display: block;
    }

    document.querySelectorAll('.scheme-wrap polygon').forEach(n => {
      n.addEventListener('click', onClick);
    });
    
    function onClick({ currentTarget: { dataset: { id } } }) {
      const selector = `.scheme-wrap__item[data-id="${id}"] .scheme-wrap__popup`;
      const popup = document.querySelector(selector);
      if (popup) {
        popup.classList.add('visible');
      }
    }
    Ответ написан
    Комментировать
  • Как обратиться к инпуту слева?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Если буквально искать элемент "слева", то перебираем предыдущие элементы относительно кликнутой кнопки, пока не наткнёмся на инпут:

    document.addEventListener('click', function(e) {
      if (e.target.classList.contains('sbros')) {
        for (let el = e.target; el = el.previousElementSibling;) {
          if (el.classList.contains('fields')) {
            el.value = el.getAttribute('default-value');
            break;
          }
        }
      }
    });

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

    document.addEventListener('click', ({ target: t }) => {
      if (t.matches('.sbros')) {
        const el = t.closest('здесь селектор обёртки').querySelector('.fields');
        el.value = el.getAttribute('default-value');
      }
    });

    Ещё вариант - можно вычислять индекс кликнутой кнопки и обращаться к инпуту с таким же индексом:

    const inputs = document.querySelectorAll('.fields');
    const buttons = [...document.querySelectorAll('.sbros')];
    buttons.forEach(n => n.addEventListener('click', onClick));
    
    function onClick(e) {
      const el = inputs[buttons.indexOf(e.target)];
      el.value = el.getAttribute('default-value');
    }
    Ответ написан
    Комментировать
  • Как разбить объект на несколько частей?

    0xD34F
    @0xD34F Куратор тега JavaScript
    На части какого размера надо порезать объект: const chunkSize = 10;.

    Режем:

    const arr = [];
    let i = -1;
    
    for (const k in obj) {
      const j = (++i / chunkSize) | 0;
      (arr[j] = arr[j] || {})[k] = obj[k];
    }

    или

    const chunked = (data, chunkSize) =>
      Array.from(
        { length: Math.ceil(data.length / chunkSize) },
        (n, i) => data.slice(i * chunkSize, (i + 1) * chunkSize)
      );
    
    const arr = chunked(Object.keys(obj), chunkSize).map(n => {
      return n.reduce((acc, k) => (acc[k] = obj[k], acc), {});
    });

    или

    function* chunked(data, chunkSize) {
      const iter = data[Symbol.iterator]();
    
      for (let chunk = [], n = {}; !n.done && (n = iter.next());) {
        if ((n.done && chunk.length) || (!n.done && chunk.push(n.value) === chunkSize)) {
          yield chunk;
          chunk = [];
        }
      }
    }
    
    const arr = Array.from(chunked(Object.entries(obj), chunkSize), Object.fromEntries);
    Ответ написан
    1 комментарий
  • Как получить нужный объект с другого?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Object.values(arr.reduce((acc, n) => {
      const k = n.value.fromVenueId.value;
      const v = n.value.totalUsers.value;
    
      (acc[k] = acc[k] || { fromVenueId: k, totalUsers: 0 }).totalUsers += v;
    
      return acc;
    }, {}))
    Ответ написан
    Комментировать
  • Почему не удаляюся итемы?

    0xD34F
    @0xD34F Куратор тега JavaScript
    event.target.tagName != 'button'

    Ясно:

    В XML (и XML-подобных языках) возвращаемое значение будет в нижнем регистре, а в HTML - в верхнем.

    Есть и менее явный косяк в этой проверке - все ли существующие на странице кнопки должны что-то там удалять? Даже если сейчас это так, будет ли так всегда? Лучше проверять наличие класса:

    event.target.classList.contains('remove-button')
    
    // или
    
    event.target.matches('.remove-button')
    Ответ написан
    Комментировать
  • Как сделать развертывание только в одной карточке?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сколько может быть элементов с одинаковыми id? - один. Там, где id повторяются, замените их классами.

    $('.show').click(function() {
      $(this).hide().next('.var').slideDown().find('.hide').show();
    });
    
    $('.hide').click(function() {
      $(this).hide().closest('.var').slideUp().prev('.show').show();
    });
    Ответ написан
    1 комментарий
  • Почему JS не находит элемент?

    0xD34F
    @0xD34F Куратор тега JavaScript
    У вас в школе по английскому была честная двойка, или давали взятки ради троек? Ну, то есть - откройте словарь, и посмотрите, как переводится слово "next". Потом посмотрите в каком порядке расположены ваши элементы.
    Ответ написан
    2 комментария
  • Как сделать минимальное значение один?

    0xD34F
    @0xD34F Куратор тега JavaScript
    rating = Math.max(1, Math.ceil((e.clientX - горизонтальнаяКоординатаЭлемента) / ширинаЭлемента * 5))

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

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вот метод группировки (не только массивов, но и любых итерируемых объектов):

    function group(data, key, val = n => n) {
      const getKey = key instanceof Function ? key : n => n[key];
      const getVal = val instanceof Function ? val : n => n[val];
      const result = {};
    
      for (const n of data) {
        const k = getKey(n);
        (result[k] = result[k] || []).push(getVal(n));
      }
    
      return result;
    }

    Как использовать в вашем случае:

    group(arr, 'room')
    // или
    group(arr, n => n.room)

    Но можно и так:

    group(Array(5).keys(), n => n % 2 ? 'нечётные' : 'чётные')

    Или так:

    group('a8-C!39', n => (
      n.toLowerCase() !== n.toUpperCase() ? 'буква' :
      !Number.isNaN(+n)                   ? 'цифра' :
                                            'другое'
    ))

    Или вот ещё вариант:

    <input name="xxx" value="69">
    <input name="xxx" value="187">
    <input name="xxx" value="666">
    <input name="yyy" value="-1">

    group(document.querySelectorAll('input'), 'name', n => +n.value)
    Ответ написан
    4 комментария
  • Как найти блок в котором находится другой блок с определенным классом?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $(this).closest('tr').prevAll('tr:has(.name-pnd)').first()

    https://jsfiddle.net/8odvzagr/
    Ответ написан
    Комментировать
  • Как вставить элемент несколько раз во все элементы с заданным классом?

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

    const containers = document.querySelectorAll('.counts');
    const tag = 'div';
    const className = 'count';
    const count = 3;

    Добавляем:

    const html = [...Array(count)]
      .map((_, i) => `<${tag} class="${className}">${i + 1}</${tag}>`)
      .join('');
    
    for (const n of containers) {
      n.insertAdjacentHTML('beforeend', html);
    }

    или

    for (let i = 0; i < containers.length; i++) {
      for (let j = 0; j < count;) {
        const el = document.createElement(tag);
        el.classList.add(className);
        el.innerText = ++j;
        containers[i].appendChild(el);
      }
    }

    или

    const fragment = document.createDocumentFragment();
    fragment.append(...Array.from({ length: count }, (_, i) => (
      Object.assign(document.createElement(tag), {
        textContent: -~i,
        className,
      })
    )));
    
    containers.forEach(n => n.append(fragment.cloneNode(true)));
    Ответ написан