Outils pour utilisateurs

Outils du site


cours2011:jquery_semestre_4:td:les_evenements_et_plus

Les événements et plus ...

Les événements

Le problème Internet Explorer

Pas de element.addEventListener avant IE9. Mais une alternative : element.attachEvent.

D'où le code (source MDC) :

if (el.addEventListener){
  el.addEventListener('click', modifyText, false); 
} else if (el.attachEvent){
  el.attachEvent('onclick', modifyText);
}

Ou plus “performant” (High Performance JavaScript - O'Reilly) :

function addHandler(target, eventType, handler){
//overwrite the existing function
if (target.addEventListener){ //DOM2 Events
addHandler = function(target, eventType, handler){ target.addEventListener(eventType, handler, false);
};
} else { //IE
addHandler = function(target, eventType, handler){ target.attachEvent("on" + eventType, handler);
}; }
//call the new function addHandler(target, eventType, handler);
}

Mais il manque encore le fait que l'objet ”event” n'est pas passé de la même façon et qu'il comporte des différences notables…

Bref, si vous ne comprenez rien de cela, vous pouvez au moins retenir qu'il est indispensable d'utiliser une librairie JavaScript. (Vous en saurez plus que ceux qui croient qu'ils peuvent s'en passer !)

P.-S. Et la taille n'est pas un problème surtout si l'on se limite à une plate-forme et/ou un sous-ensemble de fonctionnalités (http://microjs.com/).

Ce que font les événements

Rappel : MDC : element.addEventListener idem AS3 : EventDispatcher.addEventListener().

Donc exactement les mêmes notions qu'en AS3/Flash.

La mise en place des gestionnaires d'événements

code HTML :

<h1 id="titre">Test sans Librairie JavaScript</h1>
var element = document.getElementById("titre");
// ou avec un navigateur récent 
// var element = document.querySelector("#titre");
 
element.addEventListener("click",function (event) {
	console.log("un clic sur le titre");
}, false); // Le false final n'est pas facultatif ! (contrairement à AS3)

Rien de spécial, vu et revu en AS3. Juste l'usage d'une fonction anonyme qui est plus dans le style de JavaScript.

L'objet "''event''"

MDC : event presque idem AS3 : Event

element.addEventListener("click",function (event) {
	console.log("L'objet \"event\" (plein d'info): ", event);
	console.log("A retenir \"event.target\" :", event.target);
}, false); // Le false final n'est pas facultatif ! (contrairement à AS3)

La propagation

Les événements se propagent ! : Quirksmode - JavaScript - Event order

Le moins utilisé :

               | |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  \ /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

Le plus fréquent (par défaut) :

               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------
Usage de la délégation

Dans le cadre des événements et de leurs propagations, on appelle “délégation” le fait d'écouter un “parent” dans l'intention de traiter un événement survenu à un “enfant”. On utilise “évent.target” pour déterminer l'enfant.

Code HTML :

<ul id="liste">
	<li id="item-1">Cela sera utile pour la propagation</li>
	<li>Et son pendant, l'usage de la délégation</li>
	<li><a id="un-lien" href="http://google.fr">Un lien, mais avec JavaScript...</a></li>
</ul>

code JavaScript :

document.getElementById("liste").addEventListener("click",function (event) {
	console.log("écoute le 'UL#liste'");
	console.log("\"this\" est : ", this);
	console.log("Click sur la cible \"event.target\" :", event.target);
}, false); // Le false final n'est pas facultatif ! (contrairement à AS3)
La phase de capture des événements

Le troisième paramètre (useCapture=true) permet de signifier que l'on écoute d'un “parent” AVANT que l'événement ne parvienne à l'enfant. Ce n'est pas faisable avec Internet Explorer avant la version 9 !

Code JavaScript :

document.getElementById("liste").addEventListener("click",function (event) {
	console.log("écoute le 'UL#liste' en \"montant\" ('true' pour 'useCapture')");
	console.log("\"this\" est : ", this);
	console.log("Click sur la cible \"event.target\" :", event.target);
}, true); // Attention ici "true" !

En AS3, c'est utile pour “désactiver” une sous-partie de l'application en le combinant avec ”Event.stopPropagation()”. Mais pas réalisable en JavaScript du fait du manque de support d'Internet Explorer (avant version 9).

Stopper la propagation

L'objet ”event” dispose d'une méthode permettant d'arrêter la propagation d'un événement. On ne verra pas l'exécution des gestionnaires d'événements qui auraient dû suivre l'appel de cette méthode.

MDC : event.stopPropagation idem AS3 : Event.stopPropagation()

Code JavaScript :

document.getElementById("item-1").addEventListener("click",function (event) {
	console.log("écoute le 'LI#item-1'");
	console.log("\"this\" est : ", this);
	console.log("Click sur la cible \"event.target\" :", event.target);
	event.stopPropagation(); console.log("L'événement n'ira pas plus loin ! (stopPropagation)");
}, false); // Le false final n'est pas facultatif ! (contrairement à AS3)

Supprimer le comportement par défaut

Le navigateur (ou le lecteur Flash) réalise des “tâches” suite aux actions de l'utilisateur (“événements”). Il est possible de désactiver ces traitements par défaut avec ”event.preventDefault()” (exemple : ne pas suivre un lien).

MDC : event.preventDefault idem AS3 : Event.preventDefault()

Code JavaScript :

document.getElementById("un-lien").addEventListener("click",function (event) {
	console.log("écoute le 'A#un-lien'");
	console.log("\"this\" est : ", this);
	console.log("Click sur la cible \"event.target\" :", event.target);
	event.preventDefault(); console.log("L'événement ne fera pas comme il devrait ! (preventDefault)");
}, false); // Le false final n'est pas facultatif ! (contrairement à AS3)

Les événements avec jQuery

C'est pareil et même plus simple :

  • jQuery offre des raccourcis.
  • jQuery vous encourage à utiliser la délégation (mais ne gère pas la capture)
  • L'objet ”event” est identique : event.target, event.stopPropagation(), event.preventDefault()
    • Il prend en charge (pour vous) les différences entre les navigateurs.

La mise en place des gestionnaires d'événements

code HTML :

<h1 id="titre">Test avec jQuery</h1>
var element = $("#titre");
 
element.click(function (event) {
	console.log("un clic sur le titre");
});
 
element.click(function (event) {
	console.log("L'objet \"event\" (plein d'info): ", event);
	console.log("A retenir \"event.target\" :", event.target);
});

Le long : element.addEventListener(“click”,function (event) { … } );
Devient : element.click(function (event) { … } );

Il existe une méthode pour tous les événements de souris, de formulaires, dû clavier, dû navigateur et dû chargement du document.

Outre la syntaxe plus courte, jQuery offre des bénéfices palliant à des défauts des anciens navigateurs. Notamment :

  • S'assurer que le document (DOM) est chargé et accessible : .ready(fonction ($) { ... } )
    • Souvent on utilise le raccourci : jQuery(fonction ($) { … } );
  • Les événements : .mouseenter() et .mouseleave().
    • Ne jamais utilisé mouseover et mouseout, ils posent des problèmes.
    • mouseenter et mouseleave sont des ajouts de Microsoft qui évitent bien des problèmes (pour une fois !).
    • En AS3 ces événements on également été ajoutés à FlashPlayer 9.

Usage de la délégation

Outre les raccourcis, jQuery offre d'autres méthodes pour mettre en place les gestionnaires d'événements : jQuery - event handler attachment.

Vous y trouver plein de méthodes : bind, delegate, live, … Depuis jQuery 1.7 vous ne devez plus les utilisés !

Maintenant une seule méthode : .on() (et éventuellement .off()).

Son usage est enfantin :

Code HTML :

<ul id="liste">
	<li>...</li>
	<li>...</li>
	<li>...</li>
</ul>

Si l'on veut écouter les LI on pourrait écrire : ”$(”#liste li”).click(…);” . Mais c'est une mauvaise pratique, car sans s'en rendre compte l'on met en place un gestionnaire d'événement pour CHAQUE LI.

jQuery simplifie l'usage de la délégation (on écoute le UL) en offrant la fonction adéquate :

$("#liste").on("click","li",function (event) {
	console.log("\n");
	console.log("écoute le 'UL#liste, mais seulement pour les 'LI' enfants");
	console.log("\"this\" est : ", this, "manipulation faite par jQuery !");
	console.log("Click sur la cible \"event.target\" :", event.target, "usage inutile, car 'this' 'correct'");
});

On dit et obtient exactement ce que l'on veut : on écoute les clics sur tous les LI de la liste (#liste).

Il faut procéder ainsi à chaque fois que c'est possible. Si vous voulez écouter tous les éléments d'une page, vous pouvez utilisez la racine du document ”$(document)”.

L'objet Event

jQuery gomme les différences entre les navigateurs : jQuery - event object

Mais son usage reste standard (on retrouve les méthodes habituelles) :

Autre avantage de jQuery pour les événements

Événements à usage unique

.one() d'usage identique à .on(), la seule différence, le gestionnaire d'événement ne sera exécuté qu'une fois.

Passer des données au gestionnaire d'événement

En AS3 c'est une bonne pratique d'utiliser des événements personnalisés pour passer des données. En JavaScript c'est pareil sauf que :

  • Comme on utilise souvent des fonctions anonymes, elles peuvent capturer (closure) les variables nécessaires.
  • Avec jQuery, toutes les fonctions qui mettent en place les événements acceptent un paramètre (data ou eventData) qui permet de passer ces informations. L'usage est trivial : event.data
Les "namespaces" (espaces de nom)

Quand vous attachez, des événements jQuery vous permettent de spécifier des “namespaces” (espaces de nom, nom qualifié).

Cela permet d'enlever plusieurs gestionnaires d'événement en une fois (de la documentation de jQuery) :

var validate = function () {
  // code to validate form entries
};
 
// delegate events under the ".validator" namespace
$("form").on("click.validator", "button", validate);
 
$("form").on("keypress.validator", "input[type='text']", validate); 
 
// remove event handlers in the ".validator" namespace
 
$("form").off(".validator");
Retirer les événements en JavaScript (et avec jQuery)

En AS3 c'est une obsession (EventDispatcher.removeEventListener).

En JavaScript vous pouvez vous demander comment faire surtout que vous utilisez souvent des fonctions anonymes :

  • Vous vous en moquez, car vous ne faites pas une application (vous ne créer/supprimer pas des éléments à tout-va et de toute façon l'utilisateur vas changer de page).
  • Vous faite une application qui crée/supprime des éléments, mais :
    • Vous utilisez la délégation : pas de problème un seul gestionnaire d'événement donc pas de raisons de le supprimer.
    • Vous avez des événements attachés aux éléments que vous supprimez : pas de problèmes .remove() de jQuery supprime aussi les gestionnaires d'événements (à se demander pourquoi c'est si compliqué en AS3 !).
    • Pour les cas qui restent, il serait curieux que l'usage de ”namespace” ne soit pas la solution.

AJAX

C'est quoi, le rapport entre AJAX est les événements…

AJAX : Asynchronous Javascript and XML

  • Asynchronous : le pourquoi des événements (réagir à l'événement qui se produira plus tard, le chargement des données).
  • JavaScript : Rien de neuf.
  • XML : C'est juste historique, au début cela servait à charger de l'XML. Maintenant qui ferait cela… ;-)

Qui fait de l'AJAX :

  • Vous : quand vous utiliser en AS3, flash.net.URLLoader et flash.display.Loader
  • Le problème c'est comment traiter les données une fois reçues (écouté l'événement):
    • C'est compliqué en AS3 (à se demander comment ils ont fait pour rendre cela si complexe !!!).
    • C'est simple avec jQuery.

Ajax sans jQuery (ou autre)

Vous pouvez lire la page de Wikipédia : XMLHttpRequest. Ou mieux lire le code d'une librairie JavaScript (exemple: microajax. Ou plus raisonnable pour comprendre, lire les 30 pages de JavaScript: The Definitive Guide, 6th Edition sur le sujet (chapitre Scripted HTTP).

AMHA, faites quelque chose de plus intéressant au lieu de perdre votre temps…

Ajax avec jQuery

Trés très simple

Le plus simple : .load()

Du TP :

tooltip = jQuery("<div>").load("test-ajax-glossaire.html");

Rien de plus simple :

  • Mais où sont les événements ?
    • jQuery fait tout pour vous.
  • Comment accéder aux données charger, faire un traitement avec
    • Utilisez une autre méthode…

Très simple

Simple avec $.get() (ou $.post() ou $.getJSON()) :

jQuery.get('test-ajax-glossaire.html', function (data) {console.log(data)});

OK Simple :

  • Mais il y a un événement ?
    • Oui la fonction passée en paramètre. Elle est appelée quand les données sont reçues.
  • Comment savoir si il y une erreur ?
    • Cela vient…

Simple

On utilise de jQuery :

jQuery.get('test-ajax-glossaire.html')
        .done(function (data) {console.log(data)})
        .fail(function (e) {console.log("erreur :",e)});
// ou sans "chaînage" :
var req = jQuery.get('test-ajax-glossaire.html');
req.done(function (data) {console.log(data)});
req.fail(function (e) {console.log("erreur :",e)});

On utilise deferred.done() et deferred.fail() (pour traiter l'erreur).

Ouch compliqué !

  • Non, ”.done()” et ”.fail()”, c'est comme ”.click()” : on passe la fonction à exécuter quand l'événement survient.
  • Ce qui est compliqué c'est le concept de Deferred.

et JSON ?

Tout pareil (fichier test-ajax-glossaire.json) :

{
	"consectetur":"Adipisicing elit, sed do eiusmod tempor",
	"duis":"Aute irure dolor in reprehenderit in voluptate velit esse cillum",
	"ut":"Enim ad minim veniam",
	"excepteur":"Sint occaecat cupidatat non proident",
	"laboris":"Nisi ut aliquip ex ea commodo consequat"
}

On le lit avec :

jQuery.getJSON('test-ajax-glossaire.json')
        .done(function (data) {console.log(data)})
        .fail(function (e) {console.log("erreur :",e)});
cours2011/jquery_semestre_4/td/les_evenements_et_plus.txt · Dernière modification: 2012/02/08 23:00 (modification externe)