Abbiamo conosciuto Ext e abbiamo intravisto le sue potenzialità; abbiamo steso le basi per superare i primi due grandi ostacoli: impaginazione e personalizzazioni; ora possiamo cominciare a sviluppare tutto ciò che ci viene in mente o ci viene richiesto. Per far questo abbiamo bisogno di conoscere uno ad uno gli elementi che compongono la nostra libreria e metterli nella classica cassetta degli attrezzi per poi poter essere capaci di scegliere lo strumento giusto a seconda dell'applicazione che stiamo sviluppando.
Lo scopo di questo articolo in due parti è quello di introdurre l'utilizzo degli oggetti Ext.Panel ed Ext.Window. Alla fine di questi due articoli, il lettore sarà in grado di stabilire quale dei due oggetti è più consono ai propri scopi, disegnare interfacce che contengono più Panel e Window, personalizzare esempi che assomigliano a complesse formattazioni di pagine di giornale o creare semplici motori che generano Window simili a post-it.
Object Oriented ed Ereditarietà
Le componenti Ext, come abbiamo già detto nei precedenti articoli, sono molte e tutte disegnate con un orientamento gerarchico ad oggetti. L'oggetto più utile alla base della catena di ereditarietà Ext è il Panel.
Per chi è pratico di programmazione orientate agli oggetti (Java, .NET ad esempio), è facile intravedere le analogie con oggetti tipici della programmazione desktop (Swing / SWT).
Per chi non conoscesse la programmazione OO (Object Oriented) consigliamo innanzitutto la lettura di qualche pagina di questo articolo su HTML.it: Pensare Object Oriented; inoltre possiamo semplificare molto i concetti che compongono questa utile tecnica di programmazione rapportando il nostro codice al mondo reale. Tutto cio' che ci circonda (il foglio o il monitor su cui stiamo leggendo queste righe) sono particolari istanze di una generica classe Oggetto. Quando diciamo quindi che Oggetto è un'entità astratta, intendiamo appunto questo: un oggetto può essere esteso ed istanziato in qualsiasi cosa. I concetti di ereditarietà tra oggetti si inseriscono in questo esempio se si pensa che il foglio su cui stiamo leggendo è un particolare foglio, figlio dell'oggetto Carta che a sua volta è figlio dell'oggetto Materiali e così via. Diversi fogli (un A4, una carta da regalo, un post-it) sono specializzazioni di Carta. Per chiudere questa breve carrellata esemplificativa, il foglio che abbiamo in mano è un'istanza che identifica esattamente il foglio che stiamo reggendo, con i suoi attributi che lo diversificano e lo rendono unico rispetto a un altro foglio.
Gli oggetti in Ext
Tornando ad Ext, quindi, leggiamo insieme l'albero genealogico dell'oggetto che ci interessa per comprendere a pieno le sue proprietà. Ogni oggetto deriva da una componente astratta generica chiamata Observable. Questa equivale all'oggetto più astratto che possiamo immaginare e che viene utilizzato come base per costruire altri oggetti. Per agganciarci al nostro esempio, pensiamo al seguente codice:
Foglio = function(name){ this.name = name; this.addEvents({ "stampa" : true, "archivia" : true, "straccia" : true }); } Ext.extend(Foglio, Ext.util.Observable);
Continuando la lettura genealogica del nostro oggetto, incontriamo quella che è la base per tutte le interfacce grafiche Ext: l'oggetto Component.
Ogni Component possiede un attributo xtype
, che è il suo Ext-specific type name, e i relativi metodi per identifcarlo: getXType
e isXType
.
Di seguito una lista degli xtypes validi:
xtype Class box Ext.BoxComponent button Ext.Button colorpalette Ext.ColorPalette component Ext.Component container Ext.Container cycle Ext.CycleButton dataview Ext.DataView datepicker Ext.DatePicker editor Ext.Editor editorgrid Ext.grid.EditorGridPanel grid Ext.grid.GridPanel paging Ext.PagingToolbar panel Ext.Panel progress Ext.ProgressBar propertygrid Ext.grid.PropertyGrid slider Ext.Slider splitbutton Ext.SplitButton statusbar Ext.StatusBar tabpanel Ext.TabPanel treepanel Ext.tree.TreePanel viewport Ext.Viewport window Ext.Window Toolbar components toolbar Ext.Toolbar tbbutton Ext.Toolbar.Button tbfill Ext.Toolbar.Fill tbitem Ext.Toolbar.Item tbseparator Ext.Toolbar.Separator tbspacer Ext.Toolbar.Spacer tbsplit Ext.Toolbar.SplitButton tbtext Ext.Toolbar.TextItem Form components form Ext.FormPanel checkbox Ext.form.Checkbox combo Ext.form.ComboBox datefield Ext.form.DateField field Ext.form.Field fieldset Ext.form.FieldSet hidden Ext.form.Hidden htmleditor Ext.form.HtmlEditor label Ext.form.Label numberfield Ext.form.NumberField radio Ext.form.Radio textarea Ext.form.TextArea textfield Ext.form.TextField timefield Ext.form.TimeField Trigger Ext.form.TriggerField
Risaliamo ancora la catena che ci porterà al nostro oggetto e incontriamo BoxComponent, una specializzazione di Component. è la classe base per ogni tipo di Ext.Component che usa contenitori che prendono il nome di box, ovvero forme che contengono HTML.
BoxComponent fornisce automatismi per la modellazione dei box come il dimensionamento o la posizione. Tutti gli oggetti che contengono HTML devono essere figli (sottoclassi) di BoxComponent in modo che le loro proprietà siano congrue e convivano con gli altri box nel momento in cui andremo a nidificarli uno dentro l'altro per poter ottenere i layout più disparati, utili ai nostri scopi.
Dal nonno, arriviamo finalmente al padre del nostro tanto atteso oggetto, ovvero: Container. Di default, i Containers usano gli schemi di layout che abbiamo introdotto nei precedenti articoli e che prendono il nome di ContainerLayout. In questo modo le componenti che vanno a nidificarsi l'una nell'altra sfruttano i meccanismi di collocazione nella pagina e possiamo appenderli uno dopo l'altro all'interno del Container, senza preoccuparci delle dimensioni o della convivenza cross-browser degli elementi.
Arriviamo così, attraverso gli avi, alla componente che da oggi useremo ed estenderemo fino a farla diventare il punto di partenza di ogni nostro disegno di interfaccia: il Panel.
La componente più semplice: il Panel
La classe Ext.Panel, estende Ext.Container ed è alla base di ogni altro tipo di interfaccia. I suoi attributi e le sue peculiarità ci aiutano a identificare il Panel con un ipotetico div/layer in cui suddividere le pagine dei nostri siti e delle nostre applicazioni.
Le potenzialità del Panel si intravedono dalla lista delle sue sottoclassi, ovvero: TabPanel, Tip, Window, FieldSet, FormPanel, GridPanel, TreePanel. Questi sono tutti oggetti che esamineremo, uno per uno, nei prossimi articoli e che ci consentono di strutturare i nostri dati nella forma più utile per ogni tipologia di interazione con l'utente.
Gli attributi di un Panel
Gli attributi che può assumere un panel sono veramente numerosi. Non possiamo elencare all'interno di questo articolo, per motivi di spazio, tutte le caratteristiche del nostro Panel ma provvederemo ad analizzare quelli che riusciremo ad incontrare attraverso il nostro classico esempio.
Immaginiamo che ci venga commissionata una pagina di un ipotetico giornale come quello in figura.
Impaginarla in questa maniera, magari rendendo dinamici i contenuti, rimanendo cross-browser e costruendo l'architettura in modo che sia scalabile, ovvero facilmente estendibile avrebbe richiesto esperti CSS e di sviluppo, oltre che un duro lavoro di analisi di compatibilità tra i vari browser.
Grazie ad Ext, una volta disegnata l'architettura della nostra pagina, possiamo identificare il layout più appropriato al nostro scopo e suddividere la nostra pagina nelle sue componenti elementari. Il layout che scegliamo in questo caso è il TableLayout e le componenti elementari sono gli Ext.Panel.
Identificheremo un oggetto generale che conterrà l'intera pagina e lo chiameremo "journal".
var journal = new Ext.Panel({ id:'journal-panel', title: 'La gazzetta del 2.0', layout:'table', width:800, height:700, layoutConfig: { columns: 4 }, frame:true, items: [new Ext.Panel({ title: 'The best test in all site', 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 specimen book.</p><br><p>It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.</p>', rowspan: 2, colspan: 3 }),new Ext.Panel({ html: '<center><img src="img/1.png"></center>', frame:true }),{ html: '<center><img src="img/2.png"></center>', frame:true }, ….
Le scatole cinesi
Abbiamo un Panel, che contiene un Panel che ne contiene altri e così via. Gli attributi che possiamo identificare sono pertanto un set che tende a ripetersi. In questo caso, ad esempio, vediamo:
id: identificatore univoco del layer, va a coincidere con l'id del div associato all'HTML generato da Ext per renderizzare il nostro Ext.Panel – di default è un identificativo autogenerato dalla libreria -.
title: il testo del titolo che verrà visualizzato nell'intestazione del pannello (una stringa vuota è il valore di default). Quando un titolo è specificato l'intestazione dell'elemento verrà automaticamente creata e visualizzata a meno che non si dichiari esplicitamente l'attributo header:false
.
layout: la disposizione da utilizzare in questo Container. Se non si specifica un Ext.layout.ContainerLayout, verrà visualizzata un'impostazione predefinita. I valori validi sono: absolute, accordion, anchor, border, card, column, fit, form and table.
width: la larghezza di questa componente in pixel (il default è auto
).
height: l'altezza di questa componente in pixel (il default è auto
).
layoutConfig: si tratta di un oggetto di configurazione contenente le proprietà specifiche per la scelta del layout. Per maggiori dettagli per quanto riguarda le opzioni di configurazione validi per ogni tipo di layout, consiglio di visualizzare le API di Ext in merito a:
Ext.layout.Absolute
Ext.layout.Accordion
Ext.layout.AnchorLayout
Ext.layout.BorderLayout
Ext.layout.CardLayout
Ext.layout.ColumnLayout
Ext.layout.FitLayout
Ext.layout.FormLayout
Ext.layout.TableLayout
frame: è impostato a true
per renderizzare il pannello con uno stile personalizzato con bordi arrotondati e integrato nella grafica generale del pannello; false
per renderizzare un pannello generico con il bordo quadrato di 1px (il valore di default è false
).
items: un unico elemento o un insieme di componenti figlie che verranno aggiunte al Container principale. Ogni elemento può essere qualsiasi tipo di oggetto che estende Ext.Component. Gli item vengono specificati ognuno dentro a parentesi graffe e tutti racchiusi da due parentesi quadre, cosi': [{…},{…},{…}].
Ogni elemento tra parentesi graffe, nel nostro esempio, è a sua volta un Ext.Panel. Si potrebbero definire esternamente alla variabile journal
i diversi Ext.Panel che conterranno i vari riquadri della nostra pagina e in seguito inserirli nell'attributo items
di journal, separandoli solo da virgole, senza necessità delle parentesi graffe. In pratica items
è un Array di oggetti contenuti nell'Ext.Panel. A sua volta ogni oggetto figlio conterrà elementi in items
oppure un attributo HTML di seguito descritto.
html: un frammento di HTML, o un DomHelper di Ext (vedremo nei prossimi articoli come si utilizzano queste utility per creare codice HTML direttamente dal Javascript).
Il risultato del nostro lavoro è visibile qui. Disponibile anche il pacchetto zip con il materiale completo.
Attenzione a IE
Colgo l'occasione di questo articolo per presentare il primo di tanti errori curiosi che un programmatore newbie non riuscirebbe a identificare molto semplicemente, data la natura poco chiara del codice di errore che incontriamo nel visualizzare il nostro oggetto Ext in cui è presente il seguente baco di programmazione.
Questo errore lo troviamo in Internet Explorer. La dicitura "Impossibile completare l'operazione a causa di un errore 80020101" non è molto esplicativa, né in italiano né in inglese. Credo di risparmiare qualche ora di lavoro ai futuri programmatori Ext facendo loro notare che si tratta di una virgola in più nella nostra lista di attributi o di items. Pare che in questo caso IE pretenda una certa pulizia del codice, infatti, e che, mentre Firefox o Safari o Opera ignorano il fatto che alla fine della nostra lista si presenti una virgola a cui non seguono elementi, il browser di Microsoft si blocca e non renderizza per niente la nostra pagina.
Conclusioni e anticipazioni
Abbiamo diviso il nostro articolo in due parti in modo che i lettori possano metabolizzare i concetti introdotti e il primo esempio di oggetti nidificati uno nell'altro. Nel prossimo articolo esporremo un esempio di oggetti Window che produrranno un effetto di bacheca di post-it.