Mootools 1.1 - Class.Extras.js
30 maja, 2007
Plik class.extras.js zawiera trzy klasy - Chain, Events i Options. Rozszerzają one możliwości operowania na klasach. Klasa Chain umożliwia łańcuchowe wykonywanie funkcji (jedna po drugiej). Dzięki klasie Events możemy operować zdarzeniami towarzyszącymi wykonywaniu metod klas, a klasa Options pozwoli nam na trzymanie konfiguracji klasy w oddzielnym obiekcie i oczywiście zapewni nam odpowiedni dostęp do tego obiektu.
Chain
Klasa Chain jak już wspominałem służy do wykonywania jedna po drugiej funkcji - gdy jedna funkcja zakończy swe działanie, zaczyna wykonywać się druga funkcja, po niej trzecia itd. Klasa ta udostępnia trzy metody:
- chain()
- callChain()
- clearChain()
chain
Metoda chain służy do łączenia funkcji w swego rodzaju łańcuch. Aby do danej funkcji dodać kolejną wykonywanej po niej stosujemy następujący zapis:
obiekt.funkcja().chain(function({
// kod jaki wykona się po pierwszej funkcji
}));
Jeżeli chcemy dodać kolejny element naszego "łańcucha" zapiszemy:
obiekt.funkcja().chain(function(){
// kod jaki wykona się po pierwszej funkcji
}).chain(function(){
// kod jaki wykona się po drugiej funkcji
});
W ten sposób możemy dodać tyle elementów łańcucha ile tylko dusza zapragnie. Co bardzo ważne klasy Chain możemy używać w mootools tylko z wybranymi klasami - Fx.Base, AJAX i XHRoraz oczywiście z klasami, które są zbudowane na podstawie wymienionych klas.
Alternatywnym sposobem tworzenia łańcucha jest stworzenie obiektu Chain i dołączanie do niego kolejnych elementów metodą chain :
var lancuch = new Chain;
lancuch.chain(function(){
//kod funkcji
});
W tym wypadku możemy zwiększyć ilość ogniw w pętli zamiast pisania:
chain(...).chain(...).chain(...);
Jeszcze warto dodać przed przejściem do przykładów, że zapisując:
lancuch.chains.length;
Otrzymamy dostęp do informacji o tym ile elementów posiada nasz łańcuch...
Przedstawię teraz przykład łańcuchowego wykonywania funkcji. W przykładzie oprę się na klasie Fx.Styles - poznamy ją dokładniej dopiero przy omawianiu grupy Effects, ale chciałbym już teraz pokazać jakiś ciekawy przykład, a nie suche alerty czy inne proste zmiany treści divów...
W przykładzie wykonamy następującą animację - div zwiększy swoje rozmiary dwukrotnie, następnie zmniejszy wysokość do pierwotnego poziomu, potem zmieni poziom przezroczystości do 0.25 (25%), by następnie zmniejszyć szerokość do poprzedniego poziomu i na koniec przywrócić opacity równe 1. Jak łatwo policzyć musimy wykonać łańcuch złożony z 5 operacji:
var efekty = $('div_testowy').effects({transition: Fx.Transitions.Elastic.easeOut});
efekty.start({
"width": [300,600],
"height": [300,600]
}).chain(function(){
efekty.start({
"height": [600,300]
});
}).chain(function(){
efekty.start({
"opacity": [1,0.25]
});
}).chain(function(){
efekty.start({
"width": [600,300]
});
}).chain(function(){
efekty.start({
"opacity": [0.25,1]
});
});
W poniższym przykładzie zaprezentowałem dłuższy łańcuch (ciekawszy niż ten powyżej ;) ):
callChain
Pisałem już o dwóch sposobach tworzenia łańcucha funkcji, ale nie napisałem o pewnej subtelnej różnicy pomiędzy nimi. Otóż metoda tworzenia łańcucha jaką zaprezentowałem w poprzednim przykładzie spowoduje wykonanie od razu funkcji w danej kolejności, natomiast w wypadku tworzenia obiektu klasy Chain łańcuch taki nie zostanie wykonany - ma to swoją zaletę w tym, że nie zawsze będziemy chcieli wykonać od razu dany łańcuch funkcji - do uruchomienia takiego łańcucha, opartego na obiekcie klasy Chain wykorzystuje się metodę callChain. Jak ona działa ? W sposób bardzo prosty - przy jej wywołaniu, które wygląda następująco:
lancuch.callChain();
wykonywany jest pierwsze ogniwo łańcucha, po czym jest ono z tego łańcucha usuwane, a zatem drugie ogniwo łańcucha staje się pierwszym ogniwem. A więc aby wykonać cały łańcuch potrzebujemy uruchamiać okresowo funkcję callChain dla danego łańcucha aż do momentu gdy długość łańcucha będzie równa 0 (wspominałem już jak pobrać długość łańcucha). W stosunku do poprzedniego przykładu musimy na końcu funkcji chaining() dodać kod:
var timer = (function(){
(lancuch.chains.length == 0) ? $clear(timer) : lancuch.callChain();
}).periodical(1200);
A na początku kodu funkcji dodajemy kod:
var lancuch = new Chain();
Oczywiście pierwszy element poprzedniej wersji łańcucha musimy też złączyć metodą chain z obiektem lancuch ;)
clearChain
Ostatnia metoda klasy Chain służy jak sama nazwa wskazuje do czyszczenia łańcucha. Wywołujemy ją tak samo jak metodę callChain:
obiekt_lancucha.clearChain();
Gdzie ta metoda może być przydatna ? W sytuacji gdy na przykład chcemy przerwać łańcuch w czasie jego wykonywania, po spełnieniu jakiegoś warunku, albo w sytuacji gdy chcemy "wyczyścić" zmienną łańcucha i użyć jej przy innym łańcuchu... Przykładów nie będę tutaj dawał - bardzo dociekliwi mogą sobie sami dodać w drugim przykładzie kod:
lancuch.clearChain();
w wybranym ogniwie łańcucha i zobaczyć efekty ;)
Events
Klasa Events pozwala nam zarządzać zdarzeniami naszych klas. W skład klasy Events wchodzą trzy metody:
- addEvent
- fireEvent
- removeEvent
addEvent
Metoda addEvent służy do dodania zdarzenia do danej klasy. Wszystkie klasy oparte na klasie Fx.Base mają automatycznie zaimplementowaną klasę Event oraz mają dostępne trzy zdarzenia :
- onStart
- onCancel
- onComplete
W wypadku dodawania tych zdarzeń do danego obiektu jednej z klas posiadających "Fx" w nazwie nie musimy więc implementować klasy Events. Samo dodanie zdarzenia wygląda następująco:
obiekt.addEvent(zdarzenie, function(){
// kod funkcji
});
Na przykład:
var animacja = new Fx.Style('div_testowy','height').addEvent("onStart",function(){
alert("Zaczynam powiększać diva...");
});
W wypadku wszystkich innych klas (czyli tych nie opartych na Fx.Base) musimy najpierw dodać linijkę:
NazwaObiektu.implement(new Events);
I dopiero wtedy dodajemy linijkę:
NazwaObiektu.addEvent(zdarzenie,function(){
// kod funkcji
});
Oczywiście trzeba jeszcze to zdarzenie gdzieś umieścić i je uruchomić w odpowiednim momencie, ale to już zadanie dla metody fireEvent o której napiszę za chwilę - najpierw przykład użycia metody addEvent z klasą Fx.Style (tak naprawdę głównie z klasami z grupy "Fx" używa się zdarzeń).
Pamiętacie jeszcze drugi przykład (oj dawno był ;) ) ? Wywoływaliśmy tam okresowo funkcję callChain by wykonać cały łańcuch. Jaka była wada tego rozwiązania ? Każdy z łańcuchów musiał się wykonać w jednym określonym przedziale czasowym. Dzięki zastosowaniu metody addEvent ten problem zostanie rozwiązany. Co musimy zrobić ? Usuwamy z naszego kodu linijkę z timerem i okresowym wywoływaniem funkcji, a dodajemy linijkę:
lancuch.callChain();
Ona rozpocznie cały łańcuch. A co potem ? Zmieniamy linijkę definiującą efekty z :
var efekty = $('div_testowy').effects({ duration: 1000,transition: Fx.Transitions.Elastic.easeOut });
na:
var efekty = $('div_testowy').effects({ duration: 1000, transition: Fx.Transitions.Elastic.easeOut }).addEvent("onComplete",function(){ if(lancuch.chains.length !== 0) lancuch.callChain(); });
W ten sposób każdemu wywołaniu efektu będzie towarzyszyło zdarzenie onComplete, które wykona metodę callChain()w odpowiednim momencie (tj. po zakończeniu efektu). Przykład:
fireEvent
Metoda fireEvent jak już wspominałem jest przydatna przede wszystkim przy klasach nie należących do grupy "Fx". Pozwala nam na wywołanie funkcji przypisanej do danego zdarzenia. Ma dość złożoną składnię bo poza typem zdarzenia może pobierać argumenty (gdy są 2 lub więcej zapisujemy je w tablicy) oraz opóźnienie z jakim zostanie wykonana funkcja zdarzenia:
obiekt.fireEvent("zdarzenie",[argument1,argument2,argument3],opóźnienie);
Oczywiście metody fireEvent możemy używać także wtedy gdy chcemy od razu wykonać jakieś zdarzenie bez czekania na moment kiedy powinno się samo wykonać.
removeEvent
Metoda removeEvent to ostatnia z metod klasy Events, pozwala nam na usuwanie danego zdarzenia z grupy zdarzeń danej klasy. Jej obsługa jest bardzo prosta i ogranicza się do zapisu:
obiekt.removeEvent(zdarzenie);
Na przykład by usunąć zdarzenie onComplete z obiektu Testowy zapiszemy:
Testowy.removeEvent("onComplete");
Options
Ostatnią klasą wchodzącą w skład pliku class.extras.js jest klasa Options - pozwala nam na łatwe zarządzanie parametrami używanymi w klasach. Dzięki tej klasie możemy przy tworzeniu obiektu danej klasy dodać w argumentach opcje klasy.
Aby umożliwić naszej klasie korzystanie z opcji musimy przy jej tworzeniu dodać obiekt options:
options: {
opcja1: wartosc1,
opcja2: {
pole1: wartosc2,
pole2: wartosc3
}
}
i dodatkowo przy inicjalizacji klasy dodać zapis:
this.setOptions(options);
a sam zapis metody initialize:
initialize: function(){
zmienić na :
initialize: function(options){
Ponadto jeżeli nasza klasa nie jest z grupy "Fx" musimy podobnie jak w wypadku klasy Events dodać przed pierwszym stworzeniem obiektu zapis:
Klasa.implement(new Options);
Od tego momentu wywołanie naszej klasy będzie wyglądało następująco:
var Obiekt = new Klasa({
opcja1: wartosc_x,
opcja2: {
pole1: wartosc_y,
pole2: wartosc_z
}
});
Przy czym warto pamiętać, że nie musimy wpisywać wszystkich opcji przy tworzeniu nowego obiektu - gdy jakąś opcję pominiemy zostanie ustawiona dla tej opcji wartość domyślna, czyli ta jaką zdefiniowaliśmy przy tworzeniu klasy.
W następnej części kursu przejdziemy już do plików z grupy Native...
Komentarze do wpisu "Mootools 1.1 - Class.Extras.js":
1.
Nero napisał(a):
09 lipca 2007, 11:50:59
W skrocie, oba pliki classy w Operze padaja (pisze wlasny kod na mootoolsach i opera i ie ciagle marudza)
2.
Nero napisał(a):
09 lipca 2007, 11:54:47
Oki juz spoko, marudza wtedy gdy np. ostatnia metoda klasy ma po sobie ‘,’ itp. takie drobne niuanse :) ff all gitowo czyta
3.
Dziudek napisał(a):
09 lipca 2007, 13:29:23
@Nero – Firefox ignoruje ten bug, a IE i Opera się zawsze na nim wywalają... Wydaje mi się, że gdzieś w kursie nawet na to zwracałem uwagę bo sam jako początkujący koder przy AdvAJAX zrobiłem ten błąd i sobie już prawie włosy z głowy rwałem, a jak zobaczyłem co jest przyczyną to prawie padłem z wrażenia ;]
4.
3loader napisał(a):
06 września 2007, 16:51:33
fajny blog, generalnie do tej pory korzystałem z konkurencyjnego adobe spry’a ale min obsługa klas jako takich w mootools bardzo mi się podoba. Mam jednak problem tego typu:
chciałbym wywoływać metodę własności klasy klasa.własność.metoda np. moja_klasa.animacje.fade(zmienne), z punktu widzenia skryptu takie podejście nic nie daje, ale robie duży projekt i takie podejście mocno polepszy czytelność kodu. Głowie się już dosyć długo jak to rozwiązać. Czy w mootools można to jakoś sprytnie obejść?
5.
Dziudek napisał(a):
06 września 2007, 17:04:51
3loader – można to zrobić według mnie na co najmniej dwa sposoby : poprzez dwie klasy i poprzez jedną klasę. Wersja z dwoma klasami:
var Animacje = new Class({ animacja1 : function(){ alert(„1”); }, animacja2 : function(){ alert(„2”); } }); var klasa = new Class({ initialize: function(){ this.animacje = new Animacje(); } }); var Klasa = new klasa(); Klasa.animacje.animacja2();W powyższym wypadku tworzymy nową klasę animacji, a następnie podczas inicjalizacji klasy przypisujemy tą klasę do odpowiedniej właściwości.
Metoda z jedną klasą korzysta z tego, że do właściwości obiektu można przypisać cokolwiek – w tym funkcję:
var klasa = new Class({ animacje : { animacja1 : function(){ alert(„1”); }, animacja2 : function(){ alert(„2”); } } }); var Klasa = new klasa(); Klasa.animacje.animacja2();Jak widać tworzymy obiekt animacje którego polami są funkcje. Osobiście skłaniałbym się ku tej metodzie :)
Dodaj komentarz: