/*jslint unparam: true, browser: true, indent: 2 */ ;(function ($, window, document, undefined) { 'use strict'; Foundation.libs.section = { name: 'section', version : '4.2.0', settings : { deep_linking: false, one_up: true, section_selector : '[data-section]', region_selector : 'section, .section, [data-section-region]', title_selector : '.title, [data-section-title]', active_region_selector : 'section.active, .section.active, .active[data-section-region]', content_selector : '.content, [data-section-content]', nav_selector : '[data-section="vertical-nav"], [data-section="horizontal-nav"]', 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.set_active_from_hash(); this.events(); return true; } else { return this[method].call(this, options); } }, events : function () { var self = this; $(this.scope) .on('click.fndtn.section', '[data-section] .title, [data-section] [data-section-title]', function (e) { var $this = $(this), section = $this.closest(self.settings.region_selector); if (section.children(self.settings.content_selector).length > 0) { self.toggle_active.call(this, e, self); self.reflow(); } }); $(window) .on('resize.fndtn.section', self.throttle(function () { self.resize.call(this); }, 30)) .on('hashchange', function () { if (!self.settings.toggled){ self.set_active_from_hash(); $(this).trigger('resize'); } }).trigger('resize'); $(document) .on('click.fndtn.section', function (e) { if ($(e.target).closest(self.settings.title_selector).length < 1) { $(self.settings.nav_selector) .children(self.settings.region_selector) .removeClass('active') .attr('style', ''); } }); }, toggle_active : function (e, self) { var $this = $(this), self = Foundation.libs.section, region = $this.closest(self.settings.region_selector), content = $this.siblings(self.settings.content_selector), parent = region.parent(), settings = $.extend({}, self.settings, self.data_options(parent)), prev_active_section = parent .children(self.settings.active_region_selector); self.settings.toggled = true; if (!settings.deep_linking && content.length > 0) { e.preventDefault(); } if (region.hasClass('active')) { // this is causing the style flash. if (self.small(parent) || self.is_vertical_nav(parent) || self.is_horizontal_nav(parent) || self.is_accordion(parent)) { if (prev_active_section[0] !== region[0] || (prev_active_section[0] === region[0] && !settings.one_up)) { region .removeClass('active') .attr('style', ''); } } } else { var prev_active_section = parent .children(self.settings.active_region_selector), title_height = self.outerHeight(region .children(self.settings.title_selector)); if (self.small(parent) || settings.one_up) { if (self.small(parent)) { prev_active_section.attr('style', ''); } else { prev_active_section.attr('style', 'visibility: hidden; padding-top: '+title_height+'px;'); } } if (self.small(parent)) { region.attr('style', ''); } else { region.css('padding-top', title_height); } region.addClass('active'); if (prev_active_section.length > 0) { prev_active_section .removeClass('active') .attr('style', ''); } // Toggle the content display attribute. This is done to // ensure accurate outerWidth measurements that account for // the scrollbar. if (self.is_vertical_tabs(parent)) { content.css('display', 'block'); if (prev_active_section !== null) { prev_active_section .children(self.settings.content_selector) .css('display', 'none'); } } } setTimeout(function () { self.settings.toggled = false; }, 300); settings.callback(); }, resize : function () { var self = Foundation.libs.section, sections = $(self.settings.section_selector); sections.each(function() { var $this = $(this), active_section = $this .children(self.settings.active_region_selector), settings = $.extend({}, self.settings, self.data_options($this)); if (active_section.length > 1) { active_section .not(':first') .removeClass('active') .attr('style', ''); } else if (active_section.length < 1 && !self.is_vertical_nav($this) && !self.is_horizontal_nav($this) && !self.is_accordion($this)) { var first = $this.children(self.settings.region_selector).first(); if (settings.one_up || !self.small($this)) { first.addClass('active'); } if (self.small($this)) { first.attr('style', ''); } else { first.css('padding-top', self.outerHeight(first .children(self.settings.title_selector))); } } if (self.small($this)) { active_section.attr('style', ''); } else { active_section.css('padding-top', self.outerHeight(active_section .children(self.settings.title_selector))); } self.position_titles($this); if ( (self.is_horizontal_nav($this) && !self.small($this)) || self.is_vertical_tabs($this) && !self.small($this)) { self.position_content($this); } else { self.position_content($this, false); } }); }, 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')); }, set_active_from_hash : function () { var hash = window.location.hash.substring(1), sections = $('[data-section]'), self = this; sections.each(function () { var section = $(this), settings = $.extend({}, self.settings, self.data_options(section)); if (hash.length > 0 && settings.deep_linking) { var regions = section .children(self.settings.region_selector) .attr('style', '') .removeClass('active'); var hash_regions = regions.map(function () { var content = $(self.settings.content_selector, this), content_slug = content.data('slug'); if (new RegExp(content_slug, 'i').test(hash)) return content; }); var count = hash_regions.length; for (var i = count - 1; i >= 0; i--) { $(hash_regions[i]).parent().addClass('active'); } } }); }, position_titles : function (section, off) { var self = this, titles = section .children(this.settings.region_selector) .map(function () { return $(this).children(self.settings.title_selector); }), previous_width = 0, previous_height = 0, self = this; if (typeof off === 'boolean') { titles.attr('style', ''); } else { titles.each(function () { if (self.is_vertical_tabs(section)) { $(this).css('top', previous_height); previous_height += self.outerHeight($(this)); } else { if (!self.rtl) { $(this).css('left', previous_width); } else { $(this).css('right', previous_width); } previous_width += self.outerWidth($(this)); } }); } }, position_content : function (section, off) { var self = this, regions = section.children(self.settings.region_selector), titles = regions .map(function () { return $(this).children(self.settings.title_selector); }), content = regions .map(function () { return $(this).children(self.settings.content_selector); }); if (typeof off === 'boolean') { content.attr('style', ''); section.attr('style', ''); } else { if (self.is_vertical_tabs(section) && !self.small(section)) { var content_min_height = 0, content_min_width = Number.MAX_VALUE, title_width = null; regions.each(function () { var region = $(this), title = region.children(self.settings.title_selector), content = region.children(self.settings.content_selector), content_width = 0; title_width = self.outerWidth(title); content_width = self.outerWidth(section) - title_width; if (content_width < content_min_width) { content_min_width = content_width; } // Increment the minimum height of the content region // to align with the height of the titles. content_min_height += self.outerHeight(title); // Set all of the inactive tabs to 'display: none' // The CSS sets all of the tabs as 'display: block' // in order to account for scrollbars when measuring the width // of the content regions. if (!$(this).hasClass('active')) { content.css('display', 'none'); } }); regions.each(function () { var content = $(this).children(self.settings.content_selector); content.css('minHeight', content_min_height); // Remove 2 pixels to account for the right-shift in the CSS content.css('maxWidth', content_min_width - 2); }); } else { regions.each(function () { var region = $(this), title = region.children(self.settings.title_selector), content = region.children(self.settings.content_selector); if (!self.rtl) { content .css({left: title.position().left - 1, top: self.outerHeight(title) - 2}); } else { content .css({right: self.position_right(title) + 1, top: self.outerHeight(title) - 2}); } }); // temporary work around for Zepto outerheight calculation issues. if (typeof Zepto === 'function') { section.height(this.outerHeight($(titles[0]))); } else { section.height(this.outerHeight($(titles[0])) - 2); } } } }, position_right : function (el) { var self = this, section = el.closest(this.settings.section_selector), regions = section.children(this.settings.region_selector), section_width = el.closest(this.settings.section_selector).width(), offset = regions .map(function () { return $(this).children(self.settings.title_selector); }).length; return (section_width - el.position().left - el.width() * (el.index() + 1) - offset); }, reflow : function (scope) { var scope = scope || document; $(this.settings.section_selector, scope).trigger('resize'); }, 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() < 768; }, off : function () { $(this.scope).off('.fndtn.section'); $(window).off('.fndtn.section'); $(document).off('.fndtn.section') } }; }(Foundation.zj, this, this.document));