  /*****
    * @author jcfant@
    * @version 1.1.0
    *
    * Amazon Tabs
    * ===========================
    * Tabs is a module for displaying tab content. It supports the ability to load static content
    * as well as dynamic content via ajax.
    * 
    * Set up
    * ===========================
    * Tabs relies on certain items to be present in the DOM. Without these items, the tab functionality 
    * will not work properly, although tabs will not throw errors when these items are not present.
    *
    * DOM Set Up
    * ===========================
    * <div class="widget" id="widget1">
    *   <ul class="tabs-nav">
    *       <li class="tabs-selected"><a href="#"><span>Tab 1</span></a></li>
    *       <li class=""><a href="#"><span>Tab 2</span></a></li>
    *       <li class=""><a href="#"><span>Tab 3</span></a></li>
    *   </ul>
    *   <div class="tabs-panel">
    *       <div class="panels tab1" style="display: block">Tab 1</div>
    *       <div class="panels tab2" style="display: none">Tab 1</div>
    *       <div class="panels tab3" style="display: none">Tab 1</div>
    *   </div>          
    * </div>   
    *
    * Examples
    * ===========================
    * 1.) Getting the widget to load on document.ready (PREFERRED METHOD)
    *   $(document).ready(function() { $(".widget").tabs(); });
    *   
    * 2.) Example to start a widget as a tab widget, place the following code after the widget DOM has been setup.
    *   $(".widget").tabs()
    *   
    * 3.) Customizing the tab widget (see Options below)
    *   var options = {
    *                   debug   :   true
    *                   };
    *   $(".widget").tabs(options);
    *
    * Default Options
    * ===========================
    * 
    * 
    * var baseOptions = {
    *                     tabsClass     : '.tabs-nav > li', // jQuery CSS Selector
    *                     tabsSelected  : '.tabs-selected', // jQuery CSS Selector
    *                     tabPanels     : '.panels', // jQuery CSS Selector
    *                     tabPrefix     : '.tab', // jQuery CSS Selector
    *                     debug         : false
    * };
    * 
    * Passing In Callbacks using the default css selectors
    * ===========================
    *
    * var options = {
    *                 tab0    : {
    *                                 'onload' : function(mainTabId, tabPanel, options, data) { 
    *                                                 tab.html("SHOWING").show();
    *                                                 $.get("", function(d) { tab.html(d) });
    *                                            } , 
    *                             },
    *                 //Chaining calls
    *                 tab1    : {
    *                                 'onload' : [ function(mainTabId, tabPanel, options, data) {
    *                                                             // do something ...
    *                                                             return { isOK : true, data : "I AM RETURN VALUE" }
    *                                                         },
    *                                              function(mainTabId, tabPanel, options, data) {
    *                                                             // do something else ..
    *                                                         }
    *                                             ]
    *                             },
    *                 //Chaining Calls, with one failing
    *                 tab2    : {
    *                                 'onload' : [ function(mainTabId, tab, options, data) {
    *                                                             // do something
    *                                                             return { isOK : false, data : "I AM RETURN VALUE" }
    *                                                         },
    *                                              function(mainTabId, tab, options, data) {
    *                                                             // will not execute, because isOK is false
    *                                                         }
    *                                             ]
    *                             },
    *                 //Using Objects
    *                 tab3    : {
    *                                 'onload' : [ Object.callback1, Object.callback2, Object.callback3]
    *                             }
    *             };
    * $(document).ready(function() { $(".widget").tabs(options); });
    *
    * Callbacks
    * ===========================
    * The callback option will change the value of "this" inside of your function to that of the tabs object.
    * This can be very usefull since you will be allowed to execute and retrieve information from the public methods.
    * 
    * If you are chaining functions, the first parameter to your function will be the returned data from the previous
    * function call.
    *   
    * Return Values
    *   You must return an object/hash with a minimum of { isOK : true/false } if you are chaining events. a false value will halt the chain from executing.
    *   If you want to pass data to the next object, in the return object, pass { data: Object };
    *
    *
  *****/
(function($){
    $.fn.tabs = function(newOptions) {
         /**
          * Make sure that only one dom element is present,
          * If not, loop through and call .tabs(newOptions) on each.
          *
          * Make sure to "return this", so calls can be chained.
          */
         if (this.length > 1) {
              for (var i = 0; i < this.length; i++) {
                   $(this[i]).tabs(newOptions);
              }
              return this;
         }
         
         /**
          * Refer to tabs when "this" is out of scope.
          */
         var tabs = this;
         
         /**
          * Base Options needed for the default configuration
          */
         var baseOptions = {
              tabsClass: '.tabHeaders > li',
              tabsSelected: '.selected',
              tabPanels: '.tab',
              tabPrefix: '.tab',
              debug: false
         };
         
         /**
          * Create the options by extending the base options, with options passed in.
          */
         var options = $.extend(baseOptions, newOptions);
         
         /**
          * if call backs are passed in as an option for this item
          * @param {Object} hookList
          */
         var hooks = function(thisObject, hookList){
              if (typeof hookList == 'function') {
                   hookList.apply(thisObject, []);
              } else if (/object|array/.test(typeof hookList)) {
                   var result = {
                        isOK: true
                   };
                   for (var i = 0; i < hookList.length; i++) {
                        if (result.isOK) {
                             result = hookList[i].apply(thisObject, [ result.data ]);
                        }
                   }
              }
         }
         

         /**
          * Find the tab that was clicked, and set inactive all other tabs in the list.
          *
          * @param {Object} element
          * @param {Object} tabCSS
          * @param {Object} selectedClass
          */
         var tabIndex = function(element, tabCSS, selectedClass){
              var selectedTab = 1;
              selectedClass = selectedClass.replace(/^./, "");
              $(tabCSS, tabs).each(function(){
                   if (this == element) {
                        tabs.mainTabId = selectedTab;
                        $(element).addClass(selectedClass);
                   } else {
                        $(this).removeClass(selectedClass);
                   }
                   selectedTab++;
              });
         };
         
         /**
          * Debug Logging
          * @param {Object} data
          */
         var log = function(data){
              if (options.debug) {
                   try {
                        console.log("%o: %o", data, this);
                   } catch (e) {
                        $('BODY').append($("<div class='error'>" + data + "</div>"));
                   }
              }
         };
         
         /**
          * Starts the tabs
          * 1. Find Tabs
          * 2. Set Current Tab
          */
         this.initialize = function(){
              $(options.tabsClass, tabs).click(function(e){
                   tabs.changeTab(this);
                   e.preventDefault();
              });
              this.changeTab($(options.tabsSelected, this).get(0));
              return this;
         };

         /**
          * Find the parent UL, then find the current position and show hide tabs
          *
          * @param {Object} jQuery element
          */
         this.changeTab = function(element){
              tabIndex(element, options.tabsClass, options.tabsSelected);
              
              var tabOptions = options;
              if (options[options.tabPrefix + tabs.mainTabId] != undefined) {
                   tabOptions = options[options.tabPrefix + tabs.mainTabId];
              }
              
              $(options.tabPanels, this).hide();
              $(options.tabPrefix + tabs.mainTabId, this).show();
              hooks(tabs, tabOptions.onload);
         };
         
         /**
          * Getters
          */
         this.getOptions = function(){
              return $(tabs).data("options");
         }
         this.getMainTabId = function() {
              return tabs.mainTabId;
         }
         this.getCurrentPanel = function(){
              return $('//' + options.tabPrefix + tabs.mainTabId + '/../' + options.tabPanels, tabs);
         }
         
        return this.initialize();
    };
})(jQuery);


