Source: components/tabs/_tabs.js

/**
 * @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);