Projet

Général

Profil

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

root / drupal7 / sites / all / modules / field_group / multipage / multipage.js @ e9f59589

1
(function ($) {
2

    
3
/**
4
 * This script transforms a set of wrappers into a stack of multipage pages.
5
 * Another pane can be entered by clicking next/previous.
6
 *
7
 */
8
Drupal.behaviors.MultiPage = {
9
  attach: function (context) {
10
    $('.multipage-panes', context).once('multipage', function () {
11

    
12
      var focusID = $(':hidden.multipage-active-control', this).val();
13
      var paneWithFocus;
14

    
15
      // Check if there are some wrappers that can be converted to multipages.
16
      var $panes = $('> div.field-group-multipage', this);
17
      var $form = $panes.parents('form');
18
      if ($panes.length == 0) {
19
        return;
20
      }
21

    
22
      // Create the next/previous controls.
23
      var $controls;
24

    
25
      // Transform each div.multipage-pane into a multipage with controls.
26
      $panes.each(function () {
27

    
28
        $controls = $('<div class="multipage-controls-list clearfix"></div>');
29
        $(this).append($controls);
30

    
31
        // Check if the submit button needs to move to the latest pane.
32
        if (Drupal.settings.field_group.multipage_move_submit && $('.form-actions').length) {
33
          $('.form-actions', $form).remove().appendTo($($controls, $panes.last()));
34
        }
35

    
36
        var multipageControl = new Drupal.multipageControl({
37
          title: $('> .multipage-pane-title', this).text(),
38
          wrapper: $(this),
39
          has_next: $(this).next().length,
40
          has_previous: $(this).prev().length
41
        });
42

    
43
        $controls.append(multipageControl.item);
44
        $(this)
45
          .addClass('multipage-pane')
46
          .data('multipageControl', multipageControl);
47

    
48
        if (this.id == focusID) {
49
          paneWithFocus = $(this);
50
        }
51

    
52
      });
53

    
54
      if (paneWithFocus === undefined) {
55
        // If the current URL has a fragment and one of the tabs contains an
56
        // element that matches the URL fragment, activate that tab.
57
        var hash = window.location.hash.replace(/[=%;,\/]/g, "");
58
        if (hash !== '#' && $(hash, this).length) {
59
          paneWithFocus = $(window.location.hash, this).closest('.multipage-pane');
60
        }
61
        else {
62
          paneWithFocus = $('multipage-open', this).length ? $('multipage-open', this) : $('> .multipage-pane:first', this);
63
        }
64
      }
65
      if (paneWithFocus !== undefined) {
66
        paneWithFocus.data('multipageControl').focus();
67
      }
68
    });
69
  }
70
};
71

    
72
/**
73
 * The multipagePane object represents a single div as a page.
74
 *
75
 * @param settings
76
 *   An object with the following keys:
77
 *   - title: The name of the tab.
78
 *   - wrapper: The jQuery object of the <div> that is the tab pane.
79
 */
80
Drupal.multipageControl = function (settings) {
81
  var self = this;
82
  var controls = Drupal.theme('multipage', settings);
83
  $.extend(self, settings, controls);
84

    
85
  this.nextLink.click(function () {
86
    self.nextPage();
87
    return false;
88
  });
89

    
90
  this.previousLink.click(function () {
91
    self.previousPage();
92
    return false;
93
  });
94

    
95
/*
96
  // Keyboard events added:
97
  // Pressing the Enter key will open the tab pane.
98
  this.nextLink.keydown(function(event) {
99
    if (event.keyCode == 13) {
100
      self.focus();
101
      // Set focus on the first input field of the visible wrapper/tab pane.
102
      $("div.multipage-pane :input:visible:enabled:first").focus();
103
      return false;
104
    }
105
  });
106

107
  // Pressing the Enter key lets you leave the tab again.
108
  this.wrapper.keydown(function(event) {
109
    // Enter key should not trigger inside <textarea> to allow for multi-line entries.
110
    if (event.keyCode == 13 && event.target.nodeName != "TEXTAREA") {
111
      // Set focus on the selected tab button again.
112
      $(".multipage-tab-button.selected a").focus();
113
      return false;
114
    }
115
  });
116
*/
117
};
118

    
119
Drupal.multipageControl.prototype = {
120

    
121
  /**
122
   * Displays the tab's content pane.
123
   */
124
  focus: function () {
125
    this.wrapper
126
      .show()
127
      .siblings('div.multipage-pane')
128
        .each(function () {
129
          var tab = $(this).data('multipageControl');
130
          tab.wrapper.hide();
131
        })
132
        .end()
133
      .siblings(':hidden.multipage-active-control')
134
        .val(this.wrapper.attr('id'));
135
    // Mark the active control for screen readers.
136
    $('#active-multipage-control').remove();
137
    this.nextLink.after('<span id="active-multipage-control" class="element-invisible">' + Drupal.t('(active page)') + '</span>');
138
  },
139

    
140
  /**
141
   * Continues to the next page or step in the form.
142
   */
143
  nextPage: function () {
144
    this.wrapper.next().data('multipageControl').focus();
145
    $('html, body').scrollTop(this.wrapper.parents('.field-group-multipage-group-wrapper').offset().top);
146
  },
147

    
148
  /**
149
   * Returns to the previous page or step in the form.
150
   */
151
  previousPage: function () {
152
    this.wrapper.prev().data('multipageControl').focus();
153
    $('html, body').scrollTop(this.wrapper.parents('.field-group-multipage-group-wrapper').offset().top);
154
  },
155

    
156
  /**
157
   * Shows a horizontal tab pane.
158
   */
159
  tabShow: function () {
160
    // Display the tab.
161
    this.item.show();
162
    // Update .first marker for items. We need recurse from parent to retain the
163
    // actual DOM element order as jQuery implements sortOrder, but not as public
164
    // method.
165
    this.item.parent().children('.multipage-control').removeClass('first')
166
      .filter(':visible:first').addClass('first');
167
    // Display the wrapper.
168
    this.wrapper.removeClass('multipage-control-hidden').show();
169
    // Focus this tab.
170
    this.focus();
171
    return this;
172
  },
173

    
174
  /**
175
   * Hides a horizontal tab pane.
176
   */
177
  tabHide: function () {
178
    // Hide this tab.
179
    this.item.hide();
180
    // Update .first marker for items. We need recurse from parent to retain the
181
    // actual DOM element order as jQuery implements sortOrder, but not as public
182
    // method.
183
    this.item.parent().children('.multipage-control').removeClass('first')
184
      .filter(':visible:first').addClass('first');
185
    // Hide the wrapper.
186
    this.wrapper.addClass('horizontal-tab-hidden').hide();
187
    // Focus the first visible tab (if there is one).
188
    var $firstTab = this.wrapper.siblings('.multipage-pane:not(.multipage-control-hidden):first');
189
    if ($firstTab.length) {
190
      $firstTab.data('multipageControl').focus();
191
    }
192
    return this;
193
  }
194
};
195

    
196
/**
197
 * Theme function for a multipage control.
198
 *
199
 * @param settings
200
 *   An object with the following keys:
201
 *   - title: The name of the tab.
202
 * @return
203
 *   This function has to return an object with at least these keys:
204
 *   - item: The root tab jQuery element
205
 *   - nextLink: The anchor tag that acts as the clickable area of the control
206
 *   - nextTitle: The jQuery element that contains the group title
207
 *   - previousLink: The anchor tag that acts as the clickable area of the control
208
 *   - previousTitle: The jQuery element that contains the group title
209
 */
210
Drupal.theme.prototype.multipage = function (settings) {
211

    
212
  var controls = {};
213
  controls.item = $('<span class="multipage-button"></span>');
214

    
215
  controls.previousLink = $('<input type="button" class="form-submit multipage-link-previous" value="" />');
216
  controls.previousTitle = Drupal.t('Previous page');
217
  controls.item.append(controls.previousLink.val(controls.previousTitle));
218

    
219
  controls.nextLink = $('<input type="button" class="form-submit multipage-link-next" value="" />');
220
  controls.nextTitle = Drupal.t('Next page');
221
  controls.item.append(controls.nextLink.val(controls.nextTitle));
222

    
223
  if (!settings.has_next) {
224
    controls.nextLink.hide();
225
  }
226
  if (!settings.has_previous) {
227
    controls.previousLink.hide();
228
  }
229

    
230
  return controls;
231
};
232

    
233

    
234
Drupal.FieldGroup = Drupal.FieldGroup || {};
235
Drupal.FieldGroup.Effects = Drupal.FieldGroup.Effects || {};
236

    
237
/**
238
 * Implements Drupal.FieldGroup.processHook().
239
 */
240
Drupal.FieldGroup.Effects.processMultipage = {
241
  execute: function (context, settings, type) {
242
    if (type == 'form') {
243

    
244
      var $firstErrorItem = false;
245

    
246
      // Add required fields mark to any element containing required fields
247
      $('div.multipage-pane').each(function(i){
248
        if ($('.error', $(this)).length) {
249

    
250
          // Save first error item, for focussing it.
251
          if (!$firstErrorItem) {
252
            $firstErrorItem = $(this).data('multipageControl');
253
          }
254

    
255
          Drupal.FieldGroup.setGroupWithfocus($(this));
256
          $(this).data('multipageControl').focus();
257
        }
258
      });
259

    
260
      // Focus on first multipage that has an error.
261
      if ($firstErrorItem) {
262
        $firstErrorItem.focus();
263
      }
264

    
265
    }
266
  }
267
}
268

    
269
})(jQuery);