Ответы пользователя по тегу JavaScript
  • Почему когда доходит до конца, требуется двойной клик и выдает ошибку?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    В вашем коде косяк в том значении, которое принимает i после обновления.
    Например, было 0.
    Нажали "Показать".i++, i++ // i === 2
    Нажали "Скрыть".
    Скрывается соответствующий текущему значению i===2 (0, 1, 2 - т.е. третий, он и так пока скрыт).
    i уменьшается на 1.
    Скрывается соответствующий нынешнему i===1 (т.е. второй, был видимым).
    И потом i становится равным 0. Остался видимым нулевой.
    Надеюсь, понятна причина видимости одного.
    Это лечится костылём: замените оба i-- на --i.
    Но это не устранит другой проблемы: i может уезжать в минус.

    Предлагаю держать переменную, определяющую сколько элементов сейчас видимы.
    И функцию, которая только исходя из этой переменной показывает/прячет нужное число элементов.
    код
    const divs = document.querySelectorAll('div')
    const length = divs.length;
    const btnShow = document.querySelector('.show')
    const btnHide = document.querySelector('.hide')
    
    function showVisible(visible) {
      const toShow = Math.min(visible, length);
    
      for (let i=0; i < length; i++) {
          divs[i].style.display = i < toShow ? 'block' : 'none';
      }
    }
    
    let visible = 0;
    showVisible(visible);
    
    btnShow.addEventListener('click', function () {
      visible = Math.min(visible + 2, length);
      showVisible(visible);
    });
    
    btnHide.addEventListener('click', function () {
      visible = Math.max(visible - 2, 0);
      showVisible(visible);
    });


    Ответ написан
  • При загрузке кода выполняется функция которая указана в addEventListener без клика по кнопке. Как исправить?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Так ведь передаётся не функция function(){...}, а выражение users.sort(...)
    Выражение, которое сразу же выполняется, чтобы получилось значение. И вот это значение будет (?) обработчиком события клика. Т.е. в этом коде предлагается по клику не функцию выполнить, а сортированный массив – даже не знаю, что с ним делать.

    Чтобы не сразу, оберните код в .. кхм .. функцию!
    button.addEventListener('click', function() {
      users.sort(
        function(a, b){
          return b.age-a.age
        }
      )
    });
    
    // или покороче
    button.addEventListener('click', () => users.sort((a, b) => b.age - a.age));
    Так только по событию клика массив, наконец, отсортируют.
    Ответ написан
  • Как передать значение константе без тернарного оператора?

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

    if - управляющая структура. Ничего не возвращает, ограничивает scope. Объявленная внутри нее константа наружу не выберется.

    Можно функцией:
    const example = (x => {
      if (x === 5) return "Tos";
      else return "ter";
    })(5);
    Ответ написан
  • Как отработать нажатие для массива кнопок?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Делегирование событий.

    Можно только слушать события на общем родителе, и проверять, есть ли искомый класс в кликнутом элементе:
    Ответ написан
  • Что лучше по производительность c массивами: поиск или хранить с по нужному индексу?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Для задачи, может, подойдут Set'ы (для уникальных значений)

    Напишите тесты на jsPerf.com для двух ваших вариантов и для сетов.

    Прогоните в разных браузерах, под разными ОС.
    Ответ написан
  • Как сбрасывать результат в js?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    По изменению одного из чекбоксов обновлять вычисления:$('#annun1, #diff1').on('change', computeValue);

    Но вообще микрокредитование сродни мошенничеству. Не связывались бы..
    Ответ написан
  • Блокировка кнопки до ввода данных в input?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Нужно сделать функцию, которая будет проверять и включать/выключать кнопку.
    Вызывать её по кажому изменению в инпутах:
    // элементы
    const in_1 = document.getElementById("input_1");
    const in_2 = document.getElementById("input_2");
    const btn = document.getElementById("btn");
    
    // функция проверки и вкл/выкл кнопки
    const check = () => btn.disabled =
      in_1.value.length < 3  ||  in_2.value.length < 3;
    
    // проверять при изменении инпутов
    in_1.addEventListener('input', check);
    in_2.addEventListener('input', check);
    
    // проверить разок в самом начале
    check();


    Фиддл:

    Сделал чуть более реалистично: чтобы минимум по 3 символа было в каждом инпуте.
    Ответ написан
  • Функция в качестве параметра?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Функция в JS – это тоже объект. Её можно назначить переменной, передать аргументом в другую функцию, вернуть как результат работы другой функции.

    // исходное определение:
    const flip(f) => (a, b) => f(b, a);
    
    // можно развернуть:
    function flip(sourceFunction) {
      return function(a, b) {
        return sourceFunction(b, a);
      }
    }
    Функция flip() принимает аргументом функцию. И возвращает новую функцию.

    Создаваемая-возвращаемая функция вызывает исходную с аргументами наоборот.

    можно разжевать
    function flip(f) {
      // ура, нам дали какую-то исходную функцию!
      var sourceFunction = f; // для красоты запишем её в свою переменную
      // можно и вызвать её при желании:  sourceFunction(4, 5)
      // но пока не будем. Рано. Ждём.
    
      // сделаем новую, хакерскую функцию
      var hackerFunc = function(a, b) {
        // тут пусть всю работу делает старая функция
        var result = sourceFunction(a, b);
    
        // стоп. Не то. Надо же аргументы местами поменять
        var result = sourceFunction(b, a);
    
        // хакерский результат
        return result;
      } // конец определения хакер-функции
      
      // вернём теперь хакер-функцию:
      return hackerFunc;
    }
    Вот как flip(f) возващает новую хитрую хакерскую функцию.

    Ответ написан
  • Какие есть способы по кадрам рисовать видео в canvas?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    А вот пример работы с видео в canvas – там налету меняют фон.

    Т.е. из AfterEffects выводите как обычное mp4 / h264 видео.
    Ответ написан
  • Зачем писать tooltipElem = null;?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    document.onmouseout = function(e) {
      if (tooltipElem) {
        tooltipElem.remove();
        tooltipElem = null;
      }
    };


    Чтобы при следующем событии mouseout условие if (tooltipElem) не проходило и не выполнялся лишний раз tooltipElem.remove()
    Ответ написан
  • Как создать такую паутинку на канвасе?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вот пример на D3js – интерактивный, реагирует на мышку. Реализация на SVG, но можно переписать и на canvas, если это так важно.

    index.html
    <!DOCTYPE html>
    <html>
    	<head>
    		<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/ >
    		<title>Smoothed Radar Chart</title>
    
    		<!-- Google fonts -->
    		<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,300" rel='stylesheet' type='text/css'>
    		<link href='https://fonts.googleapis.com/css?family=Raleway' rel='stylesheet' type='text/css'>
    
    		<!-- D3.js -->
    		<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
    		<script src="https://d3js.org/d3-path.v1.min.js" charset="utf-8"></script>
    		<script src="radarChart.js" charset="utf-8"></script>
    		<style>
    			body {
    				font-family: 'Open Sans', sans-serif;
    				font-size: 11px;
    				font-weight: 300;
    				fill: #242424;
    				text-align: center;
    				text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff, 0 -1px 0 #fff;
    				cursor: default;
    			}
    
    			.legend {
    				font-family: 'Raleway', sans-serif;
    				fill: #333333;
    			}
    		</style>
    	</head>
    	<body>
    		<div class="radarChart" style="display: inline-flex;"></div>
    		<div class="radarChart2" style="display: inline-flex;"></div>
    		<script>
    			//////////////////////////////////////////////////////////////
    			//////////////////////// Set-Up //////////////////////////////
    			//////////////////////////////////////////////////////////////
    
    			var margin = { top: 50, right: 80, bottom: 50, left: 80 },
    				width = Math.min(700, window.innerWidth / 4) - margin.left - margin.right,
    				height = Math.min(width, window.innerHeight - margin.top - margin.bottom);
    
    			//////////////////////////////////////////////////////////////
    			////////////////////////// Data //////////////////////////////
    			//////////////////////////////////////////////////////////////
    
    			var data = [
    				{ name: 'Allocated budget',
    					axes: [
    						{axis: 'Sales', value: 42},
    						{axis: 'Marketing', value: 20},
    						{axis: 'Development', value: 60},
    						{axis: 'Customer Support', value: 26},
    						{axis: 'Information Technology', value: 35},
    						{axis: 'Administration', value: 20}
    					]
    				},
    				{ name: 'Actual Spending',
    					axes: [
    						{axis: 'Sales', value: 50},
    						{axis: 'Marketing', value: 45},
    						{axis: 'Development', value: 20},
    						{axis: 'Customer Support', value: 20},
    						{axis: 'Information Technology', value: 25},
    						{axis: 'Administration', value: 23}
    					]
    				}
    			];
    
    			//////////////////////////////////////////////////////////////
    			////// First example /////////////////////////////////////////
          ///// (not so much options) //////////////////////////////////
    			//////////////////////////////////////////////////////////////
    			var radarChartOptions = {
    			  w: 290,
    			  h: 350,
    			  margin: margin,
    			  levels: 5,
    			  roundStrokes: true,
    				color: d3.scaleOrdinal().range(["#26AF32", "#762712"]),
    				format: '.0f'
    			};
    
    			// Draw the chart, get a reference the created svg element :
    			let svg_radar1 = RadarChart(".radarChart", data, radarChartOptions);
    
    			//////////////////////////////////////////////////////////////
    			///// Second example /////////////////////////////////////////
    			///// Chart legend, custom color, custom unit, etc. //////////
    			//////////////////////////////////////////////////////////////
    			var radarChartOptions2 = {
    			  w: 290,
    			  h: 350,
    			  margin: margin,
    			  maxValue: 60,
    			  levels: 6,
    			  roundStrokes: false,
    			  color: d3.scaleOrdinal().range(["#AFC52F", "#ff6600"]),
    				format: '.0f',
    				legend: { title: 'Organization XYZ', translateX: 100, translateY: 40 },
    				unit: '$'
    			};
    
    			// Draw the chart, get a reference the created svg element :
    			let svg_radar2 = RadarChart(".radarChart2", data, radarChartOptions2);
    		</script>
    	</body>
    </html>


    radarChart.js
    Ответ написан
  • Как делать регулярные выражения javascript?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    const re = /jsInterface.event\("user=(\d+);level/;
    let playerId;
    const scripts = document.querySelectorAll('script');
    for (let i = 0; i < scripts.length; i++) {
      const match = scripts[i].innerText.match(re);
      if (match) {
        playerId = +match[1];
        break;
      }
    }
    
    console.log(playerId)  // 4180878
    Ответ написан
  • Задачка с нахождением анаграмм в массиве?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    как можно улучшить данный код

    Избежать лишних действий.

    Например, незачем на каждом шаге снова разбивать и сортировать исходное слово – достаточно сделать это один раз:
    function anagrams(word, words) {
        const sample = word.split('').sort().join('');
        return words.filter(function (e) {
            return e.split('').sort().join('') === sample;
        })
    }


    Нет смысла проверять неподходящие по длине слова.
    function anagrams(word, words) {
        const length = word.length;
        const sample = word.split('').sort().join('');
        return words.filter(w => w.length === length)
            .filter(function (e) {
                return e.split('').sort().join('') === sample;
            })
    }


    P.S. я вот такое решение отправил. Сравнить длину. Привести к lowercase. Запоминать позиции, в которых найден очередной символ и дальше искать после этой позиции (если будут повторы этого же символа). Как только какой-то символ не найден – всё, не совпали.
    Код
    // write the function isAnagram
    var isAnagram = function(test, original) {
      const length = original.length;
    
      if (length !== test.length) return false;
    
      const A = test.toLowerCase();
      const B = original.toLowerCase();
      const dict = {};
    
      for (let i=0, char, pos; i < length; i++) {
        char = A[i];
        pos = B.indexOf(char, +dict[char]);
        if (!~pos) return false;
        dict[char] = pos + 1;
      }
    
      return true;
    };
    Ответ написан
  • Можно ли сделать сетеры для методов массива?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Может, переопределить метод на экземпляре?
    var a = [];
    a.push = function() {
      Array.prototype.push.apply(this, arguments);
      // todo
      console.log("QnA.habr");
    }
    
    a.push(5); // QnA.habr
    a.toString() // Array [ 5 ]
    Ответ написан
  • Как проверить, что переданный параметр это функция?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    typeof будет равен "function" и для Object, String, Date, например — что не входит в ваши планы.

    С другой стороны, если весь код ваш, то достаточно проверять на не-пустоту
    callback && callback();

    Библиотека UnderscoreJS так определяет, функция ли аргумент:
    Object.prototype.toString.call(callback) === '[object Function]'
    и для вас можно так:
    callback  &&  Object.prototype.toString.call(callback) === '[object Function]'  &&  callback();
    Ответ написан
  • Кто может пояснить код?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вызов inBetween(3, 6) возвращает не строку, не число, а функкцию.

    Можно длиннее записать:
    var daFunc = inBetween(3, 6); // daFunc это функция
    
    arr.filter(daFunc);

    Почти1 то же, что:
    var daFunc = function() {
      console.log(arguments);
    }
    
    arr.filter(daFunc);
    1«Почти» — потому, что контекст тут другой будет. Всякие a и b не будут определены.

    Или:
    function daFunc() { console.log(arguments); }
    
    arr.filter(daFunc);

    Или:
    arr.filter( function() { console.log(arguments); });


    В общем, arguments там никакой не внешний / родительский / фильтрованный, а свой собственный.
    С чем вызвали — то и получили. Вызвали в фильтре – аргументы фильтровские и получили.
    Ответ написан
  • Самый лучший по точности бесплатный сервис предоставляющий API для определения местоположения?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Может, Google Geolocation API посмотреть?

    Сам не пробовал. Уточните, в каких масштабах можно бесплатно пользоваться.
    Ответ написан
  • Как парсить элемент из другого сайта?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Незачем что-то парсить. ipinfo.io предоставляет API, есть бесплатный план (до 50 тыс. запросов в месяц)

    Например, с помощью jQuery, без авторизации можно получить IP, страну:
    $.get("https://ipinfo.io", function(response) {
      console.log(response.ip, response.country);
    }, "jsonp")


    Response содержит больше полей:
    {
      "ip": "134.209.xxx.xxx",
      "city": "Clifton",
      "region": "New Jersey",
      "country": "US",
      "loc": "40.8344,-74.1377",
      "org": "AS14061 DigitalOcean, LLC",
      "postal": "07014",
      "timezone": "America/New_York",
      "readme": "https://ipinfo.io/missingauth"
    }
    Ответ написан
  • Как записать это циклом?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    В исходном варианте с var переменная i в любых вызовах навешанных функций имеет последнее своё значение из цикла, равное длине experimentElem.

    Замените var на let:
    for (let i = 0; i < experimentElem.length; i++) {

    старый ответ
    Попробуйте так:
    [...experimentElem].forEach((el, i) => {
      el.addEventListener('mouseenter', event => gifElem[i].play());
      el.addEventListener('mouseleave', event => gifElem[i].pause());
    })
    Ответ написан
  • Почему для JS не создают новых директив в роде "use strict"?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вы можете использовать фичи ES6 без «лишних» полифиллов. Тем самым отсечёте всякие старые браузеры.
    Для личной сатисфакции добавить в начале кода якобы директиву:
    "Mr. Robot 2020";
    Ответ написан