Wykład 1 - Republika WWW
Transkrypt
Wykład 1 - Republika WWW
Czym jest AJAX • AJAX (Asynchronous JavaScript and XML) – akronim: A - "asynchroniczny", JA - "JavaScript", X - "XML" • pozwala na wysyłanie Ŝądań HTTP do serwera bez odświeŜania okna przeglądarki (asynchronicznie) • obiekt XMLHttpRequest (XHR) – najwaŜniejszy składnik AJAX • 1999 – Microsoft udostępnił po raz pierwszy obiekt XHR w IE5 (jako obiekt ActiveX dostępny przez JavaScript i VBScript) • obecnie XHR jest obsługiwany przez Mozilla, Firefox, Safari, Opera, Netscape (jako obiekt JavaScript) i IE7 (jako obiekt ActiveX) 2 AJAX – wprowadzenie Beata Pańczyk na podstawie: 1. 2. Lis Marcin, Ajax, Helion, 2007 Hadlock Kris, Ajax dla twórców aplikacji internetowych, Helion, 2007 Obiekt XMLHttpRequest (XHR) Niezbędne narzędzia • serce AJAX-a • pozwala na: – pobieranie przez stronę WWW danych z serwera (za pomocą metody GET) – wysyłanie do serwera (za pomocą metody POST) Ŝądania przetwarzanego w tle • eliminuje potrzebę oczekiwania po kaŜdym Ŝądaniu na przysłanie przez serwer nowej strony i pozwala uŜytkownikom kontynuować interakcję ze stroną WWW (podczas gdy Ŝądanie jest przetwarzane w tle) • metody GET i POST obiektu XHR działają jak w standardowym Ŝądaniu HTTP; najczęściej stosowanymi formatami odpowiedzi są XML, JSON (JavaScript Object Notation) • edytor tekstowy (np. kED) • przeglądarka WWW (min. IE 5.0, Firefox 1.0, Netscape 7.0, Opera 7.6, Safari dla Apple 1.2) • serwer WWW • PHP 3 Standardowy XHR XHR z obsługą baz danych klient klient • najprostsza forma modelu (X)HTML/CSS Ŝądanie-odpowiedź w AJAX • obiekt XHR Ŝąda metodą JavaScript (X)HTML GET statycznego pliku XML, JSON lub tekstowego Silnik AJAX znajdującego się w tej samej domenie śądanie HTTP metoda GET • plik zostaje wysłany przez serwer do klienta, gdzie XML/JSON dane zostają przetworzone przez kod po stronie klienta serwer 4 5 • Aktualizowanie BD na podstawie interakcji z uŜytkownikiem bez potrzeby odświeŜania okna przeglądarki • pełna kontrola nad BD poprzez XHR (X)HTML/CSS JavaScript (X)HTML Silnik AJAX śądanie HTTP XML/JSON metoda POST Silnik po stronie serwera Instrukcja do BD Odpowiedź BD Baza danych serwer 6 1 Tworzenie obiektu XHR Wynik działania skryptu <script type="text/javascript"> var XMLHttpRequestObject = false; if (window.XMLHttpRequest) { // przeglądarki poza IE XMLHttpRequestObject = new XMLHttpRequest(); } else if(window.ActiveXObject) { // IE XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP"); } if(XMLHttpRequestObject) document.write("Obiekt XMLHttpRequest został utworzony."); else document.write("Obiekt XMLHttpRequest nie został utworzony."); </script> 7 8 Właściwości obiektu XHR Właściwości obiektu XHR • readyState – kod określający status Ŝądania • responseText – odpowiedź serwera w postaci tekstowej • responseXML - odpowiedź serwera w postaci XML • status – kod odpowiedzi serwera • StatusText – kod odpowiedzi serwera w postaci tekstowej 9 <script type="text/javascript"> var XMLHttpRequestObject = false; if(window.XMLHttpRequest){ XMLHttpRequestObject = new XMLHttpRequest(); } else if(window.ActiveXObject){ XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP"); } if(XMLHttpRequestObject){ for(indeks in XMLHttpRequestObject){ try { document.write(indeks +" = " + XMLHttpRequestObject[indeks] + "<br />"); } catch(err) { document.write(indeks + "= \"brak odczytu\"<br />"); } } } </script> <body> 10 <div> </div></body></html> Metody obiektu XHR Właściwości XHR w FF • abort - przerywa Ŝądanie HTTP • getAllResponseHeaders – pobiera nagłówki HTTP w postaci ciągu znaków • getResponseHeader – pobiera wybrany nagłówek HTTP • open – inicjalizuje Ŝądanie HTTP • send – wysyła Ŝądanie HTTP do serwera • setRequestHeader – ustawia wybrany nagłówek HTTP • overrideMimeType – nadpisuje nagłówek MIME zwrócony przez serwer 11 12 2 Wysyłanie Ŝądania do serwera • open(metoda_transmisji, url, async, uzytkownik, hasło) – inicjalizacja Ŝądania – metoda_transmisji – GET, POST – url – adres pliku/skryptu na serwerze – async – czy transmisja ma być asynchroniczna (true - domyślnie) – uŜytkownik, hasło – nazwa uŜytkownika i hasło o ile dostęp do serwera wymaga autoryzacji – np. open("GET", "http://domena.pl/dane.txt"); • send(null) - wysłanie Ŝądania Przesyłanie danych między przeglądarką a serwerem • odebranie danych realizowane przez własną funkcję z przypisaną jej właściwością onreadystatechange obiektu XMLHttpRequest – funkcja obsługi zdarzenia onreadystatechange powstającego przy zmianie stanu obiektu XHR • najczęściej stosuje się funkcję anonimową (bez nazwy) postaci: XMLHttpRequestObject.onreadystatechange = function() { //tresc funkcji } 13 Zmiany stanu obiektu XHR – właściwość readyState Wartość readyState 0 Nazwa Kody stanu i nagłówki HTTP Definicja 1 NieNie została wywołana metoda open zainicjalizowany Wczytywany Dane obiektu w trakcie ładowania 2 Załadowany 3 Interaktywny 4 Gotowy Obiekt załadowany (wywołana metoda send, ale odpowiedź serwera nie jest jeszcze dostępna) Część danych odebrana i moŜe zostać odczytana Operacja zakończona – obiekt został 15 całkowicie zainicjalizowany Znaczenie 200 śądanie zakończone sukcesem 202 400 śądanie zaakceptowane do przetwarzania asynchronicznego Nieprawidłowe Ŝądanie 403 Dostęp zabroniony 404 Brak Ŝądanego dokumentu (pliku) 500 Wewnętrzny błąd serwera • Stan Ŝądania jest równowaŜny stanowi HTTP pliku, który został zaŜądany • Kody stanu HTTP reprezentują odpowiedź serwera zaleŜną od statusu Ŝądanego pliku • Dla Ŝądań HTTP i XHR dostępnych jest pięć kodów stanu: – Informacyjny: 1xx – Powodzenie: 2xx – Przekierowanie: 3xx – Błąd klienta: 4xx – Błąd serwera: 5xx • Właściwość status pozwala na odczytanie kodu odpowiedzi zwróconej przez serwer w rezultacie zapytania 16 Zmiana stanu obiektu (1) Wybrane kody odpowiedzi serwera HTTP Kod 14 17 <script type="text/javascript"> //utworzenie obiektu XMLHttpRequest function pobierzDane() { if (XMLHttpRequestObject) { var calls = 0; var div = document.getElementById("div1"); div.innerHTML = ""; XMLHttpRequestObject.open("GET", "http://localhost/dane.txt"); XMLHttpRequestObject.onreadystatechange = function() { calls++; var tekst = "Wywołanie nr " + calls + "<br />"; tekst += "readyState = " + XMLHttpRequestObject.readyState + "<br />"; if (XMLHttpRequestObject.readyState != 1) tekst += "status = " + XMLHttpRequestObject.status + "<br />"; else tekst += "status = niedostępny<br />"; tekst += "<br />"; div.innerHTML = div.innerHTML + tekst; } XMLHttpRequestObject.send(null); 18 } } </script> 3 Zmiana stanu obiektu (2) Transmisja danych z serwera (1) <body> <div> <input type="button" value="Kliknij tu" onclick="pobierzDane();" /> </div> <div id="div1"> </div> </body> </html> 19 Transmisja danych z serwera (2) 21 Pobieranie danych z róŜnych plików (1) <body> <div> <input type="button" value="Pierwszy tekst" onclick="pobierzDane(1);" /> <input type="button" value="Drugi tekst" onclick="pobierzDane(2);" /> <input type="button" value="Trzeci tekst" onclick="pobierzDane(3);" /> </div> <div id="div1"> Ten tekst zostanie zmieniony. </div> 23 </body> ... function pobierzDane() { if(XMLHttpRequestObject){ var div = document.getElementById("div1"); XMLHttpRequestObject.open("GET", "http://localhost/AJAX/dane.txt"); XMLHttpRequestObject.onreadystatechange = function() { if (XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status == 200) div.innerHTML = XMLHttpRequestObject.responseText; } XMLHttpRequestObject.send(null); } } </script> </head> <body> <div> <input type="button" value="Kliknij tu" onclick="pobierzDane();" /> </div> <div id="div1"> Ten tekst zostanie zmieniony.</div> 20 </body> </html> Odbieranie danych przez zwykłą funkcję ... function przetwarzajDane() { if(XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status == 200) { var div = document.getElementById("div1"); div.innerHTML = XMLHttpRequestObject.responseText; } } function pobierzDane() { if(XMLHttpRequestObject){ XMLHttpRequestObject.open("GET", "http://localhost/AJAX/dane.txt"); XMLHttpRequestObject.onreadystatechange = przetwarzajDane; XMLHttpRequestObject.send(null); } } </script> </head> <body> <!-- tu bez zmian --></body> </html> 22 Pobieranie danych z róŜnych plików (2) function pobierzDane(tekstId) { if(XMLHttpRequestObject) { switch(tekstId) { case 1: XMLHttpRequestObject.open("GET", "http://localhost/dane1.txt");break; case 2: XMLHttpRequestObject.open("GET", "http://localhost/dane2.txt");break; case 3: XMLHttpRequestObject.open("GET", "http://localhost/dane3.txt");break; default: return; } XMLHttpRequestObject.onreadystatechange = function() { if (XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status == 200) { var div = document.getElementById("div1"); div.innerHTML = XMLHttpRequestObject.responseText; } } XMLHttpRequestObject.send(null); } 24 } 4 Lista rozwijana i teksty (1) <body> <div> <select id="lista" size="1" onChange="pobierzDane();"> <option value="0">Wybierz opcję <option value="1">Pierwszy tekst <option value="2">Drugi tekst <option value="3">Trzeci tekst </select> </div> <div id="div1"> Ten tekst zostanie zmieniony. </div> </body> Lista rozwijana i teksty (2) 25 function pobierzDane() { if(XMLHttpRequestObject){ var lista = document.getElementById('lista'); var tekstId = parseInt(lista[lista.selectedIndex].value); switch(tekstId) { case 1:XMLHttpRequestObject.open("GET", "http://localhost/dane1.txt");break; case 2:XMLHttpRequestObject.open("GET", "http://localhost/dane2.txt");break; case 3:XMLHttpRequestObject.open("GET", "http://localhost/dane3.txt");break; default: return; } XMLHttpRequestObject.onreadystatechange = function() { if(XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status == 200) { var div = document.getElementById("div1"); div.innerHTML = XMLHttpRequestObject.responseText; } } XMLHttpRequestObject.send(null); } 26 } Wyświetlanie obrazu (2) Wyświetlanie obrazu (1) <body> <div> <input type="button" value="Kliknij tu" onclick="pobierzDane();" /> <br /><br /> </div> <div id="div1"> Tutaj pojawi się obraz. </div> </body> 27 Dynamiczne zmiany na stronie (1) <body> <div> <input type="button" value="Menu 1" onmouseover="pobierzDane('b1', 'div1')" /> <input type="button" value="Menu 2" onmouseover="pobierzDane('b2', 'div1')" /> <input type="button" value="Menu 3" onmouseover="pobierzDane('b3', 'div1')" /> <br /><br /> </div> <div id="div1"> </div> </body> 29 function pobierzDane() { if(XMLHttpRequestObject){ XMLHttpRequestObject.open("GET", "http://localhost/obraz.txt"); XMLHttpRequestObject.onreadystatechange = function() { if (XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status == 200) { var div = document.getElementById("div1"); var obraz = XMLHttpRequestObject.responseText; //pobranie //zawartości pliku obraz.txt var tag = "<img src=\"" + obraz + "\" alt=\"Opis obrazu\">"; div.innerHTML = tag; } } XMLHttpRequestObject.send(null); } } 28 Dynamiczne zmiany na stronie (2) function pobierzDane(id, el) { if (XMLHttpRequestObject) { switch(id) { case "b1":XMLHttpRequestObject.open("GET", "http://localhost/dane1.txt");break; case "b2":XMLHttpRequestObject.open("GET", "http://localhost/dane2.txt");break; case "b3":XMLHttpRequestObject.open("GET", "http://localhost/dane3.txt");break; default: return; } XMLHttpRequestObject.onreadystatechange = function() { if(XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status == 200) { var div = document.getElementById(el); var tekst = XMLHttpRequestObject.responseText; div.innerHTML = tekst; } } XMLHttpRequestObject.send(null); } 30 } 5 Dynamiczne zmiany obrazu (1) <body> <div> <input type="button" value="Menu 1" onmouseover="pobierzDane('b1', 'imgDiv1')" /> <input type="button" value="Menu 2" onmouseover="pobierzDane('b2', 'imgDiv1')" /> <input type="button" value="Menu 3" onmouseover="pobierzDane('b3', 'imgDiv1')" /> <br /><br /> </div> <div id="imgDiv1"> </div> </body> 31 Wykonanie instrukcji pobranej z serwera (2) Wykonanie instrukcji pobranej z serwera (1) <body> <div> <input type="button" value="Kliknij mnie!" onclick="pobierzDane();" /> </div> </body> Plik skrypt.js: alert("Funkcja pobrana z serwera."); 33 function pobierzDane() { if(XMLHttpRequestObject){ XMLHttpRequestObject.open("GET", "skrypt.js" ); XMLHttpRequestObject.onreadystatechange = function() { if (XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status == 200) { var kod = XMLHttpRequestObject.responseText; eval(kod); } } XMLHttpRequestObject.send(null); } } 34 AJAX i PHP AJAX i PHP <body> <div> <input type="button" value="Kliknij mnie!" onclick="pobierzDane('d1');" /> </div> <div id="d1">Ten tekst zostanie zmieniony</div> </body> Skrypt PHP na serwerze http://localhost/ajax/skrypt.php <?php $data=date("Y-m-d"); echo "Dzisiaj jest: $data <br />"; echo "Data wygenerowana przez skrypt PHP"; ?> Dynamiczne zmiany obrazu (2) function pobierzDane(id, el) { if(XMLHttpRequestObject){ switch(id) { case "b1": XMLHttpRequestObject.open("GET", "http://localhost/obraz1.txt");break; case "b2": XMLHttpRequestObject.open("GET", "http://localhost/obraz2.txt");break; case "b3": XMLHttpRequestObject.open("GET", "http://localhost/obraz3.txt");break; default: return; } XMLHttpRequestObject.onreadystatechange = function() { if(XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status == 200) { var div = document.getElementById(el); var obraz = XMLHttpRequestObject.responseText; var tag = "<img src=\"" + obraz + "\" alt=\"obraz\">"; div.innerHTML = tag; } } XMLHttpRequestObject.send(null); } 32 } 35 <script type="text/javascript"> //utworzenie obiektu XMLHttpRequestObject ... function pobierzDane(dest) { if(XMLHttpRequestObject) { var div=document.getElementById(dest); XMLHttpRequestObject.open("GET", "http://localhost/Ajax/skrypt.php"); XMLHttpRequestObject.onreadystatechange = function() { if (XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status == 200) { var kod = XMLHttpRequestObject.responseText; div.innerHTML=XMLHttpRequestObject.responseText; } } XMLHttpRequestObject.send(null); } 36 } </script> 6 Zalety AJAX-a AJAX i PHP 37 • zwiększenie poziomu interaktywności z uŜytkownikiem • skrócenie czasu ładowania stron aplikacji - asynchroniczne pobieranie z serwera danych oraz kodu JavaScript i reguł CSS wtedy gdy są potrzebne • powszechne wsparcie technologii składowych AJAX przez obecne przeglądarki bez konieczności instalowania wtyczek czy bibliotek runtime (w przeciwieństwie do alternatywnych rozwiązań - aplety Java, Flash) • ograniczenie ilości danych przesyłanych z serwera do przeglądarki i przeniesienie części przetwarzania na komputer uŜytkownika (redukcja ruchu w sieci i obciąŜenia serwera aplikacji) • coraz więcej wzorców projektowych, bibliotek, szkieletów aplikacji i środowisk IDE wspierających AJAX 38 Wady • JavaScript, w którym implementowana jest logika aplikacji po stronie klienta to język skryptowy - nie został zaprojektowany do tworzenia duŜych aplikacji; jest językiem interpretowanym, ze słabą kontrolą typów danych; mechanizmy obiektowe są oparte o prototyp (nie o klasy) • konieczność włączenia obsługi JavaScript w przeglądarce (w przypadku IE równieŜ obsługi ActiveX) • ewentualne opóźnienia w komunikacji sieciowej - nie powodują wstrzymania działań uŜytkownika, ale sprawiają, Ŝe efekty jego interakcji z aplikacją mogą nie być natychmiastowe • brak moŜliwości cofania zdarzeń i przeglądania historii (asynchroniczne przesyłanie danych nie powoduje odświeŜenia strony) • trudna implementacja złoŜonych aplikacji AJAX (trudne testowanie i debugowanie aplikacji, co wynika z natury języka JavaScript oraz z podziału logiki aplikacji między klienta i serwer) 39 7