Задать вопрос
Ответы пользователя по тегу JavaScript
  • Есть 2 input, как запретить ввод числа во второй, значение которого меньше первого?

    0xD34F
    @0xD34F Куратор тега JavaScript
    <input id="lower" type="number" value="100">
    <input id="upper" type="number" value="200">

    const lower = document.querySelector('#lower');
    const upper = document.querySelector('#upper');
    
    lower.addEventListener('input', function() {
      this.value = Math.min(this.value, upper.value);
    });
    
    upper.addEventListener('input', function() {
      this.value = Math.max(this.value, lower.value);
    });

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

    Можно сделать проверку после нажатия enter?

    updateValueOnEnter(lower, val => Math.min(val, upper.value));
    updateValueOnEnter(upper, val => Math.max(val, lower.value));
    
    function updateValueOnEnter(input, f) {
      input.addEventListener('keypress', ({ key, target: t }) => {
        if (key === 'Enter') {
          t.value = f(t.value);
        }
      });
    }
    Ответ написан
    4 комментария
  • Какое самое короткое выржение на JS, выдающее в результате True?

    0xD34F
    @0xD34F Куратор тега JavaScript
    в таблице рекордов (которую заполнял вручную автор по запросам на почту) были люди, выполнившие эту задачу за 1 символ. Вопрос: какой это был символ или как иначе они это сделали?

    Символ, полагаю, никакой - поскольку проверка решения выполняется на клиенте, просто подменили функцию или результат проверки через отладчик, ничего вручную автор там не заполняет. Можно и решение из 0 символов оформить как корректное.
    Ответ написан
    1 комментарий
  • Как корректно реализовать метод "battle" в моей мини игре?

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

    Во-вторых - фантастически козлиная реализация самого метода battle в целом. Почему этот метод должен знать о конкретных экземплярах Unit? Не должен. Что, при изменении состава команд полезете его исправлять? Это абсурд.

    Отсюда, кстати и происходит упомянутый вами "беспрерывный бой" - поскольку вы каждому члену обеих команд назначили в противники кого-то конкретного из другой команды раз и навсегда, то... как вы думаете, какова вероятность, что сразу всем членам одной команды удастся одолеть своих противников? - часто получается так, что в одной из команд жив один её участник, а в другой два - и они никак не взаимодействуют.

    Надо сделать так, чтобы участники команд не были привязаны к конкретному противнику раз и навсегда. Можно добавить в Team метод kick (аналогично таковому в Unit), где будет осуществляться выбор - кто кого атакует (например, участники команды по очереди атакуют случайного участника другой команды). Ну и соответственно, использовать этот метод в battle, типа так.
    Ответ написан
    2 комментария
  • JQuery UI datepicker - как увеличить количество option'ов для SELECT с выборов года?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Свойство yearRange.
    Ответ написан
    Комментировать
  • Почему для хелпера нужно создавать экземпляр?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Потому что методы принадлежат непосредственно экземпляру, а не конструктору. Хотите вызывать их у конструктора - ну так сделайте их его свойствами. Правда, не очень понятно, зачем тут вообще конструктор - пусть это будет простой объект, содержащий нужные методы:

    const random = {
      intFromInterval: (min, max) => Math.floor(Math.random() * (max - min)) + min,
      intFromZero: (max) => Math.floor(Math.random() * max),
    };
    
    console.log(random.intFromInterval(55, 66));
    Ответ написан
    Комментировать
  • Как сделать, чтобы NodeList.prototype.forEach заработал в Internet Explorer?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вариант раз, воспользоваться forEach'ем массива:

    Array.prototype.forEach.call(cards, function(cardDiv) {
      // ...
    });

    Вариант два, переписать через цикл for:

    for (var i = 0; i < cards.length; i++) {
      var cardDiv = cards[i];
      // ...
    }

    Вариант три - найти и добавить полифилл.
    Ответ написан
    1 комментарий
  • Как сделать скрывающиеся блоки?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.button').click(function() {
      const $this = $(this);
      const $content = $this.closest('.item').find('.block');
    
      if ($this.hasClass('closed')) {
        $this.removeClass('closed').html('Скрыть &#8593;');
        $content.slideDown();
      } else {
        $this.addClass('closed').html('Показать &#8595;');
        $content.slideUp();
      }
    }).click();
    Ответ написан
    1 комментарий
  • Как при нажатии на блок с id="какой-то текст" добавить стили к блоку, у которого class="такой же текст"?

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

    const container = document.querySelector('ul');
    const itemSelector = 'li';

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

    const randomStyles = () => ({
      'background-color': `#${(Math.random() * 0xFFFFFF | 0).toString(16).padStart(6, 0)}`,
      'padding-left': `${Math.random() * 100 | 0}px`,
    });

    .active {
      border: 3px dashed blue;
    }

    const update = (el, styles) => (
      Object.assign(el.style, styles),
      el.classList.toggle('active')
    );

    Ловить клики можно непосредственно на интересующих нас элементах:

    container.querySelectorAll(itemSelector).forEach(function(n) {
      n.addEventListener('click', this);
    }, function() {
      document.querySelectorAll(`.${this.id}`).forEach(function(n) {
        update(n, this);
      }, randomStyles());
    });

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

    container.addEventListener('click', ({ target: t }) => {
      if ((t = t.closest(itemSelector)) && container.contains(t)) {
        const styles = randomStyles();
        for (const n of document.getElementsByClassName(t.getAttribute('id'))) {
          update(n, styles);
        }
      }
    });
    Ответ написан
    1 комментарий
  • Как запускать воспроизведение аудио только тогда, когда предыдущий звук был проигран полностью?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сделайте очередь:

    const audio = new Audio();
    const queue = [];
    
    audio.onended = function() {
      if (queue.length) {
        audio.src = queue.shift();
        audio.play();
      }
    };
    
    function play(srcArray) {
      queue.push(...srcArray);
    
      if (audio.paused) {
        audio.onended();
      }
    }
    
    play([ '1.mp3', '2.mp3', '3.mp3' ]);
    Ответ написан
    2 комментария
  • Почему строка не меняется?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Нельзя строки в JS менять, строки неизменны, хотите строку с другим значением - создавайте новую.

    Ну и этот поиск индексов... Ерунда какая-то. Правильно так - сделать объект вида { 'символ': 'на что его надо заменить' }:

    const combine = (keys, values) =>
      keys.reduce((acc, n, i) => (acc[n] = values[i], acc), {});
    
    const enToRu = combine(trans[0], trans[1]);
    const ruToEn = combine(trans[1], trans[0]);

    Тогда "перевод" сведётся к чтению свойства объекта:

    const translate = (str, charset) => Array
      .from(str, n => charset[n] || n)
      .join('');
    
    
    translate(';jgf', enToRu) // 'жопа'
    translate('руддщб цщкдв!!', ruToEn) // 'hello, world!!'
    Ответ написан
    Комментировать
  • Как отследить изменение свойства объекта?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Вешаю на него сеттер...

    Не-а, не на него. Созданное ранее свойство вы перетёрли вызовом defineProperty, кроме того, вы не определяете геттер - отсюда и undefined.

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

    function test(m) {
      let money = m;
    
      Object.defineProperty(this, 'money', {
        get() {
          return money;
        },
        set(val) {
          alert(`Значение свойства money меняется с ${money} на ${val}`);
          money = val;
        },
      });
    }

    Или можно воспользоваться Proxy:

    function test(m) {
      this.money = m;
    
      return new Proxy(this, {
        set(target, prop, val) {
          alert(`Значение свойства ${prop} меняется с ${target[prop]} на ${val}`);
          target[prop] = val;
          return true;
        },
      });
    }
    Ответ написан
    4 комментария
  • Как повесить обработчик на несколько элементов?

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

    const container = document.querySelector('.container');
    const itemSelector = 'article';
    const buttonSelector = `${itemSelector} .btn`;
    const activeClass = 'active';

    Делегирование, назначаем обработчик один раз:

    container.addEventListener('click', e => {
      const button = e.target.closest(buttonSelector);
      if (button) {
        button.closest(itemSelector).classList.toggle(activeClass);
      }
    });

    Или каждой кнопке индивидуально:

    container.querySelectorAll(buttonSelector).forEach(function(n) {
      n.addEventListener('click', this);
    }, e => e.currentTarget.closest(itemSelector).classList.toggle(activeClass));
    Ответ написан
    Комментировать
  • Как собрать слово из букв?

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

    Куда: <div id="container"></div>.

    Как анимировать появление элементов:

    #container span {
      display: inline-block;
      white-space: pre;
      font-size: 40px;
      animation: span .2s ease-out;
    }
    @keyframes span {
      from {
        transform: translateX(500px);
        opacity: 0;
      }
      to {
        transform: translateX(0);
        opacity: 1;
      }
    }

    Как перебирать с задержкой массивоподобный объект:

    const forEachWithDelay = (arr, delay, callback) =>
      (function next(i) {
        if (i < arr.length) {
          setTimeout(() => (callback(arr[i]), next(-~i)), delay);
        }
      })(0);
    
    // или
    
    async function forEachWithDelay(arr, delay, callback) {
      for (let i = 0; i < arr.length; i++) {
        await new Promise(r => setTimeout(r, delay));
        callback(arr[i]);
      }
    }

    Вот так всё просто получается:

    forEachWithDelay(
      'hello, world!!',
      100,
      n => document
        .querySelector('#container')
        .insertAdjacentHTML('beforeend', `<span>${n}</span>`)
    );
    Ответ написан
    2 комментария
  • Как отсортировать массив по дате?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Сортируем существующий массив с помощью moment.js:

    arr.sort((a, b) => moment(b.date, 'DD.MM.YY') - moment(a.date, 'DD.MM.YY'));

    Собираем отсортированный новый без помощи сторонних библиотек:

    const newArr = arr
      .map(n => [ n, +n.date.split('.').reverse().join('') ])
      .sort((a, b) => b[1] - a[1])
      .map(n => n[0]);
    Ответ написан
  • Почему возникает ошибка "FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory"?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Ну, память кончилась. Потому что... так, представьте, что обрабатывается последний элемент вашего массива, и доходит очередь до вот этого:

    array[i+1]=true;

    Размер вашего массива увеличится, последний элемент перестанет быть последним, и цикл, вместо того, чтобы завершится, уйдёт на следующую итерацию. А там опять array[i+1]=true; (или array[i+1]=false;, в зависимости от условия) - массив снова увеличился, опять цикл не завершился, ну и так далее - массив будет жиреть до тех пор, пока станет невозможно выделить ему ещё памяти.

    UPD. Я так понял, речь об этой задаче.
    Решается вот прям совсем просто.

    Конечно, при использовании методов массива:

    const ops = {
      OR: arr => arr.some(Boolean),
      AND: arr => arr.every(Boolean),
      XOR: arr => !!arr.reduce((p, c) => p ^ c, 0),
    };
    
    const logicalCalc = (arr, op) => ops[op](arr);

    В противном случае код может серьёзно опухнуть:

    const ops = {
      OR(arr) {
        for (const n of arr) if (n) {
          return true;
        }
        return false;
      },
      AND(arr) {
        for (const n of arr) if (!n) {
          return false;
        }
        return true;
      },
      XOR(arr) {
        let result = false;
        for (const n of arr) if (n) {
          result = !result;
        }
        return result;
      },
    };

    Ответ написан
    Комментировать
  • Почему var name=null определяется как тип string?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Потому что объявляемая вами переменная name - глобальная, применительно к клиентскому javascript'у это означает, что она окажется свойством объекта window, у которого свойство name уже есть, и, как нам тут подсказывают, его значения могут быть только строками:

    window.name converts all stored values to their string representations using the toString method
    Ответ написан
    1 комментарий
  • Как работает аналог distinct?

    0xD34F
    @0xD34F Куратор тега JavaScript
    Прежде всего мне непонятно зачем происходит сравнение с index.

    Затем, что это сравнение для конкретного значения выдаст true ровно один раз - так как indexOf возвращает первый индекс, по которому можно найти элемент, равный указанному. То есть, если indexOf текущего элемента равен текущему индексу, значит элемент встречен впервые, и его надо оставить.
    Ответ написан
    3 комментария
  • Как найти нужный элемент удовлетворяющий условиям нескольких data-attr?

    0xD34F
    @0xD34F Куратор тега JavaScript
    $('.result').filter((i, { dataset: d }) => d.from <= id && id <= d.to)
    Ответ написан
    3 комментария