Začínáme používat Dojo Toolkit (pokračování)

Dojo Toolkit patří mezi populární javascriptové frameworky. V dnešní druhé části vás seznámíme s nástroji pro práci s DOM a kaskádovým styly.
Seriál: Seznamte se s Dojo Toolkitem (4 díly)
- Začínáme používat Dojo Toolkit 29. 5. 2009
- Začínáme používat Dojo Toolkit (pokračování) 11. 6. 2009
- Dojo Toolkit: AJAX a animace 15. 6. 2009
Nálepky:
Tento článek je překladem anglického originálu vydaného na portálu Dev.Opera. První část překladu jste si mohli přečíst nedávno.
Předávání zpráv pomocí dojo.publish a dojo.subscribe
Jedná se o šikovný způsob zasílání informací rozličným objektům. Po registraci do pojmenovaného kanálu pomocí dojo.subscribe()
bude zaregistrovaná funkce zavolaná kdykoliv bude na stejném kanálu zavolána dojo.publish()
.
var subscription = dojo.subscribe("/system/alerts", function(msg) {
console.log(msg);
});
// a následně:
dojo.publish("/system/alerts", ["Byl jste odhlášen"]);
Jedná se o užitečný způsob pro komunikaci mezi sekcemi stránky bez toho, aby o sobě jednotlivé komponenty musely předem vědět. V příkladu výše jsme handle volání dojo.subscribe
uložili do proměnné. Podobně jako u volání dojo.disconnect
, které jsme si představili posledně, můžeme sledování kdykoliv odhlásit předáním handlu do volání dojo.unsubscribe
:
var handle = dojo.subscribe("/foo/bar", function(msg) {
console.log("V tomto příkladu se nikdy nespustím.")
});
dojo.unsubscribe(handle);
dojo.publish("/foo/bar", ["Bflmpsvz"]);
Tento způsob komunikace (v originále nazývaný topics pozn. překl.) je používán na řadě míst Dojo API. Tak například dojo.dnd
(komponenta Drag and Drop) používá události „/dnd/move/start“ a „/dnd/move/stop“. Komponenta Dijitu dijit.layout.TabContainer
tento způsob používá pro události typu addChild
, selectChild
, removeChild
atd.
Nástroje polí
Jedná se o dojo.map
, dojo.filter
, dojo.every
, dojo.some
, dojo.forEach
, dojo.indexOf
a další. Dojo nabízí metody polí, které můžete najít v JavaScriptu 1.6, které poskytují funkcionální přístup pro řadu problémů.
Nejpoužívanější bude asi forEach
, která spustí funkci na každém prvku v poli:
var arr = ["one","two","three","four"]; dojo.forEach(arr, function(elm, index, theArray) {
// elm je iterovaná položka pole:
console.log(elm);
// index označuje, kde se v poli právě nacházíme:
console.log('run ', index, ' times');
// theArray obsahuje celé pole, pokud byste jej náhodou potřebovali:
console.log(elm == theArray[index]);
// měla by vrátit 'true'
});
Volitelný třetí parametr metody forEach
je kontext ( scope
), který využívá metodu dojo.hitch
(popsali jsme si ji minule) k přepnutí kontextu naší funkce na jiný objekt.
var arr = ["one","two","three","four"];
var obj = {
log: function(elm) {
console.log(elm);
}
};
dojo.forEach(arr, function(elm) {
// elm je iterovaná položka pole:
this.log(elm);
}, obj);
Metoda filter snižuje počet prvků pole v závislosti na návratové hodnotě volané funkce:
var arr = ["one","two","three","four"];
var newArr = dojo.filter(arr, function(elm, i) {
// nechme jen sudá čísla:
return i % 2 !== 0;
});
console.log(newArr);
Metoda map vytvoří nové pole z prvků získaných z návratových hodnot volané funkce:
var arr = ["a","b","c","d"];
var other = ["one", "two", "three", "four"];
var newArr = dojo.map(arr, function(elm, i) {
if(i % 2 == 0) {
// jen liché prvky z dalšího pole
return other[i];
}
});
console.log(newArr);
Metody indexOf
a lastIndexOf
vrátí celé číslo indexu prvního nalezeného výskytu hledané položky v poli, nebo –1 pokud ji nenajdou:
var arr = ["one","two","three","four","five","one"];
console.log(dojo.indexOf(arr, "two")); // 1
console.log(dojo.lastIndexOf(arr, "one")); // 5
console.log(dojo.indexOf(arr, "one")); // 0
console.log(dojo.indexOf(arr, "unknown")); // -1
Nástroje k DOM a CSS
Metody dojo.place
, dojo.clone
, dojo.attr
, dojo.style
, dojo.addClass/removeClass/toggleClass
, dojo.marginBox
a dojo.coords
vám zpříjemní manipulaci s DOM z JavaScriptu.
Metoda dojo.place
umístí prvek (node) relativně k jinému prvku (nodu):
// vlož nové <li> na začátek ul id="miUl":
var li = dojo.doc.createElement('li');
dojo.place(li, "myUl", "first");
// nastav nějaký obsah:
li.innerHTML = "Hi!";
Metoda dojo.clone
vytvoří klon prvku, a vrátí ho jako svou návratovou hodnotu:
var input = dojo.query(".cloneMe")[0];
dojo.query("#someButton").onclick(function(e) {
// vlož nový <input /> kdykoliv klikne na "someButton"
dojo.clone(input);
dojo.place(input, e.target, "last");
});
Metoda dojo.attr
obstarává čtení a zápis atributu fungující bez problému napříč prohlížeči:
// getter:
dojo.attr("someId", "title"); // title="bar"
// setter, single:
dojo.attr("someId", "title", "A new Title");
// setter, multiple:
dojo.attr("someId", {
"tabindex": 2, // add to tab order
"onclick": function(e) {
// obsluha události click
}
});
Funkce dojo.style
pracuje se stejným API jako dojo.attr
, ale funguje pro vlastnosti CSS:
// getter:
dojo.style("someId", "height");
// setter, single:
dojo.style("someId", "padding", "8px");
// setter, multiple:
dojo.style("someId", {
"fontSize": "14pt",
"color": "#333"
});
Mezi jednoduchými nástroji pro nastavování atributu class najdeme dojo.addClass
, dojo.removeClass
, dojo.toggleClass
a dojo.hasClass
. Všechny fungují na podobném principu: předejte jim řetězec s ID nebo referenci na prvek DOM. dojo.hasClass
vrací logickou hodnotu true
, pokud má daný prvek DOM nastenou požadovanou třídu.
Nalezení prvku ve stránkce, nastavení jeho velikosti můžete provést následovně:
// vrátí x, y, t, l, w a h hodnoty pro id="someNode"
var pos = dojo.coords("someNode");
console.log(pos);
// zahrne případný scroll offsets do hodnot "t" a "l"
var abs = dojo.coords("someNode", true);
console.log(abs);
// získá marginBox a nastaví další prvek na stejnou velikost
var mb = dojo.marginBox("someNode");
dojo.marginBox("otherNode", mb);
Nástroje pro práci s DOM vás zbaví nepříjemností s obcházením rozdílných implementací v prohlížečích a nabízí jednoduché API pro běžné úlohy.
Selektorový engine dojo.query včetně CSS3
Jinak řečeno: „Dej mi prvky DOM, ať s nimi můžu něco provést.“
Většina API z core používá (tam, kde to dává smysl) dojo.query
. Jinými slovy, cokoliv můžete vykonat na jednom prvku DOM, to můžete stejným způsobem vykonat na sadě nalezených prvků. Dříve použitý příklad s onclick
můžeme přepsat následovně:
dojo.addOnLoad(function() {
dojo.query("#someNode").connect("onclick", function(e) {
console.log('kliknul na prvek dojo.byId("someNode")', e.target);
});
});
Pro větší pohodlí jsou k dispozici aliasy, můžete tak použít:
dojo.query("#someNode").onclick(function(e) {
console.log('kliknul na prvek dojo.byId("someNode")', e.target);
});
Najdete zde všechny události z DOM úrovně 2: .onclick
, .onmouseenter
, .onmouseleave
, .onmousemove
, .onmouseover
, .onmouseout
, .onfocus
, .onblur
, .onkeypress
, .onkeydown
, .onkeyup
, .onsubmit
a .onload
. Metody dojo.query
jsou také řetězitelné, většina volání vrací stejnou instanci NodeList
.
dojo.addOnLoad(function() {
// napoj funkce mouseenter a mouseleave functions na všechny prvky div se třídou "hoverable":
dojo.query("div.hoverable")
.connect("onmouseenter", function(e) {
dojo.style(e.target, "opacity", 1);
})
.connect("onmouseout", function(e) {
dojo.style(e.target, "opacity", 0.42);
})
.style( {
// nastav počáteční průhlednost na 0.42 jakoby nastal mouseout
opacity: 0.42,
// a také barvu:
backgroundColor:"#ededed"
});
});
Rozšíření dojo.query
(nebo „vytvoření pluginu“) je velmi snadné:
dojo.extend(dojo.NodeList, {
makeItRed: function() {
return this.style({ color:"red" });
},
setColor: function(color) {
return this.style({ color: color });
}
});
// spustí makeItRed na všech nodech
dojo.query(".greenNodes").makeItRed();
// nastaví barvu pro všechny .redNodes na odstín šedé:
dojo.query(".redNodes").setColor("#ededed");
Někdy se hodí pracovat přímo s referencí na prvek DOM. Když například registrujete handler onclick
na prvku div
, každý prvek uvnitř tohoto div
u bude po kliknutí event.target
, za předpokladu, že událost k div
u probublá. Někdy chcete s původním prvkem pracovat přímo, například:
dojo.query("li").forEach(function(n) {
dojo.connect(n,"onclick",function(e) {
if(n == e.target) {
console.log('same node');
} else {
console.log('bubbling up from different node');
}
// ujisti se, že třídu nastavíme jen k prvku LI, bez ohledu na target
dojo.addClass(n, "beenClicked");
});
});
Dojo nezapleveluje globální jmenný prostor, nesnaží se vytvářet řady krátkých proměnných. Pokud vyžadujete aliasy pro často používané funkce, jste schopni tak učinit. K dojo.query
můžete snadno vytvořit alias:
(function($) {
$("a[href^=http://]").onclick(function(e) {
// před opuštěním stránky nech potvrdit všechny externí odkazy
if(!confirm("Visit" + $(e.target).attr("href") + "?")) {
e.preventDefault();
}
});
})(dojo.query);
Nebo způsobem, který můžete často najít ve zdrojovém Doja:
(function() {
var d = dojo;
d.addOnLoad(function() {
d.connect(d,"loaded",function() {
console.log("obfuscated some");
})
});
})();
JavaScript je velmi flexibilní jazyk. Složitější ukázku najdete v článku Neila Roberta Creating your Own $ na DojoCampus, kde je celý Dojo toolkit namapován na jednoduchou proměnnou $.
dojo.query
a dojo.NodeList
následují filosofii jako zbytek Dojo Toolkitu. Metody se specifickými use case jsou vyjmuty ze základního dojo.js
, což vám umožňí je přidat jen, pokud je potřebujete, a to pomocí jednoduchého dojo.require
:
dojo.require("dojo.NodeList-fx"); // přídá podporu animací do dojo.query
dojo.require("dojox.fx.ext-dojo.NodeList"); // přidá DojoX animační addon do dojo.query
dojo.require("dojo.NodeList-html"); // přidá pokročilé HTML nástroje do dojo.query
Jmenné konvence těchto balíčků jsou trochu odlišné. Pomlčka, která je v klasické tečkové notaci nevalidním znakem, zde plní úlohu „cross package manipulation“. Například dojo.NodeList-fx
přidá „fx“ do NodeList
u, ale nikdy nemůžete zavolat metodu dojo.NodeList-fx
přímo. Tyto metody jsou místo toho vloženy do dojo.NodeList
u. dojox.fx.ext-dojo.NodeList
můžete sémanticky číst „Tento modul přímo rozšiřuje Dojo třídu NodeList v DojoX FX projektu.“
Tento článek je překladem textu Introducing The Dojo Toolkit a je zde zveřejněn s laskavým svolením Opera Software.
pane kolego, kdy bude clanek o dijit?
Zarazilo mě, že by dojo.attr ctělo id. A opravdu nevyžaduje, můžu
podat i DomNode: http://api.dojotoolkit.org/….3/dojo.attr .