Ответы пользователя по тегу JavaScript
  • Почему не срабатывает onload() на vk.com?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Так работает:
    var mdk_win = window.open('https://vk.com/mudakoff', 'mdk_win', 'width=600,height=400');
    mdk_win.addEventListener('load', function(){
      console.log('окно MDK загружено');
    });
    Ответ написан
    2 комментария
  • Как сравнить два массива и удалить из второго совпадающие элементы JS?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    arr2 = arr2.filter(e => !~arr.indexOf(e));
    // facebook.com,ya.ru


    Метод массива filter() создаёт новый массив, в котором остаются только те элементы исходного, для которых функция проверки вернула true.

    Внутри этой функции проверяем, есть ли очередной элемент в массиве arr: вернёт ли indexOf() что-то отличное от -1. Для короткой записи такой проверки удобно использовать побитовое НЕ ~ которое даст 0 в единственном случае, когда операнд равен -1. Его отрицание ! даст true в том же единственном случае. Итого эта функция вернёт true только, если элемент не найден в массиве arr.
    Ответ написан
    2 комментария
  • Как проверить существует ли переменная?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Так, как вы написали, ваш код имеет смысл в двух случаях:

    1. Внутри функции:
    function test(varbl) {
      varbl = varbl || 0;
      alert(varbl);
    }
    
    test();
    test( 100500);


    2. Вне функции, и вы должны были бы где-то выше:
    1. объявить эту переменную: var varbl;
    2. дать или не дать ей какое-то значение: if( Math.random() > 0.5) varbl = 100500;

    Тогда далее ваш код вполне будет работать, без ошибок и именно так, как вы и написали.
    Ответ написан
    Комментировать
  • Что делает функция JS?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Логическое И && принимает значение true в единственном случае – если оба операнда true.

    a && b проверяет по очереди: сначала, приводится ли к значению true первый операнд, a? Если нет, то дальше проверять нет смысла и выражение возвращает первый операнд, а.

    Если же a не пустой и при переводе в логическое true | false даёт таки true, то так же проверяется второе выражение, b.

    В вашем примере сначала проверяется, что там в jj. Если пустота, то более ничего не делается. Если же там, например, функция, то надо проверить и второй операнд. Для этого надо выполнить функцию jj(false).

    Таким образом, проверяется, не пусто ли jj, и если не пусто, то вызывается функция jj(false).
    Ответ написан
    Комментировать
  • Как можно переписать это код?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вместо return +a[attr] > +b[attr] ? 1: -1;
    можно return +a[attr] - b[attr];

    const sortFunc = function sortFunc(data, elem) {
    	switch( elem.getAttribute('name')) {
    		case 'id':
    		case 'salary':
    			data.sort((a, b) => +a[attr] - b[attr]);
    			break;
    		case 'user':
    		case 'position':
    		case 'gender':
    			data.sort((a, b) => a[attr] > b[attr] ? 1 : (a[attr] < b[attr] ? -1 : 0));
    			break;
    		default:
    			throw('Bad attribute');
    	}
    };
    Ответ написан
    Комментировать
  • В чем ошибка использования arguments функции?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Calc = function(){
      this.sum = function(){
        return Array
          .prototype
          .slice
          .call(arguments)
          .reduce(function(p,c){return +p+c}, 0)
      }
    }
    
    let c = new Calc;
    c.sum(2,4,6) // 12
    Ответ написан
    9 комментариев
  • Как повернуть многомерный массив на 45 градусов?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Для проверки диагоналей не нужно поворачивать матрицу на 45°, достаточно проверять сумму индексов:
    00 01 02
    10 11 12
    20 21 22

    Диагонали слева снизу вправо вверх:
    00        :  0+0 = 0
    10, 01    :  1+0 = 0+1 = 1
    20, 11, 02:  2+0 = 1+1 = 0+2 = 2

    И так далее. Сумма индексов в таких диагоналях постоянна. Максимум в правой нижней клетке составляет удвоенный макс. индекс.

    Чтобы проверить диагонали слева сверху вправо вниз, надо инвертировать индексы одного из измерений, напр. строк: не 0..N, а N..0
    var arr = [
      'o,x,x'.split(','),
      'x,o,o'.split(','),
      'o,x,o'.split(','),
    ];
    
    var r, c, key, diags = {};
    for(r = 0; r < arr.length; r++) {
      for(c = 0; c < arr[r].length; c++) {
        key = r + arr[r].length - 1 - c; // слева сверху вправо вниз
        // key = r + c; // слева снизу вправо вверх
        
        if( diags.hasOwnProperty(key)) {
          if( diags[key] !== arr[r][c]) diags[key] = false;
        } else {
          diags[key] = arr[r][c];
        }
      }
    }
    
    for( key in diags) if( diags[key] === false) delete diags[key];
    // {"0":"x","2":"o","3":"x","4":"o"}
    Ответ написан
  • Как сделать возврат значения из callback?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Функция user_params() отработает сразу и вернет null. А ответ от ВК будет получен когда-то потом и попадёт во вложенную функцию.

    Как вариант, передавайте третьим параметром функцию, которую позже вызовут и в которую передадут ответ ВК:
    function user_params(id, param, callback) {
      vk('users.get', {user_ids: id, fields: param}, function(error, response){
        if (error) {
          console.log(error);
        } else callback(response[0][param]);
      });
    };
    Ответ написан
    1 комментарий
  • Какой плагин использовать для реализации анимации?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вроде бы можно сделать целиком на CSS3.

    Понадобится картинка, которая при повторении даст такой узор – фигура в центре + 4 фрагмента по углам. Анимировать масштаб этого фона и расширяющуюся маску clip-path, которая сначала показывает только одну центральную фигуру, а затем расширяется и открывает весь экран. Ну и в прозрачность увести фон слегка.
    Ответ написан
  • Стоит ли изучить backbone js?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Чтобы никто не сломал себе ногу, стоит разобраться с модулями в JavaScript – начните использовать сборщик: Require.js или Webpack или Browserify. А код разделяйте в небольшие логически изолированные куски - модули – лежащие каждый в своём файле.

    Backbone.js в 2017 по-моему вполне актуален. Он не конкурирует с тем же React, который играет роль View в паттерне MVC. Посмотрите, например, реализацию простейшего TodoMVC на Backbone + React.
    Ответ написан
    Комментировать
  • Как округлить минуты в нужную сторону?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Получить минуты, округлить в большую сторону до 15-минутного значения, установить это значение минут:
    function roundTS(ts) {
      var D = new Date(ts);
      var m = 15 + Math.ceil( D.getMinutes() / 15);
      D.setMinutes(m);
      return D.getTime();
    }


    А если требуется именно с массивом минут, то примерно так:
    function roundMinArr( D, arr) {
      var i, m = D.getMinutes();  
      arr.sort((a,b)=>a-b);
      for(i in arr) {
        if( arr[i] < m) continue;
        D.setMinutes(arr[i]);
        return D;
      }
      D.setMinutes(60 + arr[0]);
      return D;
    }
    
    var D = roundMinArr( new Date('2017-08-16T12:17+03:00'), [0,15,35,44,59]);
    D.toString() // Wed Aug 16 2017 12:35:00 GMT+0300 (MSK)
    Ответ написан
    Комментировать
  • Как сделать при нечётном клике один звук, а при чётном другой?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Можно, как и просит ТС, прямо в HTML. При первом клике инициализировать массив из двух аудио, и переназначить функцию onclick:

    this.a=[
      new Audio('https://wav-library.net/sfx/mix/LightSwitch.mp3'),
      new Audio('https://wav-library.net/prmusic/rock/Run.mp3')
    ];
    this.f=()=>{ // это будет новый обработчик клика
      var cc=!!this.cc; // для краткости записи
      this.a[+!cc].pause(), // если предыдущий длинный играет - стоп его!
      this.a[+!cc].currentTime=0, // ..и перемотать на начало.
      a[+cc].play(), // играть новый
      this.cc=!cc // переназначить счётчик ( true | false )
    };
    this.onclick=this.f, // переназначить хэндлер клика
    this.f() // вызвать для первого клика принудительно

    CodePen

    HTML с этим скриптом будет такой:
    <td onclick="this.a=[ new Audio('https://wav-library.net/sfx/mix/LightSwitch.mp3'), new Audio('https://wav-library.net/prmusic/rock/Run.mp3')];
    this.f=()=>{var cc=!!this.cc;this.a[+!cc].pause(),this.a[+!cc].currentTime=0,a[+cc].play(),this.cc=!cc};
    this.onclick=this.f,this.f()">click me!</td>
    Ответ написан
  • Как достать нужное свойство из многомерного объекта?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    function getById( obj, id) {
      var i, found;
      if( obj.id === id) return obj;
      if( obj.hasOwnProperty('childGroups')) {
        for( i in obj.childGroups) {
          if( found = getById( obj.childGroups[i], id)) return found;
        }
      }
      return;
    }
    
    getById( obj,3) // {"id":3,"parentId":1,"childGroups":[{"id":6,"parentId":3},{"id":7,"parentId":3}]}
    Ответ написан
    Комментировать
  • Как посчитать количество букв или цифр?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    function countSymbols(s) {
      return s.split('').reduce(
        (p,c) => (p.hasOwnProperty(c)?p[c]++:p[c]=1, p), {}
      );
    }
    var r = countSymbols('hello'); // {"h":1,"e":1,"l":2,"o":1}
    Ответ написан
    Комментировать
  • Как достать значение объекта?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Вариант в лоб, плохой:
    function bad( obj, name) {
      return eval('obj.' + name);     
    }
    bad(r, 'foo.bar'); // 'value'


    Вариант чуть получше, проверяем на каждом шаге, есть ли такое свойство:
    function better( obj, name) {
      var parts = name.split('.'), i, cursor = r;
      
      for( i = 0; i < parts.length; i++) {
        if( !cursor.hasOwnProperty( parts[i])) throw('No such property: ' + parts[i]);
        cursor = cursor[parts[i]];
      }
      
      return cursor;
    }
    
    better(r, 'foo.bar'); // 'value'
    Ответ написан
    Комментировать
  • Рисование графиков, есть ли интересная статья или пример?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Графики === D3.js

    Можно рендерить в SVG с отличным интерактивом и идеальным качеством печати (вектор же!). Можно и в canvas, если бешеная инфографика с огромным числом элементов (скаттер-плот из десятков тысяч точек). Из минусов не низкий порог вхождения.
    Ответ написан
    Комментировать
  • Какая библиотека позволит отображать наполненность материалами по дням?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    D3js позволит. Но прямо готового решения под именно вашу задачу не подскажу, не видел.
    Ответ написан
    Комментировать
  • Как реализовать свою (желательно чистый js) или готовое решение?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Первоначальный вариант ответа с contentEditable
    Надо использовать div с contentEditable="true" и фоном, который даст подчёркивание.

    Фиддл.

    <div class="textfield" contentEditable="true">напиши-ка!
    </div>

    .textfield {
    	font-size:16px;
    	color:white;
    	min-height:16px;
    	line-height:20px;
    	width:200px;
    	border:1px solid #999;
    	background:  url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACtJREFUeNpiNDY2ZiAXMDFQAEY1j2oe1TyoNLNoOu0nX/P1fY4D42yAAAMA7aYDxR1GwC8AAAAASUVORK5CYII=')
    }
    body {background:#333; font-family:Arial, sans-serif}

    Upd. лушче всё-таки в данной задаче использовать TEXTAREA, т.к. это решает проблему paste'а HTML-разметки с форматированием, рушащим высоту строки. Брать при каждом изменении свойство scrollHeight и под него подгонять шагами высоту textarea. Fiddle
    <textarea rows="1" cols="20" id="ta1" class="textfield">напиши-ка!
    </textarea>

    var ta1 = document.getElementById('ta1');
    ta1.addEventListener('input', function(){
    	var rows = Math.ceil( ta1.scrollHeight / 20 ) - 1;
    	ta1.style.height = 20 * rows + 'px';
    });
    Ответ написан
  • Как повторить методы jQuery, например find(), closest() и т.д., на чистом JavaScript? Есть ли где-нибудь полные соответствия?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Прочитать исходники jQuery и вытащить только нужные методы.

    Например closest() определён в traversing.js:
    closest: function( selectors, context ) {
    		var cur,
    			i = 0,
    			l = this.length,
    			matched = [],
    			targets = typeof selectors !== "string" && jQuery( selectors );
    
    		// Positional selectors never match, since there's no _selection_ context
    		if ( !rneedsContext.test( selectors ) ) {
    			for ( ; i < l; i++ ) {
    				for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
    
    					// Always skip document fragments
    					if ( cur.nodeType < 11 && ( targets ?
    						targets.index( cur ) > -1 :
    
    						// Don't pass non-elements to Sizzle
    						cur.nodeType === 1 &&
    							jQuery.find.matchesSelector( cur, selectors ) ) ) {
    
    						matched.push( cur );
    						break;
    					}
    				}
    			}
    		}
    
    		return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
    	},

    Отсюда ещё надо распутать зависимости jQuery.find.matchesSelector() и jQuery.uniqueSort()
    Ответ написан
    Комментировать
  • Обертывание элемент jquery?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Через jQuery.each() обойти каждую ссылку внутри <li> внутри <ul> (по id).

    Регулярное выражение \(\d+\) совпадает с открывающейся скобкой, одной или несколькими цифрами и закрывающейся скобкой. Эту регулярку заменять на совпавший фрагмент в теге <span>:

    $('#catalog>li>a').each(function(){
      $(this).html( function(i,t){
        return t.replace(/(\(\d+\))/, '<span>$1</span>')
      });
    });
    Fiddle
    Ответ написан