/**
* @file Tabs plugin
*/
/**
* Create global UCASDesignFramework object if it doesn't already exist
*/
var UCASDesignFramework = UCASDesignFramework || {};
/**
* Main IIFE function
*/
(function(global, $, scope){
"use strict";
/**
* Namespaced object for tabs module
* (overwriting any previously created tabs module)
*/
global.tabs = {};
/**
* Support legacy usage
* This adds a tabs-container attribute to every .tabs-container that doesn't already have one
*/
function legacy() {
// Support legacy usage methods
$('.tabs-container').each(function(){
if (!$(this).attr('data-tabs-container')) {
$(this).attr('data-tabs-container',Date.now());
}
});
}
/**
* Initialise plugin
* This loops through every .tabs-container and calls bindListeners with the respective tab ID
*
*/
function init() {
legacy();
$('.tabs-container').each(function(){
bindListeners($(this).attr('data-tabs-container'));
});
}
/**
* Binds all event listeners with optional scope
*
* @param {string} [tabsContainer] - The tabs container ID
*/
function bindListeners(tabsContainer) {
var context = getContext(tabsContainer);
// Bindings
$('[data-tab]', context).on('click.tabs', function(ev) {
activateTab(this);
ev.preventDefault();
});
// Check if tabs should be fixed height
if ($('.tabs-container--fixed-height', context).length) {
// If so attach calculateHeight to resize event
$(window).on('resize.tabs', calculateHeight);
// Set the height on initialisation
calculateHeight();
}
}
/**
* Determine context
*
* @param {string} [tabsContainer] - The tabs container ID
* @return {HTMLElement} - The context
*/
function getContext(tabsContainer) {
return (tabsContainer) ? $('[data-tabs-container="' + tabsContainer + '"]') : document;
}
/**
* Removes all traces of plugin with optional scope
*
* @param {string} [tabsContainerID] - The tab container ID
*/
function destroy(tabsContainer) {
var context = getContext(tabsContainer);
// Unbind click event listeners
$('[data-tab]', context).off('click.tabs');
// Re-attach prevent default temporarily @todo come up with better way of handling default click event
$('[data-tab]', context).on('click.temp', function(ev) {
ev.preventDefault();
});
// Unbind resize event listener if fixed height tabs
if ($('.tabs-container--fixed-height', context).length) {
$(window).off('resize.tabs', calculateHeight);
}
}
/**
* Calls destroy() method and adds disabled class
*
* @param {string} [tabsContainerID] - The tab container ID
*/
function disable(tabsContainer) {
var context = getContext(tabsContainer);
destroy(tabsContainer);
$('.tabs__tab:not(".tabs__tab--active")', context).addClass('tabs__tab--disabled');
}
/**
* Re-enables tabs plugin globally or with optional scope
*
* @param {string} [tabsContainerID] - The tab container ID
*/
function enable(tabsContainer) {
destroy(tabsContainer);
var context = getContext(tabsContainer);
// Remove temporary prevent default
$('[data-tab]', context).off('click.temp');
// Re-initialise plugin
bindListeners(tabsContainer);
// Remove disabled class
$('.tabs__tab--disabled', context).removeClass('tabs__tab--disabled');
}
/**
* Sets the height of all tabs to be the same on all .tabs-container--fixed-height with optional scope
*
* @param {string} [tabsContainerID] - The tab container ID
*/
function calculateHeight(tabsContainer) {
var context = getContext(tabsContainer);
// Remove any existing style attributes.
$('.tabs-container--fixed-height .tabs__content', context).css('height', '');
// Loop through all containers on the page in the case of multiple.
$('.tabs-container--fixed-height', context).each(function() {
var tabsHeight = $(this).find('.tabs__tab-container').outerHeight();
var containerContent = $(this).find('.tabs__content');
// Loop through each content panel and calculate the one with the largest height.
containerContent.each(function () {
var height = $(this).outerHeight();
if (height >= tabsHeight) {
tabsHeight = height;
}
});
// Apply largest height to all content panels.
containerContent.css('height', tabsHeight);
});
}
/**
* Displays the referenced tab panel and hides others
* adds styling to active tab
*
* @params {HTMLElement} - DOM node to activate
*/
function activateTab(element) {
$(element).addClass('tabs__tab--active').siblings('[data-tab]').removeClass('tabs__tab--active');
$(element).parent().siblings('[data-content=' + $(element).data('tab') + ']').addClass('tabs__content--active').siblings('[data-content]').removeClass('tabs__content--active');
}
/**
* Map functions to global (public) object
*
* @return {object} global - The global object
*/
return global.tabs.init = init,
global.tabs.destroy = destroy,
global.tabs.disable = disable,
global.tabs.enable = enable;
})(UCASDesignFramework, jQuery, document);