Ce blog a déménagé et parle maintenant uniquement anglais.

This blog has moved and now only speaks English.

blog.floriancargoet.com

See you there!

/home/florian

le blog de florian cargoet : du linux, du web et du logiciel libre



ExtJS : bouton asynchrone

3 July, 2009 (23:28) | Ext JS, Webdev | Florian Cargoet

Catégorie Webdev : A propos du web, de son contenu, de ses outils...

Lorsqu’on crée un bouton avec ExtJS, par exemple un bouton de toolbar (xtype : ‘tbbutton’), on peut préciser un handler qui est une fonction à exécuter quand on clique sur le bouton. Comme il arrive que le handler soit une action asynchrone (avec un appel AJAX par exemple), j’ai réalisé une petite extension qui permet de remplacer l’icône d’un bouton par une icône de chargement pendant que le handler s’exécute. Avant de regarder le code, vous pouvez directement tester la démo.

Ext.ux.LoadButton

On étend très simplement Ext.Button en ajoutant juste deux fonctions pour gérer le changement d’icône et un appel à setLoadIcon juste avant d’appeler le handler :

?View Code JAVASCRIPT
Ext.ns('Ext.ux');
 
Ext.ux.LoadButton = Ext.extend(Ext.Toolbar.Button, {
 
    onClick : function(e){
        if(e){
            e.preventDefault();
        }
        if(e.button != 0){
            return;
        }
        if(!this.disabled){
            if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){
                this.toggle();
            }
            if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
                this.showMenu();
            }
            this.fireEvent("click", this, e);
            if(this.handler){
                //this.el.removeClass("x-btn-over");
 
                this.setLoadIcon();
                this.handler.call(this.scope || this, this, e);
            }
        }
    },
    setLoadIcon : function()
    {
        this.el.child('button').setStyle('background-image','url('+this.loadicon+')');
    },
    resetIcon : function()
    {
        this.el.child('button').setStyle('background-image','url('+this.icon+')');
    }
});
 
Ext.reg('tbloadbutton',Ext.ux.LoadButton);

Utilisation du LoadButton

Maintenant, on peut utiliser cette nouvelle classe dans notre code ExtJS :

?View Code JAVASCRIPT
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Load Button Example</title>
 
    <!-- ExtJS CSS -->
    <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2/resources/css/ext-all.css">
 
    <!-- ExtJS lib -->
    <script type="text/javascript" src="http://extjs.cachefly.net/ext-2.2/adapter/ext/ext-base.js"></script>
    <script type="text/javascript" src="http://extjs.cachefly.net/ext-2.2/ext-all.js"></script>
 
    <script type="text/javascript" src="Ext.ux.LoadButton.js"></script>
    <script type="text/javascript">
    Ext.onReady(function(){
 
        //loadbutton handler
        var deleteWorld = function(){
            win.body.update('Deleting world...');
            //my async stuff
            (function(){
                win.body.update('World deleted, good bye.');
                this.resetIcon();
            }).defer(2000, this); //give this (the button) as scope for "this.resetIcon()"
        };
 
 
        var win = new Ext.Window({
            title : 'Load Button test',
            width : 400,
            height: 300,
            tbar:[
                {
                    xtype:'tbloadbutton',
                    cls: 'x-btn-icon',
                    icon : '../../img/icons/world_delete.png',
                    loadicon : 'ajax-loader.gif',
                    handler : deleteWorld
                }
            ],
            html : 'Click the "Delete World" button.'
 
        });
        win.show();
 
    });
    </script>
</head>
<body>
</body>
</html>

Dans cet exemple, j’ai utilisé Function.defer() pour faire un appel asynchrone, mais en pratique ça sera plutôt un appel Ajax qui sera fait. Dans ce cas, n’oubliez pas l’appel à resetIcon dans la callback !

Icône de chargement

Vous pouvez créer des icônes indiquant un chargement sur le site AjaxLoad. N’oubliez pas de préciser la couleur du fond de votre thème ExtJS. En effet la transparence sur les gif n’étant pas terrible, le résultat est plutôt moche si on coche Transparent background. Pour le thème par défaut (Blue), une bonne couleur à prendre : #D9E5F3.

Note pour ExtJS 3.0

Comme ExtJS sort lundi prochain (6 juillet 2009), voyons ce qu’il faudra adapter :

  • Pas besoin de préciser cls: ‘ext-btn-icon’
  • On peut faire un peu plus court dans l’extension en remplaçant el.child(‘button’) par btnEl
  • On peut éviter d’utiliser la variable globale win dans le handler en récupérant la fenêtre par var win = this.ownerCt.ownerCt;

GitHub

Cette extension est sur GitHub. N’hésitez pas à forker et améliorer tout ça !

Update

Une page dédiée à cette extension et ses mises à jour : http://fcargoet.evolix.net/webdev/extjs/extjs-load-button/