Partiamo rapidi sulla base di quanto visto nell'articolo prcedente: principi di programmazione Object Oriented, catene di ereditarietà che dall'oggetto Observable ci hanno condotto alla classe Ext.Panel, l'esempio di impaginazione complessa e nidificata di oggetti ottenuto tramite alcuni degli attributi principali di Panel.
Le Window
Suddividere una pagina in zone risulta quindi semplice. Associare a queste zone dei Panel, è una facile conseguenza. Se volessimo che questi Panel siano trascinabili (draggable) all'interno della nostra pagina, basterebbe definire la proprietà draggable : true
. Ma chiediamo di più alle nostre interfacce e cominciamo a pensare che siamo nel Web 2.0, ovvero in un mondo fatto di contenuti rapidi, personalizzabili, condivisibili, estendibili e estremamente vicini alla user experience quotidiana che un qualsiasi utente ha con il suo pc. Ecco che la catena evolutiva delle nostre pagine ci porta quindi alla nascita dell'oggetto Window.
Cos'è una Window
Una Window è un pannello specializzato per essere utilizzato come finestra di un'applicazione. Le Windows sono trascinabili per default e possiedono caratteristiche specifiche come le proprietà di maximize e restore. Iniziare a lavorare con le Windows è utile in quanto avvicina il programmatore di interfacce web alle complessità che normalmente sono tipiche di una programmazione più sofisticata, collegata al mondo desktop.
Proprietà di Window Manager, per capire qual è la finestra visualizzata in un determinato momento, quali sono le finestre aperte e come sono collegate una all'altra; così come un Focus Manager, per capire come la finestra che è attiva debba comportarsi e debba vincolare il movimento del mouse; sono tutte problematiche che riguardano gli sviluppatori di applicazioni desktop oriented. Cominciare a sentirne parlare e venire a contatto con questi temi, aiuta il programmatore web a entrare nelle dinamiche di disegno GUI che portano gli appassionati di Web 2.0 a parlare di Web Application. Allo stesso tempo, grazie ad Ext, non abbiamo necessità di concentrarci eccessivamente su queste caratteristiche, in quanto la libreria ci soccorre anche in questo frangente con le sue utilities.
Una Window può quindi essere collegata a un Ext.WindowGroup o gestita dall' Ext.WindowManager che fornisce le utiliities che abbiamo citato.
Gli Attributi di una Window
Nell'articolo precedente non abbiamo potuto parlare di tutti gli attributi dell'oggetto Panel, rimandando il lettore a una consultazione delle API di Ext scaricabili dal sito . Essendo Window un'estensione di Panel, riusciamo ad ereditare nella prima tutte le caratteristiche del secondo. Pertanto rinnovo l'invito alla consultazione delle API. Prima però di procedere con l'analisi dell'esempio possiamo vedere insieme alcune delle caratteristiche più interessanti e immediate che le Window aggiungono al Panel per specializzarlo.
Abbiamo scelto le seguenti proprietà:
closable: true/false. Questa caratteristica istruisce la libreria Ext a renderizzare la window in modo che si possa chiudere (true) o meno (false). Se è true, viene mostrato il pulsante 'close' sulla barra di header della finestra, false la nasconde. Chiudere una finestra, per default, significa distruggerla e quindi non poterla riutilizzare. è possibile comunque personalizzare questo comportamento associando funzioni all'evento close o comunque permettere a una Window di nascondersi (hide) Window in modo da poterla mostrare nuovamente a fronte di un evento open/show. Per far questo basta semplicemente settare l'attributo closeAction
su 'hide'.
constrain: true per vincolare la finestra alla porzione di schermo dedicata dal browser alla nostra pagina (viewport), false per consentirle di uscire al di fuori dei limiti di viewport (il default è false).
defaultButton: l'id di un bottone che deve ricevere il focus del cursore quando la finestra viene attivata (ovvero riceve il focus a sua volta).
draggable: true, per consentire alla finestra di essere trascinata dalla barra di header, false per disattivare il trascinamento (il default è true).
manager: un riferimento a un WindowGroup che, come abbiamo detto prima, può implementare delle policy di gestione della finestra in un contesto con più window da gestire (default Ext.WindowMgr).
maximizable: true per mostrare il bottone 'maximize' e permettere all'utente di massimizzare la finestra, false per nascondere il pulsante e impedire che questa venga massimizzata (default false).
minHeight: l'altezza minima in pixel che può raggiungere una finestra (default 100). Questa proprietà funziona solo quando la proprietà resizable è uguale a true.
minWidth: la larghezza minima in pixel che puo' raggiungere una finestra (default 200). Questa proprietà funziona solo quando la proprietà resizable è uguale a true.
minimizable: true per mostrare il bottone 'minimize' e permettere all'utente di minimizzare la finestra, false per nascondere il pulsante e impedire che questa venga minimizzata (default false).
modal: true per far sì che questa finestra si ponga al di sopra delle altre e che non si possa cliccare su nessun altra prima di chiuderla, in quanto viene steso uno strato (overlay) che copre l'intero viewport (default a false).
resizable: true per consentire il ridimensionamento da parte dell'utente dal bordo e da ogni angolo della finestra, false per disattivare il ridimensionamento (il default è true).
x: la posizione X dell'angolo in alto a sinistra della finestra nel momento in cui viene aperta.
y: la posizione Y dell'angolo in alto a sinistra della finestra nel momento in cui viene aperta.
Creiamo un x-theme per i nostri post-it
Veniamo al nostro esempio. Abbiamo immaginato di creare una pagina che fungerà da bacheca di post-it. Più avanti nei nostri esempi potremo imparare a rendere dinamico un piccolo applicativo del genere in modo che possa memorizzare i contenuti, la posizione, le dimensioni e lo stato (mimizzato, nascosto, massimizzato, chiuso) dei vari post-it. Per ora continuiamo il nostro percorso formativo limitandoci a vedere come strutturare il lato di presentazione (front-end) della nostra web application.
Immaginiamo la nostra applicazione con un pulsante in alto a sinistra che diventerà il generatore dei nostri post-it. Dopo di che costruiamo il nostro x-theme per i post-it, secondo quanto imparato nell'articolo Temi e Layout. Creiamo una cartella di nome 'postit'. Al suo interno copiamo tutte le immagini che troviamo nei temi gray o default e che modifichiamo opportunamente perché siano ad hoc per la nostra web application. Nel nostro caso, ad esempio, vogliamo che le finestre mostrino una predominanza del colore giallo tipico degli omonimi fogliettini appicicosi che popolano le nostre scrivanie.
Poi creiamo un file di nome 'xtheme-postit.css' con tutte le caratteristiche tipiche degli x-theme e cambiamo tutti i path al suo interno in modo che puntino alla nostra cartella 'postit' (collocata dentro a ext/resources/images come tutti gli altri x-theme). Modifichiamo eventuali caratteristiche di stile, come il font che ci interessa, la sua dimensione o altro. Infine applichiamo il tema appena generato alle nostre finestre attraverso il seguente comando, collocato tra le prime righe del nostro file Javascript:
Ext.util.CSS.swapStyleSheet('theme', '../ext/resources/css/xtheme-postit.css');
Scriviamo il codice del nostro Post-it Generator
Il codice della nostra pagina HTML è molto breve e semplice. Questo perché utilizziamo una tecnica di programmazione chiamata unobtrusive Javascript. In pratica scriviamo gli elementi base della struttura della nostra pagina e li rendiamo intelligenti all'interno del codice Javascript associato. Così facendo applichiamo anche al Javascript quel pattern (metodo) vincente di codifica che va dietro al nome di MVC (Model-View-Controller); ovvero dividiamo lo strato di disegno dell'applicazione dalle logiche che implementano il funzionamento delle varie componenti.
Applicando queste tecniche semplificate riusciamo a rendere la nostra applicazione pulita, facilmente distribuibile, manipolabile ed estendibile senza che si debba mettere mano alla logica di sviluppo.
Il file, che chiameremo 'window.html' sarà cosi' composto:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>EXAMPLE 3.2 WINDOW...</title> <link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css" /> <script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../ext/ext-all.js"></script> </head> <body style="font-family:Verdana, Helvetica, Arial;font-size:10pt;background:#323232"> <input type="button" id="show-btn" value="Post It Generator" /><br /><br /> <script type="text/javascript" src="js/window.js"></script> </body> </html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>EXAMPLE 3.2 WINDOW...</title> <link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css" /> <script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../ext/ext-all.js"></script> </head> <body style="font-family:Verdana, Helvetica, Arial;font-size:10pt;background:#323232"> <input type="button" id="show-btn" value="Post It Generator" /><br /><br /> <script type="text/javascript" src="js/window.js"></script> </body> </html>
Disegniamo la nostra pagina con un elemento input di tipo button, con id uguale a show-btn
e valore uguale Post It Generator. Il valore, come ben sappiamo, lo ritroveremo sullo schermo, nella nostra pagina renderizzata dal browser. Ricordiamoci invece l'id. Lo rivedremo nel codice Javascript che, come abbiamo detto prima, sarà in grado di rendere intelligente il nostro bottone a fronte dell'evento click.
Nel file che chiameremo 'window.js' troviamo il seguente semplice codice:
Ext.onReady(function(){ var win; var button = Ext.get('show-btn'); var bd = Ext.getBody(); Ext.util.CSS.swapStyleSheet('theme', '../ext/resources/css/xtheme-postit.css'); var cnt=0; var xPos=100; var yPos=100; button.on('click', function(){ // create the window on the first click and reuse on subsequent clicks cnt++; xPos+=50; yPos+=50; if (xPos>=300) { xPos=120; yPos=100; } createPostIt(cnt,xPos,yPos); }); var createPostIt=function(cnt,xPos,yPos){ var win = new Ext.Window({ title:'Postit #'+cnt, id:'win'+cnt, layout:'fit', width:500, height:300, x:xPos, y:yPos, closeAction:'hide', frame:true, items: new Ext.Panel({ title: 'The best test in all site', layout:'fit', frame:true, Html: '<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. '+ 'Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, '+ 'when an unknown printer took a galley of type and scrambled it to make a type '+ … '(injected humour and the like).</p>', }), buttons: [{ text: 'Close', handler: function(){ win.hide(); } }] }); win.show(this); } });
Cominciamo indicando al browser di partire a interpretare il nostro codice Javascript solo dopo che la pagina è stata caricata (Ext.onReady). Dopo di che creiamo qualche variabile di shortcut per gli elementi che utilizzeremo più spesso nel nostro codice. Si noti come abbiamo messo nella variabile button l'oggetto input che abbiamo descritto nella nostra pagina HTML tramite l'id che avevamo notato prima.
Associamo un'azione all'evento di click del pulsante rappresentato dalla variabile button. Qui troviamo il codice con cui creiamo la nostra finestra, in modo che ad ogni click venga disegnata con gli attributi rappresentati tra parentesi graffe, all'interno della dicitura new Ext.Window({…});
.
Ci siamo permessi di aggiungere una finezza, memorizzando le posizioni di x e y della finestra precedente quando esiste, altrimenti le abbiamo inizializzate a 100, fuori dalla funzione handler dell'evento. In questa maniera riusciamo a produrre un gradevole effetto cascade per ogni finestra aperta in successione.
Infine aggiungiamo un pulsante alla finestra che permetterà di nascondere la finestra quando viene premuto.
Il risultato del nostro lavoro è visibile qui. Disponibile anche il pacchetto zip con gli esempi.
Conclusioni e anticipazioni
Con questo esempio terminiamo l'articolo doppio su Panel e Window. Siamo riusciti a vedere come impostare i due principali oggetti che compongono una web application e abbiamo continuato il nostro cammino nelle tecniche di disegno di GUI crossbrowser utilizzando Ext.js. Negli articoli che seguiranno vedremo cosa mettere dentro alle nostre finestre, partiremo analizzando Form e Griglie e proseguiremo con TabPanel, Accordion e altre utilities che coinvolgeremo nei nostri disegni.