chmel a écrit :
Mais ce n'est pas non plus simple pour un débutant.
oui, ça, je te l'accorde, c'est loin d'être inné, qu'on soit débutant ou non, d'ailleurs.
chmel a écrit :
On peut aussi modifier la fonction en remplaçant this par l'objet qu'il représente :
big_photo.onclick=function(){this.style.display='none';}
// devient
addEvent(big_photo,"click",function(){big_photo.style.display='none';},false)
En effet, on peut bien redéfinir l'élément au sein de la fonction anonyme mais ça perd de son intérêt puisque tu es contraint de constituer un script monobloc avec des méthodes privées, donc non réutilisables...
exemple :
[#blue]// Le code suivant fonctionne...[/#]
function fnInit()
{
var big_photo = document.getElementById('big_photo');
addEvent(big_photo,"click",function(){big_photo.style.display='none';},false);
}
[#blue]// Le code suivant ne fonctionne pas...[/#]
function fnInit()
{
var big_photo = document.getElementById('big_photo');
addEvent(big_photo,"click", fnDisplay, false);
}
function fnDisplay()
{
big_photo.style.display='none';
}
Pour que ça marche, tu dois redéclarer var big_photo dans la fonction fnDisplay. On perd ici la référence qu'on pouvait obtenir avec this, ce qui ne nous arrange guère...
Je développe pour ceux que le sujet intéresse...
Tout d'abord, pour bien comprendre comment fonctionne addEvent, j'invite toujours à consulter le
tuto... ( Je suis lourd hein ?!
... mais c'est indispensable pour appréhender la suite...
) Je vais m'efforcer d'être au plus clair malgré la complexité de la chose... Accrochez vos ceintures !
Fonction addEvent
function addEvent(oElem, sEvType, fn, bCapture)
{
return oElem.addEventListener? [#blue]// Si le navigateur comprend la méthode addEventListener[/#]
oElem.addEventListener(sEvType, fn, bCapture): [#blue]// On l'applique[/#]
oElem.attachEvent? [#blue]// Sinon, on teste la méthode propriétaire d'IE attachEvent[/#]
oElem.attachEvent('on' + sEvType, fn): [#blue]// et on l'applique[/#]
oElem['on' + sEvType] = fn; [#blue]// En dernier recours, on applique la méthode intrusive[/#]
}
La principale notion à acquérir est que la fonction addEvent va jouer avec l'événement (représenté par une variable arbitraire, e, par exemple) alors qu'un element.onclick joue sur element (représenté par le mot clé this).
Cette fonction prévoit trois cas de figure :
* Les navigateurs W3C compliant
* IE
* Les anciens navigateurs
La fonction définie en tant que troisième argument d'addEvent est donc indépendante (elle n'est attachée à aucun élément). Pour que ce soit le cas, on peut passer l'élément en tant qu'argument...
En repartant de notre code précédent, on obtient :
function fnInit()
{
var big_photo = document.getElementById('big_photo');
addEvent(big_photo,"click", function() { fnDisplay(big_photo); }, false);
}
function fnDisplay(elem)
{
elem.style.display='none';
}
C'est tout de suite plus souple puisque la fonction fnDisplay est susceptible de s'appliquer à n'importe quel élément.
Maintenant, pour véritablement faire référence à l'élément d'où provient l'événement, on est censé se servir de la propriété e.target qui fait référence à l'objet source de l'événement. Ca, c'est la méthode W3C. Pour IE, on remplace e.target par window.event.srcElement parce qu'une difficulté ne suffisant pas, IE considère que tout événement dépend de window. (Je sens que j'ai déjà paumé pas mal de monde
)
Bref, voici la méthode utilitaire permettant d'obtenir l'équivalent de notre this :
Fonction getTarget
[#blue]// Récupération de la source de l'événement[/#]
function getTarget(e)
{
var target = window.event ? window.event.srcElement : e ? e.target : this;
if(!target) return false;
if(target.nodeName.toLowerCase() != 'a') target = target.parentNode; //Pour Safari
return target;
}
Cette fonction renvoit window.event.srcElement pour IE, e.target pour les navigateurs modernes et this pour les autres.
On reprend une nouvelle fois notre fonction en appliquant tout cela :
function fnInit()
{
var big_photo = document.getElementById('big_photo');
addEvent(big_photo, 'click', fnDisplay, false);
}
function fnDisplay(e)
{
var elem = getTarget(e);
elem.style.display='none';
}
Ce n'est pas fini !
Non... On a parlé du problème du this mais il y en a un autre -> return false; non plus, ça ne marche pas
Il est pourtant nécessaire d'annihiler la transmission de l'url si big_photo se trouve être un lien... et... on a toujours nos 3 cas à traiter... (esprit geek, es-tu là ?
)
Pour les W3C compliant, cela s'effectue via e.stopPropagation(); pour stopper la propagation de l'événement à d'autres éléments et e.preventDefault(); pour stopper la transmission du lien.
Sous IE, ça correspond respectivement à window.event.cancelBubble = true; et window.event.returnValue = false;
Pour les autres, on fait comme d'habitude avec un simple return false;
Une exception -> Safari. Celui-ci comprend la méthode W3C mais ne réagit pas correctement; la transmission de l'url s'effectue quand même, ce pourquoi on ajoute un return false; dans la première condition de la fonction qui sert à gérer tout ça :
fonction cancelClick
[#blue]// Empêche la propagation de l'événement et stoppe la valeur de retour[/#]
function cancelClick(e)
{
if(e && e.stopPropagation && e.preventDefault) [#blue]// W3C compliant[/#]
{
e.stopPropagation();
e.preventDefault();
return false; [#blue]// Pour Safari[/#]
}
else if(window.event && window.event.cancelBubble && window.event.returnValue) [#blue]// IE[/#]
{
window.event.cancelBubble = true;
window.event.returnValue = false;
return false; [#blue]// Pour éviter un avertissement[/#]
}
else return false; [#blue]// les autres[/#]
}
Pour conclure, je vous laisse un exemple illustrant tout ce qu'on vient de dire...
http://koalnet.com/divers/test-events/
Dans celui-ci, j'affecte deux actions au clic sur le lien en utilisant les méthodes précédentes et j'annihile la transmission de l'url.
Ce qu'il faut avoir à l'esprit, c'est :
* qu'un navigateur W3C compliant interprétera le script correctement,
* qu'IE va bien prendre nos deux actions en compte mais dans l'ordre inverse (parce que c'est IE
)
* que les anciens navigateurs n'interpréteront qu'une des deux actions...
On pourrait annihiler la méthode addEvent pour ces derniers en remplaçant oElem['on' + sEvType] = fn; par false; dès lors qu'on souhaiterait affecter plus d'une action mais ça perd tout son intérêt si on se veut compatible avec tout le monde...
C'est pourquoi tout ce que je viens de dire ne sert en gros qu'à votre culture générale et vos soirées tirage de cheveux...
Modifié par koala64 (05 Nov 2006 - 15:39)