Ebben a jegyzetben áttekintjük a HTML DOM-mal kapcsolatos fontosabb tudnivalókat, majd egy gyakorlati példán keresztül megismerkedünk a JavaScript által biztosított fontosabb DOM-manipulációs lehetőségekkel.
A webfejlesztésben a HTML nyelvet használjuk weboldalak létrehozására. Ennek a nyelvnek a segítségével mondhatjuk meg, hogy mi az, amit egy weboldalon látni szeretnénk (pl. szövegek, képek, táblázatok, űrlapok, multimédia stb.). Emellett a HTML lehetőséget biztosít a weboldalon megjelenő tartalom strukturálására is, különféle szakaszok, tartalmi egységek kialakításával.
A HTML dokumentumok úgy épülnek fel, hogy HTML objektumokat (úgynevezett tageket) ágyazunk egymásba. Ezek az objektumok egy hierarchikus fastruktúrát alkotnak a dokumentumban.
Amikor egy weboldal betöltődik, akkor a böngésző a weboldalon található HTML objektumokból elkészíti az úgynevezett dokumentum-objektum modellt, avagy röviden a DOM-ot. A DOM-fa (DOM tree) segítségével könnyen szemléltethetjük a weboldalon található HTML elemek hierarchikus viszonyait.
Példa: Egy egyszerű HTML kód és az ahhoz tartozó DOM-fa.
<!DOCTYPE html> <html lang="hu"> <head> <title>DOM példa</title> <meta charset="UTF-8"/> </head> <body> <h1>Az oldal címe</h1> <img src="my-image.png" alt="Valami klassz kép"/> <p> <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ">Valami klassz link</a> </p> </body> </html>
Megjegyzés: A
DOCTYPE
nem egy HTML tag, ezért a DOM-fában sem szerepel.
Ha egy HTML dokumentumban az A objektum (nem feltétlen közvetlenül) tartalmazza a B objektumot, akkor azt mondjuk, hogy az A objektum a B objektum őse, a B objektum pedig A-nak leszármazottja. Amennyiben ez a tartalmazás közvetlen, akkor A-t a B szülőjének, B-t pedig az A gyerekének nevezzük.
Néhány példa a fenti kódból és az ahhoz tartozó DOM-fából:
<body>
objektum leszármazottjai a <h1>
, <img>
, <p>
és <a>
objektumok, illetve a "Valami klassz link" és "Az oldal címe" szöveges csomópontok.<body>
objektum gyerekei a <h1>
, <img>
és <p>
objektumok. Másképp mondva: a <h1>
, <img>
és <p>
objektumok szülője a <body>
.<body>
objektumnak az <a>
objektum nem gyereke, csak leszármazottja, hiszen itt a tartalmazás nem közvetlen (van még a fában egy <p>
elem is köztük).Ha az A és B objektumok szülője megegyezik, akkor A és B egymás testvérei. Például a fenti kódban és az ahhoz tartozó DOM-fában a <h1>
, <img>
és <p>
elemek egymás testvérei, hiszen mindhárom elem szülője a <body>
.
A DOM-fa tetején lévő, szülővel nem rendelkező elemet a fa gyökérelemének nevezzük. A teljes HTML DOM-ban a gyökérelem mindig a <html>
objektum lesz (ugyanis ebbe ágyazunk be minden további HTML elemet).
Amikor a weboldalunk tartalmát CSS-ben formázzuk, akkor használhatunk olyan szelektorokat (kijelölőket) is, amelyek a DOM-beli viszonyaik alapján jelölnek ki HTML objektumokat. Néhány példa DOM-alapú CSS szelektorokra, a teljesség igénye nélkül:
div p
: kijelöl minden olyan <p>
-t, amely egy <div>
leszármazottjadiv > p
: kijelöl minden olyan <p>
-t, amely egy <div>
gyerekediv ~ p
: kijelöl minden olyan <p>
-t, amely egy <div>
testvére és ezen <div>
után szerepelp:nth-child(n)
: kijelöl minden olyan <p>
-t, amely a szülőjének n
-edik gyerekep:nth-of-type(n)
: kijelöl minden olyan <p>
-t, amely a <p>
típusú testvérei közül az n
-edik.A webes világban gyakran előfordul, hogy dinamikusan szeretnénk manipulálni a DOM-fát, miután már a weboldal betöltődött (pl. szeretnénk egy objektumot módosítani vagy törölni, esetleg egy új objektumot akarunk a fába beszúrni). Erre biztosítanak lehetőséget a JavaScript DOM-manipulációs műveletei.
A DOM tulajdonképpen nem más, mint egy objektumorientált reprezentációja a weboldalnak. A weboldalon szereplő elemek Node-ok (csomópontok) a DOM-fában, amelyek számos property-vel (adattaggal) és metódussal rendelkeznek. Ezeket JavaScriptből egyszerűen el tudjuk érni.
A következő fejezetben megismerkedünk a JavaScript néhány fontosabb DOM-manipulációs lehetőségével. Fogjuk párszor használni a document
objektumot, ami lényegében a böngésző által megnyitott HTML dokumentumot reprezentálja és hozzáférést biztosít a DOM-fához.
Oké, de mi értelme van ennek? Miért nem lehet csak simán a HTML-t átírogatni?
A hangsúly itt azon van, hogy azután szeretnénk a weboldal tartalmát dinamikusan módosítani, miután az oldal már betöltődött. Nézzünk néhány gyakorlati példát, amikor DOM-műveleteket használunk:
- Lekérdezünk adatokat egy szervertől, és meg szeretnénk jeleníteni azokat a weboldalunkon. Mivel a HTML oldal már betöltődött addigra, amire az adatok megérkeztek, ezért azokat úgy tudjuk megjeleníteni a weboldalon, hogy utólag szúrogatjuk be őket a DOM-fába.
- Egy űrlap kitöltését követően kliensoldalon ellenőrizzük a beírt adatok helyességét (pl. helyes e-mail cím formátum, helyes születési dátum stb.). Ekkor egy eseménykezelővel figyeljük, hogy mikor nyomja meg a felhasználó az "Elküldés" gombot, majd a "klikk" esemény hatására DOM-műveletekkel lekérjük a beírt adatokat és ellenőrizzük őket. (Nyilván nem tudjuk előre, hogy mit fog beírni a user, ezért kellenek a DOM-műveletek.)
- Szeretnénk elérni, hogy egy gombra kattintva a felhasználó válthasson világos és sötét téma között. Megint az a helyzet, hogy a weboldal már be van töltve, csupán annak a megjelenítését manipuláljuk dinamikusan, DOM-műveletek segítségével, amikor a felhasználó a gombra kattint.
Könnyen belátható, hogy a HTML önmagában nem elég robusztus ahhoz, hogy "utólag" manipuláljuk a weboldalaink szerkezetét. Ezért van szükségünk a DOM-ra és a JavaScript DOM-műveleteire.
A jegyzet hátralévő részében egy végletekig leegyszerűsített feladatlista alkalmazást fogunk elkészíteni. A weboldalon megjelennek a napi feladataink, amelyeket lehetőségünk van törölni, ha teljesítettük őket. Emellett új feladatot is bármikor létrehozhatunk.
A példaprojekt elkészítéséhez szükséges kiinduló fájlok letölthetők egy ZIP-ben, ide kattintva.
Megjegyzés: Mivel csak a DOM-műveletek bemutatása a cél, ezért az alkalmazás eléggé kezdetleges lesz: a feladatokat nem mentjük el sehova, így az oldal frissítésekor a dinamikusan hozzáadott adatok elvesznek. Emellett lesznek beégetett adataink is. Ha valaki ennél egy fokkal realisztikusabb weboldalt szeretne készíteni, akkor a 2.6. fejezetben talál tippeket a példaprojekt "felokosítására".
Egy egyszerű feladattal fogunk indítani: keressük meg JavaScriptben az alábbi <h1>
-es címsort a DOM-fában, és írassuk ki azt a konzolra!
<h1 id="page-title" class="text-center">Feladataim</h1>
HTML objektumok DOM-fában történő megkeresésére többféle lehetőségünk is van:
document.getElementById(id)
: visszaadja az adott id
értékkel rendelkező elemet (egyetlen elemet ad vissza, hiszen az id
attribútum értéke szabályosan egyedi a HTML dokumentumon belül)document.getElementsByTagName(tag)
: visszaadja az adott tagnévvel rendelkező elemeket (minden esetben egy kollekciót ad vissza, amit 0-tól kezdődően indexelünk)document.getElementsByClassName(class)
: visszaadja az adott class
értékkel rendelkező elemeket (minden esetben egy kollekciót ad vissza, amit 0-tól kezdődően indexelünk)document.querySelector(s)
: visszaadja az s
CSS szelektor által kijelölt legelső elemetdocument.querySelectorAll(s)
: visszaadja az s
CSS szelektor által kijelölt összes elemet (minden esetben egy kollekciót ad vissza, amit 0-tól kezdődően indexelünk).Példa: A felsoroltak közül bármelyik szelektorral megkereshetjük a fenti címsort. Az alábbi utasítások mindegyikének hatására a kérdéses címsor fog kiíródni a konzolra.
console.log(document.getElementById("page-title")); console.log(document.getElementsByTagName("h1")[0]); // kollekciót ad vissza, indexeljük! console.log(document.getElementsByClassName("text-center")[0]); // kollekciót ad vissza, indexeljük! console.log(document.querySelector("header h1.text-center")); console.log(document.querySelectorAll("header h1.text-center")[0]); // kollekciót ad vissza, indexeljük!
Miközben a felhasználó böngészi a weboldalunkat, történhetnek különféle események - pl. a felhasználó rákattint egy oldalelemre, egy elem fölé viszi a kurzort, egy HTML elem betöltődik vagy megváltozik. Ezekhez az eseményekhez társíthatunk eseménykezelő függvényeket, amelyek akkor hívódnak meg, ha az adott esemény bekövetkezik.
Az eseménykezelés egyik módja, hogy az elemeknek adott, eseménykezeléssel kapcsolatos attribútumokkal szabályozzuk az események működését. A kérdéses HTML elemet ellátjuk az alábbi attribútumok valamelyikével, és az attribútum értékeként megadjuk az eseménykezelést végző függvényt.
onclick
: a felhasználó rákattint az elemreonload
: az elem betöltődikonunload
: az oldalt bezárjuk vagy frissítjük (előfordulhat, hogy nem működik megfelelően!)onmouseover
: a felhasználó az elem fölé viszi a kurzortonmouseout
: a felhasználó elviszi az elemről a kurzortonchange
: az elem megváltozikMegjegyzés: Ezeken kívül vannak még további eseménykezeléssel kapcsolatos attribútumok is, amiket használhatunk. A teljes listát megtalálhatjuk ezen a linken.
Példa: A példaprojektben található "Hozzáadás" gombra kattintva az addTask()
eseménykezelő függvény hívódik meg.
<button type="button" class="add-btn" onclick="addTask()">Hozzáadás</button>
A példaprojektben kizárólag az attribútumokkal történő eseménykezelésre találunk példát. Egy másik módszer az eseménykezelésre, ha egy DOM-beli elem addEventListener()
metódusát használjuk, ezzel rendeljük hozzá az elemhez az eseménykezelő függvényt (ekkor az elemnek nem kell semmilyen attribútumot adni). Egy HTML elemhez több eseménykezelő is hozzárendelhető (akár ugyanarra az eseménytípusra is).
Az addEventListener()
metódus paraméterei sorban:
on
előtag nélkül adunk meg (pl. click
, load
, unload
stb.)Példa: Eseménykezelő hozzárendelése egy gombhoz az addEventListener()
metódussal.
<body> <button type="button" id="my-btn">Kattints rám!</button> <script> const button = document.getElementById("my-btn"); // gomb megkeresése button.addEventListener("click", function() { // kattintás esemény kezelése alert("Hurrá, működik az eseménykezelő!"); }); </script> </body>
Capturing és bubbling
Tegyük fel, hogy van egy HTML elemünk, ami egy másik HTML elembe van beágyazva! Mind a beágyazó elemhez, mind a beágyazott elemhez hozzárendelünk egy-egy eseménykezelőt ugyanarra az eseménytípusra - mondjuk a kattintásra. Ha a belső elemre kattintunk, akkor mindkét elem eseménykezelője meghívódik. Az addEventListener()
metódus harmadik paraméterével szabályozhatjuk, hogy milyen sorrendben legyenek ezek meghívva.
Ha true
-ra állítjuk a harmadik paramétert, akkor capturing történik. Ekkor az eseményt először a legkülső elem kezeli le, majd ezután mindig az eggyel "beljebb" található elem eseménykezelő függvénye hívódik meg.
Ha false
-ra állítjuk a harmadik paramétert, akkor bubbling történik. Ekkor az eseményt először a legbelső elem kezeli le, majd ezután mindig az eggyel "kijjebb" található elem eseménykezelő függvénye hívódik meg. Ha nem adjuk meg expliciten a 3. paraméter értékét, akkor alapértelmezett módon mindig bubbling történik.
Nézzünk egy példát! Figyeljük meg a konzolon, hogy az "eseménykezelők" feliratra kattintva, capturing esetén "kívülről befelé", míg bubbling esetén "belülről kifelé" sorrendben hívódnak meg az elemek eseménykezelői!
<body> <p id="my-paragraph"> Ez egy példa <strong id="my-strong">eseménykezelők</strong> használatára. </p> <script> // Két függvény, amely kiírja annak a HTML elemnek a nevét, amelyen az esemény bekövetkezett // A capture()-t majd capturing, a bubble()-t pedig majd bubbling módban fogjuk használni function capture() { console.log("Capturing: " + this.tagName); } function bubble() { console.log("Bubbling: " + this.tagName); } // A <p> és <strong> elemek megkeresése a DOM-fában const p = document.getElementById("my-paragraph"); // külső (beágyazó) elem const strong = document.getElementById("my-strong"); // belső (beágyazott) elem // Kattintás eseményre vonatkozó eseménykezelők hozzárendelése a két elemhez p.addEventListener("click", capture, true); // capturing strong.addEventListener("click", capture, true); // capturing p.addEventListener("click", bubble, false); // bubbling strong.addEventListener("click", bubble, false); // bubbling </script> </body>
A kimenet a konzolon: Capturing: P
, Capturing: STRONG
, Bubbling: STRONG
, Bubbling: P
.
Ha egy új elemet szeretnénk a DOM-fába beszúrni, akkor a következő lépéseket kell követnünk:
document.createElement(tagname)
metódussal létrehozzuk a beszúrandó HTML elemet.append()
vagy appendChild()
metódusával.Az append()
és appendChild()
metódusok mindketten arra szolgálnak, hogy egy DOM-beli objektumhoz gyerekobjektumot fűzzünk hozzá. Két fontos különbség a két metódus között:
append()
egyszerre több gyereket is hozzáfűzhet egy objektumhoz, míg az appendChild()
csak egyet.append()
Node-okat és stringeket egyaránt hozzáfűzhet egy objektumhoz gyerekként, míg az appendChild()
kizárólag Node-okkal működik.Megjegyzés: Az
append()
ésappendChild()
metódusok mindig a szülőelem legutolsó gyerekeként szúrják be az új objektumot a DOM-fába. Ha a szülő egy tetszőleges indexű gyerekeként szeretnénk beszúrni az elemet a fába, akkor használjuk a szülőinsertBefore()
metódusát.A metódus két paramétert vár: rendre a beszúrandó objektumot, és a szülőelem azon gyerekét, ami elé be fogjuk szúrni az új elemet. A szülőelemnek felhasználhatjuk a
children
property-jét, ami visszaadja az elem összes gyerekét egy indexelhető kollekcióban.Nézzünk egy példát! Szúrjunk be az alábbi weboldalra egy "Második bekezdés" feliratú
<p>
objektumot, a "Harmadik bekezdés" feliratú<p>
elem elé!<div id="parent"> <p>Első bekezdés</p> <p>Harmadik bekezdés</p> </div> <script> const parent = document.getElementById("parent"); // a szülőobjektum const newParagraph = document.createElement("p"); // az új elem létrehozása newParagraph.innerText = "Második bekezdés"; // Az új elem beszúrása a szülőobjektum második (1. indexű) gyereke elé parent.insertBefore(newParagraph, parent.children[1]); </script>
Feladat: Tegyük működőképessé az "új feladat hozzáadása" funkciót a példaprojektben!
A megoldás menete:
A feladat hozzáadását végző űrlap HTML kódja a következő:
<form> <input type="text" id="task-text" class="form-input"/> <button type="button" class="add-btn" onclick="addTask()">Hozzáadás</button> </form>
Látható, hogy a "Hozzáadás" gombhoz hozzárendeltük az onclick
attribútummal az addTask()
eseménykezelő függvényt. Ez a függvény fog meghívódni, amikor a felhasználó a gombra kattint, így ennek a törzsét kell megírnunk. Azt szeretnénk, hogy a függvény kérdezze le az űrlapmezőbe írt szöveget és szúrja be azt és egy "Törlés" gombot a weboldalon található táblázat egy új sorába. Valahogy így:
<table> <!-- A táblázat fejléce... --> <tbody> <!-- Néhány korábbi feladat... --> <tr> <td>Az újonnan beszúrt feladat szövege...</td> <td><button type="button" class="delete-btn" onclick="deleteTask(this)">X</button></td> </tr> </tbody> </table>
<tbody>
objektumot, hiszen ennek a gyerekeként fogjuk az új feladatot beszúrni!<tr>
)! A sorban helyezzünk el két táblázatcellát (<td>
)!<td>
objektumot a <tr>
gyerekeiként a DOM-fába! A <tr>
objektum pedig legyen a <tbody>
gyereke a weboldalon!A megoldás elkészítése:
Keressük meg a <tbody>
objektumot!
const tbody = document.getElementsByTagName("tbody")[0];
Hozzunk létre egy táblázatsort és két táblázatcellát! A cellákat a sor gyerekeiként, a sort pedig a <tbody>
gyerekeként szúrjuk be a DOM-fába!
const tbody = document.getElementsByTagName("tbody")[0]; const row = document.createElement("tr"); const column1 = document.createElement("td"); // Itt majd kialakítjuk az első cella tartalmát... const column2 = document.createElement("td"); // Itt majd kialakítjuk a második cella tartalmát... row.append(column1, column2); tbody.append(row);
Írjuk bele az első táblázatcellába az id="task-text"
attribútummal rendelkező beviteli mezőbe írt szöveget!
value
property-jével történik.innerText
vagy innerHTML
property-vel lehetséges. A különbség a két property között, hogy az innerHTML
értékeként megadott szöveg HTML-ként lesz értelmezve (ezért itt használhatók a szokásos HTML tagek), míg az innerText
értéke minden esetben egyszerű szövegként jelenik meg (nem lesz HTML-ként értelmezve).// ... const column1 = document.createElement("td"); column1.innerText = document.getElementById("task-text").value; // ...
Már csak a második táblázatcella tartalmát kell kialakítanunk. Ebben egy törlés gombot fogunk elhelyezni, tehát a document.createElement()
metódussal létrehozunk egy új <button>
objektumot, amit a második táblázatcella gyerekeként szúrunk be a DOM-fába. A gomb szöveges tartalma legyen X
!
Ahhoz, hogy a létrehozott gomb megfelelően működjön, hozzáadunk néhány attribútum-érték párt. Egy HTML objektum attribútumainak beállítása a setAttribute()
metódussal történik. Ennek első paramétereként megadjuk a beállítani kívánt attribútum nevét, második paraméterként pedig az attribútum értékét.
setAttribute()
segítségével adjunk a gombnak egy type="button"
attribútum-érték párt!setAttribute()
segítségével adjunk a gombnak egy onclick="deleteTask(this)"
attribútum-érték párt, amivel hozzárendeljük a gombhoz a deleteTask()
eseménykezelő függvényt!Rendeljük hozzá a gombhoz a class="delete-btn"
attribútumot, hogy ugyanúgy legyen formázva, mint a többi törlés gomb! Ehhez használjuk az elem classList
property-jét, amivel lekérhetjük az összes olyan class nevét, amivel az elem rendelkezik. A classList
-nek az add()
metódusával hozzáadjuk a gombhoz a delete-btn
class-értéket.
// ... const column2 = document.createElement("td"); const deleteBtn = document.createElement("button"); // gomb létrehozása deleteBtn.innerText = "X"; // gomb szöveges tartalmának beállítása deleteBtn.setAttribute("type", "button"); // gomb attribútumainak beállítása deleteBtn.setAttribute("onclick", "deleteTask(this)"); deleteBtn.classList.add("delete-btn"); // class="delete-btn" attribútum hozzáadása a gombhoz column2.append(deleteBtn); // gomb beszúrása a DOM-fába a 2. táblázatcella gyerekeként // ...
Tehát az addTask()
függvény végleges verziója a következőképpen néz ki:
function addTask() { const tbody = document.getElementsByTagName("tbody")[0]; const row = document.createElement("tr"); const column1 = document.createElement("td"); column1.innerText = document.getElementById("task-text").value; const column2 = document.createElement("td"); const deleteBtn = document.createElement("button"); deleteBtn.innerText = "X"; deleteBtn.setAttribute("type", "button"); deleteBtn.setAttribute("onclick", "deleteTask(this)"); deleteBtn.classList.add("delete-btn"); column2.append(deleteBtn); row.append(column1, column2); tbody.append(row); document.getElementById("task-text").value = ""; // űrlapmező tartalmának kiürítése }
1. megjegyzés: A
classList
egyéb metódusai a class-hozzáadásra szolgálóadd()
-on kívül:
remove(c)
: ac
class eltávolítása az elemrőlcontains(c)
: szerepel-e ac
class az elementoggle(c)
: ha ac
class még nem szerepel az elemen, akkor hozzáadja azt az elemhez; ha pedig már szerepel, akkor eltávolítja azt az elemről.
2. megjegyzés: A példaprojektben erre nem találunk példát, de az objektum stílusának módosítása az elem
style
property-jével lehetséges. Ez lényegében astyle
attribútum értékének módosításával állítja be a HTML elem stílusát (ezt inline CSS-nek is nevezzük).<body> <p id="my-paragraph">I'm blue da ba dee da ba die...</p> <script> // A bekezdés kék betűszínűvé tétele JavaScript segítségével document.getElementById("my-paragraph").style.color = "blue"; </script> </body>A
style
property-ről (ami tulajdonképpen egy objektum) szóló részletes referencia elérhető itt.
Ahhoz, hogy egy objektumot kitöröljünk a DOM-fából, szükségünk lesz a törlendő objektumra és annak szülőjére. A törléshez a szülő removeChild()
metódusának paramétereként adjuk meg a törlendő objektumot.
Feladat: Tegyük működőképessé a táblázat soraiban megjelenő "Feladat törlése" gombokat!
A megoldás menete:
Minden ilyen, feladat törlésére szolgáló gomb forráskódja a következő:
<button type="button" class="delete-btn" onclick="deleteTask(this)">X</button>
A gombra kattintva tehát a deleteTask()
eseménykezelő függvény hívódik meg, így ennek a törzsét kell megírnunk. Azt szeretnénk, hogy a gombra kattintva töröljük ki a táblázatból azt a sort, amihez a gomb tartozik. A függvény paraméterben megkapja az aktuális objektumot (this
), azaz a gombot, amire kattintottunk.
A törlendő sorhoz tartozó gomb tehát a függvény paramétereként adott. Ahhoz, hogy ebből megkapjuk a törlendő sort, végig kell gondolnunk a gomb és az őt tartalmazó táblázatsor viszonyát. A törlés gombok szülője egy <td>
(cella), amelynek szülője lesz a törlendő <tr>
(sor). Tehát két szülővel kell "feljebb lépnünk" a DOM-ban a megnyomott gombhoz képest. Kelleni fog még a törlendő sor szülője is, ami a <tbody>
objektum lesz.
Mindez egy ábrán szemléltetve:
<tbody>
objektumot, hiszen ennek az egyik gyerekét (egy táblázatsort) fogjuk kitörölni!<tbody>
objektum removeChild()
metódusával töröljük a megtalált sort a <tbody>
gyerekei közül!A megoldás elkészítése:
A DOM-beli elemek parentNode
property-jével lekérdezhetjük az adott elem szülőjét. Ahhoz, hogy megkapjuk a megnyomott gomb "nagyszülőjét" (a törlendő sort), kétszer egymás után alkalmazzuk a property-t.
A deleteTask()
függvény végleges verziója a következőképpen néz ki:
function deleteTask(btn) { const tbody = document.getElementsByTagName("tbody")[0]; // <tbody> megkeresése const row = btn.parentNode.parentNode; // a törlendő sor a megnyomott gomb "nagyszülője" lesz tbody.removeChild(row); // a sor kitörlése a <tbody> gyerekei közül }
Feladat: Tegyük működőképessé a weboldalon található "Összes feladat törlése" gombot!
A megoldás menete:
A fent említett gomb HTML forráskódja a következő:
<button type="button" id="delete-all-tasks-btn" class="delete-btn" onclick="deleteAllTasks()"> Összes feladat törlése </button>
A gombra kattintva tehát a deleteAllTasks()
eseménykezelő függvény hívódik meg, így ennek a törzsét kell megírnunk. Azt szeretnénk, hogy a függvény törölje ki az összes feladatot a DOM-fából. A feladatok továbbra is a <tbody>
gyerekeiként, táblázatsorok formájában vannak jelen a DOM-ban.
JavaScriptben nincs olyan explicit DOM-metódusunk, amely egy objektum összes gyerekét kitörölné, ezért egy kicsit másképp oldjuk meg a dolgokat:
hasChildNodes()
metódusával lekérdezzük, hogy vannak-e gyerekei.removeChild()
metódussal mindig kitörölünk egy gyereket.<tbody>
objektumot, hiszen ennek az összes gyerekét (a feladatokat tartalmazó táblázatsorokat) fogjuk kitörölni!<tbody>
-nak gyereke, addig mindig töröljünk ki egy tetszőleges gyereket!A megoldás elkészítése:
Teljesen mindegy, hogy mikor melyik gyereket töröljük ki, hiszen végül minden gyereket ki fogunk törölni. A példánkban én mindig a <tbody>
legelső gyerekét törlöm, amit a szülő firstChild
property-jével érhetünk el.
Tehát a deleteAllTasks()
függvény végleges verziója a következőképpen néz ki:
function deleteAllTasks() { const tbody = document.getElementsByTagName("tbody")[0]; // <tbody> megkeresése while (tbody.hasChildNodes()) { // <tbody> összes gyerekének törlése tbody.removeChild(tbody.firstChild); } }
A teljes, kikommentezett megoldás letölthető ide kattintva.
display: none
)!Megjegyzés: A "felokosított" példaprojekt letölthető ide kattintva.
Összetettebb webes projektekben általában nem a jegyzetben tárgyalt, hagyományos DOM-műveleteket szoktuk használni. Vannak ugyanis mindenféle library-k és keretrendszerek (framework-ök), amelyek használatával jelentősen leegyszerűsödik a DOM-manipuláció megvalósítása a fejlesztők számára. Viszont mivel ezek a library-k és framework-ök önmagukban megérnének egy-egy külön jegyzetet, ezért ezekbe most nem megyünk bele.