Précédent   Forum des professionnels en informatique > Webmasters - Développement Web > JavaScript > Bibliothèques & Frameworks > jQuery
jQuery Forum d'entraide sur le framework jQuery. Avant de poster : Tutoriels jQuery, FAQ jQuery, Tous les tutoriels JavaScript, Toutes les FAQ JavaScript
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 18/02/2012, 18h22   #1
Membre habitué
 
Inscription : décembre 2008
Messages : 207
Détails du profil
Informations forums :
Inscription : décembre 2008
Messages : 207
Points : 121
Points : 121
Par défaut Fausse portée de variable

Bonjour,

Présentation du code :

Le code suivant tente d'utiliser plusieurs instances de JStree (http://www.jstree.com/) afin d'offrir une multi-sélection arborescente.
Chaque liste déroulante est dissimulée puis remplacée visuellement par un simple bouton.
Ce bouton permet d'ouvrir une boîte de dialogue (jqueryUI) qui contient l'arbre JStree.
Chaque JStree est/doit-être indépendant afin que chaque sélection le soit.
La liste d'option des listes déroulantes dépend de la valeur d'un select, et est mise à jour lors d'un changement de cette valeur via AJAX (toutes les sélections ont les même options).
Une fois la sélection effectuée, la validation via UIdialog affecte la valeur au select correspondant dissimulé et change le texte du bouton.

Problème :

Peu importe le bouton sélectionné, ce sera toujours le dernier qui sera affecté (et son select associé).

Tentatives de résolutions :

J'ai essayé d'affecter bouton et arbre dans les data des select.
J'ai essayé de créer un tableau déclaré hors fonction ( select[] ) afin d'y accéder par l'index ( select[i] )

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
$( function(){
 
	first_id = $("*[name*=product_id]").val();
 
	$("select[name*=product_data_id]").each( function(i,serie){
 
		$(serie).data("treeParams", {
			"plugins" : [ "themes", "xml_data", "ui", "checkbox" ],
			"themes" : {
				"theme" : "default",
				"dots" : true
			},
			"core" : {
				"animation": 1
			},
			"xml_data" : {
				"data" : ""
			},
			"ui": {
				"select_multiple_modifier" : "ctrl",
				"disable_selecting_children" : false
			},
			"checkbox": {
				"two_state": true,
				"override_ui": true
			}
		});
 
		button = $('<input type="button" id="b'+i+'" />');
		$(serie).data("button",button);
		val = $(serie).val();
		text = $(serie).find("option:selected").text();
 
		$(serie).hide();
		button.insertAfter($(serie));
 
		if(val == null){
			button.val("Codes produit");
		} else {
 
			if(val.length == 1) {
 
				button.val(text);
				$(serie).data("treeParams").ui.initially_select = val;
 
			} else {
 
				button.val(val.length + " codes sélectionnés");
				$(serie).data("treeParams").ui.initially_select = val;
			}
		}
 
		dialog_tree = $('<div class="dialogTree"/>');
		$('body').append(dialog_tree);
 
		dialog_tree.dialog({
			resizable: true,
			width: 400,
			modal: true,
			autoOpen: false,
			buttons: {
				"Déselectionner tout": function(){
					tree.deselect_all();
					tree.uncheck_all();
					$(serie).val('');
					button.val("Codes produit");
				},
				"Sélectionner": function() {
					if(tree.get_checked().length > 0){
 
						var values = [];
						tree.get_checked().each(function(key,row){
							values.push($(row).attr('id'));
						});
						$(serie).val(values);
 
						if(tree.get_checked(null,true).length == 1){
							button.val($.trim(tree.get_checked().text()));
						} else {
							button.val(tree.get_checked(null,true).length + " codes sélectionnés");
						}
 
						$(this).dialog("close");
					}
				},
				"Fermer": function() {
					$(this).dialog("close");
				}
			},
			open: function(){
 
				if(!$(serie).data("loaded")){
 
					dialog_tree.bind("loaded.jstree", function (event, data) {
						tree = data.inst;
						tree.open_all();
						$(serie).data("loaded",true);
 
					    dialog_tree.find("ul a").dblclick(function(){
 
							toggleState = function(nodes,checked){
								tree.change_state(nodes,checked);
								nodes.each( function(key, row){
									toggleState(tree._get_children(row),checked);
								});
							};
 
							node = tree._get_node(this);
							checked = tree.is_checked(node);
							toggleState(node,checked);
							return false;
						});
				    });
 
					dialog_tree.jstree($(serie).data("treeParams"));
				}
			}
		});
 
		button.click( function(){
			dialog_tree.dialog("open");
		});
 
 
	});
 
 
	$("*[name*=product_id]").change( function(){
 
		$.ajax({
			async: false,
			url : "<?php echo $this->url(array('controller'=>'product_data','action'=>'tree'),null,true,null,true) ?>",
			data : {
				product_id : $(this).val()
			},
			success : function(json){
				$("select[name*=product_data_id]").each( function(){
					tmp = $(this).data("treeParams");
					tmp.xml_data.data = json.xml;
					$(this).data("treeParams",tmp);
				});
			},
			dataType : "json"
		});
 
		$("select[name*=product_data_id]").each( function(){
 
			if(!$(this).data("treeParams").ui.initially_select){
				$(this).data("button").val("Codes produit");
				$(this).val(0);
			} else {
 
				if($(this).val() != first_id){
					tmp = $(this).data("treeParams");
					delete tmp.ui.initially_select;
					$(this).data("treeParams",tmp);
					$(this).data("button").val("Codes produit");
					$(this).val(0);
				}
			}
 
			$("div.dialogTree").jstree("destroy");
			$(this).data("loaded",false);
 
		});
 
	}).change();
 
});
Le code HTML de base étant :

Code :
1
2
3
4
5
6
7
8
<select name="serie[1][product_data_id][]" multiple="multiple">
	<option value="1">Foo</option>
	<option value="2">Bar</option>
</select>
<select name="serie[2][product_data_id][]" multiple="multiple">
	<option value="1">Foo</option>
	<option value="2">Bar</option>
</select>

Je ne comprends pas pourquoi mon code ne fonctionne pas, et j'imagine que c'est une histoire de portée des variables déclarées, comme si chaque bouton & select variabilisé (on se comprend ?) avait pour référence le dernier.
Feng-Huang est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2012, 19h37   #2
Rédacteur
 
Avatar de danielhagnoul
 
Homme Daniel Hagnoul
Étudiant perpétuel
Inscription : février 2009
Messages : 3 221
Détails du profil
Informations personnelles :
Nom : Homme Daniel Hagnoul
Âge : 61
Localisation : Belgique

Informations professionnelles :
Activité : Étudiant perpétuel
Secteur : Enseignement

Informations forums :
Inscription : février 2009
Messages : 3 221
Points : 6 767
Points : 6 767
Bonsoir

Code complexe, incomplet pour un test et je manque de temps.

Je dis incomplet parce que : var first_id = $("*[name*='product_id']").val(); ne correspond à rien dans l'extrait de code. Il y a d'autres variables non déclarées dans l'extrait de code.

Remarque : [name*='product_data_id'].
http://api.jquery.com/attribute-contains-selector/ : la valeur doit être un texte !
__________________

FAQ jQuery

Mon cahier d’exercices sur jQuery & Co

Si un message vous a aidé ou vous semble pertinent, votez pour lui !
danielhagnoul est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/02/2012, 16h26   #3
Membre habitué
 
Inscription : décembre 2008
Messages : 207
Détails du profil
Informations forums :
Inscription : décembre 2008
Messages : 207
Points : 121
Points : 121
Je joins une archive qui permet le test. J'ai également commenté le code pour qu"il soit plus accessible.

Concernant votre/ta (puis-je ?) remarque, la sélection fonctionne et retour le jeu de DOM attendu.
Fichiers attachés
Type de fichier : zip jstree.zip (170,0 Ko, 3 affichages)
Feng-Huang est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/02/2012, 21h46   #4
Rédacteur
 
Avatar de danielhagnoul
 
Homme Daniel Hagnoul
Étudiant perpétuel
Inscription : février 2009
Messages : 3 221
Détails du profil
Informations personnelles :
Nom : Homme Daniel Hagnoul
Âge : 61
Localisation : Belgique

Informations professionnelles :
Activité : Étudiant perpétuel
Secteur : Enseignement

Informations forums :
Inscription : février 2009
Messages : 3 221
Points : 6 767
Points : 6 767
Bonsoir

Citation:
Concernant ta remarque, la sélection fonctionne et retour le jeu de DOM attendu.
Dans ce cas oui, mais il n'est pas raisonnable de compter sur "la bonne volonté" d'un programme pour faire le travail à sa place. Il vaut mieux adopter les bonnes méthodes par défaut.

Je disais aussi :
Citation:
Il y a d'autres variables non déclarées dans l'extrait de code.
C'est l'origine du problème.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
<!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>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<link href="css/jquery-ui-1.8.16.custom.css" rel="stylesheet" type="text/css" />
	<script type="text/javascript" src="js/jquery-1.5.2.min.js"></script>
	<script type="text/javascript" src="js/jquery-ui-1.8.16.custom.min.js"></script>
	<script type="text/javascript" src="js/jquery.jstree.js"></script>
	<script type="text/javascript">
	$( function(){
 
		var first_id = $("*[name*='product_id']").val(); // On stock la valeur d'origine
 
		$("select[name*='product_data_id']").each( function(i,serie){
 
			$(serie).data("treeParams", {
				"plugins" : [ "themes", "xml_data", "ui", "checkbox" ],
				"themes" : {
					"theme" : "default",
					"dots" : true
				},
				"core" : {
					"animation": 1
				},
				"xml_data" : {
					"data" : ""
				},
				"ui": {
					"select_multiple_modifier" : "ctrl",
					"disable_selecting_children" : false
				},
				"checkbox": {
					"two_state": true,
					"override_ui": true
				}
			}); // On associé les paramètres de l'arbre dans les data du select, pour individualiser l'arbre, et notamment les sélections qu'il contient
 
 
			// On remplace visuellement la liste déroulante par le bouton qui servira à ouvrir le UIDialog
 
			var button = $('<input type="button" id="b'+i+'" />');
 
			$(serie).data("button",button);
 
			var val = $(serie).val();
			var text = $(serie).find("option:selected").text();
 
			$(serie).hide();
			button.insertAfter($(serie));
 
			// On adapte le texte du bouton en fonction de la sélection initiale (HTML d'origine donc)
			if(val == null){
				button.val("Codes produit");
			} else {
 
				if(val.length == 1) {
 
					button.val(text);
					$(serie).data("treeParams").ui.initially_select = val;
 
				} else {
 
					button.val(val.length + " codes sélectionnés");
					$(serie).data("treeParams").ui.initially_select = val;
				}
			}
 
			// - //
 
 
			// On créé la boîte de dialogue
			var dialog_tree = $('<div class="dialogTree"/>');
 
			$('body').append(dialog_tree);
 
			var tree = null;
 
			dialog_tree.dialog({
				resizable: true,
				width: 400,
				modal: true,
				autoOpen: false,
				buttons: {
					"Déselectionner tout": function(){
 
						// On réinitialise le select (dissimulé) et le bouton d'ouverture du UIdialog
						tree.uncheck_all();
						$(serie).val('');
						button.val("Codes produit");
					},
					"Sélectionner": function() {
						if(tree.get_checked().length > 0){
 
							// On met à jour la valeur du select (dissimulé) et le texte du bouton d'ouverture du UIdialog
							var values = [];
							tree.get_checked().each(function(key,row){
								values.push($(row).attr('id'));
							});
							$(serie).val(values);
 
							if(tree.get_checked(null,true).length == 1){
								button.val($.trim(tree.get_checked().text()));
							} else {
								button.val(tree.get_checked(null,true).length + " codes sélectionnés");
							}
 
							$(this).dialog("close");
						}
					},
					"Fermer": function() {
						$(this).dialog("close");
					}
				},
				open: function(){
 
					// Pour éviter de sucer la mémoire du client, je ne génère le JStree que si le UIdialog est ouvert, je vérifie donc qu'il n'est pas instancié
					if(!$(serie).data("loaded")){
 
						dialog_tree.bind("loaded.jstree", function (event, data) {
 
							// null !
							//console.log( tree );
 
							// c'est ici que l'on initialise tree !
							tree = data.inst;
 
							tree.open_all();
							$(serie).data("loaded",true);
 
						    dialog_tree.find("ul a").dblclick(function(){ // Petit hack pour permet la sélection récursive lors d'un double clic sur un élément de l'arbre
 
								toggleState = function(nodes,checked){
									tree.change_state(nodes,checked);
									nodes.each( function(key, row){
										toggleState(tree._get_children(row),checked);
									});
								};
 
								node = tree._get_node(this);
								checked = tree.is_checked(node);
								toggleState(node,checked);
								return false;
							});
					    });
 
						dialog_tree.jstree($(serie).data("treeParams")); // On instancie le JStree
					}
				}
			});
 
			button.click( function(){
				dialog_tree.dialog("open");
			});
 
 
		});
 
 
		$("*[name*='product_id']").change( function(){
 
			$.ajax({ // Récupération des nouvelles options des select et donc des JStree (Un seul jeu de donnée est disponible pour ce test)
				async: false,
				url : "jstree.xml",
				data : {
					product_id : $(this).val()
				},
				success : function(xml){
					$("select[name*=product_data_id]").each( function(){
						tmp = $(this).data("treeParams");
						tmp.xml_data.data = xml;
						$(this).data("treeParams",tmp);
					});
				},
				dataType : "text"
			});
 
			$("select[name*='product_data_id']").each( function(){
 
				// On supprime (si existant) la sélection initiale stockée dans les data des select
 
				if(!$(this).data("treeParams").ui.initially_select){
 
					$(this).data("button").val("Codes produit");
					$(this).val(0);
 
				} else {
 
					if($(this).val() != first_id){
						var tmp = $(this).data("treeParams");
						delete tmp.ui.initially_select;
 
						$(this).data("treeParams",tmp);
						$(this).data("button").val("Codes produit");
						$(this).val(0);
					}
				}
 
				$("div.dialogTree").jstree("destroy"); // Destructions des arbres JStree pour libérer la mémoire et qui par la même bénéficieront de la mise à jour des données lors de leur nouvelle instanciation si il y a
				$(this).data("loaded",false);
 
			});
 
		}).change();
 
	});
	</script>
</head>
<body>
 
	<select name="product_id">
		<option value="122">DURAND Services</option>
	</select>
 
	<select name="serie[1][product_data_id][]" multiple="multiple">
		<option value="1">Foo</option>
		<option value="2">Bar</option>
	</select>
	<select name="serie[2][product_data_id][]" multiple="multiple">
		<option value="1">Foo</option>
		<option value="2">Bar</option>
	</select>
 
</body>
</html>
__________________

FAQ jQuery

Mon cahier d’exercices sur jQuery & Co

Si un message vous a aidé ou vous semble pertinent, votez pour lui !
danielhagnoul est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/02/2012, 22h54   #5
Membre habitué
 
Inscription : décembre 2008
Messages : 207
Détails du profil
Informations forums :
Inscription : décembre 2008
Messages : 207
Points : 121
Points : 121
Aaaaarrrffff, j'avais oublié : pas de déclaration = global scope. Damn it !

Et bien merci, ça m'apprendra à lire en diagonale !
Feng-Huang est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 02h11.


 
 
 
 
Partenaires

Hébergement Web