Projet

Général

Profil

Paste
Télécharger (15,6 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / shs / js / shs.js @ 13755f8d

1
/**
2
 * @file
3
 * Custom behaviors for Simple hierarchical select.
4
 */
5

    
6
(function ($) {
7

    
8
  /**
9
   * Creates the widget for Simple hierarchical select.
10
   */
11
  Drupal.behaviors.shsWidgetCreate = {
12

    
13
    // Default function to attach the behavior.
14
    attach: function (context, settings) {
15
      var self = this;
16
      $('input.shs-enabled')
17
        .not('.shs-processed')
18
        .once('shs')
19
        .addClass('element-invisible')
20
        .each(function() {
21
          var $field = $(this);
22
          var fieldName = $(this).attr('name');
23

    
24
          if (fieldName in settings.shs) {
25
            var fieldSettings = {};
26
            // Since we store the field settings within an associative array with
27
            // random strings as keys (reason: http://drupal.org/node/208611) we
28
            // need to get the last setting for this field.
29
            $.each(settings.shs[fieldName], function(hash, setting) {
30
              fieldSettings = setting;
31
            });
32
            var level = 0;
33
            var parent_id = 0;
34
            // Update class of wrapper element.
35
            $field.parent('.form-item').not('.shs-wrapper-processed').once('shs-wrapper');
36
            // Create elements for each parent of the current value.
37
            $.each(fieldSettings.parents, function(index, parent) {
38
              level++;
39
              // Create select element.
40
              $select = shsElementCreate($field.attr('id'), fieldSettings, level);
41
              if ($field.hasClass('error')) {
42
                // Add error-class if there was an error with the original field.
43
                $select.addClass('error');
44
              }
45
              $select.appendTo($field.parent());
46
              // Retrieve data for this level.
47
              getTermChildren($select, fieldSettings, parent_id, parent.tid, $field.attr('id'));
48
              // Use current term id as parent id for the next level.
49
              if (fieldSettings.multiple) {
50
                parent_id = parent['tid'];
51
              }
52
              else {
53
                parent_id = parent.tid;
54
              }
55
            });
56
            var addNextLevel = false;
57
            if ((level > 1 || parent_id) && (fieldSettings.settings.create_new_terms && fieldSettings.settings.create_new_levels)) {
58
              // Add next level in hierarchy if new levels may be created.
59
              addNextLevel = true;
60
            }
61
            if (fieldSettings.default_value && (fieldSettings.default_value.tid == parent_id)) {
62
              addNextLevel = true;
63
            }
64
            if (addNextLevel) {
65
              // Try to add one additional level.
66
              $select = shsElementCreate($field.attr('id'), fieldSettings, level);
67
              $select.appendTo($field.parent());
68
              // Retrieve data for this level.
69
              getTermChildren($select, fieldSettings, parent_id, 0, $field.attr('id'));
70
            }
71
          }
72
        });
73
    }
74
  }
75

    
76
  /**
77
   * Load direct children of a selected term.
78
   *
79
   * @param $element
80
   *   Element to fill with terms.
81
   * @param settings
82
   *   Field settings.
83
   * @param parent_value
84
    *   Value which has been selected in the parent element (== "selected term").
85
    * @param default_value
86
    *   Value to use as default.
87
    * @param base_id
88
    *   ID of original field which is rewritten as "taxonomy_shs".
89
    */
90
  getTermChildren = function($element, settings, parent_value, default_value, base_id) {
91

    
92
    // Check if parent_value is number and convert it.
93
    if (!$.isArray(parent_value) && typeof parent_value != "object") {
94
      parent_value = [parent_value];
95
    }
96

    
97
    // Check if default_value is object and convert it.
98
    if (!$.isArray(default_value) && typeof default_value == "object") {
99
      var arr = new Array;
100
      $.each(default_value, function(delta, value){
101
        arr.push(value);
102
      });
103
      default_value = arr;
104
    }
105

    
106
    $.ajax({
107
      url: Drupal.settings.basePath + 'js/shs/json',
108
      type: 'POST',
109
      dataType: 'json',
110
      cache: true,
111
      data: {
112
        callback: 'shs_json_term_get_children',
113
        arguments: {
114
          vid: settings.vid,
115
          parent: parent_value,
116
          settings: settings.settings
117
        }
118
      },
119
      success: function(data) {
120
        if (data.success == true) {
121
          if ($element.prop) {
122
            var options = $element.prop('options');
123
          }
124
          else {
125
            var options = $element.attr('options');
126
          }
127

    
128
          if (data.data.length == 0 && !(settings.settings.create_new_terms && (settings.settings.create_new_levels || (parent_value + default_value == 0)))) {
129
            // Remove element.
130
            $element.remove();
131
            return;
132
          }
133

    
134
          // Remove all existing options.
135
          $('option', $element).remove();
136
          // Add empty option (if field is not required and not multiple
137
          // or this is not the first level and not multiple).
138
          if (!settings.settings.required || (settings.settings.required && parent_value != 0 && !settings.multiple)) {
139
            options[options.length] = new Option(Drupal.t('- None -'), 0);
140
          }
141

    
142
          if (settings.settings.create_new_terms) {
143
            // Add option to add new item.
144
            options[options.length] = new Option(Drupal.t('<Add new item>', {}, {context: 'shs'}), '_add_new_');
145
          }
146

    
147
          // Add retrieved list of options.
148
          $.each(data.data, function(key, term) {
149
            options[options.length] = new Option(term.label, term.tid);
150
          });
151
          // Set default value.
152
          $element.val(default_value);
153

    
154
          // Try to convert the element to a "Chosen" element.
155
          if (!elementConvertToChosen($element, settings)) {
156
            // Display original dropdown element.
157
            $element.fadeIn();
158
            $element.css('display','inline-block');
159
          }
160

    
161
          // If there is no data, the field is required and the user is allowed
162
          // to add new terms, trigger click on "Add new".
163
          if (data.data.length == 0 && settings.settings.required && settings.settings.create_new_terms && (settings.settings.create_new_levels || (parent_value + default_value == 0))) {
164
            updateElements($element, base_id, settings, 1);
165
          }
166
        }
167
      },
168
      error: function(xhr, status, error) {
169
      }
170
    });
171
  }
172

    
173
  /**
174
   * Add a new term to database.
175
   *
176
   * @param $triggering_element
177
   *   Element to add the new term to.
178
   * @param $container
179
   *   Container for "Add new" elements.
180
   * @param term
181
   *   The new term object.
182
   * @param base_id
183
   *   ID of original field which is rewritten as "taxonomy_shs".
184
   * @param level
185
   *   Current level in hierarchy.
186
   */
187
  termAddNew = function($triggering_element, $container, term, base_id, level) {
188
    $.ajax({
189
      url: Drupal.settings.basePath + 'js/shs/json',
190
      type: 'POST',
191
      dataType: 'json',
192
      cache: true,
193
      data: {
194
        callback: 'shs_json_term_add',
195
        arguments: {
196
          vid: term.vid,
197
          parent: term.parent,
198
          name: term.name
199
        }
200
      },
201
      success: function(data) {
202
        if (data.success == true && data.data.tid) {
203
          if ($triggering_element.prop) {
204
            var options = $triggering_element.prop('options');
205
          }
206
          else {
207
            var options = $triggering_element.attr('options');
208
          }
209

    
210
          // Add new option with data from created term.
211
          options[options.length] = new Option(data.data.name, data.data.tid);
212
          // Set new default value.
213
          $triggering_element.val(data.data.tid);
214
          // Set value of original field.
215
          updateFieldValue($triggering_element, base_id, level);
216
        }
217
      },
218
      error: function(xhr, status, error) {
219
        // Reset value of triggering element.
220
        $triggering_element.val(0);
221
      },
222
      complete: function(xhr, status) {
223
        // Remove container.
224
        $container.remove();
225
        // Display triggering element.
226
        $triggering_element.fadeIn();
227
        $triggering_element.css('display','inline-block');
228
      }
229
    });
230
  }
231

    
232
  /**
233
   * Update the changed element.
234
   *
235
   * @param $triggering_element
236
   *   Element which has been changed.
237
   * @param base_id
238
   *   ID of original field which is rewritten as "taxonomy_shs".
239
   * @param settings
240
   *   Field settings.
241
   * @param level
242
   *   Current level in hierarchy.
243
   */
244
  updateElements = function($triggering_element, base_id, settings, level) {
245
    // Remove all following elements.
246
    $triggering_element.nextAll('select').each(function() {
247
      if (Drupal.settings.chosen) {
248
        // Remove element created by chosen.
249
        var elem_id = $(this).attr('id');
250
        $('#' + elem_id.replace(/-/g, '_') + '_chzn').remove();
251
      }
252
      // Remove element.
253
      $(this).remove();
254
    });
255
    //$triggering_element.nextAll('.chzn-container').remove();
256
    $triggering_element.nextAll('.shs-term-add-new-wrapper').remove();
257
    // Create next level (if the value is != 0).
258
    if ($triggering_element.val() == '_add_new_') {
259
      // Hide element.
260
      $triggering_element.hide();
261
      // Create new container with textfield and buttons ("cancel", "save").
262
      $container = $('<div>')
263
        .addClass('shs-term-add-new-wrapper')
264
        .addClass('clearfix');
265
      // Append container to parent.
266
      $container.appendTo($triggering_element.parent());
267

    
268
      // Add textfield for term name.
269
      $nameField = $('<input type="text">')
270
        .attr('maxlength', 255)
271
        .attr('size', 10)
272
        .addClass('shs-term-name')
273
        .addClass('form-text');
274
      $nameField.appendTo($container);
275

    
276
      // Add buttons.
277
      $buttons = $('<div>')
278
        .addClass('buttons');
279
      $buttons.appendTo($container);
280
      $cancel = $('<a>')
281
        .attr('href', '#')
282
        .html(Drupal.t('Cancel'))
283
        .bind('click', function(event) {
284
          event.preventDefault();
285
          // Remove container.
286
          $container.remove();
287
          // Reset value of triggering element.
288
          $triggering_element.val(0);
289
          // Display triggering element.
290
          $triggering_element.fadeIn();
291
          $triggering_element.css('display','inline-block');
292
        });
293
      $cancel.appendTo($buttons);
294
      if (level == 1 && settings.settings.required && $('option', $triggering_element).length == 1) {
295
        // Hide cancel button since the term selection is empty (apart from
296
        // "Add new term") and the field is required.
297
        $cancel.hide();
298
      }
299

    
300
      $save = $('<a>')
301
        .attr('href', '#')
302
        .html(Drupal.t('Save'))
303
        .bind('click', function(event) {
304
          event.preventDefault();
305
          // Get the new term name.
306
          var termName = $(this).parents('.shs-term-add-new-wrapper').find('input.shs-term-name').val();
307
          // Create a term object.
308
          var term = {
309
            vid: settings.vid,
310
            parent: $triggering_element.prev('select').val() || 0,
311
            name: termName
312
          };
313
          if (termName.length > 0) {
314
            termAddNew($triggering_element, $container, term, base_id, level);
315
          }
316
          else {
317
            // Remove container.
318
            $container.remove();
319
            // Reset value of triggering element.
320
            $triggering_element.val(0);
321
            // Display triggering element.
322
            $triggering_element.fadeIn();
323
            $triggering_element.css('display','inline-block');;
324
          }
325
        });
326
      $save.appendTo($buttons);
327
    }
328
    else if ($triggering_element.val() != 0) {
329
      level++;
330
      $element_new = shsElementCreate(base_id, settings, level);
331
      $element_new.appendTo($triggering_element.parent());
332
      // Retrieve list of items for the new element.
333
      getTermChildren($element_new, settings, $triggering_element.val(), 0, base_id);
334
    }
335

    
336
    // Set value of original field.
337
    updateFieldValue($triggering_element, base_id, level, settings.multiple);
338
  }
339

    
340
  /**
341
   * Create a new <select> element.
342
   *
343
   * @param base_id
344
   *   ID of original field which is rewritten as "taxonomy_shs".
345
   * @param settings
346
   *   Field settings.
347
   * @param level
348
   *   Current level in hierarchy.
349
   *
350
   * @return
351
   *   The new (empty) <select> element.
352
   */
353
  shsElementCreate = function(base_id, settings, level) {
354
    // Create element and initially hide it.
355
    if (settings.multiple) {
356
      $element = $('<select>')
357
        .attr('id', base_id + '-select-' + level)
358
        .attr('multiple', 'multiple')
359
        .addClass('shs-select')
360
        // Add core class to apply default styles to the element.
361
        .addClass('form-select')
362
        .addClass('shs-select-level-' + level)
363
        .bind('change', function() {
364
          updateElements($(this), base_id, settings, level);
365
        })
366
        .hide();
367
    }
368
    else {
369
      $element = $('<select>')
370
        .attr('id', base_id + '-select-' + level)
371
        .addClass('shs-select')
372
        // Add core class to apply default styles to the element.
373
        .addClass('form-select')
374
        .addClass('shs-select-level-' + level)
375
        .bind('change', function() {
376
          updateElements($(this), base_id, settings, level);
377
        })
378
        .hide();
379
    }
380
    // Return the new element.
381
    return $element;
382
  }
383

    
384
  /**
385
   * Update value of original (hidden) field.
386
   *
387
   * @param $triggering_element
388
   *   Element which has been changed.
389
   * @param base_id
390
   *   ID of original field which is rewritten as "taxonomy_shs".
391
   * @param level
392
   *   Current level in hierarchy.
393
   */
394
  updateFieldValue = function($triggering_element, base_id, level, multiple) {
395
    // Reset value of original field.
396
    $field_orig = $('#' + base_id);
397
    $field_orig.val(0);
398
    // Set original field value.
399
    if ($triggering_element.val() == 0 || $triggering_element.val() == '_add_new_') {
400
      if (level > 1) {
401
        // Use value from parent level.
402
        $field_orig.val($triggering_element.prev('select').val());
403
      }
404
    }
405
    else {
406
      var new_val = $triggering_element.val();
407
      if (level > 1 && multiple) {
408
        var new_value = '';
409
        for (i = 0; i < level - 1; i++) {
410
          var prev_value = $('.shs-select:eq(' + i + ')').val();
411
          if (i == 0) {
412
            new_value = prev_value;
413
          }
414
          else {
415
            new_value = new_value + '+' + prev_value;
416
          }
417
        }
418
        new_val = new_value;
419
      }
420
      // Use value from current field.
421
      if ($.isArray(new_val)) {
422
        $field_orig.val(new_val.join(','));
423
      }
424
      else {
425
        $field_orig.val(new_val);
426
      }
427
    }
428
  }
429

    
430
  /**
431
   * Convert a dropdown to a "Chosen" element.
432
   *
433
   * @see http://drupal.org/project/chosen
434
   */
435
  elementConvertToChosen = function($element, settings) {
436
    if (Drupal.settings.chosen) {
437
      var minWidth = Drupal.settings.chosen.minimum_width;
438
      // Define options for chosen.
439
      var options = {};
440
      options.search_contains = Drupal.settings.chosen.search_contains;
441
      options.placeholder_text_multiple = Drupal.settings.chosen.placeholder_text_multiple;
442
      options.placeholder_text_single = Drupal.settings.chosen.placeholder_text_single;
443
      options.no_results_text = Drupal.settings.chosen.no_results_text;
444

    
445
      // Get element selector from settings (and remove "visible" option since
446
      // our select element is hidden by default).
447
      var selector = Drupal.settings.chosen.selector.replace(/:visible/, '');
448

    
449
      if ((settings.settings.use_chosen == 'always') || ((settings.settings.use_chosen == 'chosen') && ($element.is(selector) && $element.find('option').size() >= Drupal.settings.chosen.minimum))) {
450
        $element.css({
451
          width : ($element.width() < minWidth) ? minWidth : $element.width()
452
        }).chosen(options);
453
        return true;
454
      }
455
    }
456
    return false;
457
  }
458

    
459
})(jQuery);