[résolu] Déclencher un évènement onchange dans un script

HTML5, CSS3, Javascript, support des mobiles... Que penser de votre site ? Vous manquez d'informations pour la construction d'un site qui puisse s'afficher correctement partout ? C'est un problème simple, un peu complexe ? Venez ici !
calimo
Animal mythique
Messages : 14118
Inscription : 26 déc. 2003, 11:51

[résolu] Déclencher un évènement onchange dans un script

Message 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 :-P

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 :oops:
Edit2: a->e, merci Myahoo
Dernière modification par calimo le 25 janv. 2007, 16:56, modifié 2 fois.
myahoo
Animal mythique
Messages : 8279
Inscription : 02 sept. 2005, 00:13

Re: Déclancher un évènement onchange dans un script

Message par myahoo »

calimo a écrit :Edit: majuscule mal placée :oops:
Il reste aussi un petit souci de déclenchement :P

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
calimo
Animal mythique
Messages : 14118
Inscription : 26 déc. 2003, 11:51

Message 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 :lol: )

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
Asumbaa
Tyrannosaurus Rex
Messages : 2411
Inscription : 08 déc. 2004, 20:07

Message 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
martin
Varan
Messages : 1074
Inscription : 21 janv. 2004, 16:23

Message 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 :

Code : Tout sélectionner

function myFunction() {
 alert(this.id);
}
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) :

Code : Tout sélectionner

myFunction.call(other_field, e);
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...
arno. sans ses cookies

Re: Déclancher un évènement onchange dans un script

Message 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 :-P
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.
calimo
Animal mythique
Messages : 14118
Inscription : 26 déc. 2003, 11:51

Message 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
  1. 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)
  2. Un select peut activer un ou plusieurs champs (toujours avec des noms extrêmement divers et variés :lol: )

    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
  3. Dans certains cas je veux que ça active si n'importe quoi est choisi, et pas juste "Autre"
:lol:
Mais restons dans un cas simple :D

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é). :wink:

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 :wink:
Dernière modification par calimo le 25 janv. 2007, 16:57, modifié 1 fois.
arno.
Varan
Messages : 1347
Inscription : 19 août 2004, 12:26

Message 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 :

Code : Tout sélectionner

    if (selected_option == 'o') 
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.
calimo
Animal mythique
Messages : 14118
Inscription : 26 déc. 2003, 11:51

Message 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 :

Code : Tout sélectionner

    if (selected_option == 'o') 
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 :roll:
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
Benoit
Administrateur
Messages : 4894
Inscription : 19 juil. 2003, 10:59

Message 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);
♫ Li tens s'en veit, je n'ai riens fais ;
Li tens revient, je ne fais riens. ♪
calimo
Animal mythique
Messages : 14118
Inscription : 26 déc. 2003, 11:51

Message 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. :shock: :lol:

Bon, malheureusement, ça n'a pas l'air d'avoir d'effet :oops:

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 :wink:

Message envoyé avec : Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8.1) Gecko/20061010 Firemarsupilami Firefox/2.0
Dernière modification par calimo le 25 janv. 2007, 16:58, modifié 1 fois.
arno.
Varan
Messages : 1347
Inscription : 19 août 2004, 12:26

Message 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 :shock:
calimo
Animal mythique
Messages : 14118
Inscription : 26 déc. 2003, 11:51

Message par calimo »

Ah ouais :shock:

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 :roll:

En tous cas merci d'avoir pris le temps de tester, ça fonctionne ! :D (pas avec le .onchange mais le dispatchEvent fonctionne bien). :wink:

Message envoyé avec : Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8.1) Gecko/20061010 Firemarsupilami Firefox/2.0
Benoit
Administrateur
Messages : 4894
Inscription : 19 juil. 2003, 10:59

Message 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".
♫ Li tens s'en veit, je n'ai riens fais ;
Li tens revient, je ne fais riens. ♪
martin
Varan
Messages : 1074
Inscription : 21 janv. 2004, 16:23

Message 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.
Répondre

Qui est en ligne ?

Utilisateurs parcourant ce forum : Aucun utilisateur inscrit et 5 invités