Czym jest a czym nie jest AJAX ?


  • AJAX jest skrótem od Asynchronous JavaScript And XML
  • AJAX nie jest nową, samodzielną technologią
  • AJAX to nowy sposób myślenia o aplikacjach internetowych z wykorzystaniem istniejących rozwiązań: XML, CSS, JavaScript, DOM
idź do góry

Model aplikacji


Model aplikacji
Model klasyczny:
  • Praca w trybie żądanie-odpowiedź
  • Logika biznesowa w całości po stronie serwera
  • Interakcja z serwerem poprzez linki i formularze HTML
Model AJAX:
  • Asynchroniczna komunikacja z serwerem z poziomu kodu JavaScript w przeglądarce
  • Serwer wysyła dane, fragmenty kodu, a nie całe strony
  • Dokument w przeglądarce modyfikowany programowo poprzez interfejs DOM
idź do góry

Co do czego ...


  • HTML (lub XHTML) + CSS – prezentacja danych
  • JavaScript – implementacja części logiki aplikacji po stronie klienta
  • Document Object Model (DOM) – programowa modyfikacji dokumentu w przeglądarce
  • XML – podstawowy format przesyłanych danych (alternatywnie czysty tekst lub format JSON)
  • Obiekt XMLHttpRequest – asynchroniczna komunikacja z serwerem
idź do góry

Zalety i wady ...


Zalety:
  • redukuje ruch w sieci i zmniejsza obciążenie serwera
  • odciąża serwer (przetwarzanie po stronie klienta)
  • separacja danych i formatowania
  • interaktywne, szybkie i przyjazne aplikacje
  • oparty o znane i dojrzałe już dziś technologie
  • nie wymaga instalacji wtyczek w przeglądarce (por. Java, Java Web Start, Flash)
  • prefetching
Wady:
  • język JavaScript nieodpowiedni dla dużych aplikacji
  • konieczność włączenia obsługi JavaScript
  • problem historii przeglądanych stron
  • problem zakładek do dynamicznych stron wyszukiwarki (identyfikator fragmentu #abc)
  • wrażliwy na opóźnienia w komunikacji sieciowej
  • trudna implementacja, testowanie i debugowanie aplikacji
  • niedojrzałe biblioteki i narzędzia programistyczne
idź do góry

XML


 1<book>
 2  <isbn>99-99999-99-9</isbn>
 3  <title>AJAX</title>
 4  <authors>
 5    <author>
 6      <first_name>John</first_name>
 7      <last_name>Smith</last_name>
 8    </author>
 9    <author>
10      <first_name>James</first_name>
11      <last_name>White</last_name>
12    </author>
13  </authors>
14</book>
[pokaż zawartość pliku] [pobierz plik] idź do góry

JSON


  • Obiekty
  • sekwencja par atrybut-wartość
  • Tabele: sekwencja wartości w nawiasach kwadratowych
  • Kodowanie UTF-8
  • Wartości specjalne: true, false, null
  • Znaki specjalne: \", \\, \t, \uXXXX
  • Wsparcie dla języków skryptowych, np. PHP: json_decode, json_encode
 1{
 2  "isbn": "99-99999-99-9",
 3  "title": "AJAX",
 4  "authors": [
 5    {"first_name": "John", "last_name": "Smith"},
 6    {"first_name": "James", "last_name": "White"}
 7  ],
 8  "date": {
 9    "year": 2006,
10    "month": sep,
11    "day": 12
12  }
13}
[pokaż zawartość pliku] [pobierz plik] idź do góry

Który format wybrać ?


Zalety XML:
  • powszechnie znany format ogólnego przeznaczenia
  • bogactwo narzędzi po stronie serwera (np. parsery)
  • możliwość przetwarzania odebranych z serwera danych za pomocą transformacji XSLT
  • silne wsparcie ze strony biznesu
Zalety JSON:
  • łatwość i szybkość parsowania w języku JavaScript
  • czytelny dla człowieka i maszyny
  • samodokumentujący się format
  • proste i jasne reguły poprawności powodują że parsery są szybkie i łatwe do napisania
idź do góry

Metody obiektu XMLHttpRequest


abort()
Zatrzymuje aktualne żądanie.
getAllResponseHeaders()
Zwraca kompletny nagłówek (zbiór etykiet i wartości) jako string.
getResponseHeader(”etykieta”)
Zwraca wartość pojedynczego nagłówka (jako string), którego etykieta została podana jako parametr.
open(”metoda”, ”URL”, asyn)
Określenie docelowego adresu URL i metody planowanego żądania.
send(dokument)
Wysłanie żądania.
setRequestHeader(”etykieta”, ”wartość”)
Określenie elementów nagłówka, który zostanie wysłany razem z żądaniem.
idź do góry

Atrybuty obiektu


onreadystatechange
Uchwyt dla funkcji wywoływanej przy każdej zmianie stanu.
readyState
Stan obiektu (integer):
  0 = zapytania niezainicjowane
  1 = cel otwarty
  2 = zapytanie wysłane
  3 = odbieranie odpowiedzi
  4 = żądanie zakończone
responseText
Pole przechowuje dane pobrane z serwera.
responseXML
Dane kompatybilne z DOM zwrócone z serwera.
status
Numeryczny kod zwrócony przez serwer (np. 404, 200).
statusText
Opis kodu zwróconego przez serwer.
idź do góry

Tworzenie obiektu XMLHttpRequest


Obsługa tworzenia obiektu XMLHttpRequest nie jest niestety identyczna we wszystkich przeglądarkach. W przypadku IE należy to zrobić inaczej niż w pozostałych przeglądarkach. Stąd, skrypt JavaScript odpowiedzialny za utowrzenie instancji XMLHttpRequest próbuje tworzyć ten obiekt korzystając z obydwu API, przy czym co najmniej jedna z tych prób jest zawsze nieudana.

Kod tworzący instancję XMLHttpRequest jest zwykle pewną odmianą kodu zaprezentowanego poniżej.
 1function getHTTPObject() {
 2  var xhr = false;
 3  if (window.XMLHttpRequest)   {
 4    xhr = new XMLHttpRequest();
 5  }
 6  else if (window.ActiveXObject) {
 7         try {
 8           xhr = new XMLHttpRequest();
 9         }
10         catch(e) {
11           try {
12             xhr = new ActiveXObject("Microsoft.XMLHTTP");
13           }
14           catch(e) {
15             xhr = false;
16           }
17         }
18       }
19  return xhr;
20}
[pokaż zawartość pliku] [pobierz plik] idź do góry

Obsługa odpowiedzi


W trakcie wysyłania zapytania została określona funkcja, której zadaniem jest obsługi odpowiedzi. Jest to funkcja przypisana do atrybutu onreadystatechange.
  request.onreadystatechange = nazwaFunkcjiObsługi;
Funkcja ta powinna sprawdzić stan zapytania zapisany w atrybucie readyState. Możliwe stany zostały opisane w rozdziale dotyczącym atrybutów obiektu XMLHttpRequest. Jeżeli stan ma wartość 4, oznacza to, że odebrano już pełną odpowiedź z serwera i można kontynuować przetwarzanie.
  if (request.readyState == 4) {
     // wszystko jest OK, odpowiedź została odebrana
  } else {
     // ciągle nie gotowe
  }
W następnym kroku należy sprawdzić status odpowiedzi serwera HTTP. Wszystkie możliwe kody są opisane na stronie W3C. Najczęściej sprawdza się jednak czy status ma wartość 200, oznaczającą poprawną sytuację.
  if (request.status == 200) {
      // świetnie!!
  } else {
      // wystąpił jakiś problem z zapytaniem,
      // na przykład odpowiedzią mogło być 404 (Nie odnaleziono)
      // lub 500 (Wewnętrzny błąd serwera)
  }
Dopiero po sprawdzeniu powyższych warunków można przystąpić do dalszego przetwarzania otrzymanej z serwera odpowiedzi. Może ona mieć formę danyych XML (atrybut responseXML) lub czystego tekstu (atrybut responseText) idź do góry

Hello World


 function onResponse() {
   if (req.readyState==4) {
     if (req.status==200) { 
        document.getElementById("msg").innerHTML = req.responseText;          
         }
   }
  };
UWAGA: Zwróć uwagę na zawartość pola TextBox po naciśnięciu przycisku "test".

Pobierz kod plik z komunikatem
Pobierz kod wykonywany po stronie klienta
idź do góry

GET vs. POST


metoda GET:

  var url = "ajaxParamsGET.php";
  var params = "pin="+vPin+"&code="+vCode;
  
  request.open("GET", url+"?"+params, true);        
  request.send(null);

Pobierz kod wykonywany po stronie serwera
Pobierz kod wykonywany po stronie klienta

metoda POST:

  var url = "ajaxParamsPOST.php";
  var params = "pin="+vPin+"&code="+vCode;
  
  request.open("POST", url, true);        
  request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  request.setRequestHeader("Content-length", params.length);
  request.setRequestHeader("Connection", "close");
  request.send(params);

Pobierz kod wykonywany po stronie serwera
Pobierz kod wykonywany po stronie klienta
idź do góry

Pobieranie danych w formacie XML


  txt="<table border='0'>";
  tBooks=request.responseXML.documentElement.getElementsByTagName("product");
  for (i=0;i<tBooks.length;i++) {
        
        tTitle=tBooks[i].getElementsByTagName("title"); 
        if (tTitle[0].hasChildNodes()) {
                vTitle=tTitle[0].firstChild.nodeValue;
        }
                                
        tAuthor=tBooks[i].getElementsByTagName("author"); {
          try {
                vAuthor = tAuthor[0].firstChild.nodeValue;
          }
          catch (er) {
                vAuthor = "";
          }
        }
        txt=txt + "<tr><td><b>" + vAuthor+ "</b></td><td>" + vTitle+ "</td></tr>";
  }
  txt=txt + "</table>";
  document.getElementById('ProductList').innerHTML=txt;

Pobierz kod plik z danymi o książkach
Pobierz kod plik z danymi o płytach CD
Pobierz kod wykonywany po stronie klienta
idź do góry

Dynamiczne podpowiedzi


Pobierz kod wykonywany po stronie serwera
Pobierz kod wykonywany po stronie klienta
idź do góry

Element canvas


Warto zajrzeć Instrukcja krok po kroku:
  1. Pobierz szablon dokumentu HTML
  2. Narysuj prostokąty
        ctx.fillStyle = "rgb(200,0,0)";
        ctx.fillRect (10, 10, 380, 50);
    
        ctx.fillStyle = "rgba(0, 0, 200, 0.2)";
        ctx.fillRect (30, 30, 55, 210);
    
        ctx.fillStyle = "rgb(0,255,0)";
        ctx.strokeRect (100, 75, 285, 165);  
      
    
  3. Narysuj krzywe
        x = 170;
        y = 160;
        ctx.beginPath();
        ctx.arc(x,y,50,0,Math.PI*2,true); // Outer circle
        ctx.moveTo(x+35,y);
        ctx.arc(x,y,35,0,Math.PI,false);   // Mouth (clockwise)
        ctx.moveTo(x-10,y-15);
        ctx.arc(x-15,y-15,5,0,Math.PI*2,true);  // Left eye
        ctx.moveTo(x+20,y-15);
        ctx.arc(x+15,y-15,5,0,Math.PI*2,true);  // Right eye
        ctx.stroke();
      
    
  4. Narysuj obraz z pliku PNG
        var img = new Image();
        img.onload = function() {
          ctx.drawImage(img, 240, 95);
        }
        img.src = "ajaxCanvasImage01.png";
      
    
Ciekawe przykłady idź do góry

Google Maps API


Zadanie
Wyświetl mapę prezentującą obszar okolic Centrum Wykładowego PP, zaznacz na niej samo centrum, obszar Poligrodu oraz ścieżkę prowadzącą z Centrum Wykładowego do ronda Śródka.

Warto zajrzeć Instrukcja krok po kroku:
  1. Pobierz szablon dokumentu HTML
  2. Uzyskaj swój własny klucz, żeby móc korzystać z GoogleMaps
    Rejestracja adresu w GoogleMaps
  3. Pokaż mapę dla zadanej lokalizacji
    var myOptions = {
     zoom: 15,
     center: new google.maps.LatLng(52.403767285812464,16.950294971466064),
     mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    
  4. Dodaj kontrolki pozwalające na zmianę parametrów wyświetlania mapy
    var myOptions = {
      panControl: true,
      zoomControl: true,
      mapTypeControl: false,
      scaleControl: true,
      streetViewControl: true,
      overviewMapControl: false   
    }
    
  5. Wskaż CW PP na mapie
    var cwPPmarker = new google.maps.Marker({
     position: new google.maps.LatLng(52.403767285812462,16.950294971466064),
     map: map,
      title:"Centrum Wykładowe Politechniki Poznańskiej"
    });                             
    
  6. Dodaj opis CW PP
    var contentString = 
     "tutaj można umieścić opis </br>"+
     "<a href='http://images.google.com/images?hl=en&q=Centrum+Wyk%C5%82adowe+Politechniki+Pozna%C5%84skiej&btnG=Search+Images&gbv=2'>"+
     "Zobacz jak wygląda w rzeczywistości</a>";
    
    var infowindow = new google.maps.InfoWindow({
     content: contentString
    });
    
    google.maps.event.addListener(cwPPmarker, 'click', function() {
     infowindow.open(map,cwPPmarker);
    }); 
    
  7. Wskaż na mapie Poligród
    var poligrodCoords = [
     new google.maps.LatLng(52.40306035658953,16.950488090515137),
     new google.maps.LatLng(52.40091331691532,16.948320865631104),
     new google.maps.LatLng(52.39960409510452,16.95211887359619),
     new google.maps.LatLng(52.402458148687266,16.954264640808105),
     new google.maps.LatLng(52.40350546149509,16.95411443710327),
     new google.maps.LatLng(52.403531643996764,16.951797008514404),
     new google.maps.LatLng(52.40472293138462,16.9494366645813),
     new google.maps.LatLng(52.403858923956435,16.948471069335938),
     new google.maps.LatLng(52.40306035658953,16.950488090515137)                  
    ];
    
    poligrod = new google.maps.Polygon({
     paths: poligrodCoords,
     strokeColor: "#f33f00",
     strokeOpacity: 2,
     strokeWeight: 1,
     fillColor: "#ff0000",
     fillOpacity: 0.2
    });
    
    poligrod.setMap(map);
    
  8. Wskaż na mapie trasę z CW na rondo Śródka
    var routeCoords = [                             
     new google.maps.LatLng(52.40380655932604, 16.950488090515137),
     new google.maps.LatLng(52.40384583280466, 16.95117473602295),
     new google.maps.LatLng(52.403531643996764, 16.951818466186523),
     new google.maps.LatLng(52.40358400895346, 16.954565048217773),
     new google.maps.LatLng(52.404631295035315, 16.95413589477539),
     new google.maps.LatLng(52.40577019043, 16.954050064086914),
     new google.maps.LatLng(52.40672579261582, 16.9543719291687),
     new google.maps.LatLng(52.40892490805024, 16.9559383392334),
     new google.maps.LatLng(52.40968410101556, 16.956946849822998)                                   
    ];
    
    var route = new google.maps.Polyline({
     path: routeCoords,
     strokeColor: "##0000ff",
     strokeOpacity: 1.0,
     strokeWeight: 4
    });
    
    route.setMap(map);  
    
Ciekawe przykłady idź do góry