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.
401 lines
15 KiB
401 lines
15 KiB
11 years ago
|
/*jslint unparam: true, browser: true, indent: 2 */
|
||
|
|
||
|
;
|
||
|
(function($, window, document) {
|
||
|
'use strict';
|
||
|
|
||
|
Foundation.libs.section = {
|
||
|
name : 'section',
|
||
|
|
||
|
version : '4.3.1',
|
||
|
|
||
|
settings: {
|
||
|
deep_linking: false,
|
||
|
small_breakpoint: 768,
|
||
|
one_up: true,
|
||
|
section_selector: '[data-section]',
|
||
|
region_selector: 'section, .section, [data-section-region]',
|
||
|
title_selector: '.title, [data-section-title]',
|
||
|
//marker: container is resized
|
||
|
resized_data_attr: 'data-section-resized',
|
||
|
//marker: container should apply accordion style
|
||
|
small_style_data_attr: 'data-section-small-style',
|
||
|
content_selector: '.content, [data-section-content]',
|
||
|
nav_selector: '[data-section="vertical-nav"], [data-section="horizontal-nav"]',
|
||
|
active_class: 'active',
|
||
|
callback: function() {}
|
||
|
},
|
||
|
|
||
|
init: function(scope, method, options) {
|
||
|
var self = this;
|
||
|
Foundation.inherit(this, 'throttle data_options position_right offset_right');
|
||
|
|
||
|
if (typeof method === 'object') {
|
||
|
$.extend(true, self.settings, method);
|
||
|
}
|
||
|
|
||
|
if (typeof method !== 'string') {
|
||
|
this.events();
|
||
|
return true;
|
||
|
} else {
|
||
|
return this[method].call(this, options);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
events: function() {
|
||
|
var self = this;
|
||
|
|
||
|
//combine titles selector from settings for click event binding
|
||
|
var click_title_selectors = [],
|
||
|
section_selector = self.settings.section_selector,
|
||
|
region_selectors = self.settings.region_selector.split(","),
|
||
|
title_selectors = self.settings.title_selector.split(",");
|
||
|
|
||
|
for (var i = 0, len = region_selectors.length; i < len; i++) {
|
||
|
var region_selector = region_selectors[i];
|
||
|
|
||
|
for (var j = 0, len1 = title_selectors.length; j < len1; j++) {
|
||
|
var title_selector = section_selector + ">" + region_selector + ">" + title_selectors[j];
|
||
|
|
||
|
click_title_selectors.push(title_selector + " a"); //or we can not do preventDefault for click event of <a>
|
||
|
click_title_selectors.push(title_selector);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$(self.scope)
|
||
|
.on('click.fndtn.section', click_title_selectors.join(","), function(e) {
|
||
|
var title = $(this).closest(self.settings.title_selector);
|
||
|
|
||
|
self.close_navs(title);
|
||
|
if (title.siblings(self.settings.content_selector).length > 0) {
|
||
|
self.toggle_active.call(title[0], e);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
$(window)
|
||
|
.on('resize.fndtn.section', self.throttle(function() { self.resize(); }, 30))
|
||
|
.on('hashchange.fndtn.section', self.set_active_from_hash);
|
||
|
|
||
|
$(document).on('click.fndtn.section', function (e) {
|
||
|
if (e.isPropagationStopped && e.isPropagationStopped()) return;
|
||
|
if (e.target === document) return;
|
||
|
self.close_navs($(e.target).closest(self.settings.title_selector));
|
||
|
});
|
||
|
|
||
|
$(window).triggerHandler('resize.fndtn.section');
|
||
|
$(window).triggerHandler('hashchange.fndtn.section');
|
||
|
},
|
||
|
|
||
|
//close nav !one_up on click elsewhere
|
||
|
close_navs: function(except_nav_with_title) {
|
||
|
var self = Foundation.libs.section,
|
||
|
navsToClose = $(self.settings.nav_selector)
|
||
|
.filter(function() { return !$.extend({},
|
||
|
self.settings, self.data_options($(this))).one_up; });
|
||
|
|
||
|
if (except_nav_with_title.length > 0) {
|
||
|
var section = except_nav_with_title.parent().parent();
|
||
|
|
||
|
if (self.is_horizontal_nav(section) || self.is_vertical_nav(section)) {
|
||
|
//exclude current nav from list
|
||
|
navsToClose = navsToClose.filter(function() { return this !== section[0]; });
|
||
|
}
|
||
|
}
|
||
|
//close navs on click on title
|
||
|
navsToClose.children(self.settings.region_selector).removeClass(self.settings.active_class);
|
||
|
},
|
||
|
|
||
|
toggle_active: function(e) {
|
||
|
var $this = $(this),
|
||
|
self = Foundation.libs.section,
|
||
|
region = $this.parent(),
|
||
|
content = $this.siblings(self.settings.content_selector),
|
||
|
section = region.parent(),
|
||
|
settings = $.extend({}, self.settings, self.data_options(section)),
|
||
|
prev_active_region = section.children(self.settings.region_selector).filter("." + self.settings.active_class);
|
||
|
|
||
|
//for anchors inside [data-section-title]
|
||
|
if (!settings.deep_linking && content.length > 0) {
|
||
|
e.preventDefault();
|
||
|
}
|
||
|
|
||
|
e.stopPropagation(); //do not catch same click again on parent
|
||
|
|
||
|
if (!region.hasClass(self.settings.active_class)) {
|
||
|
prev_active_region.removeClass(self.settings.active_class);
|
||
|
region.addClass(self.settings.active_class);
|
||
|
//force resize for better performance (do not wait timer)
|
||
|
self.resize(region.find(self.settings.section_selector).not("[" + self.settings.resized_data_attr + "]"), true);
|
||
|
} else if (!settings.one_up && (self.small(section) || self.is_vertical_nav(section) || self.is_horizontal_nav(section) || self.is_accordion(section))) {
|
||
|
region.removeClass(self.settings.active_class);
|
||
|
}
|
||
|
settings.callback(section);
|
||
|
},
|
||
|
|
||
|
check_resize_timer: null,
|
||
|
|
||
|
//main function that sets title and content positions; runs for :not(.resized) and :visible once when window width is medium up
|
||
|
//sections:
|
||
|
// selected sections to resize, are defined on resize forced by visibility changes
|
||
|
//ensure_has_active_region:
|
||
|
// is true when we force resize for no resized sections that were hidden and became visible,
|
||
|
// these sections can have no selected region, because all regions were hidden along with section on executing set_active_from_hash
|
||
|
resize: function(sections, ensure_has_active_region) {
|
||
|
|
||
|
var self = Foundation.libs.section,
|
||
|
is_small_window = self.small($(document)),
|
||
|
//filter for section resize
|
||
|
should_be_resized = function (section, now_is_hidden) {
|
||
|
return !self.is_accordion(section) &&
|
||
|
!section.is("[" + self.settings.resized_data_attr + "]") &&
|
||
|
(!is_small_window || self.is_horizontal_tabs(section)) &&
|
||
|
now_is_hidden === (section.css('display') === 'none' ||
|
||
|
!section.parent().is(':visible'));
|
||
|
};
|
||
|
|
||
|
sections = sections || $(self.settings.section_selector);
|
||
|
|
||
|
clearTimeout(self.check_resize_timer);
|
||
|
|
||
|
if (!is_small_window) {
|
||
|
sections.removeAttr(self.settings.small_style_data_attr);
|
||
|
}
|
||
|
|
||
|
//resize
|
||
|
sections.filter(function() { return should_be_resized($(this), false); })
|
||
|
.each(function() {
|
||
|
var section = $(this),
|
||
|
regions = section.children(self.settings.region_selector),
|
||
|
titles = regions.children(self.settings.title_selector),
|
||
|
content = regions.children(self.settings.content_selector),
|
||
|
titles_max_height = 0;
|
||
|
|
||
|
if (ensure_has_active_region &&
|
||
|
section.children(self.settings.region_selector).filter("." + self.settings.active_class).length == 0) {
|
||
|
var settings = $.extend({}, self.settings, self.data_options(section));
|
||
|
|
||
|
if (!settings.deep_linking && (settings.one_up || !self.is_horizontal_nav(section) &&
|
||
|
!self.is_vertical_nav(section) && !self.is_accordion(section))) {
|
||
|
regions.filter(":visible").first().addClass(self.settings.active_class);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (self.is_horizontal_tabs(section) || self.is_auto(section)) {
|
||
|
// region: position relative
|
||
|
// title: position absolute
|
||
|
// content: position static
|
||
|
var titles_sum_width = 0;
|
||
|
|
||
|
titles.each(function() {
|
||
|
var title = $(this);
|
||
|
|
||
|
if (title.is(":visible")) {
|
||
|
title.css(!self.rtl ? 'left' : 'right', titles_sum_width);
|
||
|
var title_h_border_width = parseInt(title.css("border-" + (self.rtl ? 'left' : 'right') + "-width"), 10);
|
||
|
|
||
|
if (title_h_border_width.toString() === 'Nan') {
|
||
|
title_h_border_width = 0;
|
||
|
}
|
||
|
|
||
|
titles_sum_width += self.outerWidth(title) - title_h_border_width;
|
||
|
titles_max_height = Math.max(titles_max_height, self.outerHeight(title));
|
||
|
}
|
||
|
});
|
||
|
titles.css('height', titles_max_height);
|
||
|
regions.each(function() {
|
||
|
var region = $(this),
|
||
|
region_content = region.children(self.settings.content_selector),
|
||
|
content_top_border_width = parseInt(region_content.css("border-top-width"), 10);
|
||
|
|
||
|
if (content_top_border_width.toString() === 'Nan') {
|
||
|
content_top_border_width = 0;
|
||
|
}
|
||
|
|
||
|
region.css('padding-top', titles_max_height - content_top_border_width);
|
||
|
});
|
||
|
|
||
|
section.css("min-height", titles_max_height);
|
||
|
} else if (self.is_horizontal_nav(section)) {
|
||
|
var first = true;
|
||
|
// region: positon relative, float left
|
||
|
// title: position static
|
||
|
// content: position absolute
|
||
|
titles.each(function() {
|
||
|
titles_max_height = Math.max(titles_max_height, self.outerHeight($(this)));
|
||
|
});
|
||
|
|
||
|
regions.each(function() {
|
||
|
var region = $(this);
|
||
|
|
||
|
region.css("margin-left", "-" + (first ? section : region.children(self.settings.title_selector)).css("border-left-width"));
|
||
|
first = false;
|
||
|
});
|
||
|
|
||
|
regions.css("margin-top", "-" + section.css("border-top-width"));
|
||
|
titles.css('height', titles_max_height);
|
||
|
content.css('top', titles_max_height);
|
||
|
section.css("min-height", titles_max_height);
|
||
|
} else if (self.is_vertical_tabs(section)) {
|
||
|
var titles_sum_height = 0;
|
||
|
// region: position relative, for .active: fixed padding==title.width
|
||
|
// title: fixed width, position absolute
|
||
|
// content: position static
|
||
|
titles.each(function() {
|
||
|
var title = $(this);
|
||
|
|
||
|
if (title.is(":visible")) {
|
||
|
title.css('top', titles_sum_height);
|
||
|
var title_top_border_width = parseInt(title.css("border-top-width"), 10);
|
||
|
|
||
|
if (title_top_border_width.toString() === 'Nan') {
|
||
|
title_top_border_width = 0;
|
||
|
}
|
||
|
|
||
|
titles_sum_height += self.outerHeight(title) - title_top_border_width;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
content.css('min-height', titles_sum_height + 1);
|
||
|
} else if (self.is_vertical_nav(section)) {
|
||
|
var titles_max_width = 0,
|
||
|
first1 = true;
|
||
|
// region: positon relative
|
||
|
// title: position static
|
||
|
// content: position absolute
|
||
|
titles.each(function() {
|
||
|
titles_max_width = Math.max(titles_max_width, self.outerWidth($(this)));
|
||
|
});
|
||
|
|
||
|
regions.each(function () {
|
||
|
var region = $(this);
|
||
|
|
||
|
region.css("margin-top", "-" + (first1 ? section : region.children(self.settings.title_selector)).css("border-top-width"));
|
||
|
first1 = false;
|
||
|
});
|
||
|
|
||
|
titles.css('width', titles_max_width);
|
||
|
content.css(!self.rtl ? 'left' : 'right', titles_max_width);
|
||
|
section.css('width', titles_max_width);
|
||
|
}
|
||
|
|
||
|
section.attr(self.settings.resized_data_attr, true);
|
||
|
});
|
||
|
|
||
|
//wait elements to become visible then resize
|
||
|
if ($(self.settings.section_selector).filter(function() { return should_be_resized($(this), true); }).length > 0)
|
||
|
self.check_resize_timer = setTimeout(function() {
|
||
|
self.resize(sections.filter(function() { return should_be_resized($(this), false); }), true);
|
||
|
}, 700);
|
||
|
|
||
|
if (is_small_window) {
|
||
|
sections.attr(self.settings.small_style_data_attr, true);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
is_vertical_nav: function(el) {
|
||
|
return /vertical-nav/i.test(el.data('section'));
|
||
|
},
|
||
|
|
||
|
is_horizontal_nav: function(el) {
|
||
|
return /horizontal-nav/i.test(el.data('section'));
|
||
|
},
|
||
|
|
||
|
is_accordion: function(el) {
|
||
|
return /accordion/i.test(el.data('section'));
|
||
|
},
|
||
|
|
||
|
is_horizontal_tabs: function(el) {
|
||
|
return /^tabs$/i.test(el.data('section'));
|
||
|
},
|
||
|
|
||
|
is_vertical_tabs: function(el) {
|
||
|
return /vertical-tabs/i.test(el.data('section'));
|
||
|
},
|
||
|
|
||
|
is_auto: function (el) {
|
||
|
var data_section = el.data('section');
|
||
|
return data_section === '' || /auto/i.test(data_section);
|
||
|
},
|
||
|
|
||
|
set_active_from_hash: function() {
|
||
|
var self = Foundation.libs.section,
|
||
|
hash = window.location.hash.substring(1),
|
||
|
sections = $(self.settings.section_selector);
|
||
|
|
||
|
sections.each(function() {
|
||
|
var section = $(this),
|
||
|
settings = $.extend({}, self.settings, self.data_options(section)),
|
||
|
regions = section.children(self.settings.region_selector),
|
||
|
set_active_from_hash = settings.deep_linking && hash.length > 0,
|
||
|
selected = false;
|
||
|
|
||
|
regions.each(function() {
|
||
|
var region = $(this);
|
||
|
|
||
|
if (selected) {
|
||
|
region.removeClass(self.settings.active_class);
|
||
|
} else if (set_active_from_hash) {
|
||
|
var data_slug = region.children(self.settings.content_selector).data('slug');
|
||
|
|
||
|
if (data_slug && new RegExp(data_slug, 'i').test(hash)) {
|
||
|
if (!region.hasClass(self.settings.active_class))
|
||
|
region.addClass(self.settings.active_class);
|
||
|
selected = true;
|
||
|
} else {
|
||
|
region.removeClass(self.settings.active_class);
|
||
|
}
|
||
|
} else if (region.hasClass(self.settings.active_class)) {
|
||
|
selected = true;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
if (!selected && !settings.deep_linking && (settings.one_up || !self.is_horizontal_nav(section) &&
|
||
|
!self.is_vertical_nav(section) && !self.is_accordion(section)))
|
||
|
regions.filter(":visible").first().addClass(self.settings.active_class);
|
||
|
});
|
||
|
},
|
||
|
|
||
|
reflow: function() {
|
||
|
var self = Foundation.libs.section;
|
||
|
|
||
|
$(self.settings.section_selector).removeAttr(self.settings.resized_data_attr);
|
||
|
self.throttle(function() { self.resize(); }, 30)();
|
||
|
},
|
||
|
|
||
|
small: function(el) {
|
||
|
var settings = $.extend({}, this.settings, this.data_options(el));
|
||
|
|
||
|
if (this.is_horizontal_tabs(el)) {
|
||
|
return false;
|
||
|
}
|
||
|
if (el && this.is_accordion(el)) {
|
||
|
return true;
|
||
|
}
|
||
|
if ($('html').hasClass('lt-ie9')) {
|
||
|
return true;
|
||
|
}
|
||
|
if ($('html').hasClass('ie8compat')) {
|
||
|
return true;
|
||
|
}
|
||
|
return $(this.scope).width() < settings.small_breakpoint;
|
||
|
},
|
||
|
|
||
|
off: function() {
|
||
|
$(this.scope).off('.fndtn.section');
|
||
|
$(window).off('.fndtn.section');
|
||
|
$(document).off('.fndtn.section');
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//resize selected sections
|
||
|
$.fn.reflow_section = function(ensure_has_active_region) {
|
||
|
var section = this,
|
||
|
self = Foundation.libs.section;
|
||
|
|
||
|
section.removeAttr(self.settings.resized_data_attr);
|
||
|
self.throttle(function() { self.resize(section, ensure_has_active_region); }, 30)();
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
}(Foundation.zj, window, document));
|