23
12
06

jQuery 2: Ajax

15:31 Technocracy

Come ogni buona libreria ‘Web 2.0′ anche jQuery contiene il suo supporto Ajax. Dato l’orientamento di jQuery verso il DOM (come abbiamo già detto, jQuery inizia con il selezionare tutti gli elementi su cui si applicherà) una delle funzionalità primarie che vengono intuitivamente in mente è il supporto a quello che viene chiamato Ahah. Ovvero, una variante Ajax che invece si chiama “Asynchronous HTML And HTTP”.

Non sono molto d’accordo con questa definizione che ritengo superflua: Javascript è comunque utilizzato, HTML dovrebbe essere XHTML (quindi XML) e HTTP è una ovvietà.

Caricamento diretto via Ajax

Comunque, a parte questa digressione, questo tipo di funzionalità non fa altro che caricare tramite Ajax il contenuto di un elemento della pagina:

Prendo un esempio preso parzialmente da PhotoShakr:

$("#list").load("form/sets?user=" + $("#email").attr("value"))

Il comando è semplice ed intuitivo, come è prevedibile da jQuery:

  1. Seleziono gli elementi con ID “list”. Essendo un ID è univoco.
  2. Carico (load) al suo interno il risultato della pagina puntata dall’URL passato come parametro.
  3. Il parametro è composto dal valore dell’elemento con id “email”, che non è altro che il campo del form contenente l’e-mail dell’utente.

Con una singola riga di codice ho interrogato il server, ottenuto il risultato e modificato la pagina.

Per rendere l’operazione un po’ più user-friendly poi ho preceduto la riga di cui sopra con:

$("#list").html("Asking Flickr...");

Che immediatamente cambia il contenuto del campo in modo che l’utente capisca subito che sta caricando qualcosa.

Dettagli su load()

Load accetta oltre all’URL anche due parametri opzionali: parametri e funzione callback.

  1. L’URL è un normale URL, non credo vi sia niente da aggiungere.
  2. I parametri sono costituiti da un hash contenente coppie di valori da passare (i.e. {test: true}).
  3. La funzione callback è un oggetto funzione javascript (anche lambda, ovvero dichiarato al momento) che viene eseguito appena si è ricevuta risposta dal server. Questa funzione prende un parametro, data, che è il contenuto della risposta (i.e. function(data) { alert(“Ok!\n” + data); } ).

Ad esempio quindi la chiamata di cui sopra poteva diventare:

$('#list').load(root + 'form/sets', {user: $('#email').attr('value')});

Che è anche più chiaro da leggersi, separando la posizione della risorsa/comando (URL) dai parametri variabili passati.

Ajax: anche post() e get()

Però load() è un comando che carica direttamente nella pagina. Ajax in realtà consente manipolazioni più complesse che potrebbero non richiedere un inserimento 1:1 diretto del risultato sulla pagina.

Per questo motivo ci sono post() e get() che funzionano con gli stessi parametri, ma con la differenza che non si applicano a nessun elemento del DOM:

Come vedete la chiamata non specifica nessun elemento. La funzione callback anche qui ha un parametro che contiene l’oggetto XML.

$.post("test.cgi", function(data) { alert("Ok! " + data); })

Preciso un dettaglio importante che potrebbe sfuggire ai meno esperti: si dovrebbe utilizzare GET nel caso in cui non si modifica alcuna risorsa sul server, mentre POST quando si inviano dati che modiicano lo stato del server.

JSON, cross domain loading

Vi è anche un’alternativa ad Ajax, che utilizza un interessante workaround in grado fra le varie cose di aggirare i problemi di sicurezza connessi con la chiamata Ajax allo stesso dominio di appartenenza. Per quanto possa portare a possibili problemi di sicurezza, tutt’ora non mi risulta ve ne siano, né che i browser lo impediscano in alcun modo.

JSON è un formato di interscambio di dati semplice, basato su sintassi JavaScript (JavaScript Object Notation). Di fatto si tratta di una serie di strutture dati javascript (hash, array, …).

La nostra libreria jQuery supporta anche questo tipo di chiamate:

$.getJSON(url, params, callback);

Qui bisogna capire un po’ meglio come passare i dati, in quanto devono essere formattati non in XML ma in JSON, ma per il resto dei dati JSON sono immediatamente disponibili e non necessitano di parsing.

Il parametro passato alla funzione callback infatti è l’oggetto JSON appena caricato.

10 comments Add yours below

1

Francesco 2007 06 11 at 14:30

Ciao, utilizzando la funzione load() per recuperare delle infomazioni dal server e caricarle in una pagina, ho riscontrato il seguente problema in IE6 (non ho ancora verificato su IE7) che la pagina viene visualizzata come se si trattasse di un xml, mentre con FF funziona benissimo!
E' possibile che caricando il risultato della richiesta cambi il content type della pagina? ma sia la pagina contenente lo scrip sia la pagina che fornisce l'hml da caricare hanno un content type text/html e un DOCTYPE Strict
Ti è mai capitato qualcosa di simile? Avresti qualche suggerimento?
2

Folletto Malefico 2007 06 11 at 15:14

Parlando in astratto è un po' difficile capire l'esatto problema. Da quello che mi dici però: come può avere DOCTYPE Strict la pagina che carichi?

Mi spiego: con load(), si carica un pezzo di HTML, non una intera pagina. Quindi, non conterrà né DOCTYPE, né head, né body. ;)
3

Francesco 2007 06 11 at 21:50

Hai ragione solo quella che contente lo script è definita come XHTML con DOCTYPE Strict. Mentre quella che carico è del semplice testo, senza alcun tag, generato dinamicamente da una jsp in funzione dei parametri passati, che nel header della risposta setta il content type a text/html ed il pageEncoding UTF-8.
4

Folletto Malefico 2007 06 12 at 11:05

Beh, per quel che mi dici non dovrebbe esserci alcun problema a parole. :P
5

palka 2008 02 26 at 12:35

fantastico!
ma guarda cosa trovo con Google :P
tanto tempo che non passavo di qua :)
visto che ci sono, perché IE7 mi dà errore quando carico dell'xml con $.ajax() ??
che fastidio :|
6

Folletto Malefico 2008 02 26 at 12:46

Uh al momento non ho modo di verificare. :|
Cmq beh, mi esimo da commenti su IE. Strano cmq perché in teoria jQuery dovrebbe gestire queste cose, forse un problema sull'XML che riceve?
7

palka 2008 02 26 at 12:50

infatti, jQuery dovrebbe uniformare tutto, ma non è la prima volta che mi capita, e di solito risolvevo usando JSON (perché magari chiamavo uno script php fatto da me, e quindi me lo potevo gestire), ma stavolta non posso farlo (sono dati che ricevo da una servlet java).
uffa.
grazie comunque, ho chiesto nella mailing list ufficiale (là non mi risponde mai nessuno tra l'altro asd), e sto googlando a più non posso.
speriamo ben.
grazie per la risposta velocissima (e scusa per l'altro commento, doppia figuraccia, non credevo avessi abilitato l'html nel commenti :P)
8

palka 2008 02 26 at 13:11

ho risolto! sono molto contento, posto qua ché non si sa mai che qualcun'altro si trovi a googlare qualcosa di simile.
una piccola modifica alla chiamata $.ajax()

$.ajax({
url: 'http.....',
type: 'get',
dataType: (jQuery.browser.msie) ? 'text' : 'xml',
success: function(xmlData, textStatus){
var data;
if ( typeof xmlData == 'string') {
data = new ActiveXObject( 'Microsoft.XMLDOM');
data.async = false;
data.loadXML( xmlData);
} else {
data = xmlData;
}

etc....
non è elegante, non è bella, però funziona.
per ora può andare, se serve :)
9

Folletto Malefico 2008 02 26 at 13:30

Non ho il codice sotto mano, qual è l'aggiunta? E il motivo si sa? :D
10

palka 2008 02 26 at 14:06

già, l'aggiunta sta in due punti. usare un dataType diverso a seconda del browser

dataType: (jQuery.browser.msie) ? 'text' : 'xml'

quindi se il browser è IE, il tipo dati diventa 'text'.
e in questo uso che vien fatto dell'xml che si ottiene come risposta alla chiamata


success: function(xmlData, textStatus){
var data;
// quindi se ho del testo vuol dire che sono in IE
if (typeof xmlData == 'string') {
data = new ActiveXObject( 'Microsoft.XMLDOM');
data.async = false;
data.loadXML( xmlData);
} else {
data = xmlData;
}

Leave your Comment

required

required, hidden, never shared

Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post ~ Subscribe to the comments via RSS Feed