Mootools 1.1 - Ajax.js
08 lipca, 2007
Plik ajax.js zawiera klasę Ajax, która jest rozszerzeniem poznanej w poprzedniej części kursu klasy XHR. Klasa Ajax zawiera 4 metody i posiada dodatkowe zdarzenie... Poza tym mamy do dyspozycji wszystkie metody, opcje i zdarzenia klasy XHR.
Stworzenie nowego obiektu tej klasy wygląda następująco:
obiekt = new Ajax(adres,opcje);
Gdzie zmienna adres to najczęściej adres pod którym znajduje się skrypt przetwarzający otrzymane dane. Zmienna opcje to tak naprawdę cały obiekt, przechowujący parametry wywołania obiektu klasy Ajax. Oprócz opcji znanych z klasy XHR mamy jeszcze do dyspozycji 4 dodatkowe opcje:
- data - opcja ta przechowuje dane jakie chcemy wysłać zapytaniem Ajax. Może być zarówno ciągiem znaków urlescape jak i obiektem gdzie rolę pól pełnią nazwy zmiennych. Trzecią możliwością jest umieszczenie w tym miejscu odwołania do elementu formularza.
- update - w tej opcji określamy element w którym pojawią się pobrane przez zapytanie dane.
- evalScripts - jeżeli pobieramy za pomocą zapytania kod JavaScript to po jego pobraniu możemy go wykonać wtedy gdy opcja ta ustawiona jest jako true. Domyślna wartość tej opcji to false.
- evalResponse - ta opcja ma podobne działanie do poprzedniej z tą różnicą, że wykonuje skrypty JS niezależnie od tego jakiego typu są pobierane dane... Domyślna wartość tej opcji to false.
Jak już wspominałem klasa Ajax udostępnia nam jedno dodatkowe zdarzenie - onComplete, które jest wywoływane w momencie zakończenia wykonywania zapytania. Jaka jest różnica pomiędzy zdarzeniem onComplete, zdarzeniem onSuccess znanym z klasy XHR ? Opcje takie jak update czy evalScripts i evalResponse zadziałają tylko w momencie wywoływania zdarzenia onComplete - stosując zdarzenie onSuccess stosowanie tych opcji mija się z celem.
Przejdźmy teraz do tego co nas najbardziej interesuje - do metod udostępnianych przez klasę Ajax.
Request
Metoda request to podstawa działania klasy Ajax - służy do wysłania zapytania zgodnie z podanymi parametrami.
Metodę tę możemy wywoływać na dwa sposoby:
obiekt = new Ajax(adres,opcje);
obiekt.request();
lub:
new Ajax(adres,opcje).request();
Pierwszy sposób jest lepszy gdy chcemy wykonywać dane zapytanie wielokrotnie, a drugie rozwiązanie jest przydatne w wypadku pojedynczych wywołań.
Wykonajmy zatem zapytanie Ajax, które pobierze tekst z danej strony i umieści go w odpowiednim elemencie. Żeby było ciekawiej to będziemy mogli pobrany tekst umieścić w wybranym przez nas elemencie. Ponieważ będziemy wykonywać kilka zapytań warto skorzystać z pierwszego sposobu zapisu by nie tworzyć kilku-kilkunastu instancji klasy Ajax - będziemy po prostu dynamicznie zmieniać wartość jednej z opcji naszego obiektu.
Ponieważ wszystko będzie najlepiej widoczne w przykładzie tu skupię się tylko na samym schemacie działania skryptu.
Stworzymy listę wyboru typu select, która pozwoli nam na wybór elementu w którym znajdzie się pobrany przez zapytanie tekst. Zapytanie zostanie wykonane w momencie kliknięcia przycisku. Zatem w tym momencie musimy zmienić wartość opcji update obiektu klasy Ajax (który utworzymy wraz ze zdarzeniem onload obiektu window).
Tworzymy obiekt klasy Ajax przy zdarzeniu onload :
window.addEvent("load",function(){
zapytanie = new Ajax('http://adres.pl');
});
Dodajemy zdarzenie onclick do przycisku, które pobiera wartość pola select i na tej podstawie zmienia opcję update obiektu klasy Ajax i wykonuje zapytanie:
window.addEvent("load",function(){
zapytanie = new Ajax('http://adres.pl');
$('btn').addEvent("click",function(){
zapytanie.options.update = $($('select').value);
zapytanie.request();
});
});
Powyższy kod w akcji prezentuję w poniższym przykładzie:
evalScripts
Metoda evalScripts służy do wykonywania skryptów zawartych w zwróconym przez zapytanie tekście, zgodnie z podanymi opcjami. Metody tej z reguły nie stosujemy ręcznie, ponieważ jest ona automatycznie wywoływana w momencie zaistnienia zdarzenia onComplete, gdy opcja evalResponse lub evalScripts ma wartość true.
Oczywiście można użyć tej metody ręcznie w momencie, gdy chcemy wykonać kody JS zawarte w wyniku zapytania w innym momencie działania naszego skryptu - czyli niekoniecznie zaraz po zakończeniu wykonania zapytania.
Przykładowo pobraliśmy kod skryptu i chcemy go wykonać na przykład w momencie kliknięcia jakiegoś elementu. Jeżeli pobraliśmy tylko kod skryptu to nie musimy zmieniać wartości opcji obiektu klasy Ajax - gdy chcemy skorzystać z właściwości opcji evalResponse to przed wywołaniem tej metody musimy zmienić wartość tej opcji na true (gdyby miała ona taką wartość od momentu inicjalizacji obiektu to nie moglibyśmy wykonać skryptu w dowolnym momencie, gdyż wykonałby się on wraz ze zdarzeniem onComplete obiektu).
Tworzymy zatem nowy obiekt klasy Ajax przy zdarzeniu onload:
window.addEvent("load",function(){
zapytanie = new Ajax('http://adres.pl');
});
Tworzymy też dwa przyciski - btn1 i btn2 z których pierwszy będzie wykonywał zapytanie, a drugi wykona zawarty w zapytaniu kod JS.
Zatem:
window.addEvent("load",function(){
zapytanie = new Ajax('http://adres.pl');
$('btn1').addEvent("click",function(){
zapytanie.request();
});
$('btn2').addEvent("click",function(){
zapytanie.evalScripts();
});
});
Jeszcze by się przydało dać jakiś sygnał, że zapytanie się wykonało - dodajemy do obiektu klasy Ajax zdarzenie onComplete:
window.addEvent("load",function(){
zapytanie = new Ajax('http://adres.pl',{onComplete: function(){alert('zapytanie zakończone...')}});
$('btn1').addEvent("click",function(){
zapytanie.request();
});
$('btn2').addEvent("click",function(){
zapytanie.evalScripts();
});
});
Oczywiście powyższy kod dotyczy sytuacji gdzie pobieramy czysty kod JS - z odpowiednim Content-Type lub kod zawarty pomiędzy znacznikami script:
To teraz wersja dla pobierania kodu JS ale bez Content-Type - to samo tylko z drobnymi modyfikacjami:
window.addEvent("load",function(){
zapytanie = new Ajax('http://adres.pl',{onComplete: function(){alert('zapytanie zakończone...')}});
$('btn1').addEvent("click",function(){
zapytanie.request();
});
$('btn2').addEvent("click",function(){
zapytanie.options.evalResponse = true;
zapytanie.evalScripts();
});
});
Jak widać zmieniła się tylko jedna linijka kodu w funkcji wykonywanej przy zdarzeniu onclick dla drugiego przycisku.
I oczywiście kod w działaniu:
getHeader
Metoda getHader służy do pobierania zawartości danego nagłówka odpowiedzi. Jako jej argument podajemy nazwę nagłówka - w wypadku gdy takowy nagłówek nie istnieje zwrócona zostaje wartość null.
Składnia tej metody wygląda następująco :
obiekt_ajax.getHeader('nazwa_naglowka');
Przykładowo gdybyśmy chcieli pobrać nagłówek Content-Type to zapiszemy:
obiekt_ajax.getHeader('Content-Type');
No i musimy pamiętać by umieścić kod pobierający zawartość nagłówka tak by wykonał się po wykonaniu zapytania - na przykład w zdarzeniu onComplete.
Przykład używający tej metody poniżej:
Object.toQueryString
Funkcja Object.toQueryString zamienia podany jako argument obiekt na ciąg znaków urlescape. Składnia tej funkcji:
Object.toQueryString(obiekt);
Na przykład:
Object.toQueryString({imie: "Tomek",nick: "Dziudek", www: "dziudek.jogger.pl"});
Powyższy kod zamieni podany obiekt na następujący ciąg znaków:
imie=Tomek&nick=Dziudek&www=dziudek.jogger.pl
Myślę, że przykład działania niepotrzebny bo podobne funkcje już poznawaliśmy i powinniście już wiedzieć kiedy ta funkcja się przyda ;)
send
Ostatnia metoda w pliku ajax.js - jest rozszerzeniem klasy Element, a co za tym idzie możemy ją łączyć z wybranym elementem - w tym wypadku formularzem. Jej działanie polega na wysyłaniu za pomocą Ajax danego formularza. Składnia funkcji:
$('formularz').send(opcje);
Opcje to w tym wypadku opcje klas Ajax i XHR - oczywiście poza parametrami typu adres czy dane, które są generowane automatycznie na podstawie zawartości formularza.
Przykładowo zapis:
$('form').send();
Spowoduje wysłanie formularza posiadającego identyfikator "form" pod adres zgodny z atrybutem action elementu form i z danymi automatycznie zamienionymi na format urlescape. Warto jeszcze dodać, że dane w tym wypadku są wysyłane metodą post.
I przykład korzystający z tej metody:
Może jest mało ciekawy, ale ma po prostu pokazać jak to mniej więcej działa ;]
To by było na tyle w temacie pliku ajax.js . W następnej części kursu zajmę się plikiem assets.js, który pozwala na dynamiczne dołączanie skryptów, styli i grafik do stron.
Komentarze do wpisu "Mootools 1.1 - Ajax.js":
1.
ewel napisał(a):
04 września 2007, 16:32:29
po pierwsze to dzieki za bardzo fajny kursik, jestem tu ostatnio prawie codziennie ;)
po drugie, mam pytanie takie: czy takiej sytuacji:
********
window.addEvent(‘domready’, function(){ $(‘myForm’).onsubmit= function(e) { new Event(e).stop(); this.send({ onComplete: function(){( new Element(‘span’).appendText(this.response.text).injectAfter($(‘login’)) )} }); };
}); ******
jest mozliwe w ogole otrzymanie odpowiedzi w formacie xml?
chodzi mi o sytuacje gdy po stronie serwera mamy obsluge bledow i w zaleznosci od tego, ktory blad wywala w odpowiednim miejscu przy formularzu pojawia sie odpowiedz z serwera. jesli odbieram odpowiedz w formacie text wszytko dziala jak nalezy (oczywiscie uaktualnione zostaje tylko jedno pole, z roznymi komunikatami o bledach, tak jakbym uzywala ‘update’), ale jak tylko wrzucam tam format xml, po stronie serwera tworze plik xml i odwoluje sie do jego poszczegolnych pol przez getElementsByTagName(pole).firstChild.data dostaje komunikaty ‘this.response.xml has no properties’
mozna to jakos obejsc?
2.
Dziudek napisał(a):
04 września 2007, 16:38:50
ewel – na pierwszy rzut oka brakuje mi po kodzie:
getElementsByTagName(pole)(swoją drogą jak pole jest ciągiem znaków, a nie zmienną to powinno byćgetElementsByTagName("pole")) właściwości:.item(0)– metoda getElementsByTagName zwraca kolekcję elementów, a nie jeden element i dopiero po tym.item(0)odwołujemy się dofirstChilditd. ;) Czyli kod powinien wyglądać następująco:getElementsByTagName('nazwa_tagu').item(0).firstChild.data3.
ewel napisał(a):
04 września 2007, 21:04:37
zmienilam, ale caly czas daje: ‘this.response.xml has no properties’....
zastanawiam sie czy zle nie tworze xml po stronie serwera, bo robie to pierwszy raz. czy wystarczy wypluc echo z deklaracja xml oraz echo z poszczegolnymi tagami?
4.
Dziudek napisał(a):
04 września 2007, 21:19:21
@ewel – IMHO na początku kodu PHP powinno być:
header("Content-type: text/xml; charset=UTF-8"); echo '<?xml version="1.0" encoding="UTF-8"?>';5.
ewel napisał(a):
04 września 2007, 21:35:53
caly czas to samo, ten sam komunikat o bledzie…
kod php do ktorego wysylam formularz mam w osobnym pliku, moze musi byc w tym samym? bo gdy wylacze javascript daje mi komunikat ze naglowki zostaly wyslane (nie, nie mam zadnych zbednych linii ani znakow w kodzie ;))
6.
Dziudek napisał(a):
04 września 2007, 21:41:39
@ewel – możesz wrzucić ten przykład na jakąś stronkę albo wysłać mi na mail ? Tak chyba będzie szybciej ;)
7.
Visa napisał(a):
11 września 2007, 21:23:52
Object.toQueryString tak to se mozna wysylac argumenty getem postem ;) zarty a jak jest w nazwie jakiegos pola & ? to co dżijaidżo ? new Ajax( ‘index.php?a=1&b=2’ ) to rozwiazanie dla nobów i prostych rzeczy nigdy nie wystarczy
Get JSON or Die trying ;)
8.
Dziudek napisał(a):
11 września 2007, 21:28:51
@Visa – JSON to swoją drogą – ja opisywałem wszystkie możliwości MooTools, a nie tylko te, które mi się podobają :)
9.
jimmy0699 napisał(a):
12 kwietnia 2008, 14:53:59
hej, na poczatek powiem ze kurs jest naprawde super i wydrukowalem sobie caly (92 kartki ;]).
mam pewien problem i bylbym wdzieczny gdybys wskazal wlasciwa droge…
while ($q=$sql->fetchArray()) { $ext1.="<a class=menu href=#>{$q['name']}</a>"; $myJava.=" var menu_ajax = $$('.menu'); menu_ajax.addEvent('click', function(e) { new Event(e).stop(); var log = $('content').empty().addClass('ajax-loading'); new Ajax(\"http://localhost/~cms/\", { method: 'get', update: $('content'), data: 'x='+".$q['id'].", onComplete: function() { log.removeClass('ajax-loading'); } }).request(); }); "; }a pytanie to: jak wyselekcjonowac zapytania…
10.
Dziudek napisał(a):
12 kwietnia 2008, 15:05:28
@jimmy0699 – chyba nie bardzo zrozumiałem pytanie ;) Nie wiem, może jestem zbyt zmęczony ostatnio, ale jakbyś mógł to opisz dokładniej o co chodzi :)
11.
jimmy0699 napisał(a):
12 kwietnia 2008, 15:12:48
mam na stronie glowne menu ;], jest ono pobierane z mysqla, i wyswietlane za pomoca
while ($q=$sql->fetchArray()) {...}w srodku jest robione menu w jakis tam sposob typu
$menu.="<a href=#></a>"oraz kod js ktory pobierze opowiednie dane metoda Ajax wedlug zmiennej$q['id']. nie jestem zbytnio obyty z js i problem polega na tym ze przy kazdym kliku pobiera wszystkie dane z wszystkich linkow menu i w rezultacie w divie wyswietla mi drugi raz strone glowna :]..12.
Dziudek napisał(a):
12 kwietnia 2008, 15:21:15
@jimmy0699 – no, teraz już jaśniej ;) Osobiście proponowałbym stworzenie sobie skryptu php, który w zależności od parametru x w adresie wyświetli tylko te dane, które mają się pojawić w divie na stronie głównej – bez żadnych nagłówków itp. Czyli wyświetli tylko to co jest rzeczywiście potrzebne :)
13.
jimmy0699 napisał(a):
12 kwietnia 2008, 15:36:25
Tak tez jest zrobione, jedyny problem w tym ze jesli w tej petli robi sie JS do obslugi tegoz menu. i definiuje je tak:
var menu_ajax = $$('.menu');oraz dalej
menu_ajax.addEvent('click', function(e) { // tu zapytanie Ajax... }to w tym nie gra cos i po kliknieciu byle gdzie pobiera ajaxem wszystkie mozliwosci parametru x.
Nie mecze zbytnio??
14.
Dziudek napisał(a):
12 kwietnia 2008, 15:50:17
@jimmy0699 – spróbuj zamiast menu_ajax.addEvent poprzez:
menu_ajax.each(function(el,i){el.addEvent("click",function(){/**kod funkcji**/});});15.
maly_john napisał(a):
30 kwietnia 2009, 11:50:45
Witam,
po analizie przykładów i próbie odpalenia tego na serwerze lokalnym wszystko fajnie działa…. niestety do tego czasu. Następnie spróbowałem przetestować powyższe przykłady na serwerze ftp.. i tu w firebugu wyrzuca w konsoli błąd 400 bad request:
POST http://www.radwansport.pl/test/CMS/home.php
400 Bad Request 177ms
Ciekawe jest to że jeżeli przepisze do powyższy url do przeglądarki od razu odpala odpowiedni skrypt home.php.
Proszę o pomoc, dziękuję
16.
aaa napisał(a):
17 grudnia 2009, 17:03:09
wszystkie przykłady padły, pojawia się error :/
Dodaj komentarz: