Projet

Général

Profil

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

root / drupal7 / sites / all / modules / field_group / horizontal-tabs / horizontal-tabs.js @ e9f59589

1
(function ($) {
2

    
3
/**
4
 * This script transforms a set of fieldsets into a stack of horizontal
5
 * tabs. Another tab pane can be selected by clicking on the respective
6
 * tab.
7
 *
8
 * Each tab may have a summary which can be updated by another
9
 * script. For that to work, each fieldset has an associated
10
 * 'horizontalTabCallback' (with jQuery.data() attached to the fieldset),
11
 * which is called every time the user performs an update to a form
12
 * element inside the tab pane.
13
 */
14
Drupal.behaviors.horizontalTabs = {
15
  attach: function (context) {
16
    $('.horizontal-tabs-panes', context).once('horizontal-tabs', function () {
17
      var focusID = $(':hidden.horizontal-tabs-active-tab', this).val();
18
      var tab_focus;
19

    
20
      // Check if there are some fieldsets that can be converted to horizontal-tabs
21
      var $fieldsets = $('> fieldset', this);
22
      if ($fieldsets.length == 0) {
23
        return;
24
      }
25

    
26
      // Create the tab column.
27
      var tab_list = $('<ul class="horizontal-tabs-list"></ul>');
28
      $(this).wrap('<div class="horizontal-tabs clearfix"></div>').before(tab_list);
29

    
30
      // Transform each fieldset into a tab.
31
      $fieldsets.each(function (i) {
32
        var horizontal_tab = new Drupal.horizontalTab({
33
          title: $('> legend', this).text(),
34
          fieldset: $(this)
35
        });
36
        horizontal_tab.item.addClass('horizontal-tab-button-' + i);
37
        tab_list.append(horizontal_tab.item);
38
        $(this)
39
          .removeClass('collapsible collapsed')
40
          .addClass('horizontal-tabs-pane')
41
          .data('horizontalTab', horizontal_tab);
42
        if (this.id == focusID) {
43
          tab_focus = $(this);
44
        }
45
      });
46

    
47
      $('> li:first', tab_list).addClass('first');
48
      $('> li:last', tab_list).addClass('last');
49

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

    
68
/**
69
 * The horizontal tab object represents a single tab within a tab group.
70
 *
71
 * @param settings
72
 *   An object with the following keys:
73
 *   - title: The name of the tab.
74
 *   - fieldset: The jQuery object of the fieldset that is the tab pane.
75
 */
76
Drupal.horizontalTab = function (settings) {
77
  var self = this;
78
  $.extend(this, settings, Drupal.theme('horizontalTab', settings));
79

    
80
  this.link.click(function () {
81
    self.focus();
82
    return false;
83
  });
84

    
85
  // Keyboard events added:
86
  // Pressing the Enter key will open the tab pane.
87
  this.link.keydown(function(event) {
88
    if (event.keyCode == 13) {
89
      self.focus();
90
      // Set focus on the first input field of the visible fieldset/tab pane.
91
      $("fieldset.horizontal-tabs-pane :input:visible:enabled:first").focus();
92
      return false;
93
    }
94
  });
95

    
96
  // Only bind update summary on forms.
97
  if (this.fieldset.drupalGetSummary) {
98
    this.fieldset.bind('summaryUpdated', function() {
99
      self.updateSummary();
100
    }).trigger('summaryUpdated');
101
  }
102

    
103
};
104

    
105
Drupal.horizontalTab.prototype = {
106
  /**
107
   * Displays the tab's content pane.
108
   */
109
  focus: function () {
110
    this.fieldset
111
      .removeClass('horizontal-tab-hidden')
112
      .siblings('fieldset.horizontal-tabs-pane')
113
        .each(function () {
114
          var tab = $(this).data('horizontalTab');
115
          tab.fieldset.addClass('horizontal-tab-hidden');
116
          tab.item.removeClass('selected');
117
        })
118
        .end()
119
      .siblings(':hidden.horizontal-tabs-active-tab')
120
        .val(this.fieldset.attr('id'));
121
    this.item.addClass('selected');
122
    // Mark the active tab for screen readers.
123
    $('#active-horizontal-tab').remove();
124
    this.link.append('<span id="active-horizontal-tab" class="element-invisible">' + Drupal.t('(active tab)') + '</span>');
125
  },
126

    
127
  /**
128
   * Updates the tab's summary.
129
   */
130
  updateSummary: function () {
131
    this.summary.html(this.fieldset.drupalGetSummary());
132
  },
133

    
134
  /**
135
   * Shows a horizontal tab pane.
136
   */
137
  tabShow: function () {
138
    // Display the tab.
139
    this.item.removeClass('horizontal-tab-hidden');
140
    // Update .first marker for items. We need recurse from parent to retain the
141
    // actual DOM element order as jQuery implements sortOrder, but not as public
142
    // method.
143
    this.item.parent().children('.horizontal-tab-button').removeClass('first')
144
      .filter(':visible:first').addClass('first');
145
    // Display the fieldset.
146
    this.fieldset.removeClass('horizontal-tab-hidden');
147
    // Focus this tab.
148
    this.focus();
149
    return this;
150
  },
151

    
152
  /**
153
   * Hides a horizontal tab pane.
154
   */
155
  tabHide: function () {
156
    // Hide this tab.
157
    this.item.addClass('horizontal-tab-hidden');
158
    // Update .first marker for items. We need recurse from parent to retain the
159
    // actual DOM element order as jQuery implements sortOrder, but not as public
160
    // method.
161
    this.item.parent().children('.horizontal-tab-button').removeClass('first')
162
      .filter(':visible:first').addClass('first');
163
    // Hide the fieldset.
164
    this.fieldset.addClass('horizontal-tab-hidden');
165
    // Focus the first visible tab (if there is one).
166
    var $firstTab = this.fieldset.siblings('.horizontal-tabs-pane:not(.horizontal-tab-hidden):first');
167
    if ($firstTab.length) {
168
      $firstTab.data('horizontalTab').focus();
169
    }
170
    return this;
171
  }
172
};
173

    
174
/**
175
 * Theme function for a horizontal tab.
176
 *
177
 * @param settings
178
 *   An object with the following keys:
179
 *   - title: The name of the tab.
180
 * @return
181
 *   This function has to return an object with at least these keys:
182
 *   - item: The root tab jQuery element
183
 *   - link: The anchor tag that acts as the clickable area of the tab
184
 *       (jQuery version)
185
 *   - summary: The jQuery element that contains the tab summary
186
 */
187
Drupal.theme.prototype.horizontalTab = function (settings) {
188
  var tab = {};
189
  var idAttr = settings.fieldset.attr('id');
190

    
191
  tab.item = $('<li class="horizontal-tab-button" tabindex="-1"></li>')
192
    .append(tab.link = $('<a href="#' + idAttr + '"></a>')
193
    .append(tab.title = $('<strong></strong>').text(settings.title))
194
    );
195

    
196
  // No need to add summary on frontend.
197
  if (settings.fieldset.drupalGetSummary) {
198
    tab.link.append(tab.summary = $('<span class="summary"></span>'))
199
    }
200

    
201
  return tab;
202
};
203

    
204
})(jQuery);