PDA

View Full Version : ExtJs complex window and reactivity improvement



ricoux63
21 May 2010, 12:49 AM
Hello everybody!

I'm new in the community of ExtJS and it's my first post on this forum. First of all, thanks to the community to make available tutorials, extensions, examples, documentations, etc...it's very useful for a newbie like me.

Currently, I'm working on an important web application project in an OpenSource engineering company. The objective of this project is to manage emergency department of a hospital. The main problematic is to have an application extremely reactive with a graphic rendering close to the original (and very old) desktop application currently used by the personnal of the hospital.

After several weeks of study on RIA development tools, we have choosen to use ExtJS in order to realize our first model. During one week, I've worked on the development of the main form of the application. It must be displayed in a window and be composed of 4 parts with a lot of different fields (trees, selectbox, pictures, buttons, textbox, radios, textfields, etc...). Althought I've created this first model quickly, a problem persists : the reactivity of the windows, specially during actions of resizing...I tried to use different layout, fixed size of components, I have not been able to improve reactivity. I looked at examples, but the complexity level is not the same (window examples have not tow big forms !!). I searched on the internet, nobody speack about reactivity problems of ExtJS components, so I decided to write a post on this forum, maybe could you help me, give me some tips or best pratices.

Window picture : here (http://picasaweb.google.com/lh/photo/J8nOSgGRHKnVe1DQhO0_gQ?feat=directlink)

Here is my window code, I hope it will be clear :

Window structure :





/* West panel with ButtonPanel parent */

var appelButtonPanel = new Application.ButtonPanel({
region:'west',
id: 'appelButtonPanel',
collapsible: true,
items:[ new Application.RegulationButton({text: 'Nouvel Appel',iconCls: 'newAppel'}),
{xtype:'spacer',flex:0.6},
new Application.RegulationButton({text: '2 Appels en Attente',iconCls: 'waitAppel'}),
new Application.RegulationButton({text: '0 Appels 18',iconCls: 'pompierAppel'}),
new Application.RegulationButton({text: '0 Suivis Affaires',iconCls: 'suiviAffaire'})]
});

/* East panel with ButtonPanel parent */

var decisionButtonPanel = new Application.ButtonPanel({
region:'east',
id: 'decisionButtonPanel',
collapsible: true,
items:[ new Application.RegulationButton({text: 'Nouvelle Décision',iconCls: 'newDecision'}),
{xtype:'spacer',flex:0.6},
new Application.RegulationButton({text: '0 Appels à Réguler',iconCls: 'regulation'}),
new Application.RegulationButton({text: '0 Régulations 18',iconCls: 'pause'}),
new Application.RegulationButton({text: '0 Décisions en Pause',iconCls: 'pause'})]
});

/* Center Panel containing my 2 forms*/

var formRegulationPanel = new Ext.Panel({
layout: 'hbox',
//layout: 'border',
region: 'center',
split:true,
//autoScroll:true,
id: 'formRegulationPanel',
border: false,
layoutConfig: {
align : 'stretch',
pack : 'start',
},
//bodyStyle:'padding:15px;',
//defaults: {autoScroll:true},
items: [new Application.AppelForm({border:false,flex:1}),
new Application.DecisionForm({border:false,flex:1})]

});


/* Main Window */

Application.FicheRegulationWindow = Ext.extend(Application.FicheWindow, {
// constructor function
constructor: function(config) {
Ext.apply(this, {
title: 'Régulation - de l\'Appel à l\'intervention',
height: 680,
width: 1200,
minHeight: 600,
minWidth: 1024,
plain: true,
layout: 'border',
items: [appelButtonPanel,decisionButtonPanel, formRegulationPanel]
});
Application.FicheRegulationWindow.superclass.constructor.apply(this, arguments);
}
});

Other components :





/* Parent Button panel */


Application.ButtonPanel = Ext.extend(Ext.Panel, {
// constructor function
constructor: function(config) {
Ext.apply(this, {
autoScroll: true,
border: false,
layout:'vbox',
split:true,
width: 140,
layoutConfig: {align : 'center'}
});
Application.ButtonPanel.superclass.constructor.apply(this, arguments);
}
});


/* Parent Buttons */



Application.RegulationButton = Ext.extend(Ext.Button, {
// constructor function
constructor: function(config) {
Ext.apply(this, {
margins:'25px 0 25px 0',
width: 120,
scale: 'large',
iconAlign: 'top'
});
Application.RegulationButton.superclass.constructor.apply(this, arguments);
}
});


/* First form */


Application.AppelForm = Ext.extend(Ext.form.FormPanel, {
// constructor function
constructor: function(config) {
Ext.apply(this, {
defaultType: 'textfield',
autoScroll: true,
id: 'formAppel',
bodyStyle: 'padding: 10px',
title: 'Prise d\'Appel',
defaults: {anchor: '95%'},
items :[{
name : 'lieuRep',
fieldLabel: 'Lieu rép '
},{
name : 'commune',
fieldLabel: 'Commune '
},{
name : 'rue',
fieldLabel: 'Rue '
},{
name : 'lieuDit',
fieldLabel: 'Lieu-dit '
},{
xtype: 'compositefield',
hideLabel: true,
name: 'secteurCompositeField',
// anchor : '-20',
// anchor : null,
msgTarget: 'under',
items: [
{xtype: 'displayfield', value: 'Nº :', width: 100},
{xtype: 'textfield', name: 'no', flex: 2},
{xtype: 'displayfield', value: 'Etage :', width: 40},
{xtype: 'textfield', name: 'etage', flex: 1},
{xtype: 'displayfield', value: 'Nº Appartement :', width: 95},
{xtype: 'textfield', name: 'noAppartement', flex: 2}]
},{
xtype:'textarea',
height:50,
name: 'cpltAdresse',
fieldLabel: 'Complt Adresse '
},{
xtype:'textarea',
height:30,
name: 'infoSup',
fieldLabel: 'Info Sup '
},{
xtype: 'compositefield',
hideLabel: true,
msgTarget: 'under',
items: [
{xtype: 'displayfield', value: ' ', flex:0},
{xtype: 'button', text: 'Faux Appel',height:40, name: 'fauxAppel', flex: 1},
{xtype: 'button', text: 'En Différé',height:40, name: 'enDiffere', flex: 1},
{xtype: 'button', text: 'En Attente',height:40, name: 'enAttente', flex: 1},
{xtype: 'button', text: 'A réguler',height:40, name: 'aReguler', flex: 1},
{xtype: 'button', text: 'Gardes',height:40, name: 'gardes', flex: 1},
{xtype: 'displayfield', value: ' ', flex:0}]
},{
xtype: 'compositefield',
hideLabel: true,
msgTarget: 'under',
items: [{
hideLabel:true,
xtype: 'displayfield',
name: 'nomAppelantLabel',
value: 'Nom Appelant :',
flex: 1
},{
hideLabel:true,
xtype: 'displayfield',
name: 'prenomAppelantLabel',
value: 'Prénom Appelant :',
flex: 1
}]
},{
xtype: 'compositefield',
hideLabel: true,
msgTarget: 'under',
items: [{
hideLabel:true,
name: 'nomAppelant',
xtype: 'textfield',
flex: 1
},
{
hideLabel:true,
xtype: 'textfield',
name: 'prenomAppelant',
flex: 1
}]
},{
xtype: 'combo',
mode: 'local',
triggerAction: 'all',
forceSelection: true,
editable: false,
name: 'motif',
fieldLabel: 'pour Motif '
},{
hideLabel:true,
xtype: 'displayfield',
name: 'interrogatoireLabel',
value: 'Interrogatoire :'
},{
xtype:'textarea',
hideLabel:true,
height:100,
name: 'interrogatoire'
},{
name : 'diagnostic',
fieldLabel: 'Diagnostic '
},{
name : 'agentAgr',
fieldLabel: 'Agent agr. '
}],
buttons: [{text: 'Cplt Aff', height:40, flex: 1},
{text: 'Victimes', height:40, flex: 1},
{text: 'Bloc-Notes', height:40, flex: 1},
{text: 'Consignes', height:40, flex: 1}]
});
Application.AppelForm.superclass.constructor.apply(this, arguments);
}
});



/* Second form */


Application.DecisionForm = Ext.extend(Ext.form.FormPanel, {
// constructor function
constructor: function(config) {
Ext.apply(this, {
autoScroll: true,
title: 'Prise de décision',
labelAlign: 'top',
bodyStyle: 'padding: 10px',
defaultType: 'textfield',
defaults: {anchor: '95%'},
items :[
radioGroup, // Fieldset with radio buttons and 2 columns.
{
xtype: 'combo',
mode: 'local',
triggerAction: 'all',
forceSelection: true,
editable: false,
name: 'decisionCombo'
},
{
xtype:'textarea',
height:50,
name: 'commentaires',
fieldLabel: 'Commentaires '
},
{
xtype: 'compositefield',
hideLabel: true,
msgTarget: 'under',
items: [
{xtype: 'displayfield', value: ' ', flex: 0},
{xtype: 'button', text: 'Cplt Dec',height:40, name: 'complementDecision', flex: 2},
{xtype: 'button', text: 'Orig/Dest',height:40, name: 'origineDestination', flex: 2},
{xtype: 'button', text: 'En Pause',height:40, name: 'enPause', flex: 2},
{xtype: 'button', text: 'Personnel',height:40, name: 'personnel', flex: 2},
{xtype: 'button', text: 'G',height:40, name: 'g', flex: 1},
{xtype: 'button', text: 'L',height:40, name: 'l', flex: 1},
{xtype: 'button', text: 'E',height:40, name: 'e', flex: 1},
{xtype: 'displayfield', value: ' ', flex: 0}]
},
tree, // TreePanel with xml data loaded
panier // An other TreePanel

],
buttons: [{text: 'Envoi Moyens', height:40, flex: 1},
{text: 'Ok', height:40, flex: 1}]
});
Application.DecisionForm.superclass.constructor.apply(this, arguments);
}
});


Thank you in advance for your answer!

Eric

Animal
21 May 2010, 1:13 AM
It looks good.

You are on the right tack trying to use fixed Component sizes wherever possible.

A resize event on an outer Container will resize all its child Components (if the Container's layout does sizing). This will cascade right down to the lowest level Containers.

It's quite expensive, so keep as many Components fixed size as you can.

Apart from that, this issue is being seriously addressed by the Ext developers, and browser makers. New generations of Ext will be much faster (especially if you drop requirement to handle IE6)

How does Chrome perform?

ricoux63
21 May 2010, 1:30 AM
I just tested my application with Chromium, and the reactivity is impressive, what a difference compared to firefox 3.6...without fixed size components.
However I'm going to follow your advise and try to improve performances with fixed size.

Thank you very much Animal for your answer.

Animal
21 May 2010, 2:30 AM
Another factor in this will be Firebug. That slows down Firefox, and leaks memory like a sieve. I have to restart Firefox every hour or so because Firebug is so flaky.