6.5 Commandes

Écrit par Neil Deakin , mise à jour par les contributeurs à MDC .
Traduit par Laurent Jouanneau (15/11/2004), mise à jour par Alain B. (04/04/2007) .
Page originale : http://developer.mozilla.org/en/docs/XUL_Tutorial/Commands

Attention : Ce tutoriel est ancien et n'est pas mis à jour. Bien que beaucoup d'informations soient encore valables pour les dernières versions de gecko, beaucoup sont aussi obsolètes. Il est préférable d'aller consulter cette page sur la version française de ce tutoriel sur developer.mozilla.org.

Une commande est une opération qui peut être invoquée.

Les éléments de commande

L'élément command est utilisé pour créer des commandes qui pourront être utilisées pour exécuter des opérations. Vous n'avez pas besoin d'utiliser les commandes si vous avez juste à appeler un script pour manipuler des choses. Cependant, une commande a l'avantage de pouvoir être désactivée automatiquement quand c'est nécessaire, et de pouvoir être invoquée de l'extérieur sans avoir besoin de connaître les détails de son implémentation. Les commandes fournissent un moyen pour séparer de façon abstraite les opérations et le code. Elles deviennent très utiles pour les grosses applications.

Par exemple, pour implémenter les commandes de menus du presse-papiers, couper, copier et coller, vous pouvez utiliser les commandes. Si vous ne les utilisiez pas, vous devriez trouver quel champ a le focus, ensuite s'assurer que l'opération est valable pour cet élément. De plus, les commandes de menus devraient être activées ou désactivées selon que l'élément cible a du texte sélectionné ou pas, et pour les opérations de collage, si le presse-papiers contient quelque chose qui peut être collé. Comme vous pouvez le voir, cela devient compliqué. En utilisant les commandes, votre travail est simplifié.

Vous pouvez utiliser une commande pour n'importe quelle opération. Mozilla les utilise la plupart du temps pour les menus. De plus, les champs de saisie de texte et autres composants graphiques disposent de plusieurs commandes natives que vous pouvez invoquer. Vous devriez les utiliser quand les opérations dépendent de l'élément sélectionné.

Une commande est identifiée par son attribut id. Mozilla utilise une convention : les id de commandes commencent par cmd_. Vous voudrez probablement utiliser le même identifiant que celui d'une commande déjà utilisée, cependant, pour vos propres commandes, vous pouvez utiliser n'importe quel id de commande souhaité. Pour éviter les conflits, il est préférable d'inclure le nom de l'application dans l'id de la commande. Un moyen simple d'utilisation des commandes est montré ci-après :

Exemple : command simple

Exemple 6.5.1 : Source Voir.

<command id="cmd_openhelp" oncommand="alert('Aide !');"/>
<button label="Aide" command="cmd_openhelp"/>

Dans cet exemple, au lieu de placer l'attribut oncommand sur l'élément button, nous le plaçons sur un élément command. Les deux sont alors liés en utilisant l'attribut command qui a la valeur de l'id de la commande. Ainsi, quand le bouton est pressé, la commande cmd_openhelp est invoquée.

Cette approche présente deux avantages.

De plus,

Exemple : Activer/Désactiver command

Exemple 6.5.2 : Source Voir

<command id="cmd_openhelp" oncommand="alert('Aide');"/>
<button label="Aide" command="cmd_openhelp"/>
<button label="Plus d'aide" command="cmd_openhelp"/>

<button label="Désactiver"
        oncommand="document.getElementById('cmd_openhelp').setAttribute('disabled','true');"/>
<button label="Activer"
        oncommand="document.getElementById('cmd_openhelp').removeAttribute('disabled');"/>

Dans cet exemple, les deux boutons utilisent la même commande. Quand le bouton « Désactiver » est pressé, la commande est désactivée en définissant son attribut disabled, et les deux boutons seront aussi désactivés.

Habituellement, un groupe de commandes se place à l'intérieur d'un élément commandset, près du début du fichier XUL, comme dans l'exemple suivant :

<commandset>
  <command id="cmd_open" oncommand="alert('Ouvrir !');"/>
  <command id="cmd_help" oncommand="alert('Aide !');"/>
</commandset>

Une commande est invoquée quand l'utilisateur active le bouton ou les autres éléments rattachés à la commande. Vous pouvez aussi invoquer une commande en appelant la méthode doCommand, que ce soit de l'élément command ou d'un élément rattaché à la commande, comme un bouton.

Le répartiteur de commandes

Vous pouvez aussi utiliser les commandes sans utiliser l'élément command, ou, au moins, sans ajouter un attribut oncommand sur la commande. Dans ce cas, la commande n'invoquera pas un script directement, mais recherchera plutôt un élément ou une fonction qui traitera la commande. Cette fonction peut être séparée du XUL lui-même, et peut être embarquée par un élément graphique en interne. Afin de trouver ce qui traitera la commande, XUL utilise un objet appelé répartiteur de commande (NdT : command dispatcher). Cet objet localise le gestionnaire d'une commande. Le gestionnaire d'une commande est appelé contrôleur. Ainsi, quand une commande est invoquée, le répartiteur de commande localise un contrôleur qui traite la commande. Vous pouvez déduire que l'élément command est un type de contrôleur pour une commande.

Le répartiteur de commandes localise un contrôleur en regardant l'élément sélectionné pour voir s'il a un contrôleur qui gère la commande. Les éléments XUL ont une propriété controllers qui est utilisée pour la vérification. Vous pouvez l'utiliser pour ajouter vos propres contrôleurs. Vous pourriez l'utiliser pour avoir une boîte de liste qui répond aux opérations de couper, copier et coller. Un exemple sera fourni plus tard. Par défaut, seuls les champs de saisie (textbox) ont un contrôleur fonctionnel. Ce contrôleur gère aussi bien les opérations de presse-papiers, sélection, défaire et refaire, que les opérations d'édition. Notez qu'un élément peut avoir plusieurs contrôleurs, qui seront alors tous pris en compte.

Si l'élément courant sélectionné n'a pas le contrôleur attendu, la fenêtre sera alors vérifiée. L'élément window a aussi une propriété controllers que vous pouvez modifier comme bon vous semble. Si le focus est à l'intérieur d'un cadre frame, chaque cadre parent est également vérifié. Ainsi, les commandes fonctionneront même si le focus est à l'intérieur d'un cadre. Ce mécanisme fonctionne bien pour un navigateur ; les commandes d'édition invoquées à partir du menu principal fonctionneront à l'intérieur de la zone de contenu. Notez que HTML a aussi un système de commandes et de contrôleur, bien que vous ne puissiez pas l'utiliser sur des pages Web sans privilèges. Mais vous pouvez l'utiliser, par exemple, dans une extension du navigateur. Si la fenêtre ne fournit pas un contrôleur capable de gérer la commande, rien ne se passera.

Vous pouvez récupérer le répartiteur de commande en utilisant la propriété commandDispatcher de l'objet document, ou à partir des contrôleurs listés dans un élément ou la fenêtre. Le répartiteur de commande contient des méthodes pour récupérer les contrôleurs pour les commandes et pour récupérer et modifier le focus.

Ajout de contrôleurs

Vous pouvez implémenter vos propres contrôleurs pour répondre aux commandes. Vous pouvez tout aussi bien surcharger la gestion par défaut d'une commande en plaçant le contrôleur correctement. Un contrôleur doit implémenter quatre méthodes qui sont listées ci-dessous :

supportsCommand (command)
Cette méthode doit renvoyer true si le contrôleur gère la commande. Si vous renvoyez false, la commande n'est pas gérée et le répartiteur de commande interrogera un autre contrôleur. Un contrôleur peut gérer plusieurs commandes.
isCommandEnabled (command)
Cette méthode doit renvoyer true si la commande est activée, false sinon. Les boutons correspondants seront désactivés automatiquement.
doCommand (command)
exécute la commande. C'est ici que vous mettrez le code pour gérer la commande.
onEvent (event)
Cette méthode gère un événement.

Exemple : implémentation d'un contrôleur

Imaginons que nous voulions implémenter une boîte de liste (listbox) qui gère la commande « Supprimer ». Quand un utilisateur sélectionne « Supprimer » dans le menu, la boîte de liste efface la ligne sélectionnée. Dans ce cas, vous avez juste à attacher un contrôleur à l'élément listbox qui exécutera l'action correspondante dans sa méthode doCommand.

Essayez d'ouvrir l'exemple qui suit dans une fenêtre du navigateur et sélectionnez des items de la liste. Vous noterez que la commande « Supprimer » du menu « Edition » du navigateur est activée et qu'elle effacera la ligne sélectionnée. L'exemple n'est cependant pas complet. Nous devrions nous assurer que la sélection et le focus soient ajustés comme il faut après l'effacement.

Exemple : voir

<window id="controller-example" title="Exemple de contrôleur" onload="init();"
        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

<script>
function init()
{
  var list = document.getElementById("theList");

  var listController = {
    supportsCommand : function(cmd){ return (cmd == "cmd_delete"); },
    isCommandEnabled : function(cmd){
      if (cmd == "cmd_delete") return (list.selectedItem != null);
      return false;
    },
    doCommand : function(cmd){
      list.removeItemAt(list.selectedIndex);
    },
    onEvent : function(evt){ }
  };

  list.controllers.appendController(listController);
}
</script>

<listbox id="theList">
  <listitem label="Océan"/>
  <listitem label="Désert"/>
  <listitem label="Jungle"/>
  <listitem label="Marécage"/>
</listbox>

</window>

Le contrôleur listController implémente les quatre fonctions décrites plus haut. La méthode supportsCommand renvoie true pour la commande cmd_delete, qui est le nom de la commande utilisée lorsque l'item de menu « Supprimer » est sélectionné. Pour les autres commandes, false est renvoyé puisque le contrôleur ne gère aucune autre commande. Si vous voulez gérer d'autres commandes, vous devrez les tester ici, car il est fréquent d'un simple contrôleur gère de multiples commandes apparentées.

La méthode isCommandEnabled renvoie true si la commande est activée. Dans le cas présent, nous vérifions s'il y a un item sélectionné dans la liste et renvoyons true si c'est le cas. S'il n'y a pas de sélection, false est renvoyé. Si vous effacez toutes les lignes dans l'exemple, la commande « Supprimer » deviendra inactive. Vous devrez cliquer sur la liste pour mettre à jour le menu dans cet exemple simple. La méthode doCommand sera appelée lorsque l'item de menu « Supprimer » sera sélectionné, et elle provoquera l'effacement de la ligne sélectionnée dans la liste. Rien ne doit se produire pour la méthode onEvent, aussi nous n'ajouterons pas de code pour celle-ci.

Surcharger un contrôleur par défaut

Nous attachons ce contrôleur à l'élément listbox en appelant la méthode appendController des objets contrôleurs de la liste. L'objet controller a un certain nombre de méthodes qui peuvent être utilisées pour manipuler les contrôleurs. Par exemple, il possède une méthode insertControllersAt qui insère un contrôleur dans un élément avant les autres. Elle peut être utile pour surcharger des commandes. Par exemple, le code suivant désactivera le collage du presse-papiers dans un champ de saisie.

var tboxController = {
  supportsCommand : function(cmd){ return (cmd == "cmd_paste"); },
  isCommandEnabled : function(cmd){ return false; },
  doCommand : function(cmd){ },
  onEvent : function(evt){ }
};

document.getElementById("tbox").controllers.insertControllerAt(0,tboxController);

Dans cet exemple, nous insérons le contrôleur à l'index 0, c'est-à-dire avant tous les autres. Le nouveau contrôleur supporte la commande 'cmd_paste' et indique qu'elle est désactivée. Le contrôleur par défaut de textbox ne sera jamais appelé parce que le répartiteur de commande trouve un contrôleur avant celui-ci, prenant en charge la commande en premier.


Dans la section suivante, nous allons voir comment mettre à jour les commandes.


Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™ sont des marques de la fondation Mozilla.