FAQ Javascript


Come nasce questa pagina? Beh, diciamo che vuole essere un aiuto per chi è alle prime armi con il javascript, e una sorta di guida per chi non si ricoda qual'è il metodo giusto per fare una determinata cosa.
Uno spunto in particolare me lo ha dato il frequentare i forum del sito HTML.it, dove spesso vengono poste domande sui concetti e i metodi di base del javascript, come aprire una finestra pop-up senza barra degli strumenti, o come controllare se l'utente ha immesso tutti i dati necessari in un form.
Controllate spesso questa pagina perché farò aggiornamenti costanti mano a mano che mi si proporranno casi di esigenze particolari.



TOC della pagina:

  1. Lavorare con le finestre.
    1. Aprire una finestra semplice.
    2. Aprire una finestra di pop-up (tutti gli attributi possibili e immaginabili).
    3. Come far muovere una finestra


  2. Controllare i form.
    1. Non inviare dati se i campi non sono compilati correttamente.


  3. Modifica di elementi all'interno della pagina corrente.
    1. I tag <div> e il Javascript. Inserire/modificare dinamicamente la pagina.
    2. Azioni differenti in base al browser usato.
    3. Preload di immagini
    4. Checkbox e abilitazione di elementi





1.a Come si apre una finestra semplice?

Il metodo più semplice per aprire una finestra con il javascript è tramite il metodo window.open(). Gli argomenti che possono essere passati a questo metodo sono molti (vedi punto 1.b), ma per aprire la più semplice finestra o caricare un nuovo documento in una finestra preesistente si deve usare il metodo come segue:

window.open("nuovapagina.html", "finestra");

dove nuovapagina.html è il nome del documento HTML da aprire, mentre finestra può essere:
Per fare un esempio pratico, se volessi aprire la pagina 'index.html' in una nuova finestra chiamata "fin_uno" scriverei:

window.open("index.html", "fin_uno");



1.b Come si apre una finestra popup?

Al precedente punto abbiamo visto come aprire semplicemente e velocemente un nuovo documento in una nuova o nella stessa pagina.
Tuttavia questo modo di aprire una finestra potrebbe non soddisfare la maggiorparte di voi. Sento già le vostre lamentele sul fatto che quelle finestre fanno un po' come gli pare, e non ne abbiamo nessun controllo, se non sul loro contenuto.
In questa FAQ cercherò di spiegare nel modo più completo e accurato possibile tutto quello che si può fare tramite window.open().

La sintassi completa di questo metodo è la seguente

window.open(url, nome_finestra, attributi, sostituto);

Vediamo dettagliatamente cosa sono i quattro argomenti. Lascio per ultimi gli attributi in quanto sono la parte più interessante del metodo.

Per default, gli oggetti del browser come la statusbar, la toolbar e così via, sono visibili. Il che significa che non specificare questi attributi ha lo stesso effetto di scrivere, ad esempio, "status=yes, toolbar=yes".

Adesso che abbiamo visto tutti gli attributi che possiamo assegnare ad una nuova finestra vediamo un esempio pratico. Una finestra di popup, con la sola barra del titolo e di dimensioni 300x300.

window.open("pag1.html", "_blank", "toolbar=no, location=no, menubar=no, status=no, scrollbars=no, width=300, height=300");

Adesso inserite questo codice dentro una funzione o richiamatelo direttamente tramite un link, e si aprirà la vostra finestra di popup!!!

Ma è possibile fare dell'altro? Posso cambiare anche la posizione della nuova finestra?

Ebbene sì! Però è meglio farlo fare al documento aperto. Basta creare una funzione che al suo interno contenga la funzione:

window.moveTo( x , y );

dove x e y sono le nuove coordinate dell'angolo superiore sinistro della finestra.

Se poi volessimo anche modificare tramite questo documento la dimensione della finestra, basterebbe usare il metodo:

window.resizeTo(larghezza,altezza);

dove le dimensioni sono indicate in pixel (si omette però l'unità di misura e si scrive solo il numero).



1.c Come posso far muovere una finestra?

Mi è stato chiesto se era possibile creare un effetto di movimento per una finestra così che questa 'entrasse' da una parte dello schermo e si fermasse in un punto stabilito. Premetto che per posizionare una finestra completamente fuori dallo schermo con Navigator non è possibile senza avere attive alcune impostazioni particolari (che ignoro in quanto non lo uso), ma che dovrebbero chiamarsi UniversalBrowserWrite.

Riprendo pari pari l'esempio che ho fatto per spiegare come questo sia possibile. Premetto che la nuova finestra, quella con l'effetto, deve essere aperta con un window.open da un'altra pagina, altrimenti si perde il controllo sulle dimensioni della stessa (a meno di non specificarle, ma incorreremo in un brutto effetto di sfarfallio dovuto al resize) e non si possono eliminare gli elementi che non servono (statusbar, toolbar ecc...).
Nella pagina che richiama quella con l'effetto mettiamo un link così:

<a href="javascript:apriFinMove()">Apri la finestra effetto all'ingresso</a> <br><br>
<script language="javascript">
function apriFinMove()
{
window.open("f_effetto.html", "fin_effetto", "height=300, width=300, statusbar=no, toolbar=no, scrollbar=no, menubar=no");
}
</script>

Questo ci serve per fare in modo che la finestra non sia fullscreen e abbia dimensioni definite in precedenza.
La nuova pagina, f_effetto.html, dovrà avere un codice simile a questo:

<html>
<head>
<title>
Prova finestra semovente
</title>
</head>
<body bgcolor="#ffeeff" text="green" onLoad="posizioneIniz()">
<font face="arial">
<center>
Prova finestra con effetto di entrata da sinistra.
</center>
<script language="javascript">

/*Date le dimensioni dello schermo, per fermare la finestra nel centro
dello schermo, usiamo il metodo larghezza(o altezza) dello schermo diviso due,
meno larghezza(o altezza) della finestra (300x300) diviso due
*/

var posXFinale = ((screen.availWidth)/2)-150;
var posYFinale = ((screen.availHeight)/2)-150;


//Al caricamento della pagina (funzione onLoad del body) facciamo
//richiamare questa funzione che posiziona la pagina fuori dallo schermo
//in asse con lo scorrimento che dovra' fare, e poi si da' il via alle
//danze con la funzione che posiziona la finestra.

var intv;

function posizioneIniz()
{
 window.moveTo(-310, posYFinale);
 intv = setInterval("posiz()", 50);
}

//Viene aggiornata ogni volta che la finestra si sposta.
//Quando supera il valore stabilito da posXFinale, ferma l'intervallo
//e stoppa tutto!

var posX = -310;

function posiz()
{
 if(posX>=posXFinale)
 {
  clearInterval(intv);
 }
 else
 {
  window.moveTo(posX+5, posYFinale);
  posX+=5;
 }
}

posiz();

</script>
</body>
</html>

Come vedete dai commenti del codice, al caricamento della pagina, questa viene spostata nella posizione di partenza, fuori dallo schermo e successivamente si richiama la funzione, tramite un intervallo, ogni 50 millisecondi.
Ad ogni chiamata della funzione posiz() viene aggiornata la posizione della finestra, spostandola di 5 pixel. Quando poi raggiungiamo o superiamo la posizione finale (ovvero quando la finestra è al centro dello schermo) togliamo l'intervallo, facendo così fermare la finestra in quella posizione




2.a Come si controllano i dati immessi nei form?

Volete che l'utente inserisca alcuni dati prima di procedere nella visione del sito? O semplicemente volete fare in modo che tutti i dati da passare alla vostra pagina Asp o Php siano inseriti nel form? È molto semplice. Innanzitutto bisogna fare in modo che alla pressione del tasto di submit venga inibito l'invio del contenuto del form, attivando invece il controllo sui dati.
Questo può essere fatto direttamente all'interno del tag <form> come nell'esempio seguente:

<form action="post" onSubmit="return false;controllo();">

Il return false; garantisce che la normale funzione del tasto di submit sia inibita, mentre viene richiamata al suo posto la funzione controllo() che vado a spiegare adesso.

La funzione controllo() deve essere fatta in modo tale da controllare i campi che l'utente deve assolutamente compilare, e solo se sono tutti pieni proseguire con l'invio degli stessi.
Il metodo che ritengo più efficace per verificare la corretta compilazione dei form è quello di utilizzare degli array.
Mi spiego meglio: creiamo un array contenente gli id dei campi di testo, e un altro che contenga (nello stesso numero) dei valori booleani, che impostiamo per comodità a true.
Il risultato sarà simile al seguente:

var arrayNomi = new Array("Campo1", "Campo2", "Campo3");
var arrayValori = new Array(true, true, true);

nel caso dovessimo controllare tre elementi.
A questo punto dovrebbe essere abbastanza chiaro che vogliamo creare una associazione tra i nomi dei campi e il valore dell'altro array. Se il valore corrispondente ad un id, al termine del controllo, è true allora il campo si considera compilato correttamente, altrimenti vuol dire che qualcosa è stato tralasciato.
Ora la nostra funzione deve fare il controllo vero e proprio. Vi farò vedere il metodo più semplice (quello degli if in sequenza, ma per i più bravi, sappiate che si può risparmiare qualche riga di testo utilizzando un for sugli array) per realizzarlo.

Controlliamo il valore della proprietà value dei campi di testo (gli input="text" per intenderci) e se è uguale alla stringa nulla, il valore corrispondente dell'arrayValori sarà impostato a false.

if(document.forms[0].elements[1].value=='')
{
arrayValori[0] = false;
}
if(document.forms[0].elements[2].value=='')
{
arrayValori[1] = false;
}
if(document.forms[0].elements[3].value=='')
{
arrayValori[2] = false;
}

Come vedete per accedere alle proprietà dei vari elementi ho usato una notazione che ad alcuni potrebbe sembrare strana, ovvero la notazione puntata, al posto di scrivere direttamente l'id del campo di testo.
Questo per due motivi precisi: il primo è che questo identifica UNIVOCAMENTE gli elementi di un form, indipendentemente dal loro id, secondo perché in questo modo il codice può essere riutilizzabile.

Un poche parole per accedere ad una proprietà si passa attraverso:
document (il documento corrente), forms[0] il primo form del documento (i vari form sono memorizzati in un array, quindi il primo ha indice zero), poi attraverso gli elements[ n ] dove n è il numero dell'elemento desiderato (questi partono da UNO, e non da zero), e infine viene richiamata la proprietà value, sulla quale si fa il confronto.

Modificato così, se necessario, l'array dei valori, si passa a elaborare il suo contenuto.
Per farlo ci serviamo di una clausola if usando un po' di logica booleana.

if((arrayValori[0]&&arrayValori[1]&&arrayValori[2])==false)
{
alert("Attenzione: alcuni campi sono stati lasciati vuoti.\n"+
"compilare il form in tutte le sue parti prima di procedere.");

for(i=0;i<arrayValori.length;i++)
{
arrayValori[i]=true;
}
}

Questo ci garantisce che con anche un solo campo non inserito, i dati non saranno inviati.

Nota per chi non conosce la logica booleana: vedi la sezione operatori booleani.

Quando i dati non sono tutti, viene mandato un alert box che invita a compilare tutti i campi. Viene inoltre ripristinato lo stato di default dell'array dei valori (tutto true preparandolo per una sucessiva chiamata della funzione).
Se invece l'utente ha fatto il bravo ed ha compilato tutto, ecco cosa succede:

if((arrayValori[0]&&arrayValori[1]&&arrayValori[2])==true)
{
document.forms[0].action="tratta_dati.asp";
document.forms[0].submit();
}

viene aggiunto al form l'action, in questo caso una pagina asp che tratta i dati immessi, e successivamente tramite il metodo submit() vengono inviati alla pagina argomento dell'action del form. In poche parole è come se si fosse fatto click sul bottone di submit.

In effetti il risultato, per l'utente che compila il form, è uguale a quello della semplice pressione del tasto di submit, tranne che nel fatto che se non ha messo correttamente tutti i dati, verrà avvisato.

Nota extra alla fine della spiegazione: nel caso vogliate rendere più raffinato questo script, facendo indicare quali campi sono stati tralasciati, basta che 'catturiate' il loro nome in questo modo: create una variabile di testo, inizializzata con una frase del tipo "Non hai immesso dati nei campi:\n" e successivamente fate un for sull'arrayValori. Dove trovate un false prendete dall'arrayNomi l'elemento con lo stesso indice e concatenatelo alla variabile sopra creata. Ricordatevi poi di ripulire la stringa dai nomi dei campi una volta visualizzato il messaggio di errore per evitare errori o ripetizioni al successivo controllo.




3.a Come cambiare dinamicamente gli elementi della pagina?

Uno dei tag più interessanti per la sua duttilità (se mai una manciata di bit lo possono essere) è <div>.
Questo tag crea un oggetto altamente personalizzabile tramite attributi (javascript e CSS) e si presta in particolar modo a contenere testi o immagini che possono essere modificate.
Un esempio pratico di cosa possono fare lo trovate sempre in questo sito sia nella pagina dei download (dove è presente un box che illustra in maniera dettagliata cosa cè dentro i files che scaricherete) e nella sezione dei link, dove ho creato dei box con le descrizioni dei siti elencati, box che seguono il mouse quando si sposta.
L'importante per poter modificare tali oggetti è il fatto che essi devono avere un id tramite il quale noi possiamo indicare agli script a quale oggetto apportare le modifiche. Un esempio pratico qui fa bene:

<div id="box1">
<!-- Qui ci va l'elemento -->
</div>
Uno dei modi più semplici per modificare qualsiasi cosa ci sia dentro uno di questi 'contenitori' è quello di usare innerHTML. Questo metodo permette di ridefinire una stringa di testo (che nel nostro caso può essere benissimo del codice HTML) che sostituirà tutto quello che avete tra i tag <div> e </div>.
Facciamo un esempio. In un certo punto di una pagina voi avete messo questo codice:

<div id="box1">
Questo è un testo di prova dentro un <div> con id="box1"
</div>

Mettiamo che vogliate cambiare (magari alla pressione di un pulsante) questo testo in qualcosa tipo: 'Io sono il testo modificato!!!'.
Basta creare in javascript una funzione (che andremo ad associare al pulsante che creeremo) in questo modo:

<script language="javascript">

function cambiaTesto()
{
 box1.innerHTML = "Io sono il testo modificato!!!";
}

</script>

Come premiamo sul bottone, viene richiamata la funzione e il testo si modifica.
Se al posto del solo cambiamento del testo avessimo voluto anche cambiare la dimensione, sarebbe stato necessario aggiungere i tag, per esempio, <h1> (all'inizio della stringa) e </h1> (alla fine).
Adesso, conoscendo un po' di HTML potete capire che al testo possiamo sostituire una immagine, oppure possiamo 'cancellare' un testo semplicemente sostituendogli una stringa vuota, oppure creare qualsiasi combinazione o effetto più ci aggradi.

Un ultimo consiglio è quello di stare attenti alle dimensioni dei <div>. Se vi è possibile specificatele sempre, specialmente l'altezza, altrimenti potrebbe succedere che sostituendo un testo più corto ad uno lungo, si noterà uno scatto della pagina che si riprende lo spazio inutilizzato. Se invece specifichiamo che, per esempio, l'altezza deve essere di 150 pixel, può venire anche Billgheits ma quel maledetto <div> rimarrà di 150 pixel!!!

Un altro attributo importante (applicabile a qualsiasi tag, ma particolarmente utile in queste situazioni) è visibility, che ci permette di mostrare o nascondere a nostro piacimento un certo elemento della pagina.
Sempre lavorando sul nostro box, possiamo nasconderlo o visualizzarlo in due modi: tramite i CSS, specificando all'interno del tag l'attributo style="visibility:hidden" o style="visibility:visible" oppure tramite uno script in questo modo:

box1.style.visibility = "visible";

oppure

box1.style.visibility = "hidden";


Un discorso simile può essere fatto tramite l'attributo display di style. Questo attributo CSS offre 4 opzioni tra cui scegliere (block, inline, list-item e none) di cui l'unico che mi è tornato utile è stato il none in quanto con visibility si nasconde un oggetto ma non si recupera il suo spazio, mente con display è come se l'elemento non ci fosse proprio!





3.b Come eseguire azioni differenti a seconda del browser usato?

Per risolvere il problema di compatibilità delle vostre pagine con i vari browser è possibile far eseguire alcune azioni o scelte in base al browser con cui si sta navigando.
Per sapere il nome del browser basta usare la proprietà navigator.appName e assegnarla ad una stringa. Questa conterrà il nome del programma che state usando per vedere la pagina corrente. Ad esempio potete decidere di far aprire una pagina specifica se chi visita il vostro sito usa Internet Explorer, rimandando invece gli utilizzatori di Netscape Navigator ad un'altra pagina.

In aggunta possiamo anche sapere che versione del navigatore è utilizzata. Per far questo basta usare la proprietà navigator.appVersion. Tramite tali proprietà è possibile creare un sito visibile con tutti i browser, magari creando pagine diverse per le differenti versioni e i vari browser.




3.c Posso evitare l'orribile rettangolo vuoto quando una immagine pesante viene caricata?

Per evitare che durante il caricamento di una immagine venga visualizzato il rettangolo vuoto con al massimo il testo alternativo, è possibile creare uno script che si preoccupi di caricare (ma senza mostrarla) una immagine, e nel frattempo usare un qualcosa (immagine piccola o testo) per occupare lo spazio dell'immagine con un messaggio di caricamento in corso.
Dato che questo è uno degli argomenti che ho trattato in uno script apposito, cliccate qui per visualizzarlo.




3.d Posso abilitare degli oggetti solo se l'utente seleziona determinati checkbox?

Può essere necessario talvolta tener disabilitati bottoni o link fintanto che non sono state effettuate delle scelte da parte dell'utente.
Specialmente se usate in pagine in cui si devono sottoporre richieste su database che richiedono un certo numero di elementi scelti dall'utente, possiamo inibire l'utilizzo di pulsanti nel caso la richiesta non contenga tutti i dettagli di cui abbiamo bisogno.
Poniamo di avere una sorta di sondaggio, dove si vogliono sapere alcuni dati dei partecipanti, come il colore, l'animale, il cibo preferiti, e si possa anche scegliere più di un elemento per gruppo.
Creiamo quindi tre gruppi di checkbox in questo modo:

<form name="form1">
<input type="checkbox" name="blu" value="blu" onclick="segna(0);contr();">Blu
<input type="checkbox" name="rosso" value="rosso" onclick="segna(1);contr();">Rosso
<input type="checkbox" name="verde" value="verde" onclick="segna(2);contr();">Verde
<br>
<br>
<input type="checkbox" name="jena" value="jena" onclick="segna(3);contr();">Jena
<input type="checkbox" name="tarpone" value="tarpone" onclick="segna(4);contr();">Tarpone
<input type="checkbox" name="iguana" value="iguana" onclick="segna(5);contr();">Iguana
<br>
<br>
<input type="checkbox" name="pizza" value="pizza" onclick="segna(6);contr();">Pizza
<input type="checkbox" name="hotdog" value="hotdog" onclick="segna(7);contr();">Hotdog
<input type="checkbox" name="trippa" value="trippa" onclick="segna(8);contr();">Trippa
<div id="bottone"><input type="submit" name="Submit" value="Avvia la ricerca" DISABLED></div>
</form>

Il cui risultato è il seguente:

Blu Rosso Verde

Jena Tarpone Iguana

Pizza Hotdog Trippa


Notate che il bottone ha l'attributo DISABLED che ne impedisce il funzionamento.
A questo punto non ci resta che creare uno script che abbia queste caratteristiche: memorizzare in array lo stato dei checkbox (selezionati o no) e controllare se le condizioni che abbiamo imposto (ovvero che almeno un checkbox per ogni gruppo sia selezionato) siano rispettate.
Per farlo creiamo due funzioni: la prima modifica l'array per tenere conto dello stato dei checkbox, l'altra esegue un controllo su questi array e se tutto è ok attiva il bottone.
Ecco qui di seguito lo script commentato che esegue quanto appena detto:

<script language="JavaScript">

//I l'array che conterrà lo stato dei checkbox (9 elementi) i cui indici sono
//nello stesso ordine in cui appaiono i vari checkbox

var arrValori = new Array(false, false, false, false, false, false, false, false, false);


//Funzione che modifica il valore del checkbox de/selezionato nell'array
function segna(quale)
{
arrValori[quale] = !arrValori[quale];
}

//Si controlla il valore degli array, per vedere se almeno un elemento
//per gruppo è stato selezionato
function contr()
{
if( ((arrValori[0]==true)||(arrValori[1]==true)||(arrValori[2]==true)) &&
((arrValori[3]==true)||(arrValori[4]==true)||(arrValori[5]==true)) &&
((arrValori[6]==true)||(arrValori[7]==true)||(arrValori[8]==true)) )
{
//Se il risultato è positivo si riscrive l'interno del div
//'bottone' in modo da essere abilitato
bottone.innerHTML="<input type='button' name='bott' value='- - - Invia - - -'>";
}
else
{
//Questo serve per disabilitare se da una situazione giusta si ritorna
//ad una senza i checkbox necessari selezionati
bottone.innerHTML="<input type='button' name='bott' value='- - - Invia - - -' DISABLED>";
}
}
</script>





Gli operatori booleani


Gli operatori booleani permettono di effettuare operazioni sui valori true e false detti, appunto, booleani.
Gli operatori più usati negli script sono AND, OR, NOT. Sono operatori normalmente binari o con più argomenti e, nel caso binario, funzionano così:

AND
true AND true = true
true AND false = false
false AND true = false
false AND false = false
(il simbolo usato nel codice sorgente per l'AND è &&)

OR
true OR true = true
true OR false = true
false OR true = true
false OR false = false
(il simbolo usato nel codice sorgente per l'OR è ||)

NOT (operatore unario)
NOT true = false
NOT false = true


Il risultato di un AND con più argomenti è true soltanto se TUTTI gli elementi sono true. Anche un solo false rende tutto false.

Il risultato di un OR con più elementi è false soltanto se TUTTI gli elementi sono false. Anche un solo true rende tutto true.

Ci sono altri operatori come lo XOR, o OR esclusivo, e l'OR e l'AND bit a bit, ma queste sono usati con minore frequenza negli script, e complicherebbero inutilmente questo documento che deve essere una raccolta di FAQ e non una lezione sulla logica booleana. Se desiderate maggiori informazioni mandatemi pure una e-mail oppure usate un motore di ricerca inserendo come parole chiavi "logica booleana" oppure "operatori booleani".