Mercurial > web-octave
comparison js/foundation/foundation.tab.js @ 0:7abe02bf29ec
initial commit
author | Alex Krolick <whokilledtheelectricmonk@gmail.com> |
---|---|
date | Sat, 07 Nov 2015 18:04:42 -0800 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:7abe02bf29ec |
---|---|
1 ;(function ($, window, document, undefined) { | |
2 'use strict'; | |
3 | |
4 Foundation.libs.tab = { | |
5 name : 'tab', | |
6 | |
7 version : '5.5.3', | |
8 | |
9 settings : { | |
10 active_class : 'active', | |
11 callback : function () {}, | |
12 deep_linking : false, | |
13 scroll_to_content : true, | |
14 is_hover : false | |
15 }, | |
16 | |
17 default_tab_hashes : [], | |
18 | |
19 init : function (scope, method, options) { | |
20 var self = this, | |
21 S = this.S; | |
22 | |
23 // Store the default active tabs which will be referenced when the | |
24 // location hash is absent, as in the case of navigating the tabs and | |
25 // returning to the first viewing via the browser Back button. | |
26 S('[' + this.attr_name() + '] > .active > a', this.scope).each(function () { | |
27 self.default_tab_hashes.push(this.hash); | |
28 }); | |
29 | |
30 this.bindings(method, options); | |
31 this.handle_location_hash_change(); | |
32 }, | |
33 | |
34 events : function () { | |
35 var self = this, | |
36 S = this.S; | |
37 | |
38 var usual_tab_behavior = function (e, target) { | |
39 var settings = S(target).closest('[' + self.attr_name() + ']').data(self.attr_name(true) + '-init'); | |
40 if (!settings.is_hover || Modernizr.touch) { | |
41 // if user did not pressed tab key, prevent default action | |
42 var keyCode = e.keyCode || e.which; | |
43 if (keyCode !== 9) { | |
44 e.preventDefault(); | |
45 e.stopPropagation(); | |
46 } | |
47 self.toggle_active_tab(S(target).parent()); | |
48 | |
49 } | |
50 }; | |
51 | |
52 S(this.scope) | |
53 .off('.tab') | |
54 // Key event: focus/tab key | |
55 .on('keydown.fndtn.tab', '[' + this.attr_name() + '] > * > a', function(e) { | |
56 var keyCode = e.keyCode || e.which; | |
57 // if user pressed tab key | |
58 if (keyCode === 13 || keyCode === 32) { // enter or space | |
59 var el = this; | |
60 usual_tab_behavior(e, el); | |
61 } | |
62 }) | |
63 // Click event: tab title | |
64 .on('click.fndtn.tab', '[' + this.attr_name() + '] > * > a', function(e) { | |
65 var el = this; | |
66 usual_tab_behavior(e, el); | |
67 }) | |
68 // Hover event: tab title | |
69 .on('mouseenter.fndtn.tab', '[' + this.attr_name() + '] > * > a', function (e) { | |
70 var settings = S(this).closest('[' + self.attr_name() + ']').data(self.attr_name(true) + '-init'); | |
71 if (settings.is_hover) { | |
72 self.toggle_active_tab(S(this).parent()); | |
73 } | |
74 }); | |
75 | |
76 // Location hash change event | |
77 S(window).on('hashchange.fndtn.tab', function (e) { | |
78 e.preventDefault(); | |
79 self.handle_location_hash_change(); | |
80 }); | |
81 }, | |
82 | |
83 handle_location_hash_change : function () { | |
84 | |
85 var self = this, | |
86 S = this.S; | |
87 | |
88 S('[' + this.attr_name() + ']', this.scope).each(function () { | |
89 var settings = S(this).data(self.attr_name(true) + '-init'); | |
90 if (settings.deep_linking) { | |
91 // Match the location hash to a label | |
92 var hash; | |
93 if (settings.scroll_to_content) { | |
94 hash = self.scope.location.hash; | |
95 } else { | |
96 // prefix the hash to prevent anchor scrolling | |
97 hash = self.scope.location.hash.replace('fndtn-', ''); | |
98 } | |
99 if (hash != '') { | |
100 // Check whether the location hash references a tab content div or | |
101 // another element on the page (inside or outside the tab content div) | |
102 var hash_element = S(hash); | |
103 if (hash_element.hasClass('content') && hash_element.parent().hasClass('tabs-content')) { | |
104 // Tab content div | |
105 self.toggle_active_tab($('[' + self.attr_name() + '] > * > a[href=' + hash + ']').parent()); | |
106 } else { | |
107 // Not the tab content div. If inside the tab content, find the | |
108 // containing tab and toggle it as active. | |
109 var hash_tab_container_id = hash_element.closest('.content').attr('id'); | |
110 if (hash_tab_container_id != undefined) { | |
111 self.toggle_active_tab($('[' + self.attr_name() + '] > * > a[href=#' + hash_tab_container_id + ']').parent(), hash); | |
112 } | |
113 } | |
114 } else { | |
115 // Reference the default tab hashes which were initialized in the init function | |
116 for (var ind = 0; ind < self.default_tab_hashes.length; ind++) { | |
117 self.toggle_active_tab($('[' + self.attr_name() + '] > * > a[href=' + self.default_tab_hashes[ind] + ']').parent()); | |
118 } | |
119 } | |
120 } | |
121 }); | |
122 }, | |
123 | |
124 toggle_active_tab : function (tab, location_hash) { | |
125 var self = this, | |
126 S = self.S, | |
127 tabs = tab.closest('[' + this.attr_name() + ']'), | |
128 tab_link = tab.find('a'), | |
129 anchor = tab.children('a').first(), | |
130 target_hash = '#' + anchor.attr('href').split('#')[1], | |
131 target = S(target_hash), | |
132 siblings = tab.siblings(), | |
133 settings = tabs.data(this.attr_name(true) + '-init'), | |
134 interpret_keyup_action = function (e) { | |
135 // Light modification of Heydon Pickering's Practical ARIA Examples: http://heydonworks.com/practical_aria_examples/js/a11y.js | |
136 | |
137 // define current, previous and next (possible) tabs | |
138 | |
139 var $original = $(this); | |
140 var $prev = $(this).parents('li').prev().children('[role="tab"]'); | |
141 var $next = $(this).parents('li').next().children('[role="tab"]'); | |
142 var $target; | |
143 | |
144 // find the direction (prev or next) | |
145 | |
146 switch (e.keyCode) { | |
147 case 37: | |
148 $target = $prev; | |
149 break; | |
150 case 39: | |
151 $target = $next; | |
152 break; | |
153 default: | |
154 $target = false | |
155 break; | |
156 } | |
157 | |
158 if ($target.length) { | |
159 $original.attr({ | |
160 'tabindex' : '-1', | |
161 'aria-selected' : null | |
162 }); | |
163 $target.attr({ | |
164 'tabindex' : '0', | |
165 'aria-selected' : true | |
166 }).focus(); | |
167 } | |
168 | |
169 // Hide panels | |
170 | |
171 $('[role="tabpanel"]') | |
172 .attr('aria-hidden', 'true'); | |
173 | |
174 // Show panel which corresponds to target | |
175 | |
176 $('#' + $(document.activeElement).attr('href').substring(1)) | |
177 .attr('aria-hidden', null); | |
178 | |
179 }, | |
180 go_to_hash = function(hash) { | |
181 // This function allows correct behaviour of the browser's back button when deep linking is enabled. Without it | |
182 // the user would get continually redirected to the default hash. | |
183 var default_hash = settings.scroll_to_content ? self.default_tab_hashes[0] : 'fndtn-' + self.default_tab_hashes[0].replace('#', ''); | |
184 | |
185 if (hash !== default_hash || window.location.hash) { | |
186 window.location.hash = hash; | |
187 } | |
188 }; | |
189 | |
190 // allow usage of data-tab-content attribute instead of href | |
191 if (anchor.data('tab-content')) { | |
192 target_hash = '#' + anchor.data('tab-content').split('#')[1]; | |
193 target = S(target_hash); | |
194 } | |
195 | |
196 if (settings.deep_linking) { | |
197 | |
198 if (settings.scroll_to_content) { | |
199 | |
200 // retain current hash to scroll to content | |
201 go_to_hash(location_hash || target_hash); | |
202 | |
203 if (location_hash == undefined || location_hash == target_hash) { | |
204 tab.parent()[0].scrollIntoView(); | |
205 } else { | |
206 S(target_hash)[0].scrollIntoView(); | |
207 } | |
208 } else { | |
209 // prefix the hashes so that the browser doesn't scroll down | |
210 if (location_hash != undefined) { | |
211 go_to_hash('fndtn-' + location_hash.replace('#', '')); | |
212 } else { | |
213 go_to_hash('fndtn-' + target_hash.replace('#', '')); | |
214 } | |
215 } | |
216 } | |
217 | |
218 // WARNING: The activation and deactivation of the tab content must | |
219 // occur after the deep linking in order to properly refresh the browser | |
220 // window (notably in Chrome). | |
221 // Clean up multiple attr instances to done once | |
222 tab.addClass(settings.active_class).triggerHandler('opened'); | |
223 tab_link.attr({'aria-selected' : 'true', tabindex : 0}); | |
224 siblings.removeClass(settings.active_class) | |
225 siblings.find('a').attr({'aria-selected' : 'false'/*, tabindex : -1*/}); | |
226 target.siblings().removeClass(settings.active_class).attr({'aria-hidden' : 'true'/*, tabindex : -1*/}); | |
227 target.addClass(settings.active_class).attr('aria-hidden', 'false').removeAttr('tabindex'); | |
228 settings.callback(tab); | |
229 target.triggerHandler('toggled', [target]); | |
230 tabs.triggerHandler('toggled', [tab]); | |
231 | |
232 tab_link.off('keydown').on('keydown', interpret_keyup_action ); | |
233 }, | |
234 | |
235 data_attr : function (str) { | |
236 if (this.namespace.length > 0) { | |
237 return this.namespace + '-' + str; | |
238 } | |
239 | |
240 return str; | |
241 }, | |
242 | |
243 off : function () {}, | |
244 | |
245 reflow : function () {} | |
246 }; | |
247 }(jQuery, window, window.document)); |