11548 sujets

JavaScript, DOM et API Web HTML5

Salut à tous ...

Je vous expose mon soucis (un peu compliqué)

Je suis en train de dévellopper un genre de menu déroulant en javascript/objet. Ce n'est pas un menu déroulant, mais c'est approchant !

En gros, j'ai un objet parent(ul) qui contient plusieurs objets enfants(li).

L'objet parent est accessible via une variable globale définie dans le javascript. Il définit des méthodes pour ajouter et supprimer des enfants. Une référence à ces enfant est stockée dans un tableau à l'intérieur du parent.

Chaque enfant possède lui aussi des méthodes pour créer des petits-enfants ... (ce n'est pas le problème).

Mon soucis est liée aux évènement.
En effet, à chaque objet sont liés des évènement (mouseover et mouseout).
Le problème est lors de la création d'un enfant, je doit lui ajouter ces évènements. Hors il faut que je puisse dans cette déclaration rajouter l'information de QUEL enfant est concerné.

Première réflexion : utiliser this ... très drole ! ca ne marche pas des masse.

Pour Firefox (et compatibles) j'ai trouvé :
AddEvent( b, "mouseover", eval("function(){ PARENT.Enfant[ \""+this.ID+"\" ].Show();}")  );

la fonction AddEvent est juste l'appel à addEventListener ou AttachEvent en fonction du navigateur
b est l'objet html de l'enfant

En gros le principe est de générer la syntaxe de la fonction en incluant le this.ID qui permet de retrouver l'enfant concerné depuis le parent.

Malheureusement, cette déclaration ne plait pas du tout à IE !
pourtant
AddEvent( b, "mouseover", function(){ PARENT.Enfant[ 'ENF1' ].Show();}  );

ceci fonctionne très bien sur les 2 navigateur ...
Je souhaite juste remplacer le ENF1 dynamiquement par le this.ID de l'objet concerné.
A noter que le this.ID pointe sur l'objet lors de la déclaration de la fonction. Pas du tout lors du déclenchement de l'évènement.

Si quelqu'un à une proposition à soumettre, je suis preneur ! ca fait plusieurs jours que ca me prend là tête !
SNIF Smiley bawling
Modifié par MangaII (29 Mar 2007 - 08:40)
Salut,

Je ne comprends pas pourquoi ta solution ne fonctionne pas, mais il y a de toute façon beaucoup plus simple et propre que l'utilisation d'eval :
function mouseOverFn(id) {
  return function() {
    PARENT.Enfant[ id].Show();
  };
}

AddEvent(b, "mouseover", mouseOverFn(this.ID));

Modifié par Julien Royer (28 Mar 2007 - 09:05)
Bien vu ... MAIS !

Je ne peux pas vérifier de suite (ca attendra ce soir). Mais j'avais essayé un truc du genre, et il me semble qu'il considère la fonction passée a addeventlistener (attachevent) comme une chaine de caractère.
Je crois que dans ce cas, il ne remplacera pas this.ID par sa valeur. Et il me sort un message genre PARENT.Enfant[ this.ID ] undefined ...

Je vérifierai ce soir qd même ...

Pour ce qui est de ma solution, elle ne fonctionne pas dans IE ! il me dit type incompatible. En gros il n'apprécie pas le eval du début. Il veut forcément quelque chose qui commence par function ... IE n'est pas mon ami.

PS : C'est génial ... une réponse aussi claire à une question aussi pourrie ! J'ADORE (version Chouchou) ce site ! Smiley biggrin
Julien Royer a écrit :
Salut,

Je ne comprends pas pourquoi ta solution ne fonctionne pas, mais il y a de toute façon beaucoup plus simple et propre que l'utilisation d'eval :
function mouseOverFn(id) {
  return function() {
    PARENT.Enfant[ id].Show();
  };
}

AddEvent(b, "mouseover", mouseOverFn(this.ID));


Me revoilà ...

Je confirme ! ca n'est pas si facile ! je n'arrive toujours pas à le faire fonctionner.
Avec la solution que tu propose en effet, le paramêtre passe. Par contre,j'ai un nouveau soucis, la fonction (mouseOverFn) est appellée immédiatement lorsque je la déclare (je ne sais pas pourquoi) et ca me génère des erreurs car il ne trouve pas les objets. il m'annonce que la fonction Show n'existe pas. Si je rajoute un "function(){ ... }" autour :
AddEvent( b, "mouseover", function(){mouseOverFn(this.ID);}  );

alors l'appel de la fonction n'est pas usurpé, mais le paramêtre ne passe plus (ce qui est logique).


La seule solution "statique" qui fonctionne sur tous les navigateur c'est :
AddEvent( b, "mouseover", function(){mouseOverFn( 'ENF1');}  );

Mon pb est toujours le même, faire passer dynamiquement l'id de l'enfant à mouseOverFn !

Ou comprendre pourquoi il appelle tout seul la fonction lorsque je la déclare avec addEventListener ... et que ca plante.
MangaII a écrit :
Je confirme ! ca n'est pas si facile ! je n'arrive toujours pas à le faire fonctionner.
A mon avis, c'est ta fonction AddEvent qui doit être incorrecte (tu as dû mettre des parenthèses en trop). Peut-on la voir ?
Modérateur
this se rapporte à l'événement... pas à l'élément...
Modifié par koala64 (29 Mar 2007 - 06:30)
Ca y'es ! ca fonctionne !

En effet,
function mouseOverFn(id) {
  return function() {
    PARENT.Enfant[ id].Show();
  };
}
AddEvent(b, "mouseover", mouseOverFn(this.ID));

Ca marche très bien. FF et IE !!!

J'avais pas fait gaffe hier soir que le but était de retourner une fonction.
Par contre, ce que je ne comprend pas super bien c'est comment id est transmis à la fonction PARENT.Enfant .... Nulle part on lui explicite de le transmettre ..

Enfin, ca marche ! c'est le principal ...

Merci les gars ! Z'etes les plus fort !
Modifié par MangaII (29 Mar 2007 - 08:41)
koala64 a écrit :
this se rapporte à l'événement... pas à l'élément...
Non, this se rapporte à l'objet window, sous IE, et à l'élement sous les navigateurs qui supportent addEventListener. Smiley cligne
MangaII a écrit :
J'avais pas fait gaffe hier soir que le but était de retourner une fonction.
Par contre, ce que je ne comprend pas super bien c'est comment id est transmis à la fonction PARENT.Enfant .... Nulle part on lui explicite de le transmettre ..
Sisi. Smiley smile

Quand tu crées ta fonction anonyme, elle garde une référence sur l'argument id de la fonction mouseOverFn. On appelle ça une closure (je ne sais pas s'il existe une traduction française).
Modérateur
a écrit :
Non, this se rapporte à l'objet window, sous IE, et à l'élement sous les navigateurs qui supportent addEventListener. Smiley cligne
Au moment où on passe le this en argument, en effet, oui mais plus dans la fonction réceptrice.

Dans ce dernier cas, le this correspond à e.target pour ceux qui supportent addEventListener donc on se réfère bien à l'événement
... et comme e.target correspond à l'élément, ben c'est pareil...

erf... C'est pas clair... Smiley confus

Donc, pour tenter de faire plus clair, il suffit de voir le comportement d'IE où on récupère l'élément avec window.event.toElement ou e.toElement
... et le this ne correspond plus à rien... (ni window, ni window.event, ni l'élément)
koala64 a écrit :
Dans ce dernier cas, le this correspond à e.target pour ceux qui supportent addEventListener donc on se réfère bien à l'événement
... et comme e.target correspond à l'élément, ben c'est pareil...
Non, this correspond dans ce cas à e.currentTarget.
koala64 a écrit :
Donc, pour tenter de faire plus clair, il suffit de voir le comportement d'IE où on récupère l'élément avec window.event.toElement ou e.toElement
... et le this ne correspond plus à rien... (ni window, ni window.event, ni l'élément)
Sisi, this correspond à window dans ce cas. Smiley smile

Quant à toElement, il n'existe a priori que pour les événements de type mouseover ou mouseout.
Modérateur
arf...

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
	<head>
		<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
		<title>Exemple</title>

		<script type="text/javascript">//<![CDATA[

(function() {

var oO =
{
	_Connect:
	function(oElem, sEvType, fn, bCapture)
	{
		oElem.addEventListener ?
			oElem.addEventListener(sEvType, fn, bCapture):
			oElem.attachEvent ?
				oElem.attachEvent('on' + sEvType, fn):
				oElem['on' + sEvType] = fn;
	},

	_Init: function()
	{
		var oA = document.getElementsByTagName('a')[0];

		oO._Connect(oA, 'mouseover', oO._Alert, false);		
	},

	_Alert: function(e)
	{
		alert((e.target || window.event.toElement).href); //ok pour tout le monde
		alert((this || this.event.toElement).href); // this.event.toElement ne fonctionne pas pour IE donc this n'est pas window
		alert((e.currentTarget).href); // ne fonctionne pas sous IE
	}
};

oO._Connect(window, 'load', oO._Init, false);

})();

		//]]></script>
	</head>	
	<body>

<p><a href="#">test</a></p>

	</body>
</html>
Modérateur
ok, je viens de voir l'erreur Smiley lol

c'est :
alert((this.event.toElement || this).href);
et pas l'inverse... sinon, c'est normal... Smiley langue
Modifié par koala64 (29 Mar 2007 - 11:07)
Pour currentTarget, c'est normal, il n'est pas supporté par IE. D'ailleurs, c'est bien le problème, il n'y a aucun moyen direct d'accéder à l'élément sur lequel tu as ajouté ton gestionnaire d'événements si tu utilises attachEvent.

<edit>En fait, il est possible que l'on soit d'accord mais que l'on ne se comprenne pas. Smiley lol
Modifié par Julien Royer (29 Mar 2007 - 11:19)