Introduzione a LoadVars per JavaScript
Andrea Giammarchi 16/08/2005
Cos'e' il LoadVars
Fin dalla versione 6 (MX) del FLash di Macromedia l' interazione server-side con il linguaggio ActionScript e' cambiata sensibilmente grazie a questo nuovo oggetto chiamato LoadVars.
Questo non e' altro che un modo asincrono di inviare / leggere dati da un SWF ad un linguaggio server-side , qualunque esso sia.
Puo' anche leggere, ovviamente, semplici files di testo i quali saranno gli unici presi in considerazione in questa pillola poiche' una volta capito come interagire si puo' tranquillamente implementare il tutto con il linguaggio che conoscete meglio.
Lo scopo di questo porting per JavaScript e' quello di utilizzare gli stessi metodi e la stessa procedura di interazione senza essere costretti a sfruttare un programma proprietario e costoso quale e' il Flash.
Sintassi base
codice:
<html>
<head>
<script type="text/javascript" src="LoadVars.js"></script>
<script type="text/javascript">
// istanzio l' oggetto javascript
var mioLV = new LoadVars();
// dichiaro cosa fare a caricamento avvenuto
// tramite la funzione onLoad
mioLV.onLoad = function(s) // s e' una booleana di conferma caricamento dati
{
if(s) // se il caricamento e' avvenuto con successo
{
alert(this.risultato);
}
else // problemi durante il caricamento dati
{
alert('Problemi durante il caricamento dati');
}
}
// funzione da richiamare a pagina caricata
function startExample() {
// carico il file di testo
mioLV.load('esempio.txt');
}
</script>
</head>
<body onload="startExample();">
<div>
LoadVars Test
</div>
</body>
</html>
Il file esempio.txt sara' un file di testo contenente la seguente stringa:
risultato=tutto ok
Come noterete appena la pagina viene caricata una finestra di alert ci mostra il contenuto di una variabile, ovvero di mioLV.risultato che dentro la funzione di mioLV puo' essere richiamata semplicemente con this , riferito per l' appunto a se stesso.
Come primo esempio potrebbero non essere chiare le potenzialita' dell' oggetto, pero' penso sia importante per cominciare a prendere familiarita' con la sintassi da usare.
Ricezione di piu' dati ordinati
Se volessimo resituire all' oggetto LoadVars piu' di un risultato, ad esempio tramite una query, bastera' restituire chiavi univoche , ognuna con il valore che ci interessa.
Esempio di altro file di testo:
codice:
&risultato_0=primo risultato&
&risultato_1=secondo risultato&
&risultato_2=terzo risultato&
Osserviamo subito che ci sono delle e commerciali che separano i vari risultati, infatti ogni informazione che vogliamo inviare dovra' essere formata da una coppia chiave => valore ed ogni coppia deve essere separata da una e commerciale ( & ).
Quanto scritto qui sopra poteva essere scritto anche cosi':
risultato_0=primo risultato&risultato_1=secondo risultato&risultato_2=terzo risultato
il fatto di chiudere tutto tra 2 & ed andare a capo e' solo per avere un file con testo pulito.
Meglio ancora, essendo un' interazione client/server, scrivere eventuali coppie chiavi/valori utilizzando il minor numero possibili di caratteri, almeno per le chiavi, cosi' da avere una pagina leggera da caricare e rendere la navigazione "real-time" anche con le connessioni piu' lente.
Esempio ottimizzato:
r0=primo risultato&r1=secondo risultato&r2=terzo risultato
Su 3 valori non e' indicativo ma su una mole di dati consistente questo tipo di ottimizzazione si fa sentire e come.
Ora passiamo al javascript , perche' uso risultato_X e come posso fare per leggermi N risultati senza sapere quanti saranno ???
codice:
// ...
mioLV.onLoad = function(s) {
if(s) {
// uso una variabile temporanea per scorrermi tutti i risultati
var a = 0;
// ciclo tutto cio' che e' stato letto al caricamento del file di testo
// ogni variabile (chiave) restituita puo' essere letta come
// this.risultato_N
// ma ovviamente anche come
// this['risultato_N']
// il quale ci permette di crearci a piacere cio' che vogliamo leggere
while(this['risultato_' + a]) // mentre esiste risultato_N con N da 0 a N + 1
{
// mostra questo risultato
alert(this['risultato_' + a]);
// incrementa a di 1 cosi' da ripetere questo ciclo se esiste
a++;
}
}
else
alert('Problemi durante il caricamento dati');
}
// ...
Come c'e' da aspettarsi, gli alert saranno 3 ed ognuno conterra' il valore corrispondente.
primo risultato
secondo risultato
terzo risultato
Ecco che e' gia' possibile richiedere un' intera query ad un linguaggio server side, sfruttando questo tipo di ordine numerico.
r0=Titolo news&t0=testo news&r1=altro titolo&t1=altro testo .... etc etc
cosi' da popolarci dinamicamente uno o piu' campi della nostra pagina web.
Invio di dati
Oltre a leggere pagine statiche e/o pagine create dinamicamente possiamo anche interagire con queste tramite l' invio di dati dal client.
Il primo e piu' semplice metodo per inviare i dati e' l'utilizzo di variabili appese all' url in fase di caricamento.
codice:
// ...
mioLV.load('esempio.server?nick=andr3a&nome=Andrea');
// ...
In questo modo la pagina esempio.server , dove server sara' ovviamente l' estensione dedicata per il vostro linguaggio server-side , ricevera' in modalita' GET le due variabili nick e nome contenente i 2 valori andr3a e Andrea.
Per cosa puo' essere utile ? Per inviare ad esempio un limite di risultati alla vostra query , esempio.server?limit=10 , dove lato client incrementiamo il limite di 10 in 10 e ci sfogliamo ad esempio un archivio news senza mai ricaricare la pagina e senza appesantire la banda con troppi dati.
SELECT title, content FROM news LMIT {GET}, 10
con GET diverso ed inviato dal client avremmo un esempio.server?limit=0 , per le prime 10 , esempio.server?limit=10 , per le altre 10, esempio.server?limit=20 ... e cosi' via ...
Ma ovviamente sto' facendo esempi semplici , potete fare quello che volete con le variabili inviate al server.
Un altro metodo piu' elegante per inviare dati e' usare l' oggetto LoadVars stesso tramite la creazione di variabili interne.
codice:
var mioLV = new LoadVars();
mioLV.nick = 'andr3a';
mioLV.nome = 'Andrea';
// ...
La cosa differente rispetto al metodo descritto prima e' che bisogna utilizzare una funzione dedicata e interna al LoadVars, che puo' essere send o sendAndLoad.
Con send inviamo solo dati senza leggere niente e possiamo scegliere come inviare questi dati, ovvero se usare GET o POST.
codice:
mioLV.send('esempio.server', 'POST');
// oppure
mioLV.send('esempio.server', 'GET');
A seconda del metodo scelto il server ricevera' le variabili in post o get di nome nick e nome con contenuto andr3a ed Andrea.
Il metodo sendAndLoad invece ci permette di inviare le variabili e di leggere , dopo aver inviato , il contenuto della pagina.
codice:
mioLV.send('esempio.server', mioLV, 'POST');
In questo caso dobbiamo specificare anche chi ricevera' il risultato della pagina esempio.server , che dovra' essere un oggetto LoadVars identico o diverso da quello usato per inviare i dati.
Se non abbiamo necessita' particolari possiamo usare questo stesso oggetto , mioLV , cosi' da non andare in confusione con le troppe variabili da usare nel JS.
Se volessimo inviare sia variabili in POST che GET ovviamente bastera' usare send o sendAndLoad appendendo le GET alla pagina da caricare e le POST interne alla variabile.
codice:
mioLV.nome = 'Andrea';
mioLV.send('esempio.server?nick=andr3a', mioLV, 'POST');
In questo modo il server ricevera' la GET nick con valore andr3a e la POST nome con valore Andrea.
Vi sembra facile , comodo , fantastico ??
.... e questa e' solo la base , si possono fare preloads dei dati , gestione errori / eventi o altro ancora 
Errori comuni
La prima cosa sbagliata tipica di questa interazione e' questa:
codice:
var nome = 'nessuno';
var mioLV = new LoadVars();
mioLV.onLoad = function(s) {
if(s)
nome = this.risultato;
}
mioLV.load('esempio_sbagliato.txt');
document.elemento.innerHTML = nome;
No, no e no ... l' evento onLoad e' un evento asincrono, non potete fare niente fuori da questo evento se cio' che dovete fare sfrutta variabili caricate da un LoadVars ...
Questo significa che anche se this.risultato sara' valido, esistente, funzionante, il valore della variabile nome non cambiera' mai se non dentro l' evento onLoad quindi in questo caso' sara' sempre 'nessuno'.
Per fare la stessa cosa in modo giusto si potrebbe risolvere cosi'
codice:
function scriviNome(nome) {
document.elemento.innerHTML = nome;
}
var nome = 'nessuno';
var mioLV = new LoadVars();
mioLV.onLoad = function(s) {
if(s)
nome = this.risultato;
scriviNome(nome);
}
mioLV.load('esempio_sbagliato.txt');
dove la funzione scriviNome verra' richiamata al momento opportuno ( e' possibile ovviamente usare document.elemento.innerHTML = nome; dentro l' onLoad ).
Quindi ricordarsi sempre di non usare i riferimenti dinamici o da caricare di un oggetto LoadVars prima che questo sia stato di fatto caricato.
Un altro errore tipico e' quello di non cancellare i risultati di un precende onLoad , ovvero lasciare l' oggetto popolato che puo' dare risultati inaspettati.
Significa che se carico r0 , r1 , r2 ... rN , quando riutilizzero' l' ogggetto per caricare altri dati questo avra' comunque memorizzati i precedenti risultati quindi anche se il server mi da solo r0 ed r1 , l' oggetto avra' ancora r2, r3, ..., rN della precedente interazione.
Con un bel delete this['r' + X] in fase di lettura dati ricevuti possiamo evitare questo inconveniente.
Considerazioni
I browsers piu' datati potrebbero non poter utilizzare questo tipo di interazione ma sarebbe possibile creare interi siti dinamici lato server come lato client senza dover fare mai un refresh.
Ovviamente consiglio eventuali alternative ad applicativi basati su questo oggetto perche' un client testuale o che non supporta JavaScript o ce l' ha disabilitato potrebbe non essere in grado di vedere niente.
Risorse ed esempi
Oggetto LoadVars
Esempio funzionante con preload
Esempio con errore server side
Documentazione Completa