Salut à tous
je travail depuis maintenat quelques temps avec ExtJS

j'ai rencontré quelqes petits pbs et j'ai trouvé quelques bricoles pour lever certaines limitations
Les tableaux javascripts
Propriétées:
  • length

Méthodes :
  • concat()
  • join()
  • pop()
  • push()
  • reverse()
  • shift()
  • slice()
  • splice()
  • sort()
  • unshift()

Metodes ajoutées par Extjs
  • indexOf()
  • remove()


si vous utilisez les tableaux comme des piles (FILO) vous pouvez utiliser push et pop pour ajouter et suprimer des éléments dans votre pile.
Mais vous n'avez rien pour lire sans l'enlever l'élément qui est au sommet de la pile. vous pouvez soit faire un pop push soit calculer l'index du sommet pour lire l'élément. ce simple code ajoute la methode top pour lire cet élément
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @class Array
*/
Ext.applyIf(Array.prototype, {
    /**
    * Return the last object in array
    * @return {Object}|null The objec in the array (or null if it is not found)
    */
    top : function(){
        if (0 == this.length){
            return null;
        }
        return this[this.length -1];
    }
});
Vous avez alors toutes les méthode necessaire au fonctionnement d'une pile
  • pop()
  • push()
  • top()


Les classes extj
Extjs utilise des classes qui embarquent des informations sur elles-même dans les objets crées. il est parfois intéréssant de pouvoir connaitre les classes utilisées par un objet.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Ext.applyIf(Object.prototype, {
    getClass : function(){
        if (this.constructor&&this.constructor.prototype&&this.constructor.prototype.baseCls) {
            return this.constructor.prototype.baseCls;
        } else {
            return undefined;
        }
    },
    getSuperClass : function(){
        if (this.constructor&&this.constructor.superclass&&this.constructor.superclass.baseCls) {
            return this.constructor.superclass.baseCls;
        } else {
            return undefined;
        }
    },
    isInstanceOf :function(aClass){
        return (aClass == this.getClass());
    },
    isA: function(aClass){
        if (undefined == this.getClass()) {
            return false;
        }else if (this.isInstanceOf(aClass)) {
            return true;
        } else {
            return this.constructor.superclass.isA(aClass);
        }
    }
});
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
this.getClass();               //=> x-window
this.getSuperClass();          //=> x-panel
this.isInstanceOf('x-window'); //=> true
this.isInstanceOf('x-panel');  //=> false
this.isA('x-window');          //=> true
this.isA('x-panel');           //=> true
L'objet Ajax
l'objet Ajax peut être utilisé plusieurs fois mais on est par fois surpris pas son comportement c'est simplement qu'apres usage l'objet ajax garde les handler déjà définis. cela est parfois pratique mais généralement mieux vait nettoyer tout ça
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
// When ajax request are complete remove all handler.
Ext.Ajax.on('requestcomplete', function(ajax, xhr, o){
    if(typeof urchinTracker == 'function' && o && o.url){
        urchinTracker(o.url);
    }
});
Les cookies
Lorsque on place un cookie c'est généralement dans le domaine dans lequel on se trouve. il fat donc regarder l'url de la page et calculer ce domaine. mais attention car un cookie ne peux être placé dans un domaine sans '.'
ce petit code ajoute la methode getDefaultDomain au CookieProvider d'Extjs pour récupérer le domaine par defaut.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
Ext.state.CookieProvider.getDefaultDomain = function () {
    var mots = location.hostname.split(".");
    var domain = "";
    for(var i = 1; i < mots.length; i++) {
        domain = domain + "." + mots[i];
    }
    return ("" == domain) ? null : domain;
}
Les tabPanels
Les tabPanels sont bien pratique en autre il est agréable de pouvoir les imbriquer les uns dans les autres lorsqu'on travaille sur beaucoup d'éléments imbriques. ils offre alors la particularité de pouvoir mettre les onglets en bas. Mais là hélas les tabPanel ne savent plus gérer les ascensseurs de façon automatique. c'est du à quelques lignes d'Extjs qui ne tiennent pas compte de la position. heureusement Extjs peut facilement être patché dynamiquement.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//patch tab panel for autoscroll at bottom
Ext.TabPanel.prototype.autoScrollTabs= function(){
    var count = this.items.length;
    var ce = this.tabPosition != 'bottom' ? 'header' : 'footer';
    var ow = this[ce].dom.offsetWidth;
    var tw = this[ce].dom.clientWidth;
 
    var wrap = this.stripWrap;
    var wd = wrap.dom;
    var cw = wd.offsetWidth;
    var pos = this.getScrollPos();
    var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
 
    if(!this.enableTabScroll || count < 1 || cw < 20){
         return;
    }
    if(l <= tw){
        wd.scrollLeft = 0;
        wrap.setWidth(tw);
        if(this.scrolling){
            this.scrolling = false;
            this[ce].removeClass('x-tab-scrolling');
            this.scrollLeft.hide();
            this.scrollRight.hide();
            if(Ext.isAir){
                wd.style.marginLeft = '';
                wd.style.marginRight = '';
            }
        }
    }else{
        if(!this.scrolling){
            this[ce].addClass('x-tab-scrolling');
            if(Ext.isAir){
                wd.style.marginLeft = '18px';
                wd.style.marginRight = '18px';
            }
        }
        tw -= wrap.getMargins('lr');
        wrap.setWidth(tw > 20 ? tw : 20);
        if(!this.scrolling){
            if(!this.scrollLeft){
                this.createScrollers();
            }else{
                this.scrollLeft.show();
                this.scrollRight.show();
            }
        }
        this.scrolling = true;
        if(pos > (l-tw)){
             wd.scrollLeft = l-tw;
        }else{
             this.scrollToTab(this.activeTab, false);
        }
        this.updateScrollButtons();
    }
};
 
Ext.TabPanel.prototype.createScrollers = function(){
    var ce = this.tabPosition != 'bottom' ? 'header' : 'footer';
    var h = this.stripWrap.dom.offsetHeight;
 
            var sl = this[ce].insertFirst({
 
        cls:'x-tab-scroller-left'
    });
    sl.setHeight(h);
    sl.addClassOnOver('x-tab-scroller-left-over');
    this.leftRepeater = new Ext.util.ClickRepeater(sl, {
        interval : this.scrollRepeatInterval,
        handler: this.onScrollLeft,
        scope: this
    });
    this.scrollLeft = sl;
 
            var sr = this[ce].insertFirst({
 
        cls:'x-tab-scroller-right'
    });
    sr.setHeight(h);
    sr.addClassOnOver('x-tab-scroller-right-over');
    this.rightRepeater = new Ext.util.ClickRepeater(sr, {
        interval : this.scrollRepeatInterval,
        handler: this.onScrollRight,
        scope: this
    });
    this.scrollRight = sr;
};
templates et Panel
Les template permettent de définir des modèles d'affichage et les panel des conteneurs. Or chose étrange Extjs n'offre pas de les associers.
voici un code trouvé sur le forum d'Extjs.com qui ajoute ce manque.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//add templatePanel class
Ext.namespace('Ext.ux');
 
Ext.ux.TemplatePanel = Ext.extend(Ext.Panel, {
    initComponent: function() {
        Ext.ux.TemplatePanel.superclass.initComponent.call(this);
        if (typeof this.tpl === 'string') {
            this.tpl = new Ext.XTemplate(this.tpl);
        }
    },
    onRender: function(ct, position) {
        Ext.ux.TemplatePanel.superclass.onRender.call(this, ct, position);
        if (this.data) {
            this.update(this.data);
        }
    },
    update: function(data) {
        this.tpl.overwrite(this.body, data);
    }
});
Ext.reg('templatepanel', Ext.ux.TemplatePanel);
il es d'usage de placer les extention à ext dans le namespace Ext.ux (user extensions)

Panel et layout
les layout permettent de definir des positionnement d'élément dans un contener. dans les exemple sur les Panel on trouve l'attribut 'layout: "table"' afec la description du contenus ensuite. cela ne fonctionne pas toujours. et il faut redimentionner le contener pour voir apparaitre le contenus. il se trouve que l'objet Panel vas transformer la shiane "table" de l'attribut 'layout' en objet sur certains évènements. mais pas lors de l'affichage initial. voici un pout de code à ajouter dans la construction de votre panel pour résoudre ce problème.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
    onRender: function(ct, position) {
        Ext.ux.TemplatePanel.superclass.onRender.call(this, ct, position);
        if (this.layout) {
            if(typeof this.layout == 'string'){
                this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
            }
            this.setLayout(this.layout);
            this.doLayout();
        }
    },
Chargement asynchrone
lorsqu'on a beaucoup de scripts à charger il es efficace de le faire de façon asynchrone. on lance des appel ajax les un après les autres et les scripts se chargent. lorsque chacun d'eux à fini il exécute sa méthode success ou failure associé. mais comment savoir que tous ont fini ? (cela est vrais pour tous les traitement assynchrone) comment fixer un point de rendez-vous à un ensemble d'appel assynchrones ?
la solution consiste à monitorer les fins de traitements. au début on place la liste des traitements à éffecturer dans un coin puis on lance tous ces traitements. chque fois que l'un deux à fini on le retire de la liste lorsque le dernier sort tous les traitements sont arrivés à leur terme.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//sync tread
Ext.app.SyncTread = function(cfg){
    Ext.apply(this, cfg);
    this.items = [];
    this.addEvents({
        'ready' : true
    });
};
Ext.extend(Ext.app.SyncTread, Ext.util.Observable, {
    isReady : false,
 
    add: function(item) {
        //system.trace(this.name + ' add '+item);
        this.items.push(item);
    },
 
    afterLoad: Ext.emptyFn,
 
    after: function(item) {
        //system.trace(' <b>after</b> ' + this.name + ' '+item);
        try{
            this.items.remove(item);
        } catch(e){}
        if(0 === this.items.length) {
            this._afterLoad();
        }
    },
 
    _afterLoad: function() {
        this.fireEvent('ready', this);
        this.isReady = true;
        if (this.afterLoad) {
            //try {
                this.afterLoad();
            //}catch(e){}
        }
    },
 
    onReady: function(fn, scope){
        if(!this.isReady){
            this.on('ready', fn, scope);
        }else{
            fn.call(scope, this);
        }
    }
});
cette classe definit des objets de syncronisation;
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    var lodingSync = new Ext.app.SyncTread({
        name: 'loding',
        afterLoad: function() {
            alert('All modules Loaded');
        }
    });
 
lodingSync.add('Login'); // ajout d'un éléments à synchroniser
 
 
//ajout d'un traitement à faire apres la synchronisation
lodingSync.onReady(
    function() {
        new Ext.app.Login(system.config.module.Login);
    }
)
 
 
// lancement du traitement Assynchrone
...
 
lodingSync.after('Login'); // retrait de l'élément (ce code est à placer dans la methode success d'un appel ajax par exemple)
voilà je crois que c'est à peut près tout pour aujourd'hui
A+JYT