Page 1 sur 2
[résolu] Déclencher un évènement onchange dans un script
Publié : 07 déc. 2006, 15:27
par calimo
Bonjour tout le monde !
J'ai le script suivant:
Code : Tout sélectionner
var select = document.getElementById('select');
select.setAttribute('onchange', 'javascript:DisableEnable(this)');
function DisableEnable(select) {
var selected_option = select.options[select.selectedIndex].value;
var other_field = document.getElementById('other_field');
if (selected_option == 'o') {
other_field.removeAttribute('disabled');
}
else {
other_field.setAttribute('disabled', 'disabled');
}
}
Lorsque mon <select id='select'> change et que l'utilisateur sélectionne l'option "Other" (valeur 'o', O minuscule), le champ avec l'id="other_field" est activé, sinon il est désactivé.
Maintenant, si ce champ est lui-même un <select> qui contient un 'other' sur un autre champ (c'est tordu mais c'est comme ça), et si ce champ était justement sur 'other' avec son champ other (appelons-le field_other_other) activé, et que je change le premier champ, field_other est bien désactivé, mais malheureusement field_other_other, lui, reste activé.
Je ne sais pas si vous m'avez suivi... j'espère
J'aimerais donc pouvoir déclencher un évènement onchange sur field_other afin de récurser et désactiver aussi field_other_other.
J'ai donc essayé de faire other_field.onchange mais ça ne fonctionne pas (pas de message d'erreur non plus, visiblement).
Ma question est donc : y a-t-il un moyen de déclencher un onchange dans un script, sans intervention de l'utilisateur ?
Question subsidiaire : pourquoi est-ce que
Code : Tout sélectionner
select_element.addEventListener('change', DisableEnable(select), false);
ne fonctionne pas à la place du setAttribute('onchange', ...) ?
Merci
Message envoyé avec : Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8.0.8) Gecko/20061025 Firefox/1.5.0.8
Edit: majuscule mal placée

Edit2: a->e, merci Myahoo
Re: Déclancher un évènement onchange dans un script
Publié : 07 déc. 2006, 18:28
par myahoo
calimo a écrit :Edit: majuscule mal placée

Il reste aussi un petit souci de décl
enchement
Il n'y aurait pas possibilité d'utiliser une autre fonction, comme
onClick ?
Message envoyé avec : Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.1) Gecko/20061010 Firefox/2.0
Publié : 08 déc. 2006, 08:50
par calimo
Non, ça s'applique sur un select et on peut le changer à la souris, mais également ou au clavier (ou grâce à n'importe quel autre dispositif qui pourrait être inventé à l'avenir permettant de changer une sélection

)
Je pourrais doubler du onclick et du onkeypress mais ça ne changerait probablement rien au problème, non ?
Message envoyé avec : Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8.0.8) Gecko/20061025 Firefox/1.5.0.8
Publié : 08 déc. 2006, 10:13
par Asumbaa
Salut Calimo,
Pourquoi ne pas compléter ta fonction en la rendant récursive ? Sur ton élément à disabler (miam, le néologisme), tu regardes si c'est un select avec option "autre", si oui tu relances ta fonction dessus ?
Message envoyé avec : Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.1) Gecko/20061010 Firefox/2.0
Publié : 08 déc. 2006, 12:17
par martin
déjà, un peu de formulation :
Tu peux effectivement utiliser un setAttribute pour ajouter un évènement onchange, mais je trouve plus simple (concis) d'utiliser la propriété onchange de l'élément :
Code : Tout sélectionner
var select = document.getElementById('select');
select.onchange = myFunction;
function myFunction(e) {
...
}
L'autre formulation possible est effectivement de passer par addEventListener, qui permet d'avoir plusieurs actions enregistrées plutôt qu'une seule (attention, pour IE il faut passer par attachEvent) :
Code : Tout sélectionner
var select = document.getElementById('select');
select.addEventListener('change', 'myFunction', false);
function myFunction(e) {
...
}
Le scope lors de l'appel à myFunction via l'événement onchange est tel que this représente l'élément select, et non l'objet window. La variable e contient l'event (pas pour IE, mais récupérable quand même si besoin est).
exemple :
affichera 'select';
Sinon tu peux vérifier dans ta fonction si other_field est un autre élément select ( if (other_field.tagName.toLowerCase()=='select' ), si oui tu traites ce cas en vérifiant de nouveau sa value, et tu désactives les 2 (other_field et other_other_fied).
Tu dois sinon effectivement pouvoir faire du récursif, comme te le propose Asumbaa, si other_field est un select, tu lui applique myFunction, mais en passant par call() pour lui indiquer le bon scope (la bonne valeur de this) :
mais il faut se débrouiller pour lui passer l'id du champ à vérifier... par exemple prévoir un argument optionel.
ps: la variable e n'est pas forcément nécessaire dans ces exemples, si tu n'as besoin de traiter d'infos sur l'événement déclencheur.
ps2 vérifie les nom de méthodes sur devmo, je te file çà de mémoire...
Re: Déclancher un évènement onchange dans un script
Publié : 08 déc. 2006, 13:03
par arno. sans ses cookies
calimo a écrit :
Maintenant, si ce champ est lui-même un <select> qui contient un 'other' sur un autre champ (c'est tordu mais c'est comme ça), et si ce champ était justement sur 'other' avec son champ other (appelons-le field_other_other) activé, et que je change le premier champ, field_other est bien désactivé, mais malheureusement field_other_other, lui, reste activé.
Je ne sais pas si vous m'avez suivi... j'espère
T'as pas un exemple ??
Parceque là, j'ai rien compris
Ma question est donc : y a-t-il un moyen de déclancher un onchange dans un script, sans intervention de l'utilisateur ?
Au pif :
createEvent, dispatchEvent
Question subsidiaire : pourquoi est-ce que
Code : Tout sélectionner
select_element.addEventListener('change', DisableEnable(select), false);
ne fonctionne pas à la place du setAttribute('onchange', ...) ?
Le deuxième argument de addEventListener ça doit être une fonction je crois. Là, tu appelles le résultat, et tu passes le résultat de cet appel comme argument.
Publié : 09 déc. 2006, 11:39
par calimo
En gros, lorsque dans le premier select je sélectionne "Autre", le deuxième est activé. Idem, lorsque je sélectionne "Autre" dans le deuxième, le champ en-dessous est activé.
Maintenant, choisissez "autre" dans les premiers et deuxième selects
le dernier champ est activé.
Changez d'avis et remettez une autre option dans le premier champ. Le deuxième se désactive, et j'aimerais bien que le troisième fasse de même !
En fait, c'est plus compliqué que ça, car
- Dans une "vraie" page, j'ai plusieurs selects pouvant déclancher l'activation d'autres champs (donc ils ont évidemment tous des noms différents) sans relation entre eux (le champ A peut activer B et C activer D sans qu'il n'y ait de relation entre A ou B et C et D, bien qu'il peut y en avoir dans certains cas)
- Un select peut activer un ou plusieurs champs (toujours avec des noms extrêmement divers et variés
)
J'ai donc une grosse fonction usine à gaz qui prend une grosse structure de données sous forme de tableau associatif, avec le champ et les champs à activer/désactiver, et non pas les champs eux-mêmes - Dans certains cas je veux que ça active si n'importe quoi est choisi, et pas juste "Autre"
Mais restons dans un cas simple
Le plus simple, pour moi, serait de pouvoir déclancher un évènement "onchange" sur le deuxième select, exactement comme si l'utilisateur avait d'abord désactivé le deuxième select avant de le faire pour le premier. Ainsi, la désactivation serait automatiquement propagée.
Dans cet exemple, je pourrais appeler la fonction DisableEnable au lieu du onchange, mais comme je l'ai dit plus tôt, je passe une grosse structure de données, donc ce n'est pas possible simplement (je pourrais le faire mais disons que c'est beaucoup plus compliqué).
J'ai regardé create/dispatchEvent, ça m'a l'air terriblement compliqué, mais je vais essayer quand-même. Je vais voir aussi si ce que propose martin peut être utilisé
Merci pour votre aide !
Message envoyé avec : Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8.1) Gecko/20061010 Firedragon Firefox/2.0
PS : ce serait bien que ça fonctionne pour IE aussi, mais je verrai ça plus tard, ce n'est pas le plus important

Publié : 09 déc. 2006, 12:06
par arno.
J'ai pas le temps de regarder ton truc à fond, donc ptêt que je dis des énormes bêtises, mais :
Maintenant, choisissez "autre" dans les premiers et deuxième selects
le dernier champ est activé.
Changez d'avis et remettez une autre option dans le premier champ. Le deuxième se désactive, et j'aimerais bien que le troisième fasse de même !
Code : Tout sélectionner
if (select.id == 'field') {
other_field = document.getElementById('other_field');
}
else if (select.id == 'other_field') {
other_field = document.getElementById('other_other_field');
}
if (selected_option == 'o') {
other_field.removeAttribute('disabled');
}
else {
other_field.setAttribute('disabled', 'disabled');
other_field.selectedIndex = '';
other_field.onchange;
}
admettons que tu appelles DisableEnable avec "other_field" comme argument :
tu vas avoir : other_field = other_other_field
tu vas appeler DisableEnable(other_other_filed) ;
=>
var selected_option = select.options[select.selectedIndex].value
ça va bloquer !
autre chose :
other_field sera désactivé, mais quelle sera la valeur de selected_option ? Est-ce que tu as testé ?
Enfin bref, tout ça pour dire qu'il y a peut-être un problème d'algorithme avant toute chose.
Cela dit, je répète : j'ai regardé vite fait. C'est possible que j'écrive des bêtises.
Publié : 09 déc. 2006, 15:58
par calimo
arno. a écrit :admettons que tu appelles DisableEnable avec "other_field" comme argument :
tu vas avoir : other_field = other_other_field
tu vas appeler DisableEnable(other_other_filed) ;
=>
var selected_option = select.options[select.selectedIndex].value
ça va bloquer !
Oui, je teste select.options, je pense au bon endroit. Mais bon, c'est un test minimal qui essaye d'être plus ou moins lisible (ce n'est pas trop mon fort, mais j'essaye de m'appliquer).
Je répète (ou je précise si j'ai oublié de le dire ?) il n'y a aucun message dans la console d'erreurs (donc j'en déduis que le problème ne vient pas de là).
autre chose :
other_field sera désactivé, mais quelle sera la valeur de selected_option ? Est-ce que tu as testé ?[/quote]Bonne question. Mais en fait c'est pareil si je mets other_field.selectedIndex = '' avant other_field.setAttribute
arno. a écrit :Enfin bref, tout ça pour dire qu'il y a peut-être un problème d'algorithme avant toute chose.
Oui, c'est très possible, mais où ?
C'est pas faute d'avoir essayé de retourner le problème dans tous les sens, mais je ne vois pas comment faire mieux.
Message envoyé avec : Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8.1) Gecko/20061010 Firelimace Firefox/2.0
Publié : 09 déc. 2006, 19:32
par Benoit
calimo a écrit :J'ai regardé create/dispatchEvent, ça m'a l'air terriblement compliqué, mais je vais essayer quand-même. Je vais voir aussi si ce que propose martin peut être utilisé

À priori, c'est pas si compliqué.
Code : Tout sélectionner
// Crée un évènement HTML
var evt = document.createEvent("HTMLEvents");
// L'initialise à la valeur "change", avec les valeurs par défaut
evt.initEvent("change", true, false);
// L'envoie au champ "other_field"
other_field.dispatchEvent(evt);
Publié : 09 déc. 2006, 19:51
par calimo
Mouais, c'est quand-même tordu, savoir s'il faut mettre des true ou des false sur les bubbles et les cancelable, etc.
Bon, malheureusement, ça n'a pas l'air d'avoir d'effet
Toujours au même endroit (il faudra probablement faire un Ctrl+F5 ou Maj+Actualiser).
Et surtout toujours pas le moindre message d'erreur (un alert indique que ça passe bien au bon endroit, mais rien de plus

)
Merci quand-même
Message envoyé avec : Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8.1) Gecko/20061010 Firemarsupilami Firefox/2.0
Publié : 09 déc. 2006, 20:35
par arno.
Intéressant
On dirait que quand l'élément est désactivé, le onchange ne peut plus marcher.
mets l'instruction :
other_field.setAttribute('disabled', 'disabled');
à la fin de ton bloc else : tu verras, c'est surpenantifiant

Publié : 09 déc. 2006, 21:08
par calimo
Ah ouais
Vous pensez que ça pourrait être un bug ? Ou bien un corollaire de
# les commandes inactives ne reçoivent pas l'attention ;
?
http://www.la-grange.net/w3c/html4.01/i ... f-disabled
En tous cas merci d'avoir pris le temps de tester, ça fonctionne !

(pas avec le .onchange mais le dispatchEvent fonctionne bien).
Message envoyé avec : Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8.1) Gecko/20061010 Firemarsupilami Firefox/2.0
Publié : 09 déc. 2006, 22:34
par Benoit
J'ai pas beaucoup pris part à la discussion, mais en général il faut se rappeler que les propriétés DOM sont différentes des attributs. C'est notamment flagrant quand on parle des styles, mais je pense que c'est pareil pour les évènements.
Quand tu parles d'un évènement ou d'une fonction "onchange", c'est une hérésie. L'
évènement DOM c'est "change". C'est comme pour l'attribut "onclick", ça spécifie ce qu'il faut faire lors de l'élément "click", mais il n'y a pas une fonction "onclick".
Publié : 10 déc. 2006, 16:25
par martin
Je me permet de rajouter quelque chose malgré le [résolu] ajouté au titre.
Franchement je ne vois pas pourquoi il faudrait passer par la création d'un évènement avec createEvent et dispatchEvent.
Il suffit d'associer un comportement à l'évènement déclenché par l'utilisateur, il est bien suffisant, pas besoin d'en générer de nouveau.
En fait tu veux associer une contrainte à chaque élément du formulaire, et que si un élément change, les contraintes soit appliquées en cascade.
Pourquoi pas établir çà en javascript. Exemple un élément select_1 impose un changement d'un élément select_2, qui lui impose un changement d'un input_1. Récupérons ces éléments, et créons leur une propriété contrainte ciblant un autre élément :
Code : Tout sélectionner
var select_1 = document.getElementById('select_1');
var select_2 = document.getElementById('select_2');
var input_1 = document.getElementById('input_1');
select_1.contrainte = select_2;
select_2.contrainte = input_1;
ensuite on défini une fonction qui applique les changements :
Code : Tout sélectionner
function appliqueContrainte(e, src) {
if (!src) src = this;
// on teste ce qu'on veut, par exemple src.id,
// et on fait les changements voulus
if (src.value == 'ceci') {
} else {
}
// si il existe une contrainte suivante, on l'applique
if (src.contrainte) appliqueContrainte(e, src.contrainte);
}
et on associe cette fonction à l'événement change des select :
Code : Tout sélectionner
select_1.addEventListener('change', 'appliqueContrainte', false);
select_2.addEventListener('change', 'appliqueContrainte', false);
note: la variable e est indiqué en variable dans appliqueContrainte, car Firefox va effectivement y mettre l'événement déclencheur, même si on ne s'en sert pas.