Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Gestion d'evenement dans un objet

10 réponses
Avatar
bertrand
Bonjour,

Encore moi et mes objets.
J'ai un objet MyObjet qui crée du code html du style :

MyObjet.prototype.MyMethode = function()
{
var nBtn = document.createElement("button");
nBody.appendChild(nBtn);
}

Je voudrais pouvoir appeler une méthode de mon objet quand on clique sur
le bouton. J'ai donc ceci

MyObjet.prototype.MyMethode = function()
{
var nBtn = document.createElement("button");
nBody.appendChild(nBtn);
nBtn.onclick = this.myBtnClicked;
}

MyObjet.prototype.myBtnClicked = function(event)
{
alert(this);
}

Le problème, c'est que la fonction est bien appelée mais this ne fait
plus référence à mon objet mais à mon bouton ???
Comment puis je faire ???

Merci pour vos réponses,

Matt...

10 réponses

Avatar
Pascal
bertrand a écrit :
Bonjour,



Bonjour,

Le problème, c'est que la fonction est bien appelée mais this ne fa it
plus référence à mon objet mais à mon bouton ???
Comment puis je faire ???



C'est le comportement attendu dans la gestion d'évènement que de
récupérer par "this" le nœud qui le déclenche.
Mais pourquoi vouloir récupérer dans cette gestion l'objet qui a serv i à
créer le bouton ?
Je pose la question car j'ai le sentiment qu'en y répondant il se peut
que l'on découvre que le problème soit ailleurs !

Cordialement,
Pascal
Avatar
bertrand
Pascal a écrit :
bertrand a écrit :
Bonjour,



Bonjour,

Le problème, c'est que la fonction est bien appelée mais this ne fait
plus référence à mon objet mais à mon bouton ???
Comment puis je faire ???



C'est le comportement attendu dans la gestion d'évènement que de
récupérer par "this" le nœud qui le déclenche.
Mais pourquoi vouloir récupérer dans cette gestion l'objet qui a servi à
créer le bouton ?
Je pose la question car j'ai le sentiment qu'en y répondant il se peut
que l'on découvre que le problème soit ailleurs !

Cordialement,
Pascal





Bonjour,

Voici mon code :

var MyObject = function(nConteneur)
{
this.nConteneur = nConteneur;

var nBtn = document.createElement("button");
nConteneur.appendChild(nBtn);
nBtn.onclick = this.clicked;

var nText = document.createTextNode("Cliquez");
nBtn.appendChild(nText);
}

MyObject.prototype.clicked = function(event)
{
var nBtn = document.createElement("button");
this.nConteneur.appendChild(nBtn);
}

Le problème c'est quand je passe dans la fonction clicked, je n'ai plus
accès à mon objet MyObject donc je n'ai plus accès à mon nConteneur.

Merci,

Matt...
Avatar
bertrand
bertrand a écrit :
Pascal a écrit :
bertrand a écrit :
Bonjour,



Bonjour,

Le problème, c'est que la fonction est bien appelée mais this ne fait
plus référence à mon objet mais à mon bouton ???
Comment puis je faire ???



C'est le comportement attendu dans la gestion d'évènement que de
récupérer par "this" le nœud qui le déclenche.
Mais pourquoi vouloir récupérer dans cette gestion l'objet qui a servi
à créer le bouton ?
Je pose la question car j'ai le sentiment qu'en y répondant il se peut
que l'on découvre que le problème soit ailleurs !

Cordialement,
Pascal





Bonjour,

Voici mon code :

var MyObject = function(nConteneur)
{
this.nConteneur = nConteneur;

var nBtn = document.createElement("button");
nConteneur.appendChild(nBtn);
nBtn.onclick = this.clicked;

var nText = document.createTextNode("Cliquez");
nBtn.appendChild(nText);
}

MyObject.prototype.clicked = function(event)
{
var nBtn = document.createElement("button");
this.nConteneur.appendChild(nBtn);
}

Le problème c'est quand je passe dans la fonction clicked, je n'ai plus
accès à mon objet MyObject donc je n'ai plus accès à mon nConteneur.

Merci,

Matt...



Bonjour,

Ça n'inspire personne ???

Matt...
Avatar
Mickaël Wolff
bertrand a écrit :
Le problème c'est quand je passe dans la fonction clicked, je n'ai plus
accès à mon objet MyObject donc je n'ai plus accès à mon nConteneur.



Ce que Pascal n'a pas dit clairement, c'est que ta fonction clicked
est maladroitement affectée comme un attribut de ton objet de
*contrôle*, alors que c'est une fonction qui va être appliquée sur
l'objet écouté. Une solution consisterait à utiliser correctement cette
fonction en utilisant l'astuce suivante :

var that = this ;
nBtn.onclick = function() { that.clicked() ; } ;


--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
bertrand
Mickaël Wolff a écrit :
bertrand a écrit :
Le problème c'est quand je passe dans la fonction clicked, je n'ai
plus accès à mon objet MyObject donc je n'ai plus accès à mon nConteneur.



Ce que Pascal n'a pas dit clairement, c'est que ta fonction clicked
est maladroitement affectée comme un attribut de ton objet de
*contrôle*, alors que c'est une fonction qui va être appliquée sur
l'objet écouté. Une solution consisterait à utiliser correctement cette
fonction en utilisant l'astuce suivante :

var that = this ;
nBtn.onclick = function() { that.clicked() ; } ;





Bonsoir,

Impeccable...

Je te remercie, tu viens de m'enlever une épine du pied...

Matt...
Avatar
Bol
Bonjour,

Je voudrais pouvoir appeler une méthode de mon objet quand on clique sur
le bouton. J'ai donc ceci

MyObjet.prototype.MyMethode = function()
{
var nBtn = document.createElement("button");
nBody.appendChild(nBtn);



// liaison des deux objects
nBtn.MyObject = this;

nBtn.onclick = this.myBtnClicked;



nBtn.onclick = function (ev) { this.MyObject.myBtnClicked(ev); }

MyObjet.prototype.myBtnClicked = function(event)
{
alert(this);
}



A+
Bol
Avatar
Laurent vilday
Bol :

Bonjour,



Bonjour à toi. Ah ! Bol is back :)

Je voudrais pouvoir appeler une méthode de mon objet quand on clique sur
le bouton. J'ai donc ceci

MyObjet.prototype.MyMethode = function()
{
var nBtn = document.createElement("button");
nBody.appendChild(nBtn);



// liaison des deux objects
nBtn.MyObject = this;
nBtn.onclick = this.myBtnClicked;



nBtn.onclick = function (ev) { this.MyObject.myBtnClicked(ev); }

MyObjet.prototype.myBtnClicked = function(event)
{
alert(this);
}





Houla, vraiment ? Ca créerai pas une monstrueuse référence circulaire
cette affaire là ? L'histoire nous a montré que c'était à éviter comme
la peste. Déjà que j'étais pas fan de la solution de Mickaël Wolff mais
là je trouve que c'est bien plus cochon comme solution, bien que les
deux propositions soient valides et remplissent leur office.

A) code original (annoté de quelques commentaires pour la forme)

// généralement on ne met de majuscule sur la première
// lettre que pour le constructeur, mais bon comme je disais
// c'est qu'une question de forme, chacun sa préférence.
MyObjet.prototype.MyMethode = function()
{
var nBtn = document.createElement("button");

// euh c'est qui nBody ? D'où qu'il vient lui ?
// pourquoi c'est une variable globale qui est
// utilisée ? M'est avis qu'il y a un bug ici.
nBody.appendChild(nBtn);

// pourquoi myBtnClicked est dans le prototype de MyObjet ?
// Ca n'a pas d'intérêt puisque le contexte d'exécution
// va changer. Ce qui est d'ailleurs le "problème" initial.
nBtn.onclick = this.myBtnClicked;

} // manque un ; ici

// event comme nom d'argument c'est plutôt mal choisi
// à cause de IE qui possède un window.event à ce moment là.
MyObjet.prototype.myBtnClicked = function(event)
{
alert(this);

} // manque un ; ici

B) ce que j'aurais plutôt tendance à proposer :

function MyObjet(val)
{
this.val = val;
}

MyObjet.prototype.myMethode = function()
{
var nBtn = document.createElement("button");
nBtn.onclick = (function(THIS){
return function(e)
{
MyObjet.myBtnClicked.call(THIS, e);
};
})(this);
document.body.appendChild(nBtn);
};

MyObjet.myBtnClicked = function(E/*vent*/)
{
alert(this.val);
};

var x = new MyObjet('fooBar');
x.myMethode();

C) ou encore ceci :

function MyObjet(val)
{
this.val = val;
}

MyObjet.map = {};
MyObjet.uid = 0;
MyObjet.prototype.myMethode = function()
{
var nBtn = document.createElement("button");
nBtn.id = 'myButton' + (MyObjet.uid++);
MyObjet.map[nBtn.id] = this;
nBtn.onclick = MyObjet.myBtnClicked;
document.body.appendChild(nBtn);
};

MyObjet.myBtnClicked = function(E/*vent*/)
{
if ( this.id in MyObjet.map )
{
alert(MyObjet.map[this.id].val);
}
};

var x = new MyObjet('barFoo');
x.myMethode();

D) ou encore ... plein de solutions envisageables.

Et bon, de là à savoir quelle solution est la meilleure dans le cas
précis, aucune idée car comme le soulignais Pascal, je pense qu'il y a
un problème de design quelque part. Il faudrait plus d'informations sur
le contexte réel pour déterminer ce qu'il convient de faire.

--
laurent
Avatar
bertrand
Bonsoir,

Laurent vilday a écrit :

A) code original (annoté de quelques commentaires pour la forme)

// généralement on ne met de majuscule sur la première
// lettre que pour le constructeur, mais bon comme je disais
// c'est qu'une question de forme, chacun sa préférence.



Comme vous l'avez dit, c'est une question de forme...

MyObjet.prototype.MyMethode = function()
{
var nBtn = document.createElement("button");

// euh c'est qui nBody ? D'où qu'il vient lui ?
// pourquoi c'est une variable globale qui est
// utilisée ? M'est avis qu'il y a un bug ici.



Non, ce n'est pas une variable globale. Mais une propriété de mon objet.
Erreur de ma part this.nBody.appendChild(nBtn);

nBody.appendChild(nBtn);

// pourquoi myBtnClicked est dans le prototype de MyObjet ?
// Ca n'a pas d'intérêt puisque le contexte d'exécution
// va changer. Ce qui est d'ailleurs le "problème" initial.



Bien vu !!!

nBtn.onclick = this.myBtnClicked;

} // manque un ; ici

// event comme nom d'argument c'est plutôt mal choisi
// à cause de IE qui possède un window.event à ce moment là.



Ok. Je précise que c'est pour un client léger.
On utilise que firefox, mais j'en prends compte.

MyObjet.prototype.myBtnClicked = function(event)
{
alert(this);

} // manque un ; ici



Ok.


B) ce que j'aurais plutôt tendance à proposer :

function MyObjet(val)
{
this.val = val;
}

MyObjet.prototype.myMethode = function()
{
var nBtn = document.createElement("button");
nBtn.onclick = (function(THIS){
return function(e)
{
MyObjet.myBtnClicked.call(THIS, e);
};
})(this);
document.body.appendChild(nBtn);
};

MyObjet.myBtnClicked = function(E/*vent*/)
{
alert(this.val);
};

var x = new MyObjet('fooBar');
x.myMethode();
C) ou encore ceci :

function MyObjet(val)
{
this.val = val;
}

MyObjet.map = {};
MyObjet.uid = 0;
MyObjet.prototype.myMethode = function()
{
var nBtn = document.createElement("button");
nBtn.id = 'myButton' + (MyObjet.uid++);
MyObjet.map[nBtn.id] = this;
nBtn.onclick = MyObjet.myBtnClicked;
document.body.appendChild(nBtn);
};

MyObjet.myBtnClicked = function(E/*vent*/)
{
if ( this.id in MyObjet.map )
{
alert(MyObjet.map[this.id].val);
}
};

var x = new MyObjet('barFoo');
x.myMethode();

D) ou encore ... plein de solutions envisageables.

Et bon, de là à savoir quelle solution est la meilleure dans le cas
précis, aucune idée car comme le soulignais Pascal, je pense qu'il y a
un problème de design quelque part. Il faudrait plus d'informations sur
le contexte réel pour déterminer ce qu'il convient de faire.




Merci pour votre réponse.
Je pense que la méthode B est bien pour moi car plus simple.
J'essaie et je vous tiens au courant.

Merci encore,

Matt...
Avatar
Bol
Salut Laurent

// liaison des deux objects
nBtn.MyObject = this;
nBtn.onclick = this.myBtnClicked;



nBtn.onclick = function (ev) { this.MyObject.myBtnClicked(ev); }

MyObjet.prototype.myBtnClicked = function(event)
{
alert(this);
}





Houla, vraiment ? Ca créerai pas une monstrueuse référence
circulaire cette affaire là ?



De toutes les façons dès qu'il reference d'objets entre eux
il faut faire le menage, et systematiquement dès qu'il y a
closure, il faut nettoyer le contexte

MyObjet.prototype.MyMethode = function()
{
var nBtn = document.createElement("button");
nBtn.MyObject = this;
nBtn.onclick = function (ev) { this.MyObject.myBtnClicked(ev); }
this.nBody.appendChild(nBtn);
nBtn=null;
}

Après pour le nettoyage des instances de MyObject,
nous n'avons pas le reste du code.

Pour ce qui est de la cochonnerie, excuse moi mais le "that"
pour conserver un this en closure, ... hum hum. ;-)

A+
Bol
Avatar
Mickaël Wolff
Bol a écrit :

Après pour le nettoyage des instances de MyObject,
nous n'avons pas le reste du code.

Pour ce qui est de la cochonnerie, excuse moi mais le "that"
pour conserver un this en closure, ... hum hum. ;-)



Moi non plus ça ne me plaisait pas au début, et finalement je me suis
dit que ce n'était pas si mal que ça. Bon d'accord, la variable n'a pas
un nom très explicite.

Si tu as mieux je suis preneur.

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org