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

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    У элемента нет метода .colorAdd(), чтобы вызывать так, как вы написали. Вместо
    elem.colorAdd();
    можно сделать
    colorAdd.apply(elem);

    Это вызовет функцию colorAdd(), назначив её контекстом (значением this) переданный первым параметром elem и всё сработает так, как вы задумали. Фиддл.
    Ответ написан
    1 комментарий
  • Как последовательно вызвать промисы с минимальной задержкой?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Попытался разобраться с Promise и async/await. Примерно понял, благодаря вашему вопросу, документации и ответу Антон

    Чтобы для самого первого элемента не добавлялась задержка, сделал доп. условие:
    const delay = _ => new Promise(rs => setTimeout(rs, 3e3));
    
    async function notSoFast(promise) {
      result = await Promise.all([ promise, delay()]);
      return result[0];
    }
    
    async function runPromisesInSequence(promises) {
      for (let i=0; i<promises.length; i++) {
        if(i === 0) {
          console.timeEnd( await promises[0]);
        } else {
          console.timeEnd( await notSoFast(promises[i]));
        }
      }
    }
    
    function makePr(label, dur) {
      return new Promise(rs => {
        console.log('%s started', label);
        console.time(label); // начало отсчёта
        setTimeout(_ => {
          console.log('%s timer completed', label);
          rs(label);
        }, dur);
      });
    }
    
    runPromisesInSequence([
      makePr('r1', 1000),
      makePr('r2', 5000),
      makePr('r3', 0000),
    ]);
    /* Выводит:
    r1 started
    r2 started
    r3 started
    r3 timer completed
    r1 timer completed
    r1: 1005ms
    r2 timer completed
    r2: 5007ms
    r3: 8009ms
    */


    Fiddle
    Ответ написан
    Комментировать
  • Как вывести на JS 27 число текущего месяца и года в формате даты?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    var D = new Date();
    D.setDate(27);
    D.toString()
    Ответ написан
    Комментировать
  • Как выделить все символы русского алфавита на странице, при условии, что атрибуты некоторых элементов могут содержать его?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Нужно рекурсивно обойти всё DOM дерево и рассматривать только текстовые узлы. Регуляркой заменять один-или-несколько-подряд символов из кириллического алфавита (+пробелы, пожалуй) на них же, в обёртке из тега форматирования.
    Примерно так
    function replacer(el){
      var i, node, span;
      if(el.hasChildNodes()) {
        for(i=0; i<el.childNodes.length; i++) {
          node = el.childNodes[i];
          if(node.nodeType === Node.ELEMENT_NODE) {
            if( !!~['SCRIPT','NOSCRIPT'].indexOf(node.nodeName)) continue;
            replacer(node);
          } else if( node.nodeType === Node.TEXT_NODE) {
            if(node.nodeValue.match(/^\s+$/)) continue;
            span = document.createElement("span");
            span.innerHTML = node.nodeValue.replace(/([а-яА-Я]+)/ug, '<i>$1</i>');
            el.insertBefore(span, node);
            el.removeChild(node);
          }
        }
      }
    }
    
    replacer(document.body);

    Тут для простосты схалтурил и вообще каждый текстовый узел заменяю на <span>, чтобы просто innerHTML ему заменить.

    Fiddle
    Ответ написан
    Комментировать
  • Как выделить слово с цветом?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вместо клавишных событий можно слушать событие input – когда значение меняется.

    Две строки – образец и введённый текст – бить на слова по пробелам. Если последний введённый символ не пробел, то последнее введенное слово проверять пока рано. Несовпавшее слово заменяется на обёрнутое в тег.

    примерно так
    const dGet = document.getElementById.bind(document);
    const reSpace = /\s+/;
    const div = dGet('text');
    const text = div.innerText;
    const words = text.trim().split(reSpace);
    dGet('text_input').addEventListener('input', function(e){
      var i, myWords = e.target.value.trim().split(reSpace),
      theWords = words.slice();
      var toCheck = e.target.value.substr(-1) === ' ';
      if(!toCheck) myWords.length--;
      for(i=0; i<Math.min(myWords.length, words.length); i++) {
        if(words[i] !== myWords[i]) {
          theWords[i] = '<i>' + words[i] + '</i>';
        } else {
          theWords[i] = '<b>' + words[i] + '</b>';
        }
      }
      div.innerHTML = theWords.join(' ');
    });
    Fiddle
    Ответ написан
    Комментировать
  • Как запретить выполнение функций на определенном этапе?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Создайте переменную, описывающую состояние. Состояния может быть два: Выбор или Проверка.

    В функциях проверяйте, какое нынче состояние.
    1. rrr() может работать только в Выборе;
    2. ggg() – в Выборе;
    3. yyy() – переключает класс в любом состоянии и меняет состояние.

    И кнопка переключает состояния. Если сейчас 1, то в 2; а если 2, то в 1.

    примерно так
    const STATE_SELECT = 1;
    const STATE_CHECK = 2;
    var state = STATE_SELECT;
    
    var rrr = function() {
      if(state === STATE_CHECK) return;
      $(this).toggleClass("red");
    };
    var ggg = function() {
      if(state === STATE_CHECK) return;
      $(this).toggleClass("green");
    };
    var yyy = function() {
      $(".green").toggleClass("yellow");
      if(state === STATE_CHECK) {
        state = STATE_SELECT;
      } else {
        state = STATE_CHECK;  
      }
    };
    
    $("div").hover(rrr);
    $("div").click(ggg);
    $("button").click(yyy);
    Фиддл
    Ответ написан
    2 комментария
  • Бегущая линия по лендингу?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Прорисовку линии делают с помощью SVG и анимации длины и положения штриха. Линию делают не сплошной, а пунктирной, и длину этого одного пунктира соразмерной длине всей линии.
    Ответ написан
    Комментировать
  • Код не работает, что не хватает?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Просто уберите function start() { и закрывающую } в конце : )

    Сам JS должен располагаться внизу документа прямо перед </body></html>

    fiddle
    Ответ написан
    Комментировать
  • Как сделать плавное перемещение элемента по нажатию клавиш?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Такое поведение происходит из-за того, что вы ловите событие нажатия, и из-за настроек компьютера.

    Точно так же в любом текстовом поле, если нажать букву и держать, она сначала появится один раз, затем пауза, затем она станет добавляться с регулярной частотой.

    Вместо этого используйте состояния. Когда клавишу нажали, игра перешла в состояние «едем вверх» например. И по таймеру или requestAnimationFrame() обновлять координаты игрока и дисплей.

    Когда клавишу отпустили, игра перешла в состояние «всё, не едем».
    Примерно так
    var player = {x:200, y:200, el:document.getElementById('player')};
    player.el.style.left = '' + Math.round(player.x) + 'px';
    player.el.style.top  = '' + Math.round(player.y) + 'px';
    
    var delta = {x:0, y:0};
    
    document.addEventListener('keydown', function(e){
      if(     e.key == 'ArrowRight') delta.x = 1;
      else if(e.key == 'ArrowLeft')  delta.x = -1;
      else if(e.key == 'ArrowUp')    delta.y = -1;
      else if(e.key == 'ArrowDown')  delta.y = 1;
    });
    
    document.addEventListener('keyup', function(e){
      if(     e.key == 'ArrowRight') delta.x = 0;
      else if(e.key == 'ArrowLeft')  delta.x = 0;
      else if(e.key == 'ArrowUp')    delta.y = 0;
      else if(e.key == 'ArrowDown')  delta.y = 0;
    });
    
    var ts = null;
    function step(timestamp) {
      if(!ts) ts = timestamp;
      var passed = timestamp - ts;
      //if(passed < 200) return window.requestAnimationFrame(step);
      ts = timestamp;
      if(delta.x || delta.y) {
        player.x += delta.x * passed / 10;
        player.y += delta.y * passed / 10;
        player.el.style.left = '' + Math.round(player.x) + 'px';
        player.el.style.top  = '' + Math.round(player.y) + 'px';
      };
      window.requestAnimationFrame(step);
    }
    
    window.requestAnimationFrame(step);


    При таком подходе можно одновременно зажимать, скажем, стрелку влево и стрелку вверх – точка поедет по диагонали.
    Фиддл.
    Ответ написан
    Комментировать
  • Как отслеживать состояние элемента в JavaScript?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Варианты:

    1. Хороший-быстрый-правильный: обойтись правилами CSS.
    2. MutationObserver
    3. Плохой-медленный-костыль: зарядить setInterval() и проверять свойства элемента пару раз в секунду.
    Ответ написан
    Комментировать
  • Как отменить изменения в DOM сделанные на js?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Ситуация выглядит как-то неправильно. Обычно либо стилями добиваются разного отображения на разных дисплеях – посмотрите, к примеру, Bootstrap – либо делают вообще отдельную разметку для мобилок и десктопов на разных поддоменах.

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

    Ещё можно держать исходную разметку в невидимом теге <script type="template" id="sourceCode">. Скриптом копировать её оттуда, применять изменения и вставлять в DOM. При изменении размера, снова доставать нетронутую исходную разметку и переделывать под другую ширину.
    Ответ написан
    1 комментарий
  • Как завершить выполнение скрипта на jquery?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    $('body').on('beforeSubmit', 'form', function(){
    тут вешается слушатель события перед отправкой формы на верхний элемент DOM'а, <body>. С закрытием модального окна он не исчезает и слушатель, повешенный на него, остаётся.

    Следующее открытие модального окна повесит на body ещё один слушатель – уже два.

    Попробуйте .on(...) заменить на .one(...) – это костыль, т.к. если форму не отправят, а только закроют модалку, в следующий раз отправится дважды.

    Правильно – делать .off() при закрытии модалки.
    Ответ написан
  • Как задать начальное положение танку?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Поменяйте местами две строчки, чтобы стало:
    .startWith(config.playerInitCoords)
    .scan(cords)


    Фиддл
    Ответ написан
    Комментировать
  • Как мы num получаем, ведь в цикле есть только i и arr.length?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    С каждым шагом цикла num увеличивается на 1.

    Вообще цикл здесь не нужен. Вместо for{ ... } достаточно num = arr.length; или вообще всю функцию
    сократить
    function func() {
      var num = this.value.split(' ').length;
      document.getElementById('result').innerHTML = num;
    }


    Ещё хорошо бы отрезать лишние пробелы по краям строки и считать несколько пробелов как один:
    function func() {
      var num = this.value.trim().split(/\s+/).length;
      document.getElementById('result').innerHTML = num;
    }

    Фиддл.
    Ответ написан
  • Как понимать такое объявление переменных: var = var = false?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    «А — ассоциативность»

    Ассоциативность определяет порядок, в котором обрабатываются операторы с одинаковым приоритетом. Например, рассмотрим выражение:

    a OP b OP c

    Левая ассоциативность (слева-направо) означает, что оно обрабатывается как (a OP b) OP c, в то время как правая ассоциативность (справа-налево) означает, что они интерпретируются как a OP (b OP c). Операторы присваивания являются право-ассоциативными, так что вы можете написать:

    a = b = 5;

    с ожидаемым результатом, что a и b будут равны 5. Это происходит, потому что оператор присваивания возвращает тот результат, который присваивает. Сначала b становится равным 5, затем a принимает значение b.
    Ответ написан
    Комментировать
  • Как из массива сделать новый массив-матрицу, создав столбцы и колонки?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Как я понял, длина входного массива всегда на 1 меньше квадрата целого. Иначе не получится, дописав один ноль, получить квадратную матрицу.

    Округляем в большую сторону квадратный корень из длины входного массива – это будет сторона квадратной матрицы. Проверяем, что длина всего на 1 отличается от квадрата.

    Старый вариант в лоб

    Дальше перебор строк и столбцов и наполнение.
    function toMatrix(arr) {
      const len = arr.length;
      const side = Math.ceil( Math.sqrt(len));
      if( side * side - len !== 1) throw "Bad array length";
      let result = [], index;
      for(let row = 0; row < side; row++) {
        result.push([]);
        let currentRow = result[result.length - 1];
        for(let col = 0; col < side; col++) {
          index = side * row + col;
          if(index > len) break;
          if(index === len) {
            currentRow.push(0);
          } else {
            currentRow.push(arr[index]);
          }
        }
      }
      
      return result;
    }
    
    
    toMatrix([1,2,5]) // [[1,2],[5,0]]
    toMatrix([1,2,3,4,5,6,7,8]) // [[1,2,3],[4,5,6],[7,8,0]]


    Upd. незачем по одному копировать элементы, надо орудовать целыми строками )
    function toMatrix(arr) {
      const len = arr.length;
      const side = Math.ceil( Math.sqrt(len));
      if( side * side - len !== 1) throw "Bad array length";
      let result = [];
      for(let row = 0; row < side; row++) {
        result.push( arr.slice(side * row, side * (row+1))); // выкусываем подряд строку, side элементов
      }
      result[side - 1].push(0); // в последниюю строку дописываем 0
      
      return result;
    }
    
    toMatrix([1,2,5]) // [[1,2],[5,0]]
    toMatrix([1,2,3,4,5,6,7,8]) // [[1,2,3],[4,5,6],[7,8,0]]
    Ответ написан
    4 комментария
  • Как создать список всех id, с которыми у меня диалог в vk через группу?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Метод messages.getDialogs() поможет.
    Вызывать с ключом доступа Сообщества с правами messages.
    Ответ написан
    Комментировать
  • Можно ли получить доступ к объекту?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Без перебора, в общем случае, способа нет.

    Но вы можете добавить индекс (словарь) и при занесении внутренних объектов записывать в индекс пары
    значение_поля_внутреннего_объекта: ключ_внешнего_объекта


    Примерно так
    var house = {}; // внешний объект
    var names = {}; // доп. словарь для поиска
    function add(num, flat) {
      house[num] = flat; // добавили внутренний объект
      names[flat.name] = num; // запись для поиска в словарь
    }
    
    add(11, {name:"Vasya", phone:"555-111", area:111, price:1111});
    add(22, {name:"Lena", phone:"555-222", area:222, price:2222});

    Чтобы найти свойство, под которым записан объект, смотрите в "словаре":
    names["Lena"] // 22
    
    function get(name) {
      return house[ names[name]];
    }
    
    get("Lena") // {name:"Lena", phone:"555-222", area:222, price:2222}


    Хотя проще сделать просто словарь значение_поля: сам_внутренний_объект
    Ответ написан
    Комментировать
  • Какова суть генерации своих событий в JavaScript?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Попробую на пальцах объяснить.

    Событие – это конверт, на котором написано его название. Внутрь конверта можете вложить что-нибудь, а можете оставить конверт пустым.

    Элемент – это столик. Кто угодно может подойти и положить на столик свой конверт.

    Слушатель – это мужик, который топчется около столика и смотрит, нет ли чего с интересующим его названием. Может несколько человек поджидать конвертики с определённым названием – прочтут все, если только в конверте не написано «по прочтении съесть» – тогда кто-то съест и дальше не передаст.

    Как создать/отправить конверт. В любом месте кода создайте конверт и дайте ему название: var myEvent = new Event('teaTime'); Остается положить конверт на нужный столик:
    document.getElementById('stolik').dispatchEvent(myEvent);


    Чтобы в событие вложить какие-то данные, нужно использовать другой конструктор и передать нагрузку в поле detail:
    var event = new CustomEvent('saySomething', { detail: "Hello there!" });


    Для чего нужно создавать свои события? Чтобы развязать куски кода. Например, в разных местах документа можно нажать на кнопку повторяющегося виджета. Виджет создаст на document событие "widgetClicked". А ещё несколько одинаковых компонентов в странице, слушающих document на предмет события "widgetClicked", получат пинок и что-нибудь вытворят.
    Ответ написан
    2 комментария
  • Почему так происходит "data.foreach is not a function"?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Дело в том, что массив фильмов, если посмотреть, содержится не в корневом объекте ответа, а в поле results.

    Т.е. вам надо поменять на:data.results.forEach( film => {
    Ответ написан