Linux E X P R E S

Facebook

jQuery (4) – pohyb ve stromě DOM

jquery.png

Při práci s DOM se často potřebujeme různě pohybovat po stromě a následně pracovat s jednotlivými objekty či jejich skupinami. Framework jQuery má na takový pohyb řadu užitečných metod.


Pár slov o stromě DOM

Objektový model dokumentu (DOM) je v zásadě tvořen stromem, který má nějaký kořen a pod ním jsou různé větve zakončené listy, tedy objekty bez dalších potomků (nerodičovské objekty). Webový prohlížeč si při načítání stránky a zpracování zdrojového kódu (X)HTML vytváří tento strom, se kterým lze následně pracovat.

Tato „práce“ spočívá jak v přístupu k jednotlivým uzlům (objektům), tak i v nakládání s celými větvemi, podstromy. Lze přidávat nové objekty, existující odebírat nebo přesouvat, případně kopírovat jinam – to vše právě i hromadně, po celých podstromech. V rámci stromu se lze i pohybovat, tedy vyjít od jednoho objektu a přecházet jinam.

Pohybujeme se ve stromě

Pohyb směrem dolů

Často je potřeba postupovat ve stromě do větší hloubky. Získáme přístup k nějakému objektu a potřebujeme pracovat s jeho potomky nebo potomky potomků atd. Něco už se objevilo v minulém článku, možností je ale mnohem více. Podívejme se na tento příklad:

var o = $('#abcd');
var cld1 = o.children();
var cld2 = o.children('p');
var sub = o.find('p');

První řádek slouží k získání instance jQuery pro nějaký objekt s identifikátorem „abcd“. Z něj se na druhém řádku vychází pro získání instance pro všechny přímé potomky objektu (až na výjimky, viz dále). Třetí řádek vybere jen ty potomky, kteří mají element p (každého jistě napadne, že by zde šlo také vyjít z instance cld1 a použít metodu filter()). A konečně poslední řádek prohledá celý podstrom na elementy p.

Pokud to lze, je vhodnější pro výběr přímých potomků používat vždy metodu children(), přestože někdy může dávat stejné výsledky jako find(). Lze tak předejít neočekávanému chování a je to také rychlejší. Pozor však na případy, kdy se z nějakého důvodu vloží mezi úrovně například „neutrální“ element div, protože tím se pro children() změní situace, aniž by byl na stránce vidět nějaký rozdíl.

Další úskalí spočívá v tom, že children() nevrátí všechny objekty, nýbrž jen elementy. Textové a komentářové objekty (text neobalený žádným elementem a HTML komentáře) tato metoda ignoruje. Většinou je takové chování žádoucí, protože nás tyto objekty obvykle nezajímají. Pokud je však potřebujeme, musí se to udělat jinak (k příkladu si prosím přimyslete první řádek z toho předchozího – bude to tak i u dalších příkladů):

var all = o.contents();

Pozor, metoda contents() je bezparametrická, nelze použít žádný selektor jako filtr (pokud je potřeba, je to řešitelné následným zavoláním metody filter())!

Pokud je v instanci, pro niž se metody volají, více objektů, bude to fungovat tak, jako kdyby se to zavolalo pro každý objekt zvlášť a získané množiny objektů se sloučily do jedné – vrácená instance tedy bude obsahovat všechny. Lze tak vlastně procházet více podstromů najednou.

Pohyb směrem nahoru

Opačným případem je, že máme instanci jQuery pro nějaký objekt „dole“ a potřebujeme se dostat směrem vzhůru:

var par1 = o.parent();
var par2 = o.parent('.aaa');
var par3 = o.parents('div');
var par4 = o.parentsUntil('body');

První případ je nejjednodušší, metoda vrací instanci jQuery pro rodičovský objekt. Ten je standardně jeden, pro objekt nejvyšší úrovně (document) není ale samozřejmě žádný. Také tady platí, že pokud je v instanci jQuery více objektů, rodič se najde pro každého a vloží se do cílové množiny; obrací se však pořadí (oproti původnímu) a odstraňují duplikáty.

Druhý řádek přidává filtr podle selektoru. Buď se tedy najde jeden rodič nebo žádný. Ve třetím řádku je metoda, která hledá všechny rodiče v cestě nahoru ke kořeni. Tady se typicky využívá filtr, protože nás nezajímají objekty všech typů, ale třeba právě uvedený div. Objekty se přidají do množiny v pořadí hledání, tedy opačně než v dokumentu.

Metoda parents() končí na elementu html, výše už nejde. Ke kořenovému objektu celého dokumentu (tedy document; je instancí javascriptové třídy HTMLDocument) se lze dostat pouze metodou parent() zavolanou na elementu html (i když je otázka, k čemu by to bylo dobré).

Na posledním řádku je pak metoda hledající všechny rodiče až po definovaného (který už do množiny zařazen není). Množinu lze omezit filtrem (druhý argument metody), jako „zarážku“ pro hledání lze využít jak selektor (jak je tomu v příkladu), tak i instance elementu nebo objektu jQuery, což se často hodí.

var ul = o.closest('ul');

Tato metoda prohledává strom směrem vzhůru, počínaje aktuálním objektem, než nalezne objekt odpovídající selektoru (je to vlastně find(), ovšem nahoru). Metoda se hodí k nalezení nadřazeného objektu, u kterého nevíme, kde se přesně ve stromě nachází.



Pohyb na stejné úrovni

Ve stromě se lze pohybovat i v rámci stejné úrovně, tedy přistupovat k sourozeneckým objektům. Opět pár příkladů:

var sibs = o.siblings('div.foto');
var sib1 = o.siblings().first();
var sib2 = o.next('p');
var sib3 = o.siblings().addBack();

První řádek vybere všechny sourozence objektu, které jsou elementem div a mají třídu „foto“. Potřebujeme-li pouze prvního sourozence, použijeme druhý řádek – metoda first() ostatní zahodí. Třetí příkaz vybere následujícího sourozence (podle pořadí, jak jdou v dokumentu za sebou), ale jen pokud má element p (nefunguje to tedy tak, že by se nejdřív použil selektorový filtr a teprve potom vybral objekt), jinak vrátí prázdnou množinu.

Čtvrtý řádek vybere všechny sourozence a přidá k nim i původní objekt – jinak řečeno, vybere všechny objekty na dané úrovni.

Když potřebujeme něco složitějšího

Někdy nestačí jen prostý pohyb ve stromě a potřebujeme nějaký složitější výběr objektů.

var ht = $('table').has('th');

Potřebujeme najít objekt, který má pod sebou objekty určitých vlastností. Například to může být tabulka, která obsahuje hlavičkové buňky, jako je tomu ve výše uvedeném příkladu. Poslouží zde metoda has(), které stačí dát selektor, případně instanci typu Element, a ta už zjistí, který objekt má někde pod sebou „ty správné“ potomky.

var ht = $('table').has('th').not($('table').has('td'));

Tohle je trochu „divočejší“ rozšíření předchozího příkladu. Vybere tabulky, které mají hlavičkové buňky, ale současně nemají žádné obyčejné. Metoda not() odstraňuje objekty z výběru buď na základě selektoru, nebo může využít i instanci jQuery s množinou objektů (případně lze použít i funkci, ale to teď ponecháme stranou).

Všechny zde popsané metody, plus ještě pár dalších, které jsou v jQuery k dispozici (a ke kterým se dostaneme někdy později), lze samozřejmě všelijak kombinovat. Nic by se ale nemělo přehánět, protože nadměrný pohyb ve stromě zbytečně spotřebovává výkon, nehledě na to, že se ve složitějších konstrukcích už nemusí nikdo vyznat.

A teď DOM upravíme...

Jak výběr pomocí selektoru, tak i pohyb ve stromě bývají obvykle jen přípravou na to, že se bude s objekty nebo celými podstromy něco dělat. Příště se podíváme na to, jak upravovat obsah objektů, přidávat nové, přemísťovat je a odstraňovat.

Diskuze (1) Nahoru