Nonostante la sua semplicità, la classe Ext.Viewport è di fondamentale importanza per quelle applicazioni che intendono sfruttare intensivamente ExtJS mentre ricopre un ruolo abbastanza inutile se si intende utilizzare il framework per arricchire soluzioni software già avviate.
Un Ext.Viewport è semplicemente l'Ext.Container principale di tutta l'applicazione, quello che verrà renderizzato all'interno del body della pagina HTML e che conterrà, direttamente o indirettamente, tutti i widget necessari alla realizzazione dell'interfaccia utente. La caratteristica principale di questo componente è quella di renderizzarsi e ridimensionarsi automaticamente sulla base della pagina web. Esso non supporta lo scrolling (dovranno essere i componenti interni ad esso a sfruttarlo) e potrà esistere un unico Ext.Viewport all'interno dell'applicazione.
Dati per assodati questi concetti, un Ext.Viewport è un container semplice, con un proprio layout e una serie di item figli. Gli esempi infatti sono semplicemente una copia degli esempi realizzati nell'articolo precedente: invece che costruire un panel da renderizzare nel body, ora utilizzeremo la classe Ext.Viewport che adatterà il nuovo componente in maniera automatica (demo):
<html>
<head>
<script src="../extjs/adapter/ext/ext-base.js"></script>
<script src="../extjs/ext-all.js"></script>
<link rel="stylesheet" href="../extjs/resources/css/ext-all.css" />
<script>
Ext.onReady(function() {
new Ext.Viewport({
layout:'border',
items: [{
title: 'Center',
region: 'center',
html: 'I'm the center panel'
},{
title: 'West',
html: 'I'm the west panel and you can resize me',
region: 'west',
width: 100,
minWidth: 50,
maxWidth: 150,
split: true
},{
title: 'North',
html: 'I'm the north panel',
region: 'north',
heigth: 30
}, {
html: 'I'm the south panel with no title',
region: 'south',
heigth: 30
}]
});
});
</script>
</head>
<body>
</body>
</html>
Una volta renderizzato in pagina il viewport, quest'ultimo occuperà automaticamente l'intera finestra del browser e si occuperà di ridimensionare i proprio figli quando viene ridimensionato lo spazio a disposizione per l'applicazione.
Nell'esempio in questione abbiamo utilizzato un border layout inserendo (oltre a quello centrale che è obbligatorio) anche i pannelli west, north e south. Ovviamente è possibile implementare diverse soluzioni del viewport sfruttando eventuali altri layout offerti da ExtJS.
Ecco per esempio un viewport realizzato sulla base di un AccordionLayout (demo):
<html>
<head>
<script src="../extjs/adapter/ext/ext-base.js"></script>
<script src="../extjs/ext-all.js"></script>
<link rel="stylesheet" href="../extjs/resources/css/ext-all.css" />
<script>
Ext.onReady(function() {
new Ext.Viewport({
layout:'accordion',
title:'panel',
height: 300,
width: 400,
layoutConfig: {
animate: true
},
items: [{
xtype:'panel',
title:'panel 2',
html: 'I'm the panel 2'
},{
xtype:'panel',
title:'panel 3',
html: 'I'm the panel 3'
},{
xtype:'panel',
title:'panel 4',
html: 'I'm the panel 4'
}]
});
});
</script>
</head>
<body>
</body>
</html>
Ext.Panel
Come già introdotto nell'articolo precedente, la classe Ext.Panel permette di realizzare dei pannelli a loro volta personalizzabili e contenitori di altri widget grafici. Ciascun pannello per poter essere renderizzato correttamente in pagina necessita di un layout grazie al quale verranno posizionati eventuali widget figli.
Le caratteristiche principali di un pannello sono:
- possibilità di inserire toolbar superiori e inferiori;
- possibilità di inserire dei bottoni nella parte inferiore;
- possibilità di essere collassato o allargato a partire dalla barra del titolo;
- possibilità di inserire HTML libero sfruttando l'apposita configurazione.
Vediamo ora qualche pannello in azione:
<html>
<head>
<script src="../extjs/adapter/ext/ext-base.js"></script>
<script src="../extjs/ext-all.js"></script>
<link rel="stylesheet" href="../extjs/resources/css/ext-all.css" />
<script>
Ext.onReady(function() {
var panel = new Ext.Panel({
layout: 'fit',
title: "Titolo del pannello",
collapsible: true,
height: 400,
width: 500,
frame: true,
items: [
new Ext.Panel({
title:"Pannello interno",
html: "<b>Un</b> po' di <u>html</u>"
})
],
buttons: [{
text: "nuovo pannello",
handler: function() {
var newPanel = new Ext.Panel({
layout: 'fit',
title: "Nuovo pannello",
height: 400,
width: 500,
frame: true,
html: "Sono una pannello!"
});
newPanel.render(document.body);
}
}]
});
panel.render(document.body);
});
</script>
</head>
<body>
</body>
</html>
In questo esempio abbiamo creato un pannello con dimensioni fisso e collassabile (basta cliccare sulla freccia a destra del titolo) che contiene un pannello figlio e un bottone. Alla pressione del bottone viene creato un nuovo pannello a run-time e viene appeso dinamicamente al body. Nonostante l'esempio banale con questo esempio abbiamo introdotto tutte le principali caratteristiche della classe Ext.Panel.
Ext.Window
La classe Ext.Window permette di realizzare finestre modali e non da utilizzare all'interno delle nostre applicazioni per offrire un'interfaccia ricca e funzionale. Dal punto di vista del comportamento una Ext.Window può essere associata ad un Ext.Panel che viene renderizzato al di sopra degli altri elementi della pagina offrendo accesso più o meno esclusivo ad esso. Rispetto ad un semplice pannello una finestra può offrire:
- possibilità di resize;
- possibilità di drag&drop;
- possibilità di limitare lo spostamento della finestra all'interno di un particolare widget;
- possibilità di chiusura o nascondimento.
L'ultima caratteristiche necessità di un ulteriore approfondimento. Di default ciascuna Ext.Window che viene chiusa (utilizzando il bottone posizionato in alto a destra) viene distrutta completamente e i suoi elementi HTML vengono rimossi dal DOM della pagina rendendo quindi di fatto la finestra inutilizzabile. Se la necessità applicativa è quella di riutilizzare la finestra è possibile cambiare il comportamento impostando la proprietà closeAction
uguale ad hide
.
Vediamo qualche esempio:
<html>
<head>
<script src="../extjs/adapter/ext/ext-base.js"></script>
<script src="../extjs/ext-all.js"></script>
<link rel="stylesheet" href="../extjs/resources/css/ext-all.css" />
<script>
Ext.onReady(function() {
var button = new Ext.Button({
text: 'Crea finestra 1',
handler: function() {
var w = new Ext.Window({
items: {
xtype:'panel',
html: 'Io sono una finestra di poco conto, puoi crearmi e cancellarmi!'
},
height: 200,
width: 400,
title: "Finestra 1"
});
w.render(document.body);
w.show();
}
});
button.render(document.body);
var w = new Ext.Window({
items: {
xtype:'panel',
html: 'Prova ad eliminarmi se ci riesci!!'
},
height: 200,
modal: true,
closeAction: 'hide',
width: 400,
title: "Finestra 2"
});
w.render(document.body);
var button2 = new Ext.Button({
text: 'Mostra finestra 2',
handler: function() {
w.show();
}
});
button2.render(document.body);
});
</script>
</head>
<body>
</body>
</html>
In questo primo esempio abbiamo creato due bottoni.
Il primo ad ogni click si occuperà di costruire una finestra e di mostrarla in pagina una volta renderizzata all'interno del body del documento. Questa finestra una volta chiusa verrà completamente eliminata dal DOM della pagina e non ci sarà modo di recuperare l'oggetto in nessun modo.
Il secondo bottone invece semplicemente mostra una finestra modale già costruita e renderizzata in precedenza (nel nostro caso al document.ready
). Importante in questo caso l'utilizzo della configurazione closeAction
che permette di chiudere una finestra senza effettivamente eliminarla dal DOM. Senza questa configurazione un'eventuale seconda apertura genererebbe un errore.
Configurare bene le finestre di un'applicazione da questo punto di vista è fondamentale per due ragioni principali: innanzitutto per evitare di incappare in errori che possono limitare le funzionalità della stessa ma anche evitare il proliferarsi di elementi in pagina non più utilizzati che possono influenzare notevolmente le prestazioni del browser. Le finestre sono i componenti che più di tutti possono creare questo tipo di complessità data la loro natura (demo):
<html>
<head>
<script src="../extjs/adapter/ext/ext-base.js"></script>
<script src="../extjs/ext-all.js"></script>
<link rel="stylesheet" href="../extjs/resources/css/ext-all.css" />
<script>
var center, windowList = [];
Ext.onReady(function() {
center = new Ext.Panel({
region:'center',
title: 'Regione centrale',
buttons: [{
text: 'Crea finestra',
handler: function() {
var w = new Ext.Window({
items: {
xtype:'panel',
html: 'Non riesco a muovermi liberamente!'
},
height: 200,
width: 400,
title: "Finestra",
constrain: true,
collapsible: true
});
w.render(center.el);
w.show();
windowList.push(w);
}
}, {
text: "Collassa finestre",
handler: function() {
for(var i = 0; i<windowList.length;i++) {
windowList[i].collapse();
}
}
}, {
text: "Chiudi finestre",
handler: function() {
for(var i = 0; i<windowList.length;i++) {
windowList[i].close();
}
}
}]
});
var east = new Ext.Panel({
region:'east',
width: 200,
title: 'Regione est'
});
new Ext.Viewport({
layout: 'border',
items: [center, east]
});
});
</script>
</head>
<body>
</body>
</html>
In questo secondo esempio abbiamo costruito un viewport sfruttando il border layout composto da 2 pannelli: quello centrale e quello east. Grazie all proprietà constrain possiamo forzare la creazione di finestre contestualizzate ad un particolare container. Oltre ad esso grazie alle comode e complete API esposte da ExtJS abbiamo inserito due bottoni per collassare e chiudere automaticamente tutte le finestre create in precedenza.
Conclusioni
In questo articolo abbiamo introdotto 3 componenti fondamentali per qualsiasi applicazione:
- la classe Ext.Viewport serve per creare dei layout di pagina che occupino tutto il body e che scalino in risposta ad un eventuale resize della finestra del browser;
- la classe Ext.Panel permette di realizzare pannelli semplici che contengono testo HTML o un altro componente presente nella libreria ExtJS;
- la classe Ext.Window permette di realizzare finestre draggabili personalizzabili sia nelle dimensioni che nel contenuto.