Projet

Général

Profil

Paste
Télécharger (9,23 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ctools / js / dependent.js @ 6e3ce7c2

1
/**
2
 * @file
3
 * Provides dependent visibility for form items in CTools' ajax forms.
4
 *
5
 * To your $form item definition add:
6
 * - '#process' => array('ctools_process_dependency'),
7
 * - '#dependency' => array('id-of-form-item' => array(list, of, values, that,
8
 *   make, this, item, show),
9
 *
10
 * Special considerations:
11
 * - Radios are harder. Because Drupal doesn't give radio groups individual IDs,
12
 *   use 'radio:name-of-radio'.
13
 *
14
 * - Checkboxes don't have their own id, so you need to add one in a div
15
 *   around the checkboxes via #prefix and #suffix. You actually need to add TWO
16
 *   divs because it's the parent that gets hidden. Also be sure to retain the
17
 *   'form_process_checkboxes' in the #process array, because the CTools process will
18
 *   override it.
19
 */
20

    
21
(function ($) {
22
  Drupal.CTools = Drupal.CTools || {};
23
  Drupal.CTools.dependent = {};
24

    
25
  Drupal.CTools.dependent.bindings = {};
26
  Drupal.CTools.dependent.activeBindings = {};
27
  Drupal.CTools.dependent.activeTriggers = [];
28

    
29
  Drupal.CTools.dependent.inArray = function(array, search_term) {
30
    var i = array.length;
31
    while (i--) {
32
      if (array[i] == search_term) {
33
         return true;
34
      }
35
    }
36
    return false;
37
  };
38

    
39

    
40
  Drupal.CTools.dependent.autoAttach = function() {
41
    // Clear active bindings and triggers.
42
    for (var i in Drupal.CTools.dependent.activeTriggers) {
43
      $(Drupal.CTools.dependent.activeTriggers[i]).unbind('change.ctools-dependent');
44
    }
45
    Drupal.CTools.dependent.activeTriggers = [];
46
    Drupal.CTools.dependent.activeBindings = {};
47
    Drupal.CTools.dependent.bindings = {};
48

    
49
    if (!Drupal.settings.CTools) {
50
      return;
51
    }
52

    
53
    // Iterate through all relationships
54
    for (var id in Drupal.settings.CTools.dependent) {
55
      // Test to make sure the id even exists; this helps clean up multiple
56
      // AJAX calls with multiple forms.
57

    
58
      // Drupal.CTools.dependent.activeBindings[id] is a boolean,
59
      // whether the binding is active or not.  Defaults to no.
60
      Drupal.CTools.dependent.activeBindings[id] = 0;
61
      // Iterate through all possible values
62
      for (var bind_id in Drupal.settings.CTools.dependent[id].values) {
63
        // This creates a backward relationship.  The bind_id is the ID
64
        // of the element which needs to change in order for the id to hide or become shown.
65
        // The id is the ID of the item which will be conditionally hidden or shown.
66
        // Here we're setting the bindings for the bind
67
        // id to be an empty array if it doesn't already have bindings to it
68
        if (!Drupal.CTools.dependent.bindings[bind_id]) {
69
          Drupal.CTools.dependent.bindings[bind_id] = [];
70
        }
71
        // Add this ID
72
        Drupal.CTools.dependent.bindings[bind_id].push(id);
73
        // Big long if statement.
74
        // Drupal.settings.CTools.dependent[id].values[bind_id] holds the possible values
75

    
76
        if (bind_id.substring(0, 6) == 'radio:') {
77
          var trigger_id = "input[name='" + bind_id.substring(6) + "']";
78
        }
79
        else {
80
          var trigger_id = '#' + bind_id;
81
        }
82

    
83
        Drupal.CTools.dependent.activeTriggers.push(trigger_id);
84

    
85
        if ($(trigger_id).attr('type') == 'checkbox') {
86
          $(trigger_id).siblings('label').addClass('hidden-options');
87
        }
88

    
89
        var getValue = function(item, trigger) {
90
          if ($(trigger).length == 0) {
91
            return null;
92
          }
93

    
94
          if (item.substring(0, 6) == 'radio:') {
95
            var val = $(trigger + ':checked').val();
96
          }
97
          else {
98
            switch ($(trigger).attr('type')) {
99
              case 'checkbox':
100
                // **This check determines if using a jQuery version 1.7 or newer which requires the use of the prop function instead of the attr function when not called on an attribute
101
                if ($().prop) {
102
                  var val = $(trigger).prop('checked') ? true : false;
103
                }
104
                else {
105
                  var val = $(trigger).attr('checked') ? true : false;
106
                }
107

    
108
                if (val) {
109
                  $(trigger).siblings('label').removeClass('hidden-options').addClass('expanded-options');
110
                }
111
                else {
112
                  $(trigger).siblings('label').removeClass('expanded-options').addClass('hidden-options');
113
                }
114

    
115
                break;
116
              default:
117
                var val = $(trigger).val();
118
            }
119
          }
120
          return val;
121
        };
122

    
123
        var setChangeTrigger = function(trigger_id, bind_id) {
124
          // Triggered when change() is clicked.
125
          var changeTrigger = function() {
126
            var val = getValue(bind_id, trigger_id);
127

    
128
            if (val == null) {
129
              return;
130
            }
131

    
132
            for (var i in Drupal.CTools.dependent.bindings[bind_id]) {
133
              var id = Drupal.CTools.dependent.bindings[bind_id][i];
134
              // Fix numerous errors
135
              if (typeof id != 'string') {
136
                continue;
137
              }
138

    
139
              // This bit had to be rewritten a bit because two properties on the
140
              // same set caused the counter to go up and up and up.
141
              if (!Drupal.CTools.dependent.activeBindings[id]) {
142
                Drupal.CTools.dependent.activeBindings[id] = {};
143
              }
144

    
145
              if (val != null && Drupal.CTools.dependent.inArray(Drupal.settings.CTools.dependent[id].values[bind_id], val)) {
146
                Drupal.CTools.dependent.activeBindings[id][bind_id] = 'bind';
147
              }
148
              else {
149
                delete Drupal.CTools.dependent.activeBindings[id][bind_id];
150
              }
151

    
152
              var len = 0;
153
              for (var i in Drupal.CTools.dependent.activeBindings[id]) {
154
                len++;
155
              }
156

    
157
              var $original = $('#' + id);
158
              if ($original.is('fieldset') || $original.is('textarea')) {
159
                continue;
160
              }
161

    
162
              var object = $original.parent();
163

    
164
              if (Drupal.settings.CTools.dependent[id].type == 'disable') {
165
                if (Drupal.settings.CTools.dependent[id].num <= len) {
166
                  // Show if the element if criteria is matched
167
                  // **This check determines if using a jQuery version 1.7 or newer which requires the use of the prop function instead of the attr function when not called on an attribute
168
                  if (typeof $().prop == 'function') {
169
                    object.prop('disabled', false);
170
                    object.addClass('dependent-options');
171
                    object.children().prop('disabled', false);
172
                  }
173
                  else {
174
                    object.attr('disabled', false);
175
                    object.addClass('dependent-options');
176
                    object.children().attr('disabled', false);
177
                  }
178
                }
179
                else {
180
                  // Otherwise hide. Use css rather than hide() because hide()
181
                  // does not work if the item is already hidden, for example,
182
                  // in a collapsed fieldset.
183
                  // **This check determines if using a jQuery version 1.7 or newer which requires the use of the prop function instead of the attr function when not called on an attribute
184
                  if (typeof $().prop == 'function') {
185
                    object.prop('disabled', true);
186
                    object.children().prop('disabled', true);
187
                  }
188
                  else {
189
                    object.attr('disabled', true);
190
                    object.children().attr('disabled', true);
191
                  }
192
                }
193
              }
194
              else {
195
                if (Drupal.settings.CTools.dependent[id].num <= len) {
196
                  // Show if the element if criteria is matched
197
                  object.show(0);
198
                  object.addClass('dependent-options');
199
                }
200
                else {
201
                  // Otherwise hide. Use css rather than hide() because hide()
202
                  // does not work if the item is already hidden, for example,
203
                  // in a collapsed fieldset.
204
                  object.css('display', 'none');
205
                }
206
              }
207
            }
208
          };
209

    
210
          $(trigger_id).bind('change.ctools-dependent', function() {
211
            // Trigger the internal change function
212
            // the attr('id') is used because closures are more confusing
213
            changeTrigger(trigger_id, bind_id);
214
          });
215
          // Trigger initial reaction
216
          changeTrigger(trigger_id, bind_id);
217
        };
218
        setChangeTrigger(trigger_id, bind_id);
219
      }
220
    }
221
  };
222

    
223
  Drupal.behaviors.CToolsDependent = {
224
    attach: function (context) {
225
      Drupal.CTools.dependent.autoAttach();
226

    
227
      // Really large sets of fields are too slow with the above method, so this
228
      // is a sort of hacked one that's faster but much less flexible.
229
      $("select.ctools-master-dependent")
230
        .once('ctools-dependent')
231
        .bind('change.ctools-dependent', function() {
232
          var val = $(this).val();
233
          if (val == 'all') {
234
            $('.ctools-dependent-all').show(0);
235
          }
236
          else {
237
            $('.ctools-dependent-all').hide(0);
238
            $('.ctools-dependent-' + val).show(0);
239
          }
240
        })
241
        .trigger('change.ctools-dependent');
242
    }
243
  };
244
})(jQuery);