Uso di responseTextcaprera.dia.unisa.it/TSW/MATERIALE/ns/AJAX1.pdf · · 2014-12-01più...
Transcript of Uso di responseTextcaprera.dia.unisa.it/TSW/MATERIALE/ns/AJAX1.pdf · · 2014-12-01più...
IMPORTANTE Non riguarda AJAX
Non assegnare lo stesso nome ad una funzione javascript e all’attributo NAME di tag HTML – Si creano dei conflitti quando la funzione è
associata ad un gestore di evento • onDDDD = nomeFunzione
– Solo alcuni tag HTML danno luogo a questo problema, ma adottate sempre la regola predecente
Potete non rispettare la regola associando le funzioni ai gestori in maniera differente (registrando gli eventi con Javascript)
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 2
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 3
Che cosa è AJAX Asynchronous JavaScript and XML Non è un linguaggio di programmazione È una tecnica di web development per creare
più facilmente e più velocemente applicazioni web interattive
Lo scopo è quello di rendere le pagine web reattive facendo scambiare (in background) piccole quantità di dati con il server di modo che la pagina web non deve essere completamente ricaricata ogni volta che l’utente richiede un cambiamento
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 4
Cosa è necessario conoscere
HTML / XML – Per il momento lavoreremo con HTML
Javascript
L’oggetto XMLHttpRequest
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 5
Interazione in AJAX
Il codice Javascript, senza ricaricare la pagina, comunica con il server tramite l'oggetto XMLHttpRequest
Tra il browser ed il server si usa un trasferimento di dati asincrono
Viene comunque eseguita una richiesta HTTP (seguita da una risposta)
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 6
Javascript tradizionale Per inserire informazioni in una parte
della pagina ad esempio si seleziona una regione e la lista delle province viene automaticamente riempita
tramite una post-back si chiedono al server le informazioni necessarie e si ricarica (quindi ridisegna) tutta la pagina
una volta selezionata una regione, con javascript si richiama la pagina onChange=“this.form.submit()”
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 7
Javascript a la AJAX
Una pagina (tramite Javascript) può effettuare una richiesta HTTP ed ottenere una risposta HTTP senza dover ricaricare tutta la pagina – Gestisce una HTTP request/response
Si usa l'oggetto XMLHttpRequest
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 8
Modello di un’applicazione web
Tradizionale AJAX
Prepara la pagina
Prepara i dati
Per il momento HTML data
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 11
Browser supportati XMLHttpRequest è supportato da
– IE 6.0+, Safari, Firefox, Opera 8+, Netscape 7
Browser differenti usavano metodi differenti per crearlo. Una volta creato l’oggetto, tutti i browser lo usano allo stesso modo – IE (fino alla 6) creava un ActiveXObject – gli altri browser creano direttament oggetto
Javascript di tipo XMLHttpRequest
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 12
Usando Internet Explorer antichi Prima di IE7 era necessario creare un
ActiveXObject a seconda della versione di IE utilizzata e della versione di XMLHttpRequest supportata
In un ciclo for si esegue una clausola try-catch in cui si istanzia un oggetto ActiveX – Si veda xmlHttpRequestIE.js sul sito del
corso
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 13
Oggetto XMLHttpRequest Dopo aver creato l’oggetto può essere
eseguita una richiesta HTTP, ma è necessario specificare – Lo script lato server da invocare – La funzione Javascript che si occuperà di
manipolare i dati ricevuti dallo script L’oggetto viene creato nel seguente
modo: – var req = new XMLHttpRequest();
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 14
Proprietà di XMLHttpRequest Level 1
onreadystatechange readyState responseText responseXML status statusText
(la utilizzeremo in seguito)
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 15
Metodi di XMLHttpRequest abort() getAllResponseHeaders() getResponseHeader(headername) open(method, URL, async,
uname, pswd) send(content) setRequestHeader(label, value)
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 16
Uso di XMLHttpRequest req = new XMLHttpRequest(); req.onreadystatechange = requestStateHandler; req.open("GET", "somefile.php", true);
//req.open("GET", "somefile.xml", true); //req.open("GET", "somefile.asp", true); req.send(""); function requestStateHandler() { if (req.readyState == 4) { //se la risposta è arrivata alert(req.responseText); } }
Onore al merito L'oggetto era stato originariamente introdotto
da Microsoft e usato da Internet Explorer 5.0 come oggetto ActiveX, accessibile via JavaScript – httpRequest =
new ActiveXObject("Microsoft.XMLHTTP"); Gli sviluppatori del progetto Open Source
Mozilla crearono la loro versione di XmlHttp, non come un controllo ActiveX ma come un oggetto nativo nel browser, con il nome di XMLHttpRequest
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 17
new ActiveXObject("Msxml2.XMLHTTP.7.0")
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 18
Proprietà: onreadystatechange Contiene la funzione (callback function)
che processerà la risposta del server Se httpRequest è un oggetto di tipo
XMLHttpRequest, allora si usa la sintassi httpRequest.onreadystatechange =
nomeFunzione Sarebbe meglio usare funzioni letterali
httpRequest.onreadystatechange = function() { /* ...codice... */ }
Nota La proprietà onreadystatechange è il
gestore di evento associato all’evento readystatechange
L’evento readystatechange è scatenato ogni volta che lo stato della richiesta HTTP cambia
Lo stato della richiesta è codificato nella proprietà readyState
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 19
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 20
Proprietà: readyState Contiene lo stato della richiesta. Ogni volta che readyState cambia,
viene eseguita la funzione associata a onreadystatechange
Non avviene nello stesso modo in tutti i browser
Valori di readyState – 0 (richiesta non ancora inviata) – 1, 2, 3, – 4 (risposta arrivata) gestito da tutti i browser
allo stesso modo
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 21
Valori di readyState 0 - UNSENT
– l'oggetto XMLHttpRequest esiste, ma non è stato richiamato alcun metodo per inizializzare una comunicazione [open() non è stata ancora chiamato]
1 – OPENED – open() è stato chiamato ma send() non ancora
2 – HEADERS_RECEIVED – send() è stato eseguito ed ha effettuato la richiesta – il response status e gli header sono stati ricevuti
3 – LOADING – i dati di risposta sono in fase di download
4 – DONE – la richiesta è completa (ricevuta la risposta HTTP)
Questo ordine non è sempre identico e non è sfruttabile allo stesso modo su tutti i browser
Come usare readyState Se
httpRequest= new XMLHttpRequest();
if(httpRequest.readyState == 4) oppure if(httpRequest.readyState ==
XMLHttpRequest.DONE) Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 22
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 23
Come usare readyState Nella funzione associata a
onreadystatechange aggiungiamo un if per testare se lo stato della richiesta oggetto è uguale a 4 (XMLHttpRequest.DONE)
httpRequest.onreadystatechange = function() { if( xhttpRequest.readyState == 4 ){ /* Preleviamo i dati dalla risposta del
server e poi li usiamo… .. e se la risposta HTTP non è “OK” ???? */ } }
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 24
Proprietà: status e statusText status
– Restituisce lo stato della risposta HTTP sotto forma di numero
– 404 (Not Found), 200 (OK), … statusText
– Restituisce lo stato della risposta HTTP sotto forma di stringa
– "Not Found", "OK", …
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 25
Come usare status httpRequest.onreadystatechange = function() { if(httpRequest.readyState == 4 && httpRequest.status == 200 ) { /* Adesso possiamo prelevare i dati dalla
risposta del server ed usarli… */ } }
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 26
Proprietà: responseText
Contiene i dati trasmessi dal server sono sotto forma di stringa
httpRequest.onreadystatechange = function() { if(httpRequest.readyState == 4 && httpRequest.status == 200 )
document.myForm.myElement.value = httpRequest.responseText;
} responseText può contenere codice HTML
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 27
Proprietà: responseXML Contiene la risposta del server in
formato XML.
Questa proprietà restituisce un oggetto di tipo documento XML che può essere esaminato e manipolato usando i metodi e le proprietà associate all’intefaccia Node (W3C DOM)
Dettagli in seguito
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 28
Il metodo open(…) Ha cinque argomenti, ma in genere si
usano solo i primi tre – Il primo definisce quale metodo usare
• GET oppure POST
– Il secondo indica l'url dello script da invocare – Il terzo (booleano) specifica sa la richiesta
debba essere asincrona (true) - indica che il browser non deve aspettare una risposta dal server - oppure no (false)
httpRequest.open(“GET”,”es.php”,true);
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 29
Il metodo send(parm) con GET La variabile param è “vuota” Con il metodo GET si usa
– xhttpRequest.send(null) oppure httpRequest.send(“”)
– I parametri per lo script PHP, se necessari, devono essere indicati nella url dello script da invocare
var url = “getDati.php?q=12&nome=pippo”
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 30
Il metodo send(parm) con POST
xmlHttp.send(param); Effettua la richiesta passando i dati nella
variabile param – I parametri sono formattati come in una URL
• param = “q=12&nome=pippo&kt=234” ma passati al server tramite send
– Maggiori dettagli in seguito
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 31
Template di funzione - GET function ajaxFunction() { xmlHttp = new XMLHttpReques(); xmlHttp.onreadystatechange = funzione xmlHttp.open("GET",url,true); xmlHttp.send(null); } Gli eventuali parametri da passare allo
script sono codificati nell’url url = "script.php?a=v1&b=v2"
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 32
Template HTML È necessario decidere quando la nostra
funzione AJAX deve essere eseguita. <form name="myForm"> Name: <input type="text" name="nome"
onkeyup="ajaxFunction();" /> Time: <input type="text" size="6"
name="time" /> </form>
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 33
function ajaxFunction() { var httpRequest= new XMLHttpRequest(); httpRequest.onreadystatechange = function() { if(httpRequest.readyState == 4 &&
httpRequest.status == 200 ) { document.myForm.time.value = httpRequest.responseText;
} } httpRequest.open("GET","time.php",true); httpRequest.send(null); }
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 34
Lo script time.php La proprietà responseText contiene i dati
restituiti dal server. Per esempio vogliamo l'ora corrente. Ecco il file time.php
<?php header("Cache-Control: no-cache,must-revalidate"); // Una data nel passato per non usare la cache header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); $response=date('h:i:s'); echo $response; ?>
Invece di indicare di non usare la cache possiamo usare un altro metodo – dettagli in seguito
Importante Se si utilizza una variabile globale per
far riferimento all’oggetto XMLHttpRequest, allora il browser può gestire solo UNA richiesta AJAX per pagina.
Si evitano questi problemi usando un event listener – Opera, al momento, non inizializza un
oggetto Event quando si scatena l’evento readystatechange
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 35
Controllare!!
AJAX e i moduli Spesso i dati contenuti in un modulo
vengono inviati al server per essere elaborati utilizzando AJAX con POST
Invece di formattare i dati in coppie di nome/valore come quando sono inviati in una URL possiamo utilizzare l’oggetto Javascript formData
L’oggetto formData automaticamente associa il nome al valore di ogni controllo – Funziona con i browser moderni
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 36
Utilizzo di formData Nel documento HTML è presente un
modulo con ID settato a formID Nel codice Javascript ….
httpRequest = new XMLHttpRequest(); httpRequest.onreadystatechange = funzElabora; var modulo = document.getElementById('formID'); var dati = new formData(modulo); httpRequest.open("POST", "script.php", true); httpRequest.send(dati);
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 37
Se non si usa un modulo… Si può comunque utilizzare l’oggetto
formData Per inserire nomi/valori nell’oggetto si
usa il metodo apped – append(<name>, <value>)
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 38
var dati = new formData(); nome = document.nomeForm.nomeElemento.name; valore = document.nomeForm.nomeElemento.value; dati.append(nome, valore):
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 39
Google suggest - versione base <body> <form> Nome: <input type="text" id="txt1"
onKeyUp="showHint(this.value)"> </form> <p>Suggerimento: <span id="txtHint"></span> </p> </body>
valore contenuto nella casella di testo
posto dove mostreremo i suggerimenti
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 40
Funzione showHint function showHint(str) { if (str.length==0) { document.getElementById("txtHint").innerHTML=""; return; } // cancella il contenuto dello SPAN xmlHttp= new XMLHttpRequest(); // globale var url="getHint.php"; url += "?q="+str; // Numero casuale per prevenire uso di un file in cache url += "&sid="+Math.random(); xmlHttp.onreadystatechange = stateChanged; xmlHttp.open("GET",url,true); xmlHttp.send(null); }
Contenuto del tag che ha come ID txtHint
Può essere codice HTML
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 41
Funzione stateChanged function stateChanged() { if (xmlHttp.readyState == 4){ if (xmlHttp.status == 200)
document.getElementById("txtHint").innerHTML = xmlHttp.responseText;
else alert("Errore HTTP " + xmlHttp.status + " "+ xmlHttp.statusText); } }
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 42
Nota Gli esempi che abbiamo visto non
usano la proprietà responseXML Spesso il contenuto di responseText è
codice HTML – In tal caso, usiamo la proprietà innerHTML
per sostituire frammenti di codice HTML In questo caso, invece di AJAX, si fa
riferimento ad AHAH (Asynchronous HTML over HTTP)
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 43
Altri metodi di XMLHttpRequest getAllResponseHeaders()
– Restituisce, come una stringa, l’insieme di tutti gli header HTTP
getResponseHeader("nomeHeader") – Restituisce il valore dell’header indicato – Ad esempio, potete leggere i cookie settati
dallo script invocato da open setRequestHeader("label","valore")
– Aggiunge una coppia label/valore all’header HTTP che deve essere inviato al server
Disabilitare la cache Per disabilitare il caching dei contenuti di
una richiesta AJAX, prima di invocare il metodo send, possiamo settare un’intestazione opportuna
setRequestHeader("Cache-Control", "no-cache");
In questo modo il client non utilizzerà una risposta ad una sua richiesta già eventualmente presente nella sua cache
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 44
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 45
Usare il metodo POST var url = "script.php"; var params = "a=v1&b=v2"; xmlHttp.open("POST", url, true); //Settiamo l’header opportuno per il POST xmlHttp.setRequestHeader("Content-type",
"application/x-www-form-urlencoded"); xmlHttp.setRequestHeader("Content-length”,
params.length); xmlHttp.onreadystatechange = funzioneDaInvocare; xmlHttp.send(params);
Parametri formattati come per il GET
Non è necessario
Con Safari 5.1.7 Non possiamo settare tutti gli header Ad esempio se tentiamo di eseguire
xmlHttp.setRequestHeader("Content-length”, params.length);
il browser si rifiuta di farlo – la console degli errori segnala
– Refused to set unsafe header "Content-length”
Firefox lo permette
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 46
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 47
<input id="login" name="login" type="text" onfocus="resetta(this)" onblur="checkLogin(this.value)" />
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 48
function resetta() { document.getElementById('loginCheckFailed').className = 'hidden'; }
span.hidden{ display: none; }
<span class="hidden" id="loginCheckFailed"> Questa login è già in uso. Per favore, sceglierne un'altra. </span>
function processReqChange() { // solo se la richiesta è stata completata if (req.readyState == 4 && req.status == 200) { message = document.getElementById('loginCheckFailed'); if (req.responseText == "1") message.className = 'error'; else message.className = 'hidden'; } }
span.error{ display: block; color: black; background-color: pink; }
Nel CSS
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 49
function checkLogin(input) { var url = 'verificaLogin.php' var params = 'q=' + input; loadXMLDoc(url,params); } function loadXMLDoc(url,params) { req = new XMLHttpRequest(); req.onreadystatechange = processReqChange; req.open("POST", url, true); req.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); req.send(params); }
Nota Quando il server invia dei frammenti
di codice HTML che saranno poi inclusi nel documento principale – elemento.innerHTML = httpRequest.responseText
è buona norma indicare, settando in maniera opportuna l’header, che il tipo del contenuto inviato è di tipo text/html
– header(‘Content-Type: text/html’);
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 50
JSON (JavaScript Object Notation) È un formato leggero per lo scambio di
dati È un oggetto (array associativo)
costituito da una collezione di coppie nome/valore
Un oggetto Javascript quando è rappresentato usando JSON appare come la seguente stringa
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 51
{"bananas":"2","apples":"5","cherries":"20"}
Inviare dati in formato JSON Si crea un oggetto Javascript (e.g., dati)
contenente coppie di nome/valore Si setta l’intestazione di richiesta a
– "Content-Type", "application/json" Si usa il metodo POST, ma non si setta
– "Content-type", "application/x-www-form-urlencoded”
Il parametro di send è settato a – JSON.stringify(dati)
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 52
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 53
<button type="button" id="bt" onclick="elaboraForm()">Azione</button>
function elaboraForm() { var dati = new Object(); var inputElements = document.getElementsByTagName("input"); for (var i = 0; i < inputElements.length; i++) dati[inputElements[i].name] = inputElements[i].value; httpRequest = new XMLHttpRequest(); httpRequest.onreadystatechange = handleResponse; httpRequest.open("POST", "stampaJSON.php",true); httpRequest.setRequestHeader("Content-Type", "application/json"); httpRequest.send(JSON.stringify(dati)); }
In PHP Accediamo al payload JSON della
richiesta POST utilizzando la funzione file_get_contents() – Simile alla funzione file(), tranne che
restituisce il file in una stringa – Il file da leggere è 'php://input'
• È un flusso (stream) a sola lettura che permette di leggere dati grezzi nel corpo della richiesta inviata con POST
– $str_json = file_get_contents('php://input');
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 54
Accedere ai dati Per accedere ai dati contenuti in
$str_json utilizziamo la funzione json_decode – Restituisce un arrary associativo
$dati = json_decode($str_json , 'true'); Se $str_json contiene
{"bananas":"2","apples":"5","cherries":"20"} $dati sarà un array associativo con chiavi "bananas", "apples” e "cherries" Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 55
Inviare dati in formato JSON – V2
Si crea un oggetto Javascript (e.g., dati) contenente coppie di nome/valore
Si usa il metodo POST e si setta – "Content-type", "application/x-www-form-urlencoded”
Il parametro di send è settato a – "nome=" + JSON.stringify(dati)
In PHP si accede a $_POST['nome'] a cui si applica json_decode – Attenzione agli slash aggiunti …
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 56
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 57
function elaboraForm() { var dati = new Object(); var inputElements = document.getElementsByTagName("input"); for (var i = 0; i < inputElements.length; i++) dati[inputElements[i].name] = inputElements[i].value; httpRequest = new XMLHttpRequest(); httpRequest.onreadystatechange = handleResponse; httpRequest.open("POST","stampaJSON2.php",true); httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); var str_json = "json_string=" + (JSON.stringify(dati)) alert(str_json); httpRequest.send(str_json); }
Accedere ai dati in PHP Per settare la stringa che contiene i dati
codificati con JSON si usa – $json_str = stripslashes($_POST['json_string']);
La funzione json_decode a partire dalla codifica JSON permette di creare un array associativo contenente i valori codificati con JSON – $dati = json_decode($json_str, 'true');
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 58
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 59
Librerie AJAX Mochikit – Yahoo! UI – Dojo Toolkit
– Prototype – jx – jquery …
Con l’estensione Firebug per Firefox si possono esaminare le richieste/risposte AJAX durante la loro esecuzione
Oppure – Console Web (Firefox) – Mostra informazioni web (Safari) – Strumenti per sviluppatori (Chrome)
Eventi di Livello 2 – supporto OK
abort – La richiesta è abortita
error – La richiesta fallisce
load – La richiesta è completata con successo
loadend – La richiesta è completata con successo o
con errore Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 60
Eventi di Livello 2 – supporto OK
loadstart – La richiesta parte
progress – Quando si verifica un progresso nella
richiesta (dei dati sono invitati/ricevuti) timeout
– La richiesta è andata in timeout
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 61
Nota Tutti gli esempi che abbiamo visto (ma
anche tanti online) per reagire al completamento della richiesta, piuttosto che usare la programmazione ad eventi, fanno riferimento alla proprietà readyState di un’istanza di XMLHttpRequest
Tale approccio funziona ed è richiesto per un ampio supporto di browser differenti, ma non è raccomandato per un utilizzo futuro in applicazioni web moderne
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 62
Senza usare readyState e status
var req = new XMLHttpRequest(); req.addEventListener("progress", updateProgress, false); req.addEventListener("load", transferComplete, false); req.addEventListener("error", transferFailed, false); req.addEventListener("abort", transferCanceled, false); req.open(….);
Prof. Carlo Blundo Tecnologie di Sviluppo per il WEB 63