JavaScript je ZLO 2.0

nenávistné poznámky vzteklého kodéra

Vyhledávání v DOMu na trojí způsob

Vyhledávání HTML elementů v DOMu se používá prakticky neustále. Jeho implementace přímo v prohlížečích je ovšem natolik pitomá že prakticky každý Javascriptový framework si tohle řeší po svém. V tomto příspěvku předvedu jak tyto věci řeší knihovny lib.elm, jQuery a Yahoo UI.

Vyhledání elementu podle id

Nalezení elementu podle jeho id je nejjednodušší - id musí být unikátní, máme tedy jistotu že bude nalezen právě jeden HTML element.

Knihovna lib.elm na to jde přímočaře:

var myElm = lib.elm.get("myElm");

V jQuery pracuje vyhledávání podobně jako v CSS,takže v tomto případě můžeme jako parametr vyhledávání zadat přímo CSS selektor:

var myElm = jQuery("#myElm").get();

V YUI je nalezení elementu podle id také jednoduché:

var myElm = YAHOO.util.Dom.get("myElm");

Vyhledání skupiny elementů podle třídy

Někdy je potřeba najít celou skupinu HTML elementů. Tak jako pro jednoznačnou identifikaci elementu používáme id, pro identifikaci skupiny elementů používáme atribut class (v JS píšeme className neboť class je rezervované slovo). Element může patřit i do více tříd, v takovém případě atribut class obsahuje jejich seznam, oddělovačem je mezera. Protože “vestavěná” implementace DOMu v prohlížečích nezná žádnou metodu “getElementsByClassName” (což osobně považuji za závažnou chybu), musejí vyhledávací funkce procházet DOM a to může být dost pomalé. Rozumný postup je vyhledávání co nejvíce omezit což nám všechny tři knihovny umožní.
V příkladu budeme hledat všechny DIVy z elementu #myElm které patří do třídy myCls:

Knihovna lib.elm:

var myElmCollection = lib.elm.getByClass("myCls", lib.elm.get("myElm"), "div");

jQuery sice exceluje svou stručností, ale nejsem si jistý jestli to není na úkor výkonu (zajímalo by mě jestli někdo má nějaké testy výkonu jQuery…):

var myElmCollection = jQuery("div.myCls", "#myElm").get();

Yahoo UI je obšírný jako obvykle (ale kdo by s tím chtěl dělat víc tak si jistě rychle udělá aliasy):

var myElmCollection = YAHOO.util.Dom.getElementsByClassName("myCls", "div", YAHOO.util.Dom.get("myElm"));

Obecné vyhledání skupiny elementů

Někdy je potřeba vyhledávat elementy podle jiných atributů než je tag, id či class. To je obecně vzato dosti pomalé takže se takovému vyhledávání snažte vyhnout seč to půjde.
Jako příklad jsem zvolil vyhledání všech SELECTů z formuláře #myForm, které mají nastaven atribut multiple, tzn. lze z nich vybrat více než 1 položku:

Knihovna lib.elm využívá pro vyhledávání literálové masky kompatibilní s formátem JSON. Protože nechceme detekovat přímo nějakou konkrétní hodnotu atributu multiple ale jen jeho přítomnost, použijeme v masce hodnotu true:

var myElmCollection = lib.elm.find( { "tagName": "select", "multiple": true }, lib.elm.get("myForm") );

jQuery je jako vždy stručný, tentokrát však o troško méně názorný než obvykle, neboť se mírně odchyluje od “CSS” syntaxe:

var myElmCollection = jQuery("#myForm select[@multiple]").get();

Yahoo UI vyniká flexibilitou, neboť pro filtrování elementů používá funkci. V příkladu pro jednoduchost používám anonymní funkci přímo zapsanou do argumentu, což je poněkud prohřešek proti čitelnosti, tak to po mě neopakujte:

var yuiDom = YAHOO.util.Dom;
var myElmCollection = yuiDom.getElementsBy(function (elm) { return elm.multiple }, "select", yuiDom.get("myForm"));

Shrnutí

Ukázali jsme si jak tři javascriptové knihovny dokáží vyhledávat v DOMu.

  • Knihovna lib.elm má výhodu, pokud používáte jako datový formát JSON.
  • jQuery je stručný, někdy to ale může být na úkor výkonnosti a čitelnosti programu, proto není vhodný pro “těžce zaskriptované” stránky, zvláště když je nutná optimalizace na rychlost. Pro běžné použití je však nejen dostačující ale i velice efektivní.
  • Knihovna Yahoo UI vyniká robustností a flexibilitou, rozvláčná syntaxe však může být na škodu čitelnosti kódu.


9 Komentářů k článku “Vyhledávání v DOMu na trojí způsob”

  1. MiSHAK:

    Pro upřesnění jQuery nevrací elementy ale třídu jQuery, takže pro získání čistých elementů je třeba použít ještě funkci get() tj. var myElmCollection = jQuery(”div.myCls”, “#myElm”).get(); atp.


  2. richard:

    MiSHAK: Je to tak, díky za připomínku. V praxi obvykle využívám toho že jQuery result se “tváří” jako pole elementů takže v naprosté většině případů ho můžu jako pole skutečně použít. Zrovna přednedávnem jsem o tom psal článek a vida - hned se sám dopustím nepřesnosti před kterou jiné varuji :-) .


  3. LokoN:

    V jQuery 1.1 se rychlost vyhledavni v DOM vyrazne zrychlila. http://john.jquery.com/speed/


  4. Acci:

    Metoda getElementsByClassName je součástí HTML5 a Firefox ji bude podporovat ve verzi 3.0 Viz
    http://jasnapaka.bloguje.cz/477508-podpora-dom-metody-getelementsbyclassname-v-gecku-1-9.php?global


  5. richard:

    Acci: No aspoň něco, ovšem v DOM 3.0 to pořád neni. Neaprosto nechápu jak lidem z W3C tohle mohlo utéct. Ani se nedivim že vznikají podezřelý aktivity jako HTML 5 když W3 funguje tak jak funguje.


  6. ah01:

    Zajímavé je také srovnání některých implementací getElementsByClassName: http://ejohn.org/blog/getelementsbyclassname-speed-comparison/

    V DOM to IMHO není, protože to je univerzální nástroj pro XML a className je čistě záležitost HTML.

    Mimochodem, co je zač ta knihovna lib.elm?


  7. richard:

    ah01: pěknný odkaz, už aby byl Firefox 3.

    To s tím DOMem - co se týče XML tak atribut ‘id’ taky není nijak privilegovaný a přesto je metoda getElementById. Podle mě to že neexistuje getElementsByClassName není chyba JS implementace DOMu ale přímo návrhu DOMu. Použití classů pro označování skupin elementů je stejně obecný vzor jako použití id pro označení unikátního elementu.

    Knihovny s prefixem lib jsou knihovny které momentálně používám a které jsem z části sám napsal, různé části jsou ale i převzaté (to se pozná tak že u převzaté funkce je napsaný autor). Jsou to knihovny sestavené empiricky podle mých praktických potřeb. Slíbil jsem že je zveřejním a tohle je asi nejméně bolestivá metoda jak to udělat, vzhledem k tomu že dokumentace je zatím dosti neúplná.
    Druhý důvod proč je uvádím je ten že spoustu věcí mají řešených jinak než YUI a jQuery, např. obsluhu eventů, templatovací systém (založený na JSONu), nadstavbu pro “class based inheritance” apod.


  8. Michal Aichinger:

    V tomto článku je dost mistifikaci:-)
    “Nalezení elementu podle jeho id je nejjednodušší - id musí být unikátní, máme tedy jistotu že bude nalezen právě jeden HTML element.” no právě, že v IE tuhle jistotu nemáme, neboť vrací metodou getElementById i elementy s name, resp, pokud je v DOMu první element s name, tak vrátí ten, jinak vrací ten s ID.
    “jQuery je stručné, někdy to ale může být na úkor výkonnosti a čitelnosti programu, ” - výše píšete, že nevíte jak je jQuery rychlé a ať to někdo změří a pak píšete tuhle fabulaci. Jestli máte podklady, zveřejněte je k článku, nebo neplácejte prázdnémi slovy
    ad [7] opět nemáte prvdu. atribut ID je v XML zakotven, např. zde: http://www.w3.org/TR/xml-id/


  9. richard:

    Nejde o mystifikace, jen o nepřesnosti :-)
    Co se týče MSIE a jeho práce s atributem name, myslím že jsem to už někde zmiňoval. Ačkoli vím že to takhle naprogramovali záměrně, osobně tohle chování považuju za chybu - kdyby si autoři tohoto návrhu pozorně přečetli specifikaci HTML, přišli by na to že jejich návrh byl od začátku zcestný. Pokud uděláte s popíšete názorný příklad kolize name s id, můžu ho tady pro výstrahu uveřejnit.

    Co se týče rychlosti jQuery - nešlo o fabulaci, jednak tehdy byl tento framework opravdu pomalejší, zadruhé z té doby (jaro 2007) skutečně neznám články které by se výkonem zabývaly. Už v létě 2007 se však nějaká čísla objevila - http://ajaxian.com/archives/jquery-113-800-faster-still-20kb a později http://jquery.com/blog/2007/08/24/jquery-114-faster-more-tests-ready-for-12/
    Z toho vyplývá že jQuery prošel mohutnou optimalizací na výkon a dnes je např. v selekcích plně srovnatelný s ostatními frameworky - viz http://mootools.net/slickspeed/

    Co se týče id a xml:id - souhlasím, moje poznámka ale byla o tom že mi tam chybí class. Chápu sice proč to tak je (autoři počítali s tím že tyto informace ponesou tagy) nicméně to v praxi nefunguje a jsou z toho zbytečné potíže.


Přidejte komentář

For spam detection purposes, please copy the number 1514 to the field below:




Weblog "JavaScript je ZLO 2.0" pohání všelijak překopaný WordPress,
XHTML je skoro validní, celkem respektuje Dogma W4 ale ne úplně