danielebarchiesi@0
|
1 /**
|
danielebarchiesi@0
|
2 * @file
|
danielebarchiesi@0
|
3 * Provides dependent visibility for form items in CTools' ajax forms.
|
danielebarchiesi@0
|
4 *
|
danielebarchiesi@0
|
5 * To your $form item definition add:
|
danielebarchiesi@0
|
6 * - '#process' => array('ctools_process_dependency'),
|
danielebarchiesi@0
|
7 * - '#dependency' => array('id-of-form-item' => array(list, of, values, that,
|
danielebarchiesi@0
|
8 * make, this, item, show),
|
danielebarchiesi@0
|
9 *
|
danielebarchiesi@0
|
10 * Special considerations:
|
danielebarchiesi@0
|
11 * - Radios are harder. Because Drupal doesn't give radio groups individual IDs,
|
danielebarchiesi@0
|
12 * use 'radio:name-of-radio'.
|
danielebarchiesi@0
|
13 *
|
danielebarchiesi@0
|
14 * - Checkboxes don't have their own id, so you need to add one in a div
|
danielebarchiesi@0
|
15 * around the checkboxes via #prefix and #suffix. You actually need to add TWO
|
danielebarchiesi@0
|
16 * divs because it's the parent that gets hidden. Also be sure to retain the
|
danielebarchiesi@0
|
17 * 'expand_checkboxes' in the #process array, because the CTools process will
|
danielebarchiesi@0
|
18 * override it.
|
danielebarchiesi@0
|
19 */
|
danielebarchiesi@0
|
20
|
danielebarchiesi@0
|
21 (function ($) {
|
danielebarchiesi@0
|
22 Drupal.CTools = Drupal.CTools || {};
|
danielebarchiesi@0
|
23 Drupal.CTools.dependent = {};
|
danielebarchiesi@0
|
24
|
danielebarchiesi@0
|
25 Drupal.CTools.dependent.bindings = {};
|
danielebarchiesi@0
|
26 Drupal.CTools.dependent.activeBindings = {};
|
danielebarchiesi@0
|
27 Drupal.CTools.dependent.activeTriggers = [];
|
danielebarchiesi@0
|
28
|
danielebarchiesi@0
|
29 Drupal.CTools.dependent.inArray = function(array, search_term) {
|
danielebarchiesi@0
|
30 var i = array.length;
|
danielebarchiesi@0
|
31 while (i--) {
|
danielebarchiesi@0
|
32 if (array[i] == search_term) {
|
danielebarchiesi@0
|
33 return true;
|
danielebarchiesi@0
|
34 }
|
danielebarchiesi@0
|
35 }
|
danielebarchiesi@0
|
36 return false;
|
danielebarchiesi@0
|
37 }
|
danielebarchiesi@0
|
38
|
danielebarchiesi@0
|
39
|
danielebarchiesi@0
|
40 Drupal.CTools.dependent.autoAttach = function() {
|
danielebarchiesi@0
|
41 // Clear active bindings and triggers.
|
danielebarchiesi@0
|
42 for (i in Drupal.CTools.dependent.activeTriggers) {
|
danielebarchiesi@0
|
43 $(Drupal.CTools.dependent.activeTriggers[i]).unbind('change');
|
danielebarchiesi@0
|
44 }
|
danielebarchiesi@0
|
45 Drupal.CTools.dependent.activeTriggers = [];
|
danielebarchiesi@0
|
46 Drupal.CTools.dependent.activeBindings = {};
|
danielebarchiesi@0
|
47 Drupal.CTools.dependent.bindings = {};
|
danielebarchiesi@0
|
48
|
danielebarchiesi@0
|
49 if (!Drupal.settings.CTools) {
|
danielebarchiesi@0
|
50 return;
|
danielebarchiesi@0
|
51 }
|
danielebarchiesi@0
|
52
|
danielebarchiesi@0
|
53 // Iterate through all relationships
|
danielebarchiesi@0
|
54 for (id in Drupal.settings.CTools.dependent) {
|
danielebarchiesi@0
|
55 // Test to make sure the id even exists; this helps clean up multiple
|
danielebarchiesi@0
|
56 // AJAX calls with multiple forms.
|
danielebarchiesi@0
|
57
|
danielebarchiesi@0
|
58 // Drupal.CTools.dependent.activeBindings[id] is a boolean,
|
danielebarchiesi@0
|
59 // whether the binding is active or not. Defaults to no.
|
danielebarchiesi@0
|
60 Drupal.CTools.dependent.activeBindings[id] = 0;
|
danielebarchiesi@0
|
61 // Iterate through all possible values
|
danielebarchiesi@0
|
62 for(bind_id in Drupal.settings.CTools.dependent[id].values) {
|
danielebarchiesi@0
|
63 // This creates a backward relationship. The bind_id is the ID
|
danielebarchiesi@0
|
64 // of the element which needs to change in order for the id to hide or become shown.
|
danielebarchiesi@0
|
65 // The id is the ID of the item which will be conditionally hidden or shown.
|
danielebarchiesi@0
|
66 // Here we're setting the bindings for the bind
|
danielebarchiesi@0
|
67 // id to be an empty array if it doesn't already have bindings to it
|
danielebarchiesi@0
|
68 if (!Drupal.CTools.dependent.bindings[bind_id]) {
|
danielebarchiesi@0
|
69 Drupal.CTools.dependent.bindings[bind_id] = [];
|
danielebarchiesi@0
|
70 }
|
danielebarchiesi@0
|
71 // Add this ID
|
danielebarchiesi@0
|
72 Drupal.CTools.dependent.bindings[bind_id].push(id);
|
danielebarchiesi@0
|
73 // Big long if statement.
|
danielebarchiesi@0
|
74 // Drupal.settings.CTools.dependent[id].values[bind_id] holds the possible values
|
danielebarchiesi@0
|
75
|
danielebarchiesi@0
|
76 if (bind_id.substring(0, 6) == 'radio:') {
|
danielebarchiesi@0
|
77 var trigger_id = "input[name='" + bind_id.substring(6) + "']";
|
danielebarchiesi@0
|
78 }
|
danielebarchiesi@0
|
79 else {
|
danielebarchiesi@0
|
80 var trigger_id = '#' + bind_id;
|
danielebarchiesi@0
|
81 }
|
danielebarchiesi@0
|
82
|
danielebarchiesi@0
|
83 Drupal.CTools.dependent.activeTriggers.push(trigger_id);
|
danielebarchiesi@0
|
84
|
danielebarchiesi@0
|
85 if ($(trigger_id).attr('type') == 'checkbox') {
|
danielebarchiesi@0
|
86 $(trigger_id).siblings('label').addClass('hidden-options');
|
danielebarchiesi@0
|
87 }
|
danielebarchiesi@0
|
88
|
danielebarchiesi@0
|
89 var getValue = function(item, trigger) {
|
danielebarchiesi@0
|
90 if ($(trigger).size() == 0) {
|
danielebarchiesi@0
|
91 return null;
|
danielebarchiesi@0
|
92 }
|
danielebarchiesi@0
|
93
|
danielebarchiesi@0
|
94 if (item.substring(0, 6) == 'radio:') {
|
danielebarchiesi@0
|
95 var val = $(trigger + ':checked').val();
|
danielebarchiesi@0
|
96 }
|
danielebarchiesi@0
|
97 else {
|
danielebarchiesi@0
|
98 switch ($(trigger).attr('type')) {
|
danielebarchiesi@0
|
99 case 'checkbox':
|
danielebarchiesi@0
|
100 var val = $(trigger).attr('checked') ? true : false;
|
danielebarchiesi@0
|
101
|
danielebarchiesi@0
|
102 if (val) {
|
danielebarchiesi@0
|
103 $(trigger).siblings('label').removeClass('hidden-options').addClass('expanded-options');
|
danielebarchiesi@0
|
104 }
|
danielebarchiesi@0
|
105 else {
|
danielebarchiesi@0
|
106 $(trigger).siblings('label').removeClass('expanded-options').addClass('hidden-options');
|
danielebarchiesi@0
|
107 }
|
danielebarchiesi@0
|
108
|
danielebarchiesi@0
|
109 break;
|
danielebarchiesi@0
|
110 default:
|
danielebarchiesi@0
|
111 var val = $(trigger).val();
|
danielebarchiesi@0
|
112 }
|
danielebarchiesi@0
|
113 }
|
danielebarchiesi@0
|
114 return val;
|
danielebarchiesi@0
|
115 }
|
danielebarchiesi@0
|
116
|
danielebarchiesi@0
|
117 var setChangeTrigger = function(trigger_id, bind_id) {
|
danielebarchiesi@0
|
118 // Triggered when change() is clicked.
|
danielebarchiesi@0
|
119 var changeTrigger = function() {
|
danielebarchiesi@0
|
120 var val = getValue(bind_id, trigger_id);
|
danielebarchiesi@0
|
121
|
danielebarchiesi@0
|
122 if (val == null) {
|
danielebarchiesi@0
|
123 return;
|
danielebarchiesi@0
|
124 }
|
danielebarchiesi@0
|
125
|
danielebarchiesi@0
|
126 for (i in Drupal.CTools.dependent.bindings[bind_id]) {
|
danielebarchiesi@0
|
127 var id = Drupal.CTools.dependent.bindings[bind_id][i];
|
danielebarchiesi@0
|
128 // Fix numerous errors
|
danielebarchiesi@0
|
129 if (typeof id != 'string') {
|
danielebarchiesi@0
|
130 continue;
|
danielebarchiesi@0
|
131 }
|
danielebarchiesi@0
|
132
|
danielebarchiesi@0
|
133 // This bit had to be rewritten a bit because two properties on the
|
danielebarchiesi@0
|
134 // same set caused the counter to go up and up and up.
|
danielebarchiesi@0
|
135 if (!Drupal.CTools.dependent.activeBindings[id]) {
|
danielebarchiesi@0
|
136 Drupal.CTools.dependent.activeBindings[id] = {};
|
danielebarchiesi@0
|
137 }
|
danielebarchiesi@0
|
138
|
danielebarchiesi@0
|
139 if (val != null && Drupal.CTools.dependent.inArray(Drupal.settings.CTools.dependent[id].values[bind_id], val)) {
|
danielebarchiesi@0
|
140 Drupal.CTools.dependent.activeBindings[id][bind_id] = 'bind';
|
danielebarchiesi@0
|
141 }
|
danielebarchiesi@0
|
142 else {
|
danielebarchiesi@0
|
143 delete Drupal.CTools.dependent.activeBindings[id][bind_id];
|
danielebarchiesi@0
|
144 }
|
danielebarchiesi@0
|
145
|
danielebarchiesi@0
|
146 var len = 0;
|
danielebarchiesi@0
|
147 for (i in Drupal.CTools.dependent.activeBindings[id]) {
|
danielebarchiesi@0
|
148 len++;
|
danielebarchiesi@0
|
149 }
|
danielebarchiesi@0
|
150
|
danielebarchiesi@0
|
151 var object = $('#' + id + '-wrapper');
|
danielebarchiesi@0
|
152 if (!object.size()) {
|
danielebarchiesi@0
|
153 // Some elements can't use the parent() method or they can
|
danielebarchiesi@0
|
154 // damage things. They are guaranteed to have wrappers but
|
danielebarchiesi@0
|
155 // only if dependent.inc provided them. This check prevents
|
danielebarchiesi@0
|
156 // problems when multiple AJAX calls cause settings to build
|
danielebarchiesi@0
|
157 // up.
|
danielebarchiesi@0
|
158 var $original = $('#' + id);
|
danielebarchiesi@0
|
159 if ($original.is('fieldset') || $original.is('textarea')) {
|
danielebarchiesi@0
|
160 continue;
|
danielebarchiesi@0
|
161 }
|
danielebarchiesi@0
|
162
|
danielebarchiesi@0
|
163 object = $('#' + id).parent();
|
danielebarchiesi@0
|
164 }
|
danielebarchiesi@0
|
165
|
danielebarchiesi@0
|
166 if (Drupal.settings.CTools.dependent[id].type == 'disable') {
|
danielebarchiesi@0
|
167 if (Drupal.settings.CTools.dependent[id].num <= len) {
|
danielebarchiesi@0
|
168 // Show if the element if criteria is matched
|
danielebarchiesi@0
|
169 object.attr('disabled', false);
|
danielebarchiesi@0
|
170 object.addClass('dependent-options');
|
danielebarchiesi@0
|
171 object.children().attr('disabled', false);
|
danielebarchiesi@0
|
172 }
|
danielebarchiesi@0
|
173 else {
|
danielebarchiesi@0
|
174 // Otherwise hide. Use css rather than hide() because hide()
|
danielebarchiesi@0
|
175 // does not work if the item is already hidden, for example,
|
danielebarchiesi@0
|
176 // in a collapsed fieldset.
|
danielebarchiesi@0
|
177 object.attr('disabled', true);
|
danielebarchiesi@0
|
178 object.children().attr('disabled', true);
|
danielebarchiesi@0
|
179 }
|
danielebarchiesi@0
|
180 }
|
danielebarchiesi@0
|
181 else {
|
danielebarchiesi@0
|
182 if (Drupal.settings.CTools.dependent[id].num <= len) {
|
danielebarchiesi@0
|
183 // Show if the element if criteria is matched
|
danielebarchiesi@0
|
184 object.show(0);
|
danielebarchiesi@0
|
185 object.addClass('dependent-options');
|
danielebarchiesi@0
|
186 }
|
danielebarchiesi@0
|
187 else {
|
danielebarchiesi@0
|
188 // Otherwise hide. Use css rather than hide() because hide()
|
danielebarchiesi@0
|
189 // does not work if the item is already hidden, for example,
|
danielebarchiesi@0
|
190 // in a collapsed fieldset.
|
danielebarchiesi@0
|
191 object.css('display', 'none');
|
danielebarchiesi@0
|
192 }
|
danielebarchiesi@0
|
193 }
|
danielebarchiesi@0
|
194 }
|
danielebarchiesi@0
|
195 }
|
danielebarchiesi@0
|
196
|
danielebarchiesi@0
|
197 $(trigger_id).change(function() {
|
danielebarchiesi@0
|
198 // Trigger the internal change function
|
danielebarchiesi@0
|
199 // the attr('id') is used because closures are more confusing
|
danielebarchiesi@0
|
200 changeTrigger(trigger_id, bind_id);
|
danielebarchiesi@0
|
201 });
|
danielebarchiesi@0
|
202 // Trigger initial reaction
|
danielebarchiesi@0
|
203 changeTrigger(trigger_id, bind_id);
|
danielebarchiesi@0
|
204 }
|
danielebarchiesi@0
|
205 setChangeTrigger(trigger_id, bind_id);
|
danielebarchiesi@0
|
206 }
|
danielebarchiesi@0
|
207 }
|
danielebarchiesi@0
|
208 }
|
danielebarchiesi@0
|
209
|
danielebarchiesi@0
|
210 Drupal.behaviors.CToolsDependent = {
|
danielebarchiesi@0
|
211 attach: function (context) {
|
danielebarchiesi@0
|
212 Drupal.CTools.dependent.autoAttach();
|
danielebarchiesi@0
|
213
|
danielebarchiesi@0
|
214 // Really large sets of fields are too slow with the above method, so this
|
danielebarchiesi@0
|
215 // is a sort of hacked one that's faster but much less flexible.
|
danielebarchiesi@0
|
216 $("select.ctools-master-dependent")
|
danielebarchiesi@0
|
217 .once('ctools-dependent')
|
danielebarchiesi@0
|
218 .change(function() {
|
danielebarchiesi@0
|
219 var val = $(this).val();
|
danielebarchiesi@0
|
220 if (val == 'all') {
|
danielebarchiesi@0
|
221 $('.ctools-dependent-all').show(0);
|
danielebarchiesi@0
|
222 }
|
danielebarchiesi@0
|
223 else {
|
danielebarchiesi@0
|
224 $('.ctools-dependent-all').hide(0);
|
danielebarchiesi@0
|
225 $('.ctools-dependent-' + val).show(0);
|
danielebarchiesi@0
|
226 }
|
danielebarchiesi@0
|
227 })
|
danielebarchiesi@0
|
228 .trigger('change');
|
danielebarchiesi@0
|
229 }
|
danielebarchiesi@0
|
230 }
|
danielebarchiesi@0
|
231 })(jQuery);
|