A questo punto c'è un po' di codice, vediamo di dare una struttura ragionevole al nostro "progetto". Creeremo un file per lo stile, uno per il javascript che contiene tutta la logica del msgBox, uno per l'html.
Javascript
Il codice javascript (senza i tag <SCRIPT>) può essere copiato in questo file (msgbox.js); per collegarlo al mio file HTML, inserirò il tag
<SCRIPT type="text/javascript" src="/msgbox.js"></SCRIPT>
CSS
Altrettanto vale per il css: le regole vengono copiate in un file esterno (msgbox.css) quindi facciamo riferimento a questo file dall'header del file HTML inserendo:
<LINK href="/msgbox.css" rel="stylesheet" type="text/css">
HTML
E l'HTML? quello che resta :-)
Firefox
Ora possiamo estendere un po' le funzionalità del nostro message box per includere supporto per firefox, e separare un po' di logica ripetuta in funzioni dedicate.
Il DOM è unico, ma l'implementazione delle funzioni che servono per manipolarlo è un po' diversa tra i vari browser; Per il momento le differenze son minime, quindi possiamo gestirle direttamente; in ambito applicativo, meglio utilizzare un framework che si occupi per noi di gestire queste differenze (e che qualcun altro tenga aggiornato)!!! Ho dovuto modificare due mesi fa una pagina scritta nel '97 perché - per quanto uno cerchi di essere lungimirante - i framework di riferimento evolvono e cambiano. Il prossimo capitolo è dedicato a questi framework.
Nota bene: quando scrivo Firefox, si applica a Google Chrome, Opera e Safari normalmente. Non ho controllato su questi browser tuttavia. Nel 95% dei casi è comunque sufficiente gestire due soli casi, internet explorer e "gli altri".
Scuse ufficiali
Ho rinominato un paio di funzioni e variabili in italiano. attachEvents() è diventato collegaEventi(); poi ho creato una funzione collegaEvento() che gestisce le differenze da Firefox e IE.
_msgBox.prototype.collegaEvento = function (aElement, aEventName, aEvent, aMsgResult)
{
// aElement: l'elemento cui collegare l'evento
// aEventName: "click" per esempio
// aEvent: la funzione che deve essere invocata quando si verifica aEventName
// aMsgResult: il risultato di questo bottone.
// Ora devo collegare gli eventi. Devo gestire la differenza tra firefox e ie ecc.
aElement.msgResult = aMsgResult;
if (aElement.detachEvent) // per sapere se esiste - su firefox non esiste
{ // ie
aElement.detachEvent('on'+aEventName, aEvent);
aElement.attachEvent('on'+aEventName, aEvent);
}
else
{ // other browsers
aElement.removeEventListener(aEventName, aEvent, false);
aElement.addEventListener(aEventName, aEvent, false);
}
}
_msgBox.prototype.collegaEventi = function (aCallBackFunction)
{
this.divMsg = document.getElementById("msgBox")
if (!(this.button1Div instanceof Object))
this.button1Div = document.getElementById("msgBox1");
if (!(this.button2Div instanceof Object))
this.button2Div = document.getElementById("msgBox2");
this.button1Div.style.display=(this.button1?"inline":"none");
this.button2Div.style.display=(this.button2?"inline":"none");
this.callBackFunction = aCallBackFunction
// assegnare testi e funzioni ai pulsanti.
if (this.button1)
{
this.collegaEvento(this.button1Div, 'click', this.buttonEvent, this.button1Result);
}
if (this.button2)
{
this.collegaEvento(this.button2Div, 'click', this.buttonEvent, this.button2Result);
}
}
Anche nella funzione buttonEvent è necessario gestire la differenza tra ie e firefox:
_msgBox.prototype.buttonEvent = function(e)
{
// Questo evento viene invocato dal bottone cliccato yes no ecc.
// quindi non ha un accesso diretto all'istanzqa dell'oggetto dall'interno
// e bisogna usare il riferimento assoluto
msgBox.divMsg.style.display = "none"
if (e instanceof Object)
{ // firefox
msgBox.callBackFunction(e.target.msgResult)
}
else
msgBox.callBackFunction(event.srcElement.msgResult);
}
Con queste due funzioni abbiamo finito di separare il codice.
E' evidente come per aggiungere nuove funzionalità posso concentrarmi sulle mie funzioni usando le funzioni generiche collegaEvento(). Nelle funzioni interne di un oggetto, può essere conveniente usare un paio di parametri in più per lasciare spazio alle estensioni future; mentre per i metodi esposti (pubblici) è fondamentale permettere il funzionamento anche con un numero minimo di parametri, per semplificarne l'uso all'interno del codice.
I file descritti in questo articolo si possono scaricare dall'introduzione