Microsoft Ajax et l'evenement scroll de la molette de la souris (wheelmouse)
Dans certains gros développements clients on a besoin de s'abonner à l'événement "déplacement de la molette de la souris" en JavaScript. Malheureusement cet événement n'est pas standardisé et il existe différentes façons de faire ...
Pour Internet Explorer et Opéra il faut s'abonner à l'événement 'mousewheel', pour Firefox (et Safari ?) il s'agit de l'événement 'DOMMouseScroll'. Pour récupérer les informations sur l'évenément ça ce corse un peu : pour IE on utilise la propriété window.event.wheelDelta qui est positive quand on "monte avec la molette" avec Opéra c'est la même propriété sauf qu'elle est positive quand on "descend" ... avec Firefox il s'agit de la propriété e.detail (où e est l'argument du handler de l'événement) là encore cette propriété est positive lorsque l'on "descend", pour Safari il semble que c'est le même comportement que sous Firefox. Maintenant que l'on arrive à savoir dans quelle sens on déplace la molette, regardons d'un peu plus prés les valeurs de cette propriété. Pour IE et Opéra il s'agit d'un multiple de 120 alors que pour Firefox c'est un multiple de 3 (cela semble différent pour Safari mais je n'ai pas pu tester).
A partir de tous ces renseignements on peut alors avoir un comportement commun pour tous les navigateurs, cette page : Mouse wheel programming in JavaScript nous montre comment faire via des exemples.
Le framework Microsoft Ajax Library (aka Atlas) contient une couche d'abstraction pour les événements ce qui permet de ne pas tenir compte des spécificités du navigateur client. Comme nous l'explique Bertrand Leroy sur cet article : DOM events in the Microsoft AJAX Library il suffit d'utiliser la méthode $addHandler(element, eventName, eventHandler) pour s'abonner à un événement.
Malheureusement dans la version RC de Microsoft Ajax Library l'évenement mousewheel n'est pas pris en compte ... Voici donc un petit bout de code qui permet d'utiliser la méthode $addHandler sans se préoccuper des spécificités du client :
if (Sys){
Sys.UI.DomEvent._itelios_addHandler = Sys.UI.DomEvent.addHandler;
$addHandler = Sys.UI.DomEvent.addHandler = function(element, eventName, handler){
if (eventName.toLowerCase() == 'mousewheel'){
var _handler = function(e){
if (e.rawEvent.wheelDelta){
e.wheelDelta = e.rawEvent.wheelDelta / 120 ;
if (Sys.Browser.agent == Sys.Browser.Opera)
e.wheelDelta = -e.wheelDelta;
} else if (e.rawEvent.detail){
e.wheelDelta = -e.rawEvent.detail / 3;
}
handler(e);
}
if (Sys.Browser.agent == Sys.Browser.InternetExplorer || Sys.Browser.agent == Sys.Browser.Opera){
return Sys.UI.DomEvent._itelios_addHandler(element, 'mousewheel', _handler);
} else {
return Sys.UI.DomEvent._itelios_addHandler(element, 'DOMMouseScroll', _handler);
}
} else {
return Sys.UI.DomEvent._itelios_addHandler(element, eventName, handler);
}
}
}
Comme pour le hook de la méthode buggé Date.parse je stock et redéfinis la méthode $addHandler. Vous pouvez alors utiliser ce bout de code quelque soit le navigateur :
$addHandler($get('blockID'), 'mousewheel', function(e){
debug.trace(e.wheelDelta);
e.preventDefault();
});
Si vous vous trouvez sur une page très longue (avec un scroll) et que vous ne voulez pas que la page se déplace lors du scroll de la molette il vous faudra faire appel à la méthode preventDefault de l'argument qui, comme son nom l'indique, annulera l'événement.
Un peu plus loin ?
Lorsque j'ai étudié les valeurs de wheelDelta, j'ai vu que tous les exemples le divisait par 120 ou 3. Je dispose d'une souris qui n'a pas de "cran" sur la molette (et c'est assez désagréable au début) ce qui fait que je suis très précis avec la souris et il se trouve qu'avec cette souris il faudrait que je divise la propriété par 28 sous IE et 1 pour Firefox, sous Opéra ces "scroll intermédiaire" ne sont pas pris en compte par l'événement 'mousewheel' ... j'ai donc cherché à quoi correspond ces valeurs et voici ce que les docs me disent :
[MSDN] wheelDelta Property
This property indicates the distance that the wheel has rotated, expressed in multiples of 120. A positive value indicates that the wheel has rotated away from the user. A negative value indicates that the wheel has rotated toward the user.
[Gecko] event.detail
Returns additional numerical information about the event, depending on the type of event. For mouse events the value indicates the number of subsequent clicks.
Ce n'est pas très parlant tout ça ...
Il est donc préférable d'oublier la valeur de cette propriété mais de conserver seulement le signe de celle-ci.