Projet

Général

Profil

Paste
Télécharger (8,4 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ctools / js / dependent.js @ e4c061ad

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
 *   'expand_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 (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 (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(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).size() == 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
                var val = $(trigger).attr('checked') ? true : false;
101

    
102
                if (val) {
103
                  $(trigger).siblings('label').removeClass('hidden-options').addClass('expanded-options');
104
                }
105
                else {
106
                  $(trigger).siblings('label').removeClass('expanded-options').addClass('hidden-options');
107
                }
108

    
109
                break;
110
              default:
111
                var val = $(trigger).val();
112
            }
113
          }
114
          return val;
115
        }
116

    
117
        var setChangeTrigger = function(trigger_id, bind_id) {
118
          // Triggered when change() is clicked.
119
          var changeTrigger = function() {
120
            var val = getValue(bind_id, trigger_id);
121

    
122
            if (val == null) {
123
              return;
124
            }
125

    
126
            for (i in Drupal.CTools.dependent.bindings[bind_id]) {
127
              var id = Drupal.CTools.dependent.bindings[bind_id][i];
128
              // Fix numerous errors
129
              if (typeof id != 'string') {
130
                continue;
131
              }
132

    
133
              // This bit had to be rewritten a bit because two properties on the
134
              // same set caused the counter to go up and up and up.
135
              if (!Drupal.CTools.dependent.activeBindings[id]) {
136
                Drupal.CTools.dependent.activeBindings[id] = {};
137
              }
138

    
139
              if (val != null && Drupal.CTools.dependent.inArray(Drupal.settings.CTools.dependent[id].values[bind_id], val)) {
140
                Drupal.CTools.dependent.activeBindings[id][bind_id] = 'bind';
141
              }
142
              else {
143
                delete Drupal.CTools.dependent.activeBindings[id][bind_id];
144
              }
145

    
146
              var len = 0;
147
              for (i in Drupal.CTools.dependent.activeBindings[id]) {
148
                len++;
149
              }
150

    
151
              var object = $('#' + id + '-wrapper');
152
              if (!object.size()) {
153
                // Some elements can't use the parent() method or they can
154
                // damage things. They are guaranteed to have wrappers but
155
                // only if dependent.inc provided them. This check prevents
156
                // problems when multiple AJAX calls cause settings to build
157
                // up.
158
                var $original = $('#' + id);
159
                if ($original.is('fieldset') || $original.is('textarea')) {
160
                  continue;
161
                }
162

    
163
                object = $('#' + id).parent();
164
              }
165

    
166
              if (Drupal.settings.CTools.dependent[id].type == 'disable') {
167
                if (Drupal.settings.CTools.dependent[id].num <= len) {
168
                  // Show if the element if criteria is matched
169
                  object.attr('disabled', false);
170
                  object.addClass('dependent-options');
171
                  object.children().attr('disabled', false);
172
                }
173
                else {
174
                  // Otherwise hide. Use css rather than hide() because hide()
175
                  // does not work if the item is already hidden, for example,
176
                  // in a collapsed fieldset.
177
                  object.attr('disabled', true);
178
                  object.children().attr('disabled', true);
179
                }
180
              }
181
              else {
182
                if (Drupal.settings.CTools.dependent[id].num <= len) {
183
                  // Show if the element if criteria is matched
184
                  object.show(0);
185
                  object.addClass('dependent-options');
186
                }
187
                else {
188
                  // Otherwise hide. Use css rather than hide() because hide()
189
                  // does not work if the item is already hidden, for example,
190
                  // in a collapsed fieldset.
191
                  object.css('display', 'none');
192
                }
193
              }
194
            }
195
          }
196

    
197
          $(trigger_id).bind('change.ctools-dependent', function() {
198
            // Trigger the internal change function
199
            // the attr('id') is used because closures are more confusing
200
            changeTrigger(trigger_id, bind_id);
201
          });
202
          // Trigger initial reaction
203
          changeTrigger(trigger_id, bind_id);
204
        }
205
        setChangeTrigger(trigger_id, bind_id);
206
      }
207
    }
208
  }
209

    
210
  Drupal.behaviors.CToolsDependent = {
211
    attach: function (context) {
212
      Drupal.CTools.dependent.autoAttach();
213

    
214
      // Really large sets of fields are too slow with the above method, so this
215
      // is a sort of hacked one that's faster but much less flexible.
216
      $("select.ctools-master-dependent")
217
        .once('ctools-dependent')
218
        .bind('change.ctools-dependent', function() {
219
          var val = $(this).val();
220
          if (val == 'all') {
221
            $('.ctools-dependent-all').show(0);
222
          }
223
          else {
224
            $('.ctools-dependent-all').hide(0);
225
            $('.ctools-dependent-' + val).show(0);
226
          }
227
        })
228
        .trigger('change.ctools-dependent');
229
    }
230
  }
231
})(jQuery);