Newsgroups: it.comp.lang.javascript
Date: Fri, 23 Mar 2001 10:42:38 GMT
Subject: condizionale "IF" che richiama codice javascript
From: "ivan" <ivan_terzoATlibero.it>
Ecco la situazione:
pagina HTML che richiama uno script esterno.
In tale script sono presenti dei condizionali che, al verificarsi di alcune
condizioni, devono richiamare uno script esterno contenente dati.
Come posso "caricare" uno script esterno da un'altro al verificarsi di una
condizione?
grazie a tutti |
Domanda interessante.
Può, effettivamente, essere un'esigenza comune. Questo tutorial tratterà una soluzione generica all'idea, per il semplice uso di soli dati caricati dall'esterno (articoli per un "carrello della spesa" ad esempio) sarà sufficiente leggere la parte relativa alla funzione
caricato().
Prima di cominciare un'avvertenza. Questo script è tossico, a me è venuto un gran mal di testa, se continuate nella lettura, lo fate a vostro rischio e pericolo! :-)
Let's go!
Come nei normali programmi si usano le DLL per caricare e scaricare dinamicamente "pezzi" di programma, la stessa esigenza si può sentire con il codice JavaScript quando non sia necessario (funzioni che probabilmente non servono) o opportuno (script troppo lunghi che rallentano il caricamento) includere nello stesso script tutte le funzioni che devono lavorare in una pagina.
Una possibile soluzione, la prima che viene in mente, può essere quella di spezzare lo script in una parte fissa e vari pezzi da aggiungere, poi usare la URL per passare i valori delle variabili che servono ancora, ed il nome del "pezzo" di script da aggiungere alla pagina, usando
document.write() per riscrivere il tag <SCRIPT>. Soluzione difficile da implementare per il passaggio delle variabili, e scomoda perché impone comunque il reload della pagina.
Un'altra soluzione un po' più fattibile è usare un frame nascosto che viene opportunamente ricaricato con delle pagine HTML che contengono i vari pezzi di script. In questo modo si elimina il reload della pagina principale e la necessità di passare le variabili, rendendo quindi la navigazione più pulita. Naturalmente le funzioni degli script devono tener conto del percorso all'interno della gerarchia del documento per colloquiare fra loro. Quindi una funzione nel frame visibile, per eseguirne un'altra in quello invisibile deve usare una sintassi tipo
top.frames.nascosto.funzione() e per leggere una variabile dovrebbe fare qualcosa come
top.frames.nascosto.nomevariabile. Idem per il nascosto che legge una variabile del frame visibile:
top.frames.visibile.altrafunzione().
E se invece mettessimo tutto nel documento?
Si può fare e la gestione risulta un po' più comoda, anche se rimane una piccola incompatibilità fra i due browser.
Netscape ci offre il tag
<LAYER> con la sua proprietà
SRC, analoga proprietà che troviamo, per Explorer, nel tag
<IFRAME>.
Possiamo allora, invece di aggiornare un frame nascosto, cambiare la pagina contenuta nel LAYER/IFRAME e fare riferimento ad esso per caricare e scaricare pezzi di script.
Prima di continuare vediamo i sorgenti dei files:
La pagina principale (visibile)
index.html:
<HTML>
<HEAD>
<SCRIPT>
<!--
var attr=document.layers?"layers":"frames";
var controllo="Funzione nello script caricato e variabile nel frame principale";
function carica(){
document.layers?document[attr].incluso.src="incluso.html":document[attr].incluso.location="incluso.html";}
function mostralert(){
document[attr].incluso.allerta();}
function caricato(){
alert(document[attr].incluso.variabilecaricato);}
function caricato2(){
document[attr].incluso.allerta2();}
//-->
</SCRIPT>
</HEAD>
<BODY BGCOLOR="#ffffff">
<LAYER NAME="incluso" WIDTH="0" HEIGHT="0" VISIBILITY="hide"></LAYER>
<IFRAME NAME="incluso" WIDTH=0 HEIGHT=0></IFRAME>
- <A HREF="javascript:carica()">Carica script</A> <BR>
- <A HREF="javascript:mostralert()">Esegue funzione nello script caricato</A> <BR>
- <A HREF="javascript:caricato()">Usa in una funzione nella pagina visibile una variabile nello script caricato</A> <BR>
- <A HREF="javascript:caricato2()">Una funzione nella pagina visibile esegue una funzione
nel frame caricato che visualizza una variabile dichiarata nel frame visibile (:-!)</A>
</BODY>
</HTML>
Lo script caricato
incluso.html:
<SCRIPT>
var nn=document.layers?true:false;
var variabilecaricato="La funzione e' nel frame visibile, la variabile nello script caricato";
function allerta(){alert("Questo alert e' una funzione nello script caricato")}
function allerta2(){alert(nn?controllo:top.controllo)}
</SCRIPT>
Questo è quanto ci serve... niente di più... a parte un'Aspirina :-)
Alcune annotazioni prima di continuare:
- Gli script andranno salvati con estensione ".html" (o ".htm") con all'interno i tags <SCRIPT> ... </SCRIPT>. Questo per compatibilità con Netscape. Se usassimo l'estensione ".js" il browser non saprebbe "interpretare" il documento e ci darebbe un errore: "Alert! did not find a converter or decoder";
- In tutti i files caricati andrà ripetuta la riga "var nn=document.layers?true:false;". Questo per Explorer che nei frames ha bisogno di una variabile locale perché un <IFRAME> è un documento a sé.
- Il codice nei due pezzi blu può essere copiato ed incollato in due files. Nella pagina principale vedrete solo i quattro link, e non succederà niente. Per provare il tutto dovete cliccare su "Carica script", in questo momento il file incluso verrà inserito nel documento, ed anche se non ci sarà alcun effetto visibile (il LAYER è nascosto e l'IFRAME ha dimensioni zero) i successivi tre link funzioneranno.
Gli script
Facciamo prima una panoramica, poi scendiamo nei dettagli della sintassi.
Iniziamo dal file principale.
attr è una variabile che vale "layers" se il browser è Netscape o "frames" se il browser è Explorer. Ci servirà dopo per eseguire la giusta sintassi nelle funzioni.
controllo è una variabile contenuta nella pagina principale. In uno script "reale" potrebbe essere anche un array, qui ci serve per vedere come viene vista ed usata dagli script inclusi.
carica() è la funzione che si occupa di caricare lo script esterno. Nel nostro esempio è lanciata da un link, ma in un progetto reale l'azione che esegue deriverebbe da altri script che cambiano le inclusioni secondo necessità. In tal caso sarà opportuno parametrizzarla per dirle
quale script includere. Questa è l'unica funzione (nella pagina visibile) che non può essere unificata usando
attr, perché per Netscape dobbiamo lavorare sulla proprietà
SRC del
layer, mentre per Explorer sulla proprietà
location del
document.
Le altre due funzioni simulano il lavoro normale, la prima (
caricato()) esegue una funzione nella pagina visibile che usa una variabile nello script caricato, la seconda, invece, esegue una funzione nello script caricato che usa una variabile nella pagina visibile.
Queste due funzioni vengono eseguite dal terzo e quarto link nella pagina visibile (notate che nel file incluso non ci sono tag ad eccezione di <SCRIPT> perché il nostro intento è includere solo codice JavaScript). Dei restanti due links, il primo (
Carica script) esegue la funzione
carica() di cui abbiamo già accennato, il secondo invece lancia una funzione che gira tutta nello script caricato.
Nello script caricato invece troviamo:
var nn=document.layers?true:false; È necessario per colpa di Explorer, dato che in questo browser usiamo un IFRAME, per lavorare con variabili ed eseguire le funzioni del documento
contenente bisogna risalire l'albero per prenderle.
variabilecaricato è semplicemente una variabile presente, appunto, nello script caricato. Ci serve per vedere come dalla pagina contenente lo script viene usata.
allerta() è una funzione che gira tutta nello script caricato. Qui è un
alert() che visualizza un testo qualunque, potrebbe essere
alert(variabilecaricato) a simulare una funzione caricata che usa variabili contenute nello stesso file.
allerta2(), invece, è una funzione contenuta nello script caricato che usa (ancora con
alert() nell'esempio) una variabile presente nella pagina principale.
Direi che come premessa è tutto
Era ora direte voi, ma credetemi, era necessaria. Il mal di testa viene adesso! :-)
Iniziamo dal dire perché non possiamo unificare la funzione di caricamento del file incluso. Ci serve perché dobbiamo usare due diversi TAG per includere i nostri script. <LAYER> per Netscape e <IFRAME> per Explorer, perché sono gli unici tag dei due browser che prevedono una proprietà
SRC che possiamo usare per modificare il documento incluso (
Le smentite sono ben accette!!!). Purtroppo, questa proprietà non fa parte del tag <DIV> (neanche per il solo IE) che può essere usato da entrambi i browser, quindi già dal caricamento dello script esterno avremo una sintassi diversa:
document.layers.incluso.src per Netscape e
document.frames.incluso.location="" per Explorer. Se avessimo potuto usare <DIV> sarebbe stato tutto molto più semplice. :-(
L'assenza di
SRC per il <DIV> comporta anche un'altra difficoltà che vedremo fra poco.
L'uso della funzione
allerta() è la cosa più semplice. La funzione con le sue variabili è tutta contenuta nello script incluso. Per eseguirla dalla pagina principale, ci basta lanciarla con la giusta sintassi
La funzione
mostralert() (eseguita dal secondo link) esegue una funzione contenuta nello script caricato. Qui usiamo per la prima volta la variabile
attr che abbiamo valorizzato all'inizio.
allerta() è la funzione contenuta nello script caricato, e viene eseguita con la sintassi
document.layers.incluso.allerta() se il browser è Netscape, con
document.frames.incluso.allerta() se il browser è Explorer. L'interprete JavaScript dei browser sostituisce a
attr la giusta stringa ("layers" o "frames"), evitandoci il fastidio di scrivere questa funzione, e le seguenti, in una forma del tipo:
document.layers?document.layers.incluso.allerta():document.frames.incluso.allerta() che sarebbe difficile da manutenere.
La seconda funzione:
caricato() è ancora semplice.
variabilecaricato sta nello script incluso, quindi la raggiungiamo come nel paragrafo precedente abbiamo raggiungo
allerta() e la usiamo nella nostra funzione.
Ora viene il difficile
La funzione
caricato2() viene lanciata come
allerta(), e fin qui non c'è problema. Il problema sta nella sintassi di questa funzione che è contenuta nel file incluso.
Rivediamolo con evidenziata la funzione ed i pezzi che la riguardano:
<SCRIPT>
var nn=document.layers?true:false;
var variabilecaricato="La funzione e' nel frame visibile, la variabile nello script caricato";
function allerta(){alert("Questo alert e' una funzione nello script caricato")}
function allerta2(){alert(nn?controllo:top.controllo)}
</SCRIPT>
Ricordiamo che
controllo è una variabile presente nella pagina visibile (contenente). Con Netscape (per
nn=true) non c'è problema. La sintassi eseguita di
allerta2() è
alert(controllo), come faremmo normalmente.
Con Explorer invece stiamo lavorando in un frameset. Quindi per raggiungerla dobbiamo andarla a trovare nel frame principale, quindi la sintassi equivalente (ed eseguita) è
alert(top.controllo)
Questa è l'unica difficoltà nel programmare degli script inclusi dinamicamente come chiedeva Ivan.
Se negli script inclusi ci sono delle funzioni che usano delle variabili dichiarate nella pagina contenente bisogna raggiungerle usando "top.[variabile]" (o "top.nomearray[n1]...[nn]"). Una volta tanto è Explorer che ci complica la vita per fare le cose cross browser. Se avessimo potuto usare una cosa tipo
<DIV ... SRC="incluso.html"> che si comportasse come <LAYER> per Netscape includere funzioni sarebbe stato molto più semplice.
Naturalmente questa complicazione non si ha per l'uso che vuole farne Ivan. dato che a lui serve caricare solo dei dati, li userà con una sintassi simile a quella usata nella funzione
caricato() e non se ne parla più.
Conclusioni
Questo è solo un punto di partenza. La richiesta di Ivan spalanca vari orizzonti.
In un sito in cui sia necessario manipolare dei grossi array usare una soluzione di questo tipo può migliorare di molto la fruizione del sito al visitatore, eliminando molti dei secondi necessari al download della pagina. Per un "carrello della spesa" si potrebbe usare questa soluzione per includere ogni "reparto" in un diverso file, ed aumentare così le dimensioni del negozio... se volete portare su Internet un ipermercato gestito via JavaScript ora potete farlo!!!
Ricordate che le variabili contenute negli script caricati
vengono distrutte quando lo script viene sostituito, quindi occhio! È necessario conservare nella pagina principale tutte le variabili comuni, altrimenti vi ritroverete con qualche "undefined" prima o poi.
Un'ultima cosa prima di teminare (un'altra?! eh si! :-) all'inizio ho accennato all'uso di semplici frames per gestire questi script. La cosa è fattibilissima, ma il "problema Explorer" diventerebbe un "GROSSO problema" per tutti e due i browser, e non solo dal lato dello script incluso. Perché anche per Netscape bisognerebbe risalire l'albero del documento, e non certo con una cosa semplice come "top.". Nel migliore dei casi (due frames di cui uno nascosto) potrebbe bastare un semplice "parent.nomeframe.nomevariabile", ma se i frames sono parecchi, e magari annidati ci sarebbe da perdersi...
Io per ora mi fermo qua. Spero che qualcuno abbia avuto la pazienza di leggermi fino in fondo, se poi qualcuno trova una soluzione al "problema Explorer" sarò ben felice di includerla in questo tutorial.