Mon cahier d’exercices
"Auteur : Hagnoul Daniel"
Texte : v1.1.0 2010-02-12
Texte : v0.8.6 draft 2009-10-17
Je ne pense pas que l’on puisse utiliser jQuery sans maîtriser les événements fondamentaux, ils ne sont donc pas l'objet de notre propos. De même pour les événements spéciaux (exemple : mouseenter, mouseleave), voir
https://brandonaaron.net/blog/2009/03/26/special-events et
https://brandonaaron.net/blog/2009/06/4/jquery-edge-new-special-event-hooks.
Les navigateurs internet traitent de manière anarchique les événements JavaScript, mais jQuery s'occupe en interne des particularités de chacun et offre en externe une interface unique. Il possède un système événementiel élaboré, assez facile à appréhender, mais méconnu et sous-exploité si j'en juge par les questions posées sur le forum jQuery.
Une page internet doit toujours être asynchrone. C'est l’utilisateur final, et lui seul, qui décide ce qui doit se passer à l'instant suivant, il doit toujours "avoir la main." C’est la raison pour laquelle toutes les fonctions "callback" sont asynchrones en jQuery.
JavaScript n’est pas un vrai langage-objet, mais votre code doit utiliser les objets et il doit déclencher et gérer les changements d'état d'objets à l'aide d'événements.
Utiliser les objets sans les événements c'est comme si vous vous attachiez un boulet à chaque pied avant de courir.
Définitions personnelles :
Un événement non intercepté est perdu.
Avant de voir quelques exemples d'utilisation, nous allons parcourir très succinctement les points clés de la documentation du système d'événement jQuery ce qui vous facilitera peut-être l'indispensable lecture de la documentation originale (https://api.jquery.com/bind/ et https://api.jquery.com/category/events/event-object/).
Je vous conseille de considérer les propriétés de l'objet $.Event() comme étant en lecture seule, car jQuery les utilise et les modifie à sa guise.
Propriété | Description |
---|---|
event.currentTarget | L'élément DOM concerné par l'événement lors de la phase de bouillonnement (bubbling). |
event.data | Contiens les données facultatives passées à bind lorsque le gestionnaire d'exécution actuel était lié. |
event.pageX | La position de la souris par rapport au bord gauche du document. |
event.pageY | La position de la souris par rapport au bord supérieur du document. |
event.relatedTarget | Les autres éléments DOM impliqués dans l'événement, le cas échéant. |
event.result | La dernière valeur retournée par le gestionnaire d'événement qui a été déclenché par cet événement, à moins que cette valeur n'ait pas été définie. |
event.target | L'élément DOM qui a initié l'événement. |
event.timeStamp | Cet attribut retourne le nombre de millisecondes depuis le 1er Janvier 1970, lorsque l'événement est déclenché. |
event.type | Décrit la nature de l'événement. |
event.which | Pour les événements clavier ou souris, cet attribut indique la touche ou le bouton qui a été enfoncé. |
Fonction | Description |
---|---|
event.preventDefault() | Si cette méthode est appelée, l'action par défaut de l'événement ne sera pas déclenchée. |
event.isDefaultPrevented() | Retourne « true » si event.preventDefault() a été demandé sur cet événement. |
event.stopPropagation() | Cette méthode empêche le « bouillonnement » de l'événement dans l'arbre DOM, ce qui empêche tout gestionnaire parent d'être informé de l'événement. |
event.isPropagationStopped() | Retourne « true » si event.stopPropagation() a été demandé sur cet événement. |
event.stopImmediatePropagation() | Empêche les autres gestionnaires d'événements d'être appelés. |
event.isImmediatePropagationStopped() | Retourne « true » si event.stopImmediatePropagation() a été demandé sur cet événement. |
Après avoir créé un nouvel événement, vous pouvez lui ajouter vos données :
var monEvent = new $.Event("allumeEvent");
monEvent.dvjh = {...};
Vos événements doivent existés dans un espace de noms.
Exemple :
var monEvent = new $.Event("allumeEvent.monEspaceDeNom");
L'espace de nom est très utile :
L'événement $.Event("appendAffiche.type2")
ne sera pas intercepté par
$("#affiche").bind("appendAffiche.type1", appendAfficheEventHandler).
Mais l'événement $.Event("appendAffiche")
sera intercepté partout, ce qui peut avoir son utilité pour déclencher l'événement appendAffiche dans tous les espaces de nom (exemple : type1, type2, etc.).
/* * On déclare attendre un événement en utilisant bind() * On attend un événement du type appendAffiche dans l'espace de nom type1 * On consommera l'événement dans la fonction appendAfficheEventHandler(event) */ $("#affiche").bind("appendAffiche.type1", {usage: "fréquent"}, appendAfficheEventHandler); /* * On construit l'événement du type appendAffiche dans l'espace de nom type1. */ var appendEvent = new $.Event("appendAffiche.type1"); appendEvent.dvjh = { utilisateur: "Daniel Hagnoul", css: { color: "red", fontSize: "2em" }, data: { un: 1, deux: 2, trois: 3 }, dimArray: new Array(24, 36, 48, 52, 64) }; /* * On déclenche l'événement en utilisant trigger() */ $("#btnAffiche").click(function(){ $("#affiche").trigger(appendEvent); }); /* * On consomme l'événement */ function appendAfficheEventHandler(event){ ... return false; }
Comme d'habitude, jQuery possède une écriture alternative que certains appellent même simplifiée. Je vous conseille de l'utiliser uniquement lorsque vous n'avez pas ou très peu de données à transmettre avec l'événement.
/* * On déclare attendre un événement et on consomme l'événement en utilisant * une fonction anonyme comme handler. */ $("#affiche").bind("appendAffiche.type2", {usage: "peu fréquent"}, function(event, utilisateur, dim){ ... return false; }); /* * On construit et on déclenche l'événement en utilisant trigger() */ $("#btnAffiche").click(function(){ $("#affiche").trigger("appendAffiche.type2", ["Daniel Hagnoul", "102"]); });
jQuery déconseille l’usage de : $.ajax(options) et recommande l'usage des transactions sécurisées :
Mais si j’en crois les questions posées sur le forum jQuery, c’est pourtant l’option déconseillée qui est la plus utilisée. On peut penser qu’il en est ainsi, car beaucoup non pas apprit comment gérer l’échec de la connexion avec les transactions plus sécurisées.
Voici l’exemple d’une transaction $.getJSON(). La gestion d’erreur est toujours identique, quel que soit le type de la transaction.
On crée un objet JSON – DivModifiable – qui contient toutes les propriétés et fonctions méthode nécessaires. Toute la « logique » de création et de traitement de la division est contenue dans DivModifiable.
Je vous entends : « L’exemple d’une transaction AJAX était intéressant, mais dans un programme plus complexe le nombre d’événements générés dans un court intervalle de temps peut-être important, comment va-t-on faire pour déclencher, intercepter et traiter ces événements concomitants ? »
« On peut avoir besoin de lancer et d’intercepter plusieurs fois le même événement. Comment fait-on ? »
L’exemple n° 4 est assez simpliste, mais il répond aux questions ci-dessus. Il est composé de quatre fonctions classe : Pair, Impair, Table et Total.
Les fonctions classe Pair et Impair stockent un nombre et ont une fonction méthode add(obj). Cette fonction méthode ajoute un au nombre stocké et envoie un événement à obj si la condition est remplie (pour la fonction classe Pair il faut que le nombre stocké soit pair et pour la fonction classe Impair il doit être impair).
La fonction classe Table est chargée de l’interface utilisateur. L'objet Table présente les résultats sous forme de tableau triable, pour cela il a besoin du plugin tablesorter et de la feuille de style trierTable. Ces éléments doivent être incorporés au niveau du programme appelant.
L’objet Table stocke au fur et à mesure du déroulement du programme toutes les données envoyées par l’objet qui le contrôle (Total), il construit et affiche la table lorsque sa fonction méthode print() est sollicitée.
La fonction classe Total est le cœur du programme. L’utilisateur démarre le programme en créant un objTotal(millisecondes, divID). Si le paramètre millisecondes n’existe pas il est fixé à 1000 soit 1s, il s’agit du temps d’exécution du programme. Le paramètre divID reçoit le nom attribué à l’id de la division qui affichera la table.
L’objet Total crée les objets Pair, Impair et Table. Il reçoit les données envoyées par Pair et Impair. Après traitement (il stocke le total de tous les nombres reçus), il envoie le résultat à l’objet Table. Lorsque le temps est écoulé, l’objet Total termine le programme en demandant l’affichage de la table.
Les objets communiquent uniquement par l’intermédiaire d’événements.
D’aucuns se seront étonnés de ne pas voir d’exemple avec « live. »
Il y a plusieurs raisons :
Il sert à lier un gestionnaire d'événement à un élément dont le contexte est dirigé vers un objet différent.
$.proxy(fonction, contexte);
On écrira donc : $(this).bind(eventName, $.proxy(obj.eventHandler, obj));
au lieu de : $(this).bind(eventName, eventHandler);
Car si eventHandler est une fonction d’un objet distinct de l’objet en cours dans la fonction bind() ou live() vous obtenez une erreur du genre : « this.nomFonction is not a function. »
$.proxy() est l’équivalent de : return obj.maFonction.apply(obj, [e]);
On ne doit pas oublier cette écriture, car elle permet de transmettre d’autres données : obj.maFonction.apply(obj, [e, param1, param2]);
function SlideShow(base){ var self = this; $('.leftControl', base).bind('click', $.proxy(self.onLeftControlClick, self)); //$('.rightControl', base).bind('click', $.proxy(self.onRightControlClick, self)); /* * Sans $.proxy() on obtient l'erreur "this.manageControls is not a function" * car "onRightControlClick this : [object HTMLButtonElement]" */ //$('.rightControl', base).bind('click', self.onRightControlClick); /* * ancienne méthode apply ou call * il est possible d'ajouter des arguments */ $('.rightControl', base).bind('click', function(e){ var n = 10; self.onRightControlClick.apply(self, [e, n]); //self.onRightControlClick.call(self, e, n); }); this.manageControls(); } SlideShow.prototype = { manageControls: function(){ alert("manageControls OK"); }, animate: function(){ alert("animate OK"); }, onLeftControlClick: function(){ alert("onLeftControlClick this : " + this); this.manageControls(); this.animate(); }, onRightControlClick: function(){ var tab = $.makeArray(arguments); alert("onRightControlClick this : " + this + "\nArguments = " + tab); this.manageControls(); this.animate(); } }; $(function(){ new SlideShow("#affiche"); });
Téléchargement ftp : evenement-v1.0.0.zip
Téléchargement https : evenement-v1.0.0.zip
Exemple n° 1 (simple, montre le processus en 4 étapes)
Exemple n° 2 (écriture simplifiée, déconseillée)
Veuillez poser vos questions
techniques sur les forums DVP,
s'il vous plait.
Avertissement solennel
Autodidacte en informatique, l’auteur a tous les défauts de sa qualité. Si vous vous inspirez, copiez ou pire utilisez le contenu de cette page, vous êtes téméraire, inconscient du danger !
Reconnaissant avoir été dûment informé, vous déchargez l’auteur et à fortiori l’hébergeur du site de toute responsabilité dans les graves dégâts que vous causerez sûrement !
Vous n'aurez jamais fini d'apprendre la programmation, aussi apprenez à apprendre en vous amusant.
Je vous signale que les trois premières fondations sont reprises dans un tutoriel : Outils pour construire un code jQuery évolutif.
Except where otherwise noted, content on this site is licensed under a Creative Commons License : Attribution-Share Alike 2.0 Belgium
Mention obligatoire : "Auteur : Hagnoul Daniel (https://www.developpez.net/forums/u285162/danielhagnoul/)"