Linux E X P R E S

Facebook

jQuery (5) – manipulace s objekty

jquery.png

Jednou z častých činností prováděných v JavaScriptu je manipulace s objekty v DOM, tedy změna jejich obsahu, přidávání a odebírání. Pojďme se podívat, jak se to dělá pomocí jQuery.


Jak změnit obsah objektu

Změny obsahu objektů DOM patří mezi vůbec nejčastější činnosti prováděné v JavaScriptu. Ať už se změny provádějí na základě nějakých činností v prohlížeči nebo podle dat získaných ze serveru, v moderních webových aplikacích se mění objekty „jak na běžícím pásu“.

Změna textu

Nejjednodušší je změna textového obsahu. Mějme například následující fragment HTML:

<body>
<h1>Nadpis<h1>
…
</body>

Chceme například změnit nadpis (tj. element h1) na nějaký konkrétní text. Pomocí selektoru tedy vybereme příslušný objekt a metodou text() mu nastavíme textový obsah:

$('h1').text('Nový nadpis');

Vybere-li selektor více objektů, nastaví se text všem. Změna se na zobrazené stránce projeví okamžitě. Metoda text(), podobně jako řada dalších podobných, neslouží jen ke změně, ale také k získání aktuální hodnoty:

var t = $('h1').text();
$('h1').text(t + ' nový');

Je zřejmé, co tento kód udělá – zjistí text v h1, připojí za něj další řetězec a ten opět nastaví. Pozor však na jednu věc: zatímco v nastavovacím použití metoda text() nastaví danou hodnotu všem objektům vybraných selektorem, při získávání textu se spojí veškerý textový obsah všech vybraných objektů včetně jejich podstromů. Každý prohlížeč však může odlišně naložit s „bílými znaky“ (mezerami, konci řádků apod.), takže je lepší se vyhýbat situacím, kdy se získává text z více než jednoho objektu.

Metodu nelze použít u objektů pro vstup dat (input, textarea apod.). Bude o tom řeč později.

Změna HTML

Metoda text() pracuje s holým textem. Pokud se jí předá HTML kód, převede znaky lomených závorek na HTML entity, takže se zobrazí jako zdrojový kód místo toho, aby se interpretoval. Pokud potřebujeme, aby se interpretoval (což bývá dost často), je potřeba použít jinou metodu:

$('h1').html('<a href="odkaz.html">Nadpis</a>');

Tato metoda udělá to, co bychom asi očekávali – vloží do objektu HTML kód. Ten se samozřejmě zpracuje, jako kdyby byl přímo v dokumentu. To znamená, že se případně i vytvoří nové objekty v DOM. V daném případě se vytvoří objekt pro element a, tedy pro odkaz. Hned vzápětí už lze s novými objekty běžným způsobem pracovat.

Toto se velmi často využívá ve spojení s daty vyžádanými ze serveru (AJAX – Asynchronous JavaScript And XML; název je trochu zavádějící, ale zažitý). Na základě požadavku přijde fragment HTML a ten se vloží na „správné“ místo v DOM, kde nahradí původní kód.

Podobně jako u metody text() lze i zde vkládat na více míst najednou. Pozor na použití identifikátorů – ty by měly být unikátní, proto pokud byste je použili v HTML kódu vkládaném na více míst, povede to k nepředvídatelnému a potenciálně problematickému chování.

Metoda html() umožňuje také získat současný obsah objektu. Ten nemusí přesně odpovídat tomu, co bylo ve zdrojovém kódu nebo co bylo do dokumentu později vloženo. Prohlížeče si totiž mohou DOM poněkud upravit. Na závadu funkce by to ale být nemělo.

Tuto metodu nelze použít v případech, kdy se pracuje s XML DOM. To není obvyklý případ, protože kvůli kompatibilitě se staršími prohlížeči, ale i kvůli vyšší toleranci k chybám, se XHTML zpracovává jako HTML a nikoli jako XML. Kdo by chtěl ale pracovat s XML, musí zvolit jiný postup, metoda html() je zde zapovězena.



Vkládání nových objektů

Vložit nové objekty lze již popsanou metodou html(). Jsou tu ale i jiné metody, umožňující provádět  další „kouzla“. Častým požadavkem je vložit něco před současný obsah objektu (tedy nikoli místo něj, jak dělá metoda html()) nebo za něj. To lze snadno zařídit:

$('body').prepend('<div id="hlavicka">Tady bude hlavička...</div>');
$('body').append('<div id="paticka">Powered by jQuery</div>');

Asi každý pozná, co uvedené řádky dělají. První vloží „hlavičku“ úplně na začátek všeho uvnitř elementu body (tedy těla dokumentu), druhý vloží na samý konec těla „patičku“. Je to velmi pohodlné a dá se říci, že i návykové.

Potřebujeme-li se při této činnosti „odpíchnout“ od objektu na stejné úrovni (tj. od sourozence), není potřeba si nejdřív zjišťovat rodiče a pak na něm volat uvedené metody. Jde to jednodušeji:

$('#hlavicka').after('<p>Odstavec těsně za hlavičkou</p>');
$('#paticka').before('<p>Odstavec těsně před patičkou</p>');

Obě metody navazují na hlavičku a patičku z předchozího příkladu. Vloží vždy daný odstavec těsně za hlavičku, resp. před patičku. U těchto i předchozích metod lze samozřejmě vkládat na více míst najednou – stačí, aby selektor vybral vícečlennou množinu objektů (opět ale pozor na identifikátory).

Odstraňování objektů

Odstranit objekt z DOM je velmi jednoduché a jsou zde v podstatě tři možnosti. Tady je nejprve příklad:

$('table').empty();
$('tr').remove();
var data = $('tr').detach();

První řádek vymaže všechny objekty, které jsou pod jedním či více objekty v instanci jQuery.

Jinak řečeno, co bylo uvnitř všech tabulek, je nenávratně pryč (včetně textu). Druhý řádek funguje podobně, ovšem odstraňuje z DOM přímo vybrané objekty, nikoli potomky. Navíc umožňuje aplikovat ještě filtr (v příkladu není použit). A konečně poslední řádek sice odstraní objekty obdobně jako remove(), vloží je však do dané proměnné – neztratí se tedy a lze je v případě potřeby později opět vložit. I tato metoda dovoluje použití filtru.

Kopírování a přesun objektů

Někdy potřebujeme objekty kopírovat či přesouvat na jiná místa. Stačí si představit třeba dva seznamy, mezi kterými se přesouvají položky:

<ul id="seznam1">
  <li>Položka 1</li>
  ...
</ul>
<ul id="seznam2">
</ul>

Na začátku jsou v prvním seznamu nějaké položky a druhý je prázdný. Chceme vzít první položku z prvního seznamu a vložit ji do druhého. Lze to udělat třeba takto:

$('#seznam2').append($('#seznam1 li:first-child'));

Metoda append() je jistě každému známa z předchozích odstavců. Ale co dělá tady a jak souvisí s přesunem? Ona totiž může mít jako parametr kromě jiného také instanci jQuery a v takovém případě přesune objekty z původního místa na nové. Nezkopíruje, přesune – což je ovšem přesně to, co chceme.

Pozor však na to, že pokud se takto použitá metoda append() zavolá na instanci jQuery obsahující více objektů, přesune se jen do prvního z nich a do dalších se nakopíruje (z původního místa však opět zmizí).

Obdobně lze použít i další metody určené pro vkládání obsahu, tedy prepend(), before()after(). Existují i opačně pojaté metody, volané naopak na instanci jQuery objektů, které se mají vkládat. Jsou to metody appendTo(), prependTo(), insertBefore()insertAfter(). Rozdíl je téměř jen syntaktický, i když některé věci u nich fungují mírně jinak a jdou tak trochu proti snadné použitelnosti jQuery (například můžete zkonstruovat instanci třídy jQuery obsahující HTML fragment, což může poněkud znepřehlednit kód, protože se takto obvykle nepostupuje).

Čistokrevné kopírování lze zajistit metodou clone(). Ta kopíruje vždy a ještě umožňuje definovat, jestli se budou kopírovat i data a události navázané na objekty (o tom bude řeč mnohem později, ale zaslouží si to teď zmínku).

$('#seznam2').append($('#seznam1 li:first-child').clone());

Toto je upravený příklad se dvěma seznamy. Rozdíl oproti příkladu výše je však v tom, že tentokrát se položka ze seznamu zkopíruje a bude tedy figurovat v obou seznamech.

Přesun ve dvou krocích lze zajistit pomocí již zmíněné metody detach() a následně některé z metod pro vložení. Význam to má pro ty případy, kdy je potřeba mezi oněma dvěma kroky provést nějaké operace, během kterých nesmí daný objekt (včetně svého podstromu) existovat v DOM.

„Potápění“ a „vyzvedávání“ objektů

Zvláštním případem je situace, kdy chceme přidat nebo odebrat nějakou úroveň DOM. Máme například toto:

<div id="inner">
  <p>Text...</p>
</div>

Chceme přidat ještě jednu úroveň navíc, resp. naopak jednu odebrat. Dá se to samozřejmě udělat pomocí již dříve popsaných postupů pro přesun, ale je to zbytečné. Úroveň přidáme jednodušeji takto:

$('#inner').wrap('<div id="outer"></div>');

Výsledkem bude, že se zkrátka místo elementu s identifikátorem inner vloží nová úroveň a původní objekt se vloží pod ni. Pokud bude instance jQuery obsahovat více objektů, vloží se nová úroveň pro každý zvlášť. Pokud je to nežádoucí, je třeba místo toho použít metodu wrapAll(). Ještě existuje varianta wrapInner(), která vkládá novou úroveň pod dané objekty.

Obdobně se provede i „vytažení nahoru“. Metoda odstraňuje rodiče, je tedy potřeba ji volat pro ty objekty, které je potřeba vyzvednout:

$('#inner p').unwrap();
$('#inner').children('p').unwrap();

Oba řádky dělají totéž, druhý je delší, ovšem poněkud rychlejší. To jen pro připomenutí.

To ještě není všechno

Končí tento díl seriálu, ale nikoli úpravy objektů v DOM. Příště se podíváme na atributy, které jsou nedílnou součástí HTML elementů a často významně ovlivňují to, jak bude dokument vypadat, jak bude fungovat a v neposlední řadě i to, jak v něm můžeme hledat objekty.

Diskuze (0) Nahoru