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

Dojo Toolkit

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)

  1. Začínáme používat Dojo Toolkit 29.5.2009
  2. Začínáme používat Dojo Toolkit (pokračování) 11.6.2009
  3. Dojo Toolkit: AJAX a animace 15.6.2009
  4. Dojo Toolkit: pokročilé techniky 22.6.2009

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.

Vystudoval jsem biochemii. Vymyslel jsem a založil Zdroják. Jsem vyhlášeným expertem na likvidaci komentářů. Nejsem váš hodný tatínek, který vás bude brát za ručičku, já jsem zlý moderátor diskusí. Smiřte se s tím!

Čtení na léto

Jaké knihy z oboru plánujete přečíst během léta? Pochlubte se ostatním ve čtenářské skupině Zdrojak.cz na Goodreads.com.

Komentáře: 2

Přehled komentářů

jjjjj dijit
v6ak dojo.attr: nejen ID
Zdroj: http://www.zdrojak.cz/?p=3028