Задать вопрос
Ответы пользователя по тегу JavaScript
  • Как жертве JQuery получить всех "детей" (элемент.childNodes[все дети]), неужели поочередным перебором?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Выбрать дочерние узлы первого уровня можно через contents(). Но понадобится рекурсия. Когда очередной узел текстовый, в нём можно менять содержание, но если он элемент, то надо внутрь него лезть тем же contents()

    RegExp'ы с глобальной заменой лучше простого replace на случай вставки Copy-Paste текста с большим количеством двойных дефисов, например. Поэтому же событие input, а не клавиатурные.

    Кроме того жо.. сложность выскочила с позицией курсора: при замене содержимого он сползает в начало узла. Ок, можно получить Selection и запомнить Range до всех замен и потом восстановить. Но тут кроется вторая засада: при замене меняется длина текста: два дефиса на одно тире. Поэтому нужно ещё и ловить изменение длины текста при замене в узле, в котором находится курсор.

    Вроде, получилось. Fiddle. Код:
    var curNode
    	  , startOffset
    	  , arrIN = ['--','<<','>>','->','<-']
    	  , arrOUT = ['—','«','»','→','←']
    	;
    	arrIN = arrIN.map(function(s){ return new RegExp(s,'g')});
    
    	$('#edit').on('input', onInput);
    	
    	function onInput() {
    		var selObj = window.getSelection()
    		  , range  = selObj.getRangeAt(0)
    		;
    		curNode = range.startContainer;
    		startOffset = range.startOffset;
    		$(this).contents().each(walk);
    		range.setStart(curNode, startOffset);
    	}
    
    	function walk(i, node){
    		var len
    		  , diff
    		;
    		if( node.nodeType === Node.TEXT_NODE) {
    			len = node.textContent.length;
    			node.textContent = replacer(node.textContent);
    			diff = len - node.textContent.length;
    			if( node === curNode && diff) {
    				startOffset -= diff;
    			}
    		} else if( node.nodeType === Node.ELEMENT_NODE) {
    			$(node).contents().each(walk);
    		}
    	}
    
    	function replacer(s) {
    		var i;
    		for( i = 0; i < arrIN.length; i++) s = s.replace( arrIN[i], arrOUT[i]);
    		return s;
    	}
    Ответ написан
    5 комментариев
  • Клики по ссылкам в сортировке?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Можно в глобальной переменной хранить значение активного элемента, а в data-атрибуте переключаемых пунктов записывать их текущее состояние сортировки.
    var active = undefined; // здесь будет jQuery( активный пункт )
    var $sortable = $('a.sortable'); // пунктов с сортировкой потом может быть больше 1
    $sortable.data('sort', true); // true == asc, false == desc
    
    $('a.clickme').on('click', function() {
      var $el = $(this);
    	$sortable.removeClass('asc').removeClass('desc'); // у всех убрать сортировку
    	if( $el.hasClass('sortable')) { // кликнули переключаемый пункт
    	  if( active && $el[0] === active[0]) { // он был уже активен
    			$el.data('sort', !$el.data('sort')); // изменили сортировку на другую
    			$el.addClass( $el.data('sort') ? 'asc' : 'desc') // переключили классы соотв.
    		  	.removeClass( $el.data('sort') ? 'desc' : 'asc');
    		} else {
    			$el.addClass( $el.data('sort') ? 'asc' : 'desc'); // просто добавили правильный класс
    		}
    	}
    	
    	if( active) active.removeClass('active'); // выключить предыдущий активный эл.
    	active = $el.addClass('active'); // включить активность кликнутого
    });


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

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Есть ли понимание того, какого вида функция должна в итоге получиться?
    Построил ваши точки на графике:
    1c9ba3cc0d9a4021b3c90e9d51532ba2.png
    То ли это экспериментальные данные, стремящиеся к линейной функции - тогда решать линейной регрессией.
    То ли кривая должна лечь точно по точкам, и тогда это может быть сумма синусоиды и линейной, или кривой какого-нибудь 6-го порядка.
    Ответ написан
    3 комментария
  • Как очистить массив не трогая свойства и методы?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Очистить массив, не трогая добавленные свойства и методы:
    ar.length = 0

    С вашими значениями (вы забыли return в методе sum()):
    var ar = [1, 2, 3];
    ar.sum = function() {
        return this.reduce(function(a, b) {
            return a + b;
        });
    }
    
    ar.length = 0;    // значений больше нет, но метод sum() остался
    ar.push(5, 6, 7); // добавляем новые значения
    ar.sum()          // 18
    Ответ написан
    Комментировать
  • Почему не работает такая конструкция?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Тернарный оператор возвращает значение. Это не то же самое, что if .. else

    условие ? выражение_1 : выражение_2 – эта конструкция принимает то или иное значение: выражение_1 или выражение_2.

    Нельзя ставить в тернарный оператор continue или return потому, что это не выражения, принимающие какие-то значения, а управляющие структуры.

    Если бы вы выбирали, что вернуть, можно было бы написать return isItTrue ? A : B;

    В вашем же случае выбора между return и continue годится только старый добрый if .. else
    Ответ написан
    4 комментария
  • Как получить значение id из объекта?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Попробуйте this.tracker.id
    Ответ написан
    1 комментарий
  • Как отобразить на сайте курсоры мышек посетителей?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Mozilla TogetherJS

    И забавная онлайн игра, где видны курсоры всех посетителей, и надо пройти лабиринт: cursors.io:
    4fc42d6cb91f4021a00100ef60bc116e.png
    Ответ написан
    Комментировать
  • Как строку преобразовать в объект?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Разбить в массив по точке-с-запятой. Затем каждый элемент разбить по запятой-с-пробелом в массив пар координат (они будут текстовыми строками "55.759906" и прогнать каждую через parseFloat чтобы стали числами:
    var coords = "55.759906, 37.622242;50.455898, 30.521481";
    coords = coords.split(';').map( e => e.split(', ').map(parseFloat));
    //[[55.759906,37.622242],[50.455898,30.521481]]
    
    // или вариант для старых браузеров:
    coords = coords.split(';').map( function(e){ return e.split(', ').map(parseFloat)});
    Ответ написан
    4 комментария
  • Какой библиотекой можно сделать круговые диаграммы и чарты?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    На чистом CSS можно сделать и такой кольцевой бар и «сосиски».

    D3js, по-моему, лучшая библиотека для графиков, но для этой задачи она перебор.
    Ответ написан
    Комментировать
  • Как правильно вывести определенное количество символов JQuery?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Использовать jQuery.each() (фиддл)
    var size = 30, blogContent = $('.block p');
    	blogContent.each(function(e){
    	  var $el = $(this), html = $el.html();
    		if( html.length > size) html = html.slice(0,size) + '&hellip;<a href="#" class="read-more-button">read more</a>';
    		$el.html(html);
    	});


    Но вообще это так-себе затея, т.к. может ломаться разметка – например, отгрызаться незакрытый тег.

    По-хорошему, надо либо убрать все теги, используя вместо .html() – .text(), либо ограничивать длину, урезая только содержание текстовых нод.

    p.s. вместо троеточия используйте html-entity &hellip;
    Ответ написан
    Комментировать
  • Как сделать бесконечную смену картинок?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Можно использовать остаток от деления i на число картинок:
    var i = 0;
        var image = document.getElementById("image");
        var imgs = new Array('play.png','pause.png','play.png','pause.png'); // Добавте свои картинки через запятую
        function imgsrc(){
          i++;
          image.src=imgs[i%imgs.length];
        }


    Если захотите притормозить смену картинок, можно так:
    var i = 0;
    var image = document.getElementById("image");
    var imgs = new Array('play.png','pause.png','play.png','pause.png'); // Добавте свои картинки через запятую
    function nextImage(){
      if(i++ >= imgs.length) i = 0; 
      image.src=imgs[i];
    }
    function imgsrc() { window.setInterval( nextImage, 500) }
    Ответ написан
    Комментировать
  • Как можно сделать счеты на jquery?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Можно ловить мышиные события и изменять координаты кликнутого блока (или пачки блоков).

    Сделал простой fiddle:
    var target, pos = {dx:0, dy:0};
    function onMouseDown(e){
    	target = $(e.target);
    	pos.dx = parseInt(target.css('left').replace('px','')) - e.pageX;
    	pos.dy = parseInt(target.css('top').replace('px','')) - e.pageY;
    }
    function onMouseMove(e){
      var dx, dy;
      if(!target) return;
    	target.css({
    	  left: (e.pageX + pos.dx) + 'px'
    	});
    }
    function onMouseUp(e){ target = undefined }
    
    $('.dragme').on('mousedown', onMouseDown);
    $('#container').on('mousemove', onMouseMove);
    $('#container').on('mouseleave', onMouseUp);
    $('.dragme').on('mouseup', onMouseUp);
    Ответ написан
    Комментировать
  • Js RegExp почему не всегда один результат?

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

    У экземпляра объекта Regexp есть свойство lastIndex, которое позволяет читать/писать индекс, с которого начнётся следующее сопоставление. Он поможет разобраться:
    var RE = /([A-z0-9])/g;
    console.log([
      RE.lastIndex, RE.test("aaaa"), // 0,true
      RE.lastIndex, RE.test("aaaa"), // 1,true
      RE.lastIndex, RE.test("aaaa"), // 2,true
      RE.lastIndex, RE.test("aaaa"), // 3,true
      RE.lastIndex, RE.test("aaaa"), // 4,false
      RE.lastIndex, RE.test("aaaa"), // 0,true
    ]);
    Ответ написан
    2 комментария
  • Как сократить код?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Логика не понятна, но код можно упростить так:
    var tRish = "tits_rish_a1 tits_rish_a2 tits_rish_a3";
    var tRishClasses = tRish.split(' ').map(e=>'.' + e).join(', '); // список классов .tits_rish_a1, .tits_rish...
    var tClick = "#tits_click_a1, #tits_click_a2, #tits_click_a3";
    $(function() {
    	
    	function onClick(e) {
    		var n = (n = this.id.match(/b(\d+)/)) ? n[1] : null; // n == 1, 2 или 3
    		if(!n) return;
    		
    		$(tClick).removeClass(tRish).addClass( 'tits_rish_a' + n);
    		// $(tClick).attr('id', 'tits_click_a' + n); // id менять некошерно!
    		$(tRishClasses).attr('style', '');
    	}
    	
    	$('#b1, #b2, #b3').on('click', onClick);
    });

    Одна функция обрабатывает клики. Определяет номер из id кликнутого элемента #b2 => 2 и далее использует полученный номер для составления классов/id.
    Ответ написан
    Комментировать
  • Как определить попадание точки в полигон?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    GeoQuery и searchInside() – вместо круга подсуньте многоугольник.
    Ответ написан
  • Как длинную строку разбить в массив по её переносам в контейнере?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Нетривиальный способ: добавлять исходный текст в элемент по одному слову, и смотреть за высотой элемента. Как только она скакнула – началась новая строка.

    Примерно так:
    var $el = $('h1');
    var s = $el.text().split(/\s+/);
    var i, h = {curr:0, prev:0}, parts = [], word, back=[];
    while(s.length) {
      word = s.shift();
      back.push(word);
      $el.html( back.join(' '));
      h.curr = $el.height();
      if( h.curr !== h.prev) {
        parts.push([]);
        h.prev = h.curr;
      }
      parts[ parts.length - 1].push(word);
    }
    parts = parts.map((e,i) => '<span class="row'+i+'">' + e.join(' ') + '</span>');
    
    $el.html(parts.join("\n"));

    CodePen
    92ae2d6459994d00a2d8745575845e03.png
    Ответ написан
    Комментировать
  • Как реализовать поиск до нужной позиции?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Найти значение «нужной позиции», взять подстроку исходной до этой позиции, искать в этой подстроке:
    function search( search, subject, before) {
      var limit = subject.indexOf( before);
      if( limit == -1) return -1;
      return subject.substr(0, limit).indexOf( search);
    }
    
    search( 'строка 2', 'строка 1 строка 2 строка 3 строка 4',  'строка 3') // 9


    upd. из комментариев. Если известна позиция, до которой искать, то ещё проще: str.substr(0,41).indexOf('что ищем')
    Ответ написан
    3 комментария
  • Как загрузить изображение в VK с помощью JavaScript?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Из браузера напрямую в ВК не получится. Из nodejs или Electron'а – запросто.

    Ключевой момент здесь – ответ сервера ВК на загрузку к ним файла картинки. Они отвечают без CORS-заголовков и браузер считает такой ответ небезопасным, делая его недоступным JS-скриптам.

    Загрузка файлов в ВК хорошо описана в их документации. Три шага:
    1. получить адрес сервера, принимающего картинку
    2. отправить туда картинку методом POST и получить ответ
    3. используя «ответ» сохранить фото в нужный альбом или на стену.

    Всё это легко делается и на JavaScript, вот только политика безопасности браузеров не позволяет получать ответ с чужого сервера, если тот не сопровождается специальными HTTP-заголовками. А ВК их не даёт из каких-то своих соображений «безопасности», как мне ответила их тех.поддержка:
    3e0bb81eb1264aa5995460f8930a3834.png

    Поэтому можно реализовать загрузку только через свой сервер.
    Ответ написан
    2 комментария
  • Как собрать такой массив из строки?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Может, не самый оптимальный вариант – заменить пробелы внутри скобок на какой-то символ, который в «нормальном» тексте точно не встретится. Например, специсимвол неразрывного пробела. После этого можно бить по пробелам, и после этого обратно заменить спец-символ на пробелы:
    function convert(s) {
    
      var c, i, bo = 0, div = "\u0083", arr = s.split('');
    
      for( i = 0; i < arr.length; i++) {
        c = arr[i];
        if( c === '[') {
          bo++;
        } else if( c === ']') {
          bo--;
        } else if( bo > 0 && c === ' ') {
          arr[i] = div;
        }
      }
    
      return arr
        .join('')
        .split(' ')
        .map( function(s){ return s.replace( new RegExp(div,'g'), ' ')})
      ;
    }
    
    var s = "слово1 слово2 [слово слово слово] слово3";
    convert(s) // ["слово1","слово2","[слово слово слово]","слово3"]
    Ответ написан
    Комментировать
  • Как сделать выборку по значениям полученым функцией?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Разбить пробелами в массив и взять 2-й элемент:
    $(".toolbar-bottom-count").text().split(' ')[1]
    Ответ написан
    2 комментария