jQuery: разширени селектори

Много често, като пиша JS код се опитвам да съм максимално ясен, когато пиша selector (jquery.com/selectors)-и.

Оказа се обаче, че това не е много много добра идея.

В Telemaniac TV Guide, трябваше да се покаже диалог с ~190 ТВ канала, от които потребителя да може да избере любимите си и за тях да вижда програмата за деня. Най-правилното решение (на пръв поглед) беше да дам точния път на селектора до елемента, който ми трябва от рода на:

$("#selectbox").bind("keydown", function() {
	$("ul > li > label > input[name=" + channelName + "]", container).each(
		function(k,v) { .... }
	);
}

При което очаквах директно да се насочи на правилното място..обаче, се оказа, че само докато напиша “btv” в текстовото поле това отнемаше 3+ секунди, с изродски “бъгвания” на целия Firefox. Принципно, в Safari няма проблем, но нали Firefox-a е неграмотен да се оправи с РАМ-а и CPU-то (предвид, че има 6ГБ рам на разположение и quardcore процесор…), всичко се бъгна. Няма лошо в това, дори супер – подксазва, че има нещо което не работи както трябва. И такав profile таб-а, се оказа, че има функция POS(), която заемаше 3500 ms. Като погледнах, се оказа че това е функцията, която парсва selector-ите.

Ок, понеже ги имам данните в hash реших тях да обхождам и само да крия и показвам ненужните елементи, пак трябваше да ги търся из кода, но пак реших, че като търся точно по tag и name, всичко ще е мн по-бързо. Да ама не:

$("input[name=" + channelName + "]", container).css("display", "...");

Пак 3 секунди. След още 45минути ровене из хода на jQuery, дебъгване и профилиране, се оказа че проблема е в “разширения” селектор “[name=...]“. Съотвеното решенние, което сглобих, като най-бързо:

$("input", container).each(function(k,v) {
	var elm = $(v).parent().parent();
	var name = $(v).getAttr("name");
	if(globalHash[name].search(srchVal.toLowerCase()) == -1)
		elm.css("display", "none");
	else
		elm.css("display", "block");
});

* Относно какво е това “POS”, прегледайте кода на jQuery (проблема идва от частта с preFilter-и, има доста Regular Expression и т.н…, така че има
неща които по-добре да не ползвате, при огромен html)

sourcecode
  • Христо Манолов

    Абе това с onkeydown е много грубо бе, спорд мен грешката е в подхода ти, не в jQuery — първо, сложи му един timeout и почни да търсиш елемента чак след като човека е спрял да пише (виж други autocomplete решения как са направени)… и второ, “разширени селектори” за намиране на поле по името му ? Айсиктир ;) Защо просто не направиш form.elements[channelName] — това работи още от първите дни на JavaScript в далечната 1996 година ;)

  • http://twitter.com/man0l man0l

    Мерси за споделеният опит ;)

  • http://lpetrov.mylo.bg/ Lyubomir Petrov

    Timeout-a може да свърши работа и бих го ползвал ако имам XHR/AJAX Request, но когато данните са вече налични…защо да не реагира по-бързо (веднага) ? :)
    За извикването на елементите с form.elements[...] e ок, но в случая търсенето е на друго място (в един прост масив). Примера, които съм дал е опростена демонстрация на проблема с selector-ите :)

  • http://www.facebook.com/people/Radoslav-Stankov/100000310792884 Radoslav Stankov

    Интересно, работещото приложение е станало доста добре :)

  • http://marto.lazarov.org/ Мартин Лазаров

    Макар и една година по-късно все пак:
    както Христо е отбелязал трябва да има timeout – дори и да е нещо от сорта на 50-100мс (което потребителя дори няма да усети). Това, че е локално не означава, че е бързо. Всъщност изпълнението на нещо по-бързо от 3-4-5мс в javascript е невъзможно от там и се натрупват много забавяне по трасето.

blog comments powered by Disqus