You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
6.3 KiB
167 lines
6.3 KiB
;(function ($, window, document, undefined) { |
|
'use strict'; |
|
|
|
Foundation.libs.tab = { |
|
name : 'tab', |
|
|
|
version : '5.3.3', |
|
|
|
settings : { |
|
active_class: 'active', |
|
callback : function () {}, |
|
deep_linking: false, |
|
scroll_to_content: true, |
|
is_hover: false |
|
}, |
|
|
|
default_tab_hashes: [], |
|
|
|
init : function (scope, method, options) { |
|
var self = this, |
|
S = this.S; |
|
|
|
this.bindings(method, options); |
|
this.handle_location_hash_change(); |
|
|
|
// Store the default active tabs which will be referenced when the |
|
// location hash is absent, as in the case of navigating the tabs and |
|
// returning to the first viewing via the browser Back button. |
|
S('[' + this.attr_name() + '] > .active > a', this.scope).each(function () { |
|
self.default_tab_hashes.push(this.hash); |
|
}); |
|
}, |
|
|
|
events : function () { |
|
var self = this, |
|
S = this.S; |
|
|
|
S(this.scope) |
|
.off('.tab') |
|
// Click event: tab title |
|
.on('click.fndtn.tab', '[' + this.attr_name() + '] > * > a', function (e) { |
|
var settings = S(this).closest('[' + self.attr_name() +']').data(self.attr_name(true) + '-init'); |
|
if (!settings.is_hover || Modernizr.touch) { |
|
e.preventDefault(); |
|
e.stopPropagation(); |
|
self.toggle_active_tab(S(this).parent()); |
|
} |
|
}) |
|
// Hover event: tab title |
|
.on('mouseenter.fndtn.tab', '[' + this.attr_name() + '] > * > a', function (e) { |
|
var settings = S(this).closest('[' + self.attr_name() +']').data(self.attr_name(true) + '-init'); |
|
if (settings.is_hover) self.toggle_active_tab(S(this).parent()); |
|
}); |
|
|
|
// Location hash change event |
|
S(window).on('hashchange.fndtn.tab', function (e) { |
|
e.preventDefault(); |
|
self.handle_location_hash_change(); |
|
}); |
|
}, |
|
|
|
handle_location_hash_change : function () { |
|
var self = this, |
|
S = this.S; |
|
|
|
S('[' + this.attr_name() + ']', this.scope).each(function () { |
|
var settings = S(this).data(self.attr_name(true) + '-init'); |
|
if (settings.deep_linking) { |
|
// Match the location hash to a label |
|
var hash = self.scope.location.hash; |
|
if (hash != '') { |
|
// Check whether the location hash references a tab content div or |
|
// another element on the page (inside or outside the tab content div) |
|
var hash_element = S(hash); |
|
if (hash_element.hasClass('content') && hash_element.parent().hasClass('tab-content')) { |
|
// Tab content div |
|
self.toggle_active_tab($('[' + self.attr_name() + '] > * > a[href=' + hash + ']').parent()); |
|
} else { |
|
// Not the tab content div. If inside the tab content, find the |
|
// containing tab and toggle it as active. |
|
var hash_tab_container_id = hash_element.closest('.content').attr('id'); |
|
if (hash_tab_container_id != undefined) { |
|
self.toggle_active_tab($('[' + self.attr_name() + '] > * > a[href=#' + hash_tab_container_id + ']').parent(), hash); |
|
} |
|
} |
|
} else { |
|
// Reference the default tab hashes which were initialized in the init function |
|
for (var ind in self.default_tab_hashes) { |
|
self.toggle_active_tab($('[' + self.attr_name() + '] > * > a[href=' + self.default_tab_hashes[ind] + ']').parent()); |
|
} |
|
} |
|
} |
|
}); |
|
}, |
|
|
|
toggle_active_tab: function (tab, location_hash) { |
|
var S = this.S, |
|
tabs = tab.closest('[' + this.attr_name() + ']'), |
|
anchor = tab.children('a').first(), |
|
target_hash = '#' + anchor.attr('href').split('#')[1], |
|
target = S(target_hash), |
|
siblings = tab.siblings(), |
|
settings = tabs.data(this.attr_name(true) + '-init'); |
|
|
|
// allow usage of data-tab-content attribute instead of href |
|
if (S(this).data(this.data_attr('tab-content'))) { |
|
target_hash = '#' + S(this).data(this.data_attr('tab-content')).split('#')[1]; |
|
target = S(target_hash); |
|
} |
|
|
|
if (settings.deep_linking) { |
|
// Get the scroll Y position prior to moving to the hash ID |
|
var cur_ypos = $('body,html').scrollTop(); |
|
|
|
// Update the location hash to preserve browser history |
|
// Note that the hash does not need to correspond to the |
|
// tab content ID anchor; it can be an ID inside or outside of the tab |
|
// content div. |
|
if (location_hash != undefined) { |
|
window.location.hash = location_hash; |
|
} else { |
|
window.location.hash = target_hash; |
|
} |
|
|
|
if (settings.scroll_to_content) { |
|
// If the user is requesting the content of a tab, then scroll to the |
|
// top of the title area; otherwise, scroll to the element within |
|
// the content area as defined by the hash value. |
|
if (location_hash == undefined || location_hash == target_hash) { |
|
tab.parent()[0].scrollIntoView(); |
|
} else { |
|
S(target_hash)[0].scrollIntoView(); |
|
} |
|
} else { |
|
// Adjust the scrollbar to the Y position prior to setting the hash |
|
// Only do this for the tab content anchor, otherwise there will be |
|
// conflicts with in-tab anchor links nested in the tab-content div |
|
if (location_hash == undefined || location_hash == target_hash) { |
|
$('body,html').scrollTop(cur_ypos); |
|
} |
|
} |
|
} |
|
|
|
// WARNING: The activation and deactivation of the tab content must |
|
// occur after the deep linking in order to properly refresh the browser |
|
// window (notably in Chrome). |
|
tab.addClass(settings.active_class).triggerHandler('opened'); |
|
siblings.removeClass(settings.active_class); |
|
target.siblings().removeClass(settings.active_class).end().addClass(settings.active_class); |
|
settings.callback(tab); |
|
target.triggerHandler('toggled', [tab]); |
|
tabs.triggerHandler('toggled', [target]); |
|
}, |
|
|
|
data_attr: function (str) { |
|
if (this.namespace.length > 0) { |
|
return this.namespace + '-' + str; |
|
} |
|
|
|
return str; |
|
}, |
|
|
|
off : function () {}, |
|
|
|
reflow : function () {} |
|
}; |
|
}(jQuery, window, window.document));
|
|
|