11548 sujets

JavaScript, DOM et API Web HTML5

Bonjour, je cherche simplement à ajouter en javascript une gestion de l'évènement click sur un bouton.
Ci dessous 3 methodes :


<button id="b1">b1</button>
<button id="b2">b2</button>
<button id="b3">b3</button>
<button id="b4">b4</button>

<script type="text/javascript">

// 1 - ça je pensais que c'était le plus simple mais ça ne
// fonctionne pas et je sais pas vraiment pourquoi :
b = document.getElementById("b1");
b.onclick = "alert('je suis " + b.id + "');";

// 2 - ça, ça fait pas vraiment ce que je veux car "b.id" n'est
// évalué qu'a l'execusion (et b ne pointe plus forcement le
// bon objet... c'est pour ça qu'il affiche "je suis b3")
b = document.getElementById("b2");
b.onclick = function() {alert("je suis " + b.id);}

// 3 - ça c'est bon (attention ça ne fonctionne qu'avec
// Mozilla, l'event étant géré différement sous IE...)
// Mais je trouve un peu lourd cette echnique.
b = document.getElementById("b3");
b.onclick = function(e) {alert("je suis " + e.target.id);}



Donc en résumé :
- pourquoi me la technique 1 n'est pas bonne ?
- avez vous autre chose que la technique 3 à me proposer ?
Modifié par chadom (27 Sep 2005 - 11:21)
Alors, les evemenents en javascript c'est pas tout simple Smiley langue


donc b.onclick, demande une signature de fonction, une sorte de delegate.

Ce delegate est malheureusement different pour IE et FF ... Smiley ohwell pour FF ce serait plutot function(e) et pour IE function() FF passe l'objet event en argument alors que IE non .... mais cela n'a pas d'importance car en javascript on peut appeller les fonctions avec le nombre de paramètres qu'on veut.

donc pour résumé : b.onclick demande un delegate (la signature d'une fonction)


tu peux donc faire

function toto(){alert('toto');}

b.onclick = toto; //sans les parenthèse puisque tu passe la fonction en paramètre

ou alors

b.onclick = function(){alert('toto')}

Donc ton cas 1 ne fonctionne pas car toi tu passes un string au lieu d'une fonction.

Ensuite ce qu'il faut savoir c'est quand tu donne une fonction à un event, à l'interieur de la fonction, le mot clé this appartient à l'objet qui appelle la fonction Smiley biggol

Je suis pas clair ?

imagine que tu as un objet

tonobjet.couleur = 'rose';
tonobjet.tonevenement = function(){alert(this.couleur)}

dans ta fonction, this correspond à l'objet. C'est pas évident à expliqué comme ca, surtout si tu ne connais pas la notion d'objet en javascript.

donc la pour ton bouton c'est pareil

b.onclick = function(){alert(this.id)} // t'affichera l'id

Mais si tu veux accéder à l'objet event, tu sais que pour FF tu dois faire comme ca
b.onclick = function(e){alert(e.taget.id)}

et pour IE
b.onclick = function(e){alert(window.event.target.id)}

donc combinons les 2 Smiley smile

b.onclick = function(e)
{
e = e ? e : window.event;
alert(e.target.id);
}

Aprés si t'avais beaucoup d'evenement tu utiliserais bien sur une autre solution, la librairie prototype en propose une sympa, mais ca depasse le cadre de ta question.

Enfin pour le point 2 et le fait qu'il t'affiche l'id3 c'est normal. Tu vas cliquer sur ton bouton b2 aprés avoir effectué l'action du point3 donc b aura pour valeur b3 pour contourner le problème il faut faire une petite astuce qui consiste à mettre une sorte de pointeur.

b.onclick = function(){var _b = b; aler(b.id);}

Voila : j'espere ne pas t'avoir embrouillé, mais difficile de ne pas rentrer dans les détail dans ce genre de question.
Modifié par CyrilCS (24 Sep 2005 - 19:25)
Un grand merci pour ta réponse détaillée. Smiley smile

- Pour la méthode 1 ton analyse me montre que j'avais pas assez réfléchi...
- Utiliser le this est très élégant. Merci pour cette proposition. je reste sur un petit problème car dans mon "cas réel" c'est pas l'id que je souhaite atteindre mais une chaine sans rapport avec le DOM. Je vais peut-être stocker cette valeur dans un member sans sens html du bouton (genre <button id="b1" moninfo="foo"> et utiliser "b.moninfo")...
- Pour gérer l'event sous IE j'espère que ça servira à d'autres (pour moi c'était inutile, je fais un script greasemonkey...)
- Pour l'astuce de stocker la valeur de b dans _b, il y a une idée, mais il faut alors éffectuer cette "sauvegarde" hors de la fonction (sinon on se retrouve avec le même problème, quand t'excutes _b=b, b ne pointe plus le bon objet...) Smiley murf

Encore merci de t'être penché sur mon problème...
arf je me suis trompé pour le _b il faut faire

b.onclick = function(){var _b = b; alert(_b.id);} et normalement ca marche Smiley smile

Sinon c'est pas trés propre de mettre moninfo="foo" comme ca... l'attribut moninfo n'existe pas dans les standards ... j'ai aussi eu ce meme problème, j'en ai d'ailleur parlé sur ce forum. La seule solution que j'ai trouvé serait de faire <div cyril:key="valeur"> mais je n'ai pas eu de réponses sur la validité de ce code ... Smiley ohwell

Mais pour recuperer ta variable, il faudrais mieux faire b.onclick = function(){alert(this.getAttribute('moninfo'))}
Pour le "alert(_b.id)" j'avais corrigé de moi même, mais le problème reste le même : le code "var _b = b" ne sera évalué qu'au déclenchement de l'event et non pas au moment de l'attachement de la fonction anonyme au b.onclick... donc b aura là encore pu changer... (j'ai vérifié par test pour être sûr de ne pas dire une connerie lol).

Je suis d'accord, rajouter un attribut non standard est plutôt crade... (et le dire sur alsacrations est même indécent Smiley lol )
Pour ton <div cyril:key="valeur"> désolé, mais je sais pas non plus si c'est du valide (je ne connais même pas cette notation avec un ":") T'as testé avec le validateur w3c ?
ah oui t'as raison Smiley eek

J'ai fait des petites recherches sur quand j'avais eu mon problème et voici le contexte et la solution.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
window.onload = function()
{
var li = document.getElementById('test').getElementsByTagName('li'); 

for (var i = 0; i < li.length; i++)
	li[i].onclick = new Function('', 'alert('+ i + ')')
}
</script>
</head>
<body>
<ul id="test">
	<li>test1</li>
	<li>test2</li>
	<li>test3</li>
</ul>
</body>
</html>
[code]

Ceux à quoi je pensais c'etait justement la solution qui marche dans un autre cas :s 

[code]
for (var i = 0; i < li.length; i++)
{
        val = i; //hook
	li[i].onclick = function(){alert(val))}
}


donc le code pour faire ce que tu veux :


b.onclick = new Function('', 'alert('+ b.id + ')')


C'est assez délicat à expliquer je te conseil d'aller voir ici : http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Function

Sinon pour la signification du : cela sert pour les namespace, et non je ne i'a pas encore validé car j'aime pas validé, je prefere comprendre ce que j'ecris en sachant que je suis valide, plutot que d'ecrire au pif, et dire stop quand je suis valide Smiley cligne [/i][/i]
Bingo ! we have a winner !

for (var i = 0; i < li.length; i++)
  li.onclick = new Function('', 'alert('+ i + ')')
}


Voilà qui est interessant... utiliser le constructeur de fonction !
Je teste ça dès que possible.
Là je crois qu'on a bien fait le tour du sujet lol.

Muchas gracias Cyril !