root / drupal7 / sites / all / modules / field_group / horizontal-tabs / horizontal-tabs.js @ d719f12f
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); |