Dojo toolkit

DOM kezelése

DOM-ra várás

Mikor web alkalmazást fejlesztünk, figyelnünk kell arra, hogy a DOM elérhető legyen, mielőtt hivatkoznánk rá.

<script type="text/javascript"> document.myForm.myInput.value = "myValue"; </script> <form name="myForm"> <input type="text" name="myInput"> ... </form>

A fenti kódrészlettel az a baj, hogy a form még nem létezik, amikor hivatkoznánk rá. A sorrendet ugyan megcserélhetjük, és a form után tehetjük a script elemet, de az sem az igazi megoldás, ráadásul eléggé el tudja rontani az olvashatóságot és a karbantarthatóságot, ha tele van elszórt script elemmel a kódunk. Erre nyújt megoldást a dojo/ready, illetve a dojo/domReady! plugin.

dojo/ready

Regisztrál egy függvényt, ami akkor fut le, ha kész van a DOM, és minden require() hívás, illetve más, nagyobb prioritású regisztrált függvény is befejeződött. Szerepét nagyrészt már átvette ADM API és a dojo/domReady! plugin. Azonban a dojo/ready egy priritásos sort implementál (nem úgy, mint a dojo/domReady!), így meghatározhatjuk, hogy melyik callback hívódjon meg először. Tehát ez a plugin is hasznos lehet még olyan esetekben, mikor a kód egy bizonyos végrehajtási sorrendet követel meg.

require([ "dojo/ready" ], function(ready) { ready(function() { // Akkor fut le, ha kész a DOM }); }); require([ "dojo/ready", "dojo/dom", "dojo/parser" ], function(ready, dom) { ready(80, function() { // Akkor fur le, ha kész a DOM, de még a parser előtt }); });

dojo/domReady!

Ez a plugin pusztán arra vár, hogy kész legyen a dom, nem várja meg a require() hívások befejeződését.

require([ "dojo/domReady!" ], function() { // Akkor fut le, ha kész a DOM });

Konvenció szerint egyrészt nem tartozik hozzá modulváltozó, hisz annak nem sok értelme lenne. Másrészt mindig utolsó helyen tüntetjük fel (mert a modulokhoz rendelt változónevek sorrend szerint következnek):

require( [ "dojo/dom", "dojo/query", "dojo/on", "dojo/domReady!" ], function(dom, query, on) { // do something } );

Habár nem adunk át semmi adatot a pluginnak, a felkiáltójel mégis szükséges, mert nélküle csupán betöltenénk a modult, és nem használnánk kis a speciális funckióját (vagyis hogy a callback-el várunk a DOM betöltéséig).

Widgetek esetén tipikusan nem elég, ha erre a pluginra alapozunk, hiszen sokuk addig nem elérhető, amíg egyéb modulok be nem töltődtek (pl. dojo/parser) – ezért ebben az esetben a dojo/ready-t kell használnunk.

Más esetek is vannak, mikor jobb, ha mellőzzük ennek a használatát. Például, ha az alkalmazásunk szinkron tölti be a modulokat:

DOM és HTML

A core DOM API (dojo/dom)

FüggvényLeírás és példa
byId() Ez csupán egy alias a document.getElementById függvényre, és minden böngészőben működik.

var node = dom.byId("myNodeId");
var other = dom.byId(node);
console.log(node == other);
isDescendant() Igazzal tér vissza, ha a node leszármazottja a megadott feltételezett szülőnek.

dom.isDescendant("child", "ancestor");
setSelectable() Kijelölhetőség állítása egy node-on.

dom.setSelectable("someNode", true);

A DOM attribútum API (dojo/dom-attr)

FüggvényLeírás és példa
has() Ellenőzi, hogy egy adott DOM node-on létezik-e egy adott attribútum.

domAttr.has("myNodeId", "someAttr");
get() Visszaadja egy adott DOM node egy adott attribútumát, illetve null-t, ha az attribútumnak nincs megadott vagy alapértelmezett értéke.

domAttr.get("myNodeId", "someAttr");
set() Beállítja egy adott DOM node egy adott attribútumának az értékét.

domAttr.set("myNodeId", "someAttr", "value");
domAttr.set("myNodeId", {
    someAttr1: "value1",
    someAttr2: "value2"
});
remove() Eltávolít egy adott attribútumot egy adott DOM node-ból.

domAttr.remove("myNode", "someAttr");
getNodeProp() Ugyanaz, mint a get(), csak akkor is visszaad egy alapéterlmezett/böngésző által használt értéket, ha az adott attribútum nem létezik. Például az alábbi hívás eredménye „text” lesz, ha az adott input elemen nem volt type attribútum.

domAttr.getNodeProp("myInputNodeId", "type");

A DOM Properites API (dojo/dom-prop)

FüggvényLeírás és példa
get() Egy adott DOM node egy adott tulajdonságát kérdezi le.

domProp.get("myNodeId", "innerHTML");
set() Egy adott DOM node egy adott tulajdonságát állítja be.

domProp.set("myNodeId", "innerHTML", "Hello World!");
domProp.set("myNodeId", {
    innerHTML: "Hello World!",
    class: "example"
});

A DOM class API (dojo/dom-class)

FüggvényLeírás és példa
contains() Igaz, ha az adott node tartalmazza az adott CSS osztályt, hamis, ha nem.

domClass.contains("myNodeId", "myClass");
add() Hozzáad egy CSS osztályt vagy osztályok egy halmazát egy adott DOM node-hoz (duplikációk nem lesznek).

domClass.add("myNodeId", "newClass");
remove() Eltávolít egy CSS osztályt vagy osztályok egy listáját a DOM node-ból. Ha a második argumentumát nem határozzuk meg vagy undefined, akkor az összes osztályt eltávolítja.

domClass.remove("myNodeId", "style1");
domClass.remove("myNodeId", "style1 style2");
domClass.remove("myNodeId", ["style1", "style2"]);
domClass.remove("myNodeId");
replace() Lecserél egy vagy több CSS osztályt. Gyorsabb, mintha először remove()-ot, aztán add()-ot hívnánk.

domClass.replace("myNodeId ", "add1", "remove1");
toggle() Hozzáad egy osztályt az adott node-hoz, amennyiben az még nem létezik. Ha létezik, akkor pedig eltávolítja. A harmadik opcionális paraméter mondja meg, hogy hozzáadunk, vagy eltávolítunk – ezáltal kikényszeríthetjük egy adott osztály hozzáadását, akkor is, ha az már létezik. Ez csupán egy kényelmi metódus a contains(), add(), remove() függvények tipikus kombinációjára.

domClass.toggle("example1", "style1");
domClass.toggle("example2", "style2", true);

A DOM stílus API (dojo/dom-style)

FüggvényLeírás és példa
getComputedStyle() A paraméterben megadott node-ra visszaadja az érvényben lévő stílust, amely tartalmazhat böngésző-specifikus tulajdonságokat is. Költséges, ezért mindig hasznosítsuk újra a kapott eredményt, amikor lehetséges.

var node = dom.byId("myNodeId");
var computedStyle = domStyle.getComputedStyle(node);
get() Visszaadja az adott node stílusát. Ez már az érvényben lévő stílus, nem pusztán a node.style értéke. Ha csak a node-ot adjuk át, akkor az érvényben lévő stílust adja vissza (mintha getComputedStyle()-t hívtunk volna).

var width = domStyle.get("myNodeId", "width");
set() Beállítja az adott node stílusát.

domStyle.set("myNodeId", "width", "100px");
domStyle.set("myNodeId", {
    width: "100px",
    backgroundColor: "blue"v });

Inline stílus eltávolításához adjunk át üres stringet:

domStyle.set("myNodeId", "display", "");

A DOM geometria API (dojo/dom-geometry)

Box Model
FüggvényLeírás és példa
position() Visszaadja egy adott DOM node border-box-ának szélességét és magasságát, illetve az abszolút pozícióját (x, y). Ha az opcionális inlcudeScroll paraméter értéke hamis, akkor a visszaadott x, y értékek relatívak a böngészőben látszó aktuális területhez képest (ez az alapértelmezett).

var includeScroll = false;
var output = domGeom.position(node, includeScroll);

Így néz ki egy visszaadott objektum:
{ x: 700, y: 900, w: 300, h: 150 }
getMarginBox() Visszaadja egy adott DOM node margin-box-ának szélességét és magasságát, illetve pozícióját (left, top).

var output = domGeom.getMarginBox(node, computedStyle);

A második paraméter opcionális, lekéri maga a függvény, ha nincs megadva. Célszerű azonban egyszer lekérni a getComputedStyle()-t, és átadni a referenciát.

Így néz ki egy visszaadott objektum:
{ l: 8, t: 34, w: 268, h: 168 }
setMarginBox() Beállítja egy adott DOM node margin-box-ának méretét és pozícióját. A computedStyle paraméter opcionális.

var box = { l: 20, t: 20, w: 200, h: 200 };
var computedStyle = style.getComputedStyle(node);
domGeom.setMarginBox(node, box, computedStyle);
getContentBox() Visszaadja egy adott DOM node content-box-ának szélességét és magasságát, illetve pozícióját (left, top) az aktuális box modelltől függetlenül. A computedStyle paraméter opcionális.

var output = domGeom.getContentBox(node, computedStyle);
setContentSize() Beállítja az adott DOM node tartalmának méretét, margin-tól, padding-tól és border-től függetlenül. A computedStyle paraméter opcionális.

var box = { w: 300, h: 400 };
domGeom.setContentSize(node, box, computedStyle);
getPadExtents() Speciális értékeket ad vissza, melyek hasznosak lehetnek egy node pozícionálásához (többnyire erre azonban nem lesz szükség). A computedStyle paraméter opcionális.

var output = domGeom.getPadExtents(node, computedStyle);

Így néz ki egy visszaadott objektum:
{ l: 16, t: 16, r: 16, b: 16, w: 32, h: 32 }

l/t/r/b: a bal/felső/jobb/alsó padding
w: a bal és jobb padding összege
h: a felső és alsó padding összege
getBorderExtents() Egy adott DOM node border-ének méretét adja vissza. A computedStyle paraméter opcionális.

var output = domGeom.getBorderExtents(node, computedStyle);
getPadBorderExtents() Ugyanaz, mint a getPadExtents(), annyi különbséggel, hogy ez a padding-on felül a border értékét is beleszámítja. A computedStyle paraméter opcionális.

var output = domGeom.getPadBorderExtents(node, computedStyle);
getMarginExtents() Szintén speciális értékekkel tér vissza, ezúttal margókkal kapcsolatban:

l/t/r/b: a bal/felső/jobb/alsó margin
w: teljes szélesség, a margókat is beleértve
h: teljes magasság, a margókat is beleértve

A computedStyle paraméter opcionális.

var output = domGeom.getMarginExtents(node, computedStyle);
isBodyLtr() Igaz, ha az aktuális nyelv balról jobbra halad.

domGeom.isBodyLtr();
normalizeEvent() Normalizálja egy DOM esemény geomatriáját (a pageX, pageY, offsetX, offsetY, layerX és layerY tulajdonságokat).

domGeom.normalizeEvent(e);
docSroll() Visszaad egy normalizált objektumot, illetve az aktuális scroll pozíciónak megfelelő x, y offszet értékeket.

var output = domGeom.docScroll();
fixIeBiDiScrollLeft() Balról jobbra haladó nyelvek esetén a scrollLeft értéke negatív kéne, hogy legyen, az IE azonban pozitív értékkel tér vissza. Ez ennek a javítására alkalmas:

var output = domGeom.fixIeBiDiScrollLeft(node.scrollLeft);
getMarginSize() Visszaadja egy adott DOM node margin-box-ának szélességét és magasságát. A computedStyle paraméter opcionális.

var output = domGeom.getMarginSize(node, computedStyle);

A DOM konstrukciós API (dojo/dom-construct)

FüggvényLeírás és példa
toDom() Egy HTML kódrészletből elkészíti a DOM node-ot.

var node = domConstruct.toDom("<div>I'm a Node</div>");
place() A node-ok hierarchiában való elhelyezésére szolgál. Már létező node-okat is tudunk vele máshova helyezni, illetve új node-ot is lehet létrehozni, és azt rögtön elhelyezni. Visszaadja az elhelyezett node-ot.

domConstruct.place("someNode", "refNode", "before");
domConstruct.place("someNode", "refNode", "after");
domConstruct.place("someNode", "refNode", "replace");

Elhelyezés gyerekként:
  • first
  • last (ez az alapértelmezett, ha nem adunk meg harmadik argumentumot)
  • only (az összes gyereket lecseréli a kívánt node-al)
  • pozíció szerint (0-tól indexelve)
create() Egy kényelmi funkció a gyakran használt DOM műveltek egybefoglalására: elkészít egy node-ot, beállít rajta bizonyos attribútumokat és elhelyezi a hierarchiában.

domConstruct.create("div");
domConstruct.create("div", { innerHTML: "<p>hi</p>" });
domConstruct.create("div", null, win.body());
domConstruct.create("div", null, win.body(), "first");
domConstruct.create(node, { style: { color: "red" } }, win.body());
empty() Kiüríti egy adott DOM node tartalmát (az összes gyereket törli).

domConstruct.empty("myNodeId");
destroy() Töröl egy adott DOM node-ot és annak összes gyerekét.

domConstruct.destroy("myNodeId");

DOM és lekérdezés

dojo/query

Lehetővé teszi, hogy CSS szelektorok segítségével keressünk node-ok között. Az első argumentuma a szelektor, a második opcionális argumentum pedig a kontextus, ami csökkenti a szelektor érvényességi körét, és csak a megadott node gyerekei közt keres. DOM node-ok listájával tér vissza (NodeList).

query(".someClass", "someId"); query(".someClass", node);

A dojo/query és a NodeList is a láncolhatóság figyelembevételével lett tervezve, a NodeList legtöbb függvénye NodeList-el tér vissza.

query("li").forEach(function(node) { node.innerHTML = "Something"; }).style("color", "red").style("fontSize", "12px");

dojo/NodeList

A NodeList egy JavaScript tömb, kiegészítve számos hasznos függvénnyel. Ezzel tér vissza a query(), de közvetlenül is létrehozhatunk példányokat:

var nodelist = query.NodeList(); nodelist.push(dom.byId("someId")); nodelist.push(dom.byId("someOtherId"));

Függvények: at(), concat(), end(), every(), forEach(), indexOf(), instantiate(), lastIndexOf(), map(), on(), slice(), some(), splice()

Kiterjesztés: Kifejezetten úgy lett tervezve, hogy ki lehessen terjeszteni. Tulajdonképpen pont ez az, amit a többi modul (dojo/NodeList-*) csinál. Arra kell ügyelnünk, hogy mindig térjünk vissza this-el a láncolhatóság megőrzése érdekében.