Dojo toolkit - Instalacja, Tworzenie Interfejsu Graficznego, AJAX, Funkcje wyższego rzędu, Programowanie Obiektowe, Zdarzenia, Animacja, książki o dojo.

Dojo Toolkit Tutorial
Instalacja

Aby zasintalować dojo toolkit należy zciągnąć najnowszą stabilną wersje ze strony http://download.dojotoolkit.org, następnie rozpakować do katalogu dostępnego na serwerze www np. js.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl" lang="pl">
<head>
  <title>Dojo Hello World</title>
  <script type="text/javascript" djConfig="parseOnLoad: true"
             src="js/dojo/dojo.js">
  </script>
  <script type="text/javascript">
  // tu wpisujemy kod jascript
  </script>
  <style type="text/css">
    @import "js/dijit/themes/tundra/tundra.css";
    @import "js/dojo/resources/dojo.css"
  </style>
</head>
<body>
  <p>Hello Dojo</p>
</body>
</html>
Tworzenie Interfejsu Graficznego

Interface Graficzny tworzy się za pomocą dojo.dijit. Dijit jest to skrót od Dojo Widget.

Aby dodać widget nalerzy dodać atrybut dojoType do elementów html-a. Kiedy DOM dokumentu HTML jest gotowy Dojo parsuje kod HTML w poszukiwaniu atrybutów dojoType i wstawia widgety.

<form>
<input type="text"
maxlength=25
name="last"
dojoType="dijit.form.TextBox"/>
<button dojoType="dijit.form.Button">Button<button>

Aby umożliwić tworzenie widgetów nalerzy dodać odpowiednie pliki za pomocą funkcji dojo.require.

<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.form.TextBox");
dojo.require("dijit.form.Button");
</script>

dojo.parser jest potrzebny aby umożliwić parsowanie kodu html

Aby odwołać się do widgetu należy skorzystać z funkcji dijit.byId

Tutaj możesz znaleźć listę widgetów dojo.

Funkcje wyzszego rzedu

Aby iterować po jakiejś tablicy można użyć mapowania funkcji dojo.map. Pierwszym argumentem tej funkcji jest tablica wartości, natomiast drugim funkcja. Funkcja dojo.map zwróci tablicę wartości utworzoną z kolenych wywołań funkcji przekazanej jako drugi argument.

function square(n) {
  return n * n;
}
dojo.map([1, 2, 3, 4, 5, 6], square);

Powyżesze wywołanie funkcji dojo.map zwróci kwadraty liczb od 1 do 6 czyli tablicę [1, 4, 9, 16, 25, 36].

Gdy chcemy iterować po jakiejś talibcy ale nie interesuje nas zwracana wartość możemy użyć funkcji dojo.forEach, która tak jak w przypadku funkcji dojo.map, jako pierwszy argument przyjmuje tablice wartości, a jako drugi funkcje, która zostanie wywołana dla każdego elementu tablicy.

dojo.forEach([1, 2, 3, 4, 5, 6], document.write);

Powyższy kod wyświetli liczby do 1 do 6.

Ciekawą funkcją jest funkcja dojo.partial. Funkcja jako pierwszy parametr przyjmuje funkcje, a jako kolejne argumenty wartości, które zostaną przekazane do nowo utworzonej funkcji.

function square(n) {
  return n * n;
}
var square10 = dojo.partial(square, 10);
document.write(square10());

Wywołanie funkcji square10 zwróci wartość 10 * 10.

Funkcja dojo.filter zwróci tablicę elementów dla których funkcja, przekazana jako drugi parametr, zwróci wartość true.

function print(string) {
  document.write(string);
}
function nieparzysta(liczba) {
  return liczba % 2 !== 0;
}
dojo.forEach(dojo.filter([1, 2, 3, 4, 5, 6, 7], nieparzysta), print);

W powyższym kodzie użyliśmy funkcji dojo.filter do wybrania liczb nieparzystych następnie funkcji dojo.forEach do wypisania ich w dokumencie.

DOM

Odwołanie do elementu o indetifikatorze objekt

var objekt = dojo.byId("obiekt");

Za pomocą funkcji dojo.query mamy możliwość odwoływać się do objektów określanych przez selektory CSS.

dojo.query(".klasa");

Powyższe wywołanie zwróci objekt, za pomocą którego możemy odwoływać się do każdego objektu o klasie klasa.

dojo.query("#identyfikator");

Powyższe wywołanie zwróci objekt o identyfikatorze id = "identyfikator".

Aby utworzyć nowy objekt używamy funkcji dojo.doc.createElement, natomiast za pomocą funkcji dojo.place możemy umieścić go w drzewie objektów.

var naglowek = dojo.doc.createElement("H1");
naglowek.innerHTML = "To jest treść nagłówka";
dojo.place(naglowek, "body", "last");

W powyższym kodzie użyliśmy pola innerHTML do wstawienia zawartości. Pierwszy parametr określa objekt, który ma zostać wstawiony, drugi określa objekt, wewnątrz którego zostanie wstawiony element, ostatni parametr określa gdzie ma zostać wstawiony, może także przyjmować wartość first.

Programowanie Obiektowe

Dojo Toolkit umożliwia łatwiejsze tworzenie klas (umożliwia także dziedziczenie).

Aby utworzyć nową klase korzystamy z funkcji dojo.declare.

dojo.declare("Klasa1", null, { // null - brak klasy bazowej
  constructor: function(foo) { // konstruktor
    this.foo = foo;
  },
  // metody get i set
  setFoo: function(foo) { this.foo = foo; },
  getFoo: function() { return this.foo; }
});

var objekt = new Klasa1("Lorem Ipsum");
document.write(objekt.getFoo());
objekt.setFoo("Dolor Amet");
document.write("objekt.foo: " + objekt.getFoo() + "<br/>");

dojo.declare("Klasa2", Klasa1, {
  constructor: function(foo, bar) {
    Klasa1.constructor(foo); // wywołanie konstruktora klasy bazowej
    this.bar = bar;
  },
  setBar: function(bar) { this.bar = bar; },
  getBar: function() { return this.bar; }
});

var objekt2 = new Klasa2("Lorem", "Ipsum");
document.write("objek2 foo: " + objekt2.getFoo() + " bar: " +
               objekt2.getBar() + "<br/>");

W powyższym kodzie tworzone są dwie klasy Klasa1 i Klasa2, która dziedziczy po klasie Klasa1 (drugi argument funkcji dojo.declare zawiera klasę rodzica lub tablicę klas), oraz tworzone są dwa objekty objekt i objekt2, dla których wywoływane są metody setFoo, getFoo i getBar.

Istnieje możliwość rozszeżania klas i objektów za pomocą funkcji dojo.extend i dojo.mixin.

dojo.declare("Foo", null, {
  constructor: function(foo) {
     this.foo = foo;
  },
  setFoo: function(foo) { this.foo = foo; },
  getFoo: function() { return this.foo; }
});

dojo.extend(Foo, {
  bar: "undefined",
  getBar: function() { return this.bar; },
  setBar: function(bar) { this.bar = bar; }
});
var foo = new Foo("Lorem");
foo.setBar("Ipsum");
document.write("bar = " + foo.getBar());

Powyższy kod tworzy nową klasę Foo za pomocą funkcji dojo.declare, a następnie rozszerza daną klasę o nowe metody setBar i getBar i jedno pole bar.

var foo = new Foo("Lorem Ipsum");
dojo.mixin(foo, {
  baz: "undefined",
  getBaz: function() { return this.baz; },
  setBaz: function(baz) { this.baz = baz; }
});
foo.setBaz("Dolor Amet");
document.write("foo.baz = " + foo.getBaz());

W powyższym kodzie tworzony jest nowy objekt klasy Foo z poprzedniego przykładu, następnie rozszerzany zostaje o nowe pole baz oraz dwie metody getBaz i setBaz, które są następnie wywoływane.

Zdarzenia

Odpowiedzi na zdarzenia tworzymy za pomocą funkcji dojo.connect lub za pomocą metody connect objektu zwróconego za pomocą funkcji dojo.query.

dojo.connect(dojo.byId("identyfikator"), "onclick", function(evt) {
  alert("Właśnie kliknąłeś element o identyfikatorze \"identyfikator\"");
}
// lub
dojo.query("#identyfikator").connect("onClick", function(evt) {
  alert("Właśnie kliknąłeś element o identyfikatorze \"identyfikator\"");
}

Odpowiedzi na zdarzenia można podpinać pod metody objektów.

var objekt = {
  metodaA: function() {
    alert("Wywołałeś metodę \"metodaA\".");
  }
};
var objekt2 = {
  metodaB: function() {
    alert("Wywołałeś metodę \"metodaB\".");
  }
};
dojo.connect(objekt, "metodaA", objekt2, "metodaB");

objekt.metodaA();

Wywołując metodę objekt.metodaA wywołujemy także metodę objekt2.metodaB.

Animacja

Aby użyć animacji zanikania i pojawiania się można użyć odpowiednio funkcji dojo.fadeOut i dojo.fadeIn.

dojo.addOnLoad(function() {
  var objekt = dojo.byId("objekt");
  dojo.fadeOut({
    node: objekt,
    delay: 100,
    duration: 100
  }).play();
});

W powyższym kodzie w funkcji dojo.fadeOut użyto objektu zawierającego pola node, określające element htmla który ma zostać animowany, delay, określający opóźnienie animacji w milisekundach oraz duration określające czas trwania animacji, także w milisekundach. Aby rozpocząć animacje należy wywołać metodę play objektu zwróconego przez funkcję dojo.fadeOut. Analogicznie można wywoływać funkcję dojo.fadeIn.

dojo.addOnLoad(function() {
  var visible = true;
  var objekt = dojo.byId("objekt");
  dojo.query("#przycisk").connect("onclick", function(evt) {
    if (visible) {
      dojo.fadeOut({
        node: objekt
      }).play();
      visible = false;
    } else {
      dojo.fadeIn({
        node: objekt
      }).play();
      visble = true;
    }
  });

Powyższy kod wywoła animacje zanikania i pojawiania się za każdym razem gdy klikniemy przycisk o atrybucje id = "przycisk".

Dołączając moduł dojo.NodeList-fx można używać animacji dla objektów zwróconych przez funkcje dojo.query.

dojo.require("dojo.NodeList-fx");
dojo.addOnLoad(function() {
  dojo.query("#identyfikator").fadeOut().play();
});

Za pomocą funkcji dojo.query możemy animować kilka elementów na raz, np. objekty pewnej klasy.

dojo.require("dojo.NodeList-fx");
var fade = function() {
  dojo.query(".fadeNode").fadeOut().play();
}
dojo.addOnLoad(function() {
  dojo.connect(dojo.byId("naglowek"), "onclick", "fade");
}
AJAX

Za pomocą funkcji dojo.xhrGet możemy wykonać zapytanie do serwera.

dojo.addOnLoad(function() {
  var zawartosc = dojo.byId("zawartosc");
  dojo.xhrGet({
    url: "js/plik.txt",
    handleAs: "text",
    load: function(data, args) {
      dojo.fadeOut({
        node: zawartosc,
	onEnd: function() {
	  zawartosc.innerHTML = data;
	  dojo.fadeIn({ node: zawartosc}).play();
	}
      }).play();
    }
  }); // dojo.xhrGet
}); // addOnLoad

W powyższym kodzie użyliśmy animacji do wygaszenia objektu, o parametrze id = "zawartosc", załadowania zawartości i ponownego wyświetlenia objektu. Do funkcji dojo.xhrGet przekazujemy objekt z parametrami: url - określający adres url do załadowania, handleAs - określający jak ma traktować dane, oraz load - określający funkcje która zostanie wywołana w momencie gdy dane zostaną pobrane z serwera.

Za pomocą xhrGet możemy pobierać tylko dane z serwera na którym znajduje się dana strona.

Za pomocą funkcji dojo.xhrPost możemy wykonać zapytanie POST do serwera.

dojo.addOnLoad(function() {
  dojo.xhrPost({
    url: "skrypt.php",
    content: {
      "foo": "Lorem",
      "bar": "Ipsum",
      "baz": "Dolor"
    },
    load: function(data, ioargs) {
      dojo.byId("content").innerHTML = data;
    }
  });
});

Pole content zawiera parametry które zostaną przekazane do skryptu po stronie serwera. Poniżej pokazano przykładowy skrypt php wyświetlający zawartość zmiennych POST.

<?php
header("Content-type: text/plain; charset=utf-8");
echo "foo: {$_POST['foo']}\n";
echo "bar: {$_POST['bar']}\n";
echo "baz: {$_POST['baz']}\n";
?>

Do przekazywania parametrów do skryptu, po stronie serwera, możemy użyć formularza. Poniżej przedstawiono prosty formularz hmtl.

<form id="formularz" method="POST">
  <label for="name">Name: </label>
  <input type="tet" name="name" value="Enter name" />
  <input type="submit" value="wyślij" />
</form>

Do przesłania danych do serwera użyjemy poniższego skryptu.

function formSubmit(e) {
  e.preventDefault(); // wyłączenie normalnego wywołania
  dojo.xhrPost({
    url: "skrypt.php",
    form: "formularz",
    handleAs: "text",
    handle: function(data, args) {
      if (typeof data == "error") {
        alert("Błąd wczytania danych!");
      } else {
        dojo.byId("zawartosc").innerHTML = data;
      }
    }
  });
}
dojo.onLoad(function() {
  dojo.connect(dojo.byId("formularz"), "onsubmit", "formSubmit");
});

Powyższy kod używa pola handle dla określenia funkcji, która zostanie wywołana w przypadku powodzenia lub nie powodzenia.

Ksiazki