mercoledì 12 dicembre 2007

Tutorial Ajax - Capitolo 3

Introduzione




Il nostro Ajax Engine ci permette di recuperare i dati dal web server sotto forma di codice html preformattato, oppure come risultato dell’elaborazione di pagine dinamiche scritte magari in JSP oppure in ASP.NET.

Quando si sviluppano web applications complesse ci si ritrova a dover gestire probabilmente qualche decina di interfacce grafiche diverse, collegate ad una pagina principale a cui l’utente accede previa autenticazione e sceglie quale servizio utilizzare tra l’insieme di servizi disponibili all’interno dell’applicazione.

A questo punto chi progetta l’applicazione puo’ in teoria decidere di creare un unico documento il cui contenuto puo’ venire azzerato e reinizializzato per ogni diverso servizio senza ricaricare la pagina che agisce ora solo come contenitore esterno.



Facciamo un semplice esempio per illustrare questo scenario.


Questa e’ una pagina html. Molto semplice e nemmeno il massimo dal punto di vista stilistico. E sicuramente chiunque sarebbe in grado di farla meglio. Pero’ e’ una pagina funzionante. Carica un file contenente le istruzioni di formattazione CSS ed il nostro ajax engine prima di istanziare tre contenitori – i layer- e richiamare la funzione initPage() contenuta nell’engine.

Se la funzione di inizializzazione non eseguisse nessuna operazione al suo interno, questa pagina sarebbe un bel documento vuoto agli occhi dell’utente che vuole visualizzarlo sul proprio browser.



Se pero’ riempissimo di volta in volta i tre contenitori con il contenuto necessario , dislocandoli in posti diversi grazie al file CSS?



Potremmo ad esempio creare un piccolo form all’interno del primo layer:




Se in un file remoto form.html contenesse solo il codice iniziale che vediamo sopra, e lo inserissimo nel primo layer sfruttando il metodo innerHTML, sul nostro browser apparirebbero un campo di inserimento testo, una lista a tendina ed un bottone. Ovvero l’utente vedrebbe gli oggetti che costituiscono il nostro form.

Immagino che a questo punto la strada che voglio seguire si intraveda chiaramente. Con un set di documenti html preformattati, come si trattasse delle tessere di un puzzle, possiamo comporre interfacce grafiche complesse in modo arbitrario, con effetti interessanti ed inediti finora dal punto di vista dell’interattiviita’.

Nel nostro esempio, una volta inserito il nome della citta’ possiamo intercettare l’evento che indica il cambiamento del testo visualizzato per precaricare i codici postali associati in modo trasparente. Solo quando avremo digitato una citta’ riconosciuta caricheremo - pressoche’ in tempo reale e senza che l’utente se ne accorga - solo i suoi CAP corrispondenti nella lista:





La giungla dei fornitori dati

Utilizzando l’impostazione appena vista si puo’ gia’ progettare una web application aziendale su un’unica pagina web. Se pero’ si devono organizzare piu’ servizi e si devono inserire piu’ oggetti nella nostra interfaccia grafica i cui dati (o stati) cambiano a seconda dell’interazione che si ha con l’utente, si puo’ arrivare a dover creare innumerevoli fornitori dati, ovvero documenti html preformattati o pagine dinamiche che restituiscano la porzione di codice html da inserire negli elementi sulla GUI.

Per migliorare un poco la situazione si possono accorpare piu’ oggetti in un fornitore dati.

Se cioe’ avessimo molti oggetti in un form e ognuno di essi deve essere inizializzato con i suoi dati, allora creeremo una pagina dinamica unica che dara’ come risultato il form con gli elementi valorizzati, da collegare al contenitore/layer opportuno. E non avere un fornitore per l’inizializzazione di ogni oggetto.




Ora pero’ dobbiamo dare uno sguardo a come formattare i dati restituiti dai nostri fornitori dati oltre all’html, perche’ spesso avremo la necessita’ di richiedere al web server solo un dataset senza l’html di contorno. Il formato XML
Se ci soffermiamo su AJAX inteso solamente come acronimo, notiamo che l’ XML assume un ruolo rilevante essendo indicato come formato di trasporto dei dati. In realta’ e’ scorretto pensare che l’ XML sia intrinsecamente legato ad Ajax inteso come approccio di progettazione web. Ma comunque puo’ esere utilizzato come formato di output per le richieste Ajax.

XML sta per eXtensible Markup Language, ovvero Linguaggio a Markup estesi.
Si tratta quindi di un linguaggio a markup di tipo generico che puo’ essere utilizzato per descrivere praticamente qualsiasi cosa. L’XML differisce dagli altri linguaggio a markup come l’SGML e l’ HTML per il fatto che non e’ vincolato ad un vocabolario di markup o tag.

Percio’ l’autore di un documento XML e’ libero di utilizzare qualunque termine voglia come marcatore per i tag. L’unica prescrizione e’ che il documento segua alcune regole semplici che pero’ non sono collegate al vocabolario dei tag.

Un esempio di XML






La prima linea di codice e’ una dichiarazione XML. Questa indica la versione dell’XML che si sta utilizzando e la codifica di carattere del documento. Tutto quello che segue deve essere contenuto in tags. Ciascun set di tag denota un elemento del documento. Il nome di un elemento e’ contenuto nel tag di apertura e in quello di chiusura. Il valore di un elemento e’ contenuto nel testo tra il tag di apertura e quello di chiusura. E’ importante notare come l’ XML non fa nulla. Il linguaggio fu creato solo come modalita’ di immagazzinamento dati, non per manipolarli. In quest’ottica per manipolare i dati contenuti occorre un linguaggio di programmazione, come il JavaScript, per estrarre le varie informazioni dal file XML e porli nella pagina web.



L’XML in azione


Se avessimo una pagina web con l’elenco dei dipendenti in un ufficio, memorizzato in un file XML, dobbiamo poter recuperare i vari dati dei dipendenti leggendo il file XML, facendo il parsing dei vari tag e gererando gl iopportuni tag HTML per visualizzare questi dati nella pagina web finale, presumibilmente all’interno di qualche contenitore identificato da uno o piu’ layer





I dati di ritorno, richiamati dal nostro componente XHR, verranno gestiti da un codice javascript simile a questo sull’evento onreadystatechange:



Questi dati in formato XML possono essere “percorsi” usando gli stessi metodi forniti dal Document Object Model utilizzati per “navigare” all’interno di un documento HTML.
e si conosce la struttura dell’ XML ricevuto dal server si puo’ recuperare l’informazione desiderata usando i metodi getElementsByTagName e le proprieta’ come nodeValue.

Estrazione dei dati dall’ XML

Sapendo che nel nostro documento XML e’ presente un elemento , si recupera una collezione dei vari elementi con


Sapendo che di tali elementi ce n’e’ uno solo, sono interessato solo al primo elemento di questa collezione:







Questo elemento contiene quindi il nodo desiderato. Il nodo e’ il primo elemento figlio di questo elemento:






Adesso posso prendere il valore di questo nodo testuale usando la sua proprieta’:





ed assegnamo il valore alla variabile javascript:





In questo modo possiamo recuperare anche le informazioni relative al website e alla email:





Usando I metodi del DOM come createElement, createTextNode e appendChild, possiamo ricostruire una porzione di HTML per contenere le informazioni estratte prima:








A questo punto devo inserirei nuovi markup all’interno del layer nel documento:



var details = document.getElementById("details");






Innanzitutto devo assicurarmi che il contenitore sia vuoto, senno’ svuotarlo:



while(details.hasChildNodes()){
details.removeChild(detaild.lastChild); }



poi inserisco il contenuto:



details.appendChild(header);
details.appendChild(link);



Vantaggi dell’ XML

E’ un formato molto versatile per i dati. Si puo’ definire il proprio vocabolario di tag personalizzandolo per i nostri dati. Questa flessibilita’ ha favorito la larga diffusione del formato XML, che nel tempo e’ diventato uno dei modi piu’ usati per scambiare dati nelle applicazioni web. Inoltre per fare il parsing vero e proprio riutilizziamo i metodi propri del nostro Document Object Model senza la necessita’ di usare un altro linguaggio oltre al Javascript.

Svantaggi dell’ XML



Occorre smpre usare il corretto header. E’ necessario che ad ogni tag di apertura corrisponda il suo tag di chiusura con il corretto annidamento degli elementi. E’ quindi facilecommettere un errore.
Utilizzare il DOM per distribuire il contenuto parserizzato puo’ essere una operazione non cosi’ breve per cui sono necessarie molte istruzioni.Ogni nodo deve essere creato ad attaccato al documento. Uno ad uno. Quindi per una applicazione con un file XML grande il codice puo’ diventare presto troppo complesso da gestire con facilita’. Si potrebbero usare a questo proposito le XSLT, o eXtensible Stylesheet Language Transformations, che effettuano un mapping tra XML ed XHTML.
Il problema e’ che non tutti i browser supportano questa funzione avanzata.



Il formato JSON

Abbiamo detto in precedenza che per formattare i dati richiesti al web server possiamo utilizzare un documento html statico o dinamico, oppure un documento xml, o recuperare i dati richiesti secondo il formato JavaScript Object Notation.

In molti ritengono che il formato XML sia il miglior formato per l’interscambio di dati. Come visto prima e’ un formato testuale per cui si puo’ assicurare l’interazione tra sistemi diversi attraverso la difinizione dei DTDs oppure degli Schemi XML. Questi sono dei meccanismi usati comunemente quando si devono trasmettere dati tra sistemi disomogenei o tra piattaforme diverse.

In questo modo si rende il formato dei dati indipendente dalle tecnologie utilizzate per il loro trattamento. Il prezzo da pagare e’ la necessita’ di recuerare dall’XML la strutturazione gerarchica interna a questi dati nel linguaggio proprio dei vari sistemi da cui devono essere elaborati , ed eventualmente ritrasformare i nuovi dati risultanti qualora debbano essere trasmessi ad altri sistemi.

Nel nostro caso dovremo convertire i dati ricevuti in formato XML in oggetti JavaScript.

Quando usiamo il formato diretto html, in abbinamento al metodo innerHTML, questa conversione avviene attraverso il parsing del codice effettuato dal browser e la conseguente creazione degli oggetti JavaScript all’interno del Document Object Model.

Utilizzando l’ XML dobbiamo effettuare esplicitamente il parsing del codice e la distribuzione nel DOM attraverso la valorizzazione degli attrbuti dei nodi interessati oppure la creazione di nuovi Nodi collegati a nodi preesistenti. Cio’ avviene utilizzando i metodi di trattamento forniti dal DOM stesso.

Personalmente non ho mai, se non in casi assolutamente necessari, utilizzato questa impostazione per trattare i dati ricevuti. Ritengo che porti a dover scrivere codice javascript troppo lungo - cosa di per se’ poco efficiente per un linguaggio interpretato come il javascript - e nemmeno tanto intuitivo per le strutture da utilizzare in questo caso specifico (navigazione della gerarchia del DOM, Xpath, espressioni regolari).

Da questo punto di vista la situazione ottimale sarebbe quella di avere a disposizione i dati in un formato che possa essre utilizzato direttamente dal JavaScript, html preformattato a parte.

Questo formato e’ chiamato JSON (http://json.org/) e consiste in un dataset in notazione letterale ad oggetti javascript.


Proviamo a convertire un dataset XML in JSON:








Convertito in notazione JSON diventa:





Il benieficio di questo formato e’ che e’ gia’ in un formato che JavaScript puo’ comprendere, e tutto cio’ che serve fare e’ convertire questo codice in oggetti da mostrare usando il metodo eval() alla stringa:


var data = eval( '(' + x.responseText + ')' );


Cio’ restituisce il contenuto come oggetti che possiamo manipolare attraverso l’uso della notazione array-associativa o di proprieta’ degli oggetti.





Per i fornitori dati nel nostro server l’utilizzo del formato JSON al posto del formato XML e’ decisamente piu’ efficiente e veloce (nei miei test si ha una velocizzazione fino a dieci volte). Comunque dobbiamo stare attenti ad una cosa: l’utilizzo del metodo eval() puo’ essere pericoloso perche’ esso esegue qualsiasi codice javascript, e non solo steinghe JSON. Possiamo aggirare questo problema utilizzando , al posto del metodo direttamente, una funzione di parsing che ci assicuri che solo i dati vengano convertiti in oggetti, mentre il codice potenzialmente pericoloso non venga eseguito.

Esiste una libreria open-source liberamente scaricabile all’indirizzo
http://www.json.org/js.html che contiene il parser per i dati JSON. Nella nostra web application sara’ sufficiente in cludere tale libreria nella pagina principale, insieme all’ajax engine.






Vantaggi del formato JSON


La notazione JSON e’ leggera. Mentre ogni valore in XML richiede un tag di apertura ed uno di chiusura, JSON richiede solo un nome da scrivere una volta sola.
Diversamente dall’ XML, JSON non ha bisogno di essere trasmesso dal web server con uno specifico header “content-type” ma viene trasmesso come testo semplice.


Svantaggi del formato JSON


La sintassi richiesta dal format JSON e’ molto precisa. Un apice al posto sbagliato o una parentesi mancante possono cambiare significato a tutta la stringa JSON. Occorre anche gestire con le sequenze di escape i caratteri speciali come i singoli e i doppi apici. Una stringa JSON complessa puo’ diventare assai poco leggibile a differenza di un dataset XML la cui lettura e’ agevolata dalla presenza dei tag iniziali e finali. In piu’ occorre fare la valutazione della stringa JSON in modo sicuro occorre ricordarsi di processarla con la funzione di parsing opportuna che esegue solo le proprieta’ contenute nella stringa ignorando qualsiasi funzione o metodo in essa presente.


Riassunto


In questo capitolo abbiamo visto alcuni aspetti collegati all’utilizzo del nostro ajax engine all’interno di una web application. Innanzitutto abbiamo visto l’approccio che, a fonte di una pagina html che agisce da puro contenitore, utilizza chiamate multiple ai fornitori (di dati e struttura grafica) per costruire sia l’interfaccia grafica (utilizzando fornitori HTML statici oppure dinamici), sia per popolarne gli elementi.
Poi abbiamo visto come accorpare la costruzione della GUI in un'unica chiamata remota - o in poche chiamate al server, delegando poi ai fornitori dati veri e propri il compito di popolare gli elementi costruiti. In seguito abbiamo visto come utilizzare il formato XML oppure il formato JSON per caricare e distribuire sul client i dati richiesti al server.