dependent.js
8.4 KB
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
225
226
227
228
229
230
231
/**
* @file
* Provides dependent visibility for form items in CTools' ajax forms.
*
* To your $form item definition add:
* - '#process' => array('ctools_process_dependency'),
* - '#dependency' => array('id-of-form-item' => array(list, of, values, that,
* make, this, item, show),
*
* Special considerations:
* - Radios are harder. Because Drupal doesn't give radio groups individual IDs,
* use 'radio:name-of-radio'.
*
* - Checkboxes don't have their own id, so you need to add one in a div
* around the checkboxes via #prefix and #suffix. You actually need to add TWO
* divs because it's the parent that gets hidden. Also be sure to retain the
* 'expand_checkboxes' in the #process array, because the CTools process will
* override it.
*/
(function ($) {
Drupal.CTools = Drupal.CTools || {};
Drupal.CTools.dependent = {};
Drupal.CTools.dependent.bindings = {};
Drupal.CTools.dependent.activeBindings = {};
Drupal.CTools.dependent.activeTriggers = [];
Drupal.CTools.dependent.inArray = function(array, search_term) {
var i = array.length;
while (i--) {
if (array[i] == search_term) {
return true;
}
}
return false;
}
Drupal.CTools.dependent.autoAttach = function() {
// Clear active bindings and triggers.
for (i in Drupal.CTools.dependent.activeTriggers) {
$(Drupal.CTools.dependent.activeTriggers[i]).unbind('change.ctools-dependent');
}
Drupal.CTools.dependent.activeTriggers = [];
Drupal.CTools.dependent.activeBindings = {};
Drupal.CTools.dependent.bindings = {};
if (!Drupal.settings.CTools) {
return;
}
// Iterate through all relationships
for (id in Drupal.settings.CTools.dependent) {
// Test to make sure the id even exists; this helps clean up multiple
// AJAX calls with multiple forms.
// Drupal.CTools.dependent.activeBindings[id] is a boolean,
// whether the binding is active or not. Defaults to no.
Drupal.CTools.dependent.activeBindings[id] = 0;
// Iterate through all possible values
for(bind_id in Drupal.settings.CTools.dependent[id].values) {
// This creates a backward relationship. The bind_id is the ID
// of the element which needs to change in order for the id to hide or become shown.
// The id is the ID of the item which will be conditionally hidden or shown.
// Here we're setting the bindings for the bind
// id to be an empty array if it doesn't already have bindings to it
if (!Drupal.CTools.dependent.bindings[bind_id]) {
Drupal.CTools.dependent.bindings[bind_id] = [];
}
// Add this ID
Drupal.CTools.dependent.bindings[bind_id].push(id);
// Big long if statement.
// Drupal.settings.CTools.dependent[id].values[bind_id] holds the possible values
if (bind_id.substring(0, 6) == 'radio:') {
var trigger_id = "input[name='" + bind_id.substring(6) + "']";
}
else {
var trigger_id = '#' + bind_id;
}
Drupal.CTools.dependent.activeTriggers.push(trigger_id);
if ($(trigger_id).attr('type') == 'checkbox') {
$(trigger_id).siblings('label').addClass('hidden-options');
}
var getValue = function(item, trigger) {
if ($(trigger).size() == 0) {
return null;
}
if (item.substring(0, 6) == 'radio:') {
var val = $(trigger + ':checked').val();
}
else {
switch ($(trigger).attr('type')) {
case 'checkbox':
var val = $(trigger).attr('checked') ? true : false;
if (val) {
$(trigger).siblings('label').removeClass('hidden-options').addClass('expanded-options');
}
else {
$(trigger).siblings('label').removeClass('expanded-options').addClass('hidden-options');
}
break;
default:
var val = $(trigger).val();
}
}
return val;
}
var setChangeTrigger = function(trigger_id, bind_id) {
// Triggered when change() is clicked.
var changeTrigger = function() {
var val = getValue(bind_id, trigger_id);
if (val == null) {
return;
}
for (i in Drupal.CTools.dependent.bindings[bind_id]) {
var id = Drupal.CTools.dependent.bindings[bind_id][i];
// Fix numerous errors
if (typeof id != 'string') {
continue;
}
// This bit had to be rewritten a bit because two properties on the
// same set caused the counter to go up and up and up.
if (!Drupal.CTools.dependent.activeBindings[id]) {
Drupal.CTools.dependent.activeBindings[id] = {};
}
if (val != null && Drupal.CTools.dependent.inArray(Drupal.settings.CTools.dependent[id].values[bind_id], val)) {
Drupal.CTools.dependent.activeBindings[id][bind_id] = 'bind';
}
else {
delete Drupal.CTools.dependent.activeBindings[id][bind_id];
}
var len = 0;
for (i in Drupal.CTools.dependent.activeBindings[id]) {
len++;
}
var object = $('#' + id + '-wrapper');
if (!object.size()) {
// Some elements can't use the parent() method or they can
// damage things. They are guaranteed to have wrappers but
// only if dependent.inc provided them. This check prevents
// problems when multiple AJAX calls cause settings to build
// up.
var $original = $('#' + id);
if ($original.is('fieldset') || $original.is('textarea')) {
continue;
}
object = $('#' + id).parent();
}
if (Drupal.settings.CTools.dependent[id].type == 'disable') {
if (Drupal.settings.CTools.dependent[id].num <= len) {
// Show if the element if criteria is matched
object.attr('disabled', false);
object.addClass('dependent-options');
object.children().attr('disabled', false);
}
else {
// Otherwise hide. Use css rather than hide() because hide()
// does not work if the item is already hidden, for example,
// in a collapsed fieldset.
object.attr('disabled', true);
object.children().attr('disabled', true);
}
}
else {
if (Drupal.settings.CTools.dependent[id].num <= len) {
// Show if the element if criteria is matched
object.show(0);
object.addClass('dependent-options');
}
else {
// Otherwise hide. Use css rather than hide() because hide()
// does not work if the item is already hidden, for example,
// in a collapsed fieldset.
object.css('display', 'none');
}
}
}
}
$(trigger_id).bind('change.ctools-dependent', function() {
// Trigger the internal change function
// the attr('id') is used because closures are more confusing
changeTrigger(trigger_id, bind_id);
});
// Trigger initial reaction
changeTrigger(trigger_id, bind_id);
}
setChangeTrigger(trigger_id, bind_id);
}
}
}
Drupal.behaviors.CToolsDependent = {
attach: function (context) {
Drupal.CTools.dependent.autoAttach();
// Really large sets of fields are too slow with the above method, so this
// is a sort of hacked one that's faster but much less flexible.
$("select.ctools-master-dependent")
.once('ctools-dependent')
.bind('change.ctools-dependent', function() {
var val = $(this).val();
if (val == 'all') {
$('.ctools-dependent-all').show(0);
}
else {
$('.ctools-dependent-all').hide(0);
$('.ctools-dependent-' + val).show(0);
}
})
.trigger('change.ctools-dependent');
}
}
})(jQuery);