/*
Author: Dharma Poudel (@rogercomred)
Description: Yet another jQuery tabs plugin with unlimited animations and transitions.
Version: 2.0
License:  GPLv3 ( http://www.gnu.org/licenses/gpl-3.0.html )
*/

;(function($, window, document, undefined){
'use strict';

  function jQueryTab(wrapper, options) {
    this.options = $.extend (true, {}, $.fn.jQueryTab.defaults, options );
    this._defaults = $.fn.jQueryTab.defaults;
    this.wrapper = wrapper;
    this.$wrapper = $(wrapper);
    this.tabs = this.$wrapper.find('.'+this.options.tabClass);
    this.tabItems = this.tabs.find('li');
    this.tabLinks = this.tabItems.find("a");
    this.wrap = this.$wrapper.find('.'+this.options.contentWrapperClass);
    this.contents = this.wrap.find('.'+this.options.contentClass);
    this.headerClass = this.options.accordionClass;
    this.activeClass = this.options.activeClass;
    this.init();
  }

  /* jQueryTab object */
  jQueryTab.prototype = {
  
      init:function(){
        var self = this,
            initialTab = self.getActiveTab();   		// get the tab to open initially

        if(self.options.responsive){
          self.addHeader();                 // call fxn to add accordian headers
          self.alinks = self.wrap.find('.'+self.headerClass);
        }
        
        self.resize();
        self.cssSetUp();
        self.handleEvent();
      },
      
      addHeader: function(){
        var self = this;
            
        self.wrap.find('.'+self.headerClass).remove();
        self.tabLinks.each(function(){
          var $tab_content = self.contents.eq($(this).parent().index());
          $('<a />').attr({ 'class': self.headerClass, 'href' : '#'+$tab_content.attr('id') })
                    .text($(this).text())
                    .insertBefore($tab_content);
        });
      },
      
      cssSetUp: function(){
        this.wrap.addClass('toggle_border');
        this.contents.addClass('toggle_position toggle_display');
        if(this.options.responsive) {
          this.tabs.addClass('toggle_display');
          
        }
      },
      
      handleClasses: function(activeContent){
        var self = this;
        self.contents.removeClass(self.options.tabInTransition).addClass(self.options.tabOutTransition);  
        activeContent.removeClass(self.options.tabOutTransition).addClass(self.options.tabInTransition);
      },
      
      resize: function(){
        var self = this,
            currentTab    =  self.getActiveTab(),
            activeContent = self.contents.eq(currentTab);
            self.reOrder(activeContent);
            
        self.tabItems.eq(currentTab).addClass(self.activeClass);
        if(self.options.responsive) self.alinks.eq(currentTab).addClass(self.activeClass);

        if (self.options.responsiveBelow < $(window).width()) {
            self.contents.show();
            self.handleClasses(activeContent);
            self.wrap.height(activeContent.outerHeight());
        }else{
          if(self.options.responsive){
              self.contents.hide().removeClass(self.options.tabOutTransition, self.options.tabInTransition);
              activeContent.fadeIn(self.options.accordionIntime);
            }
        }
        
        (self.options.useCookie) ? self.setCookie.call(self, currentTab) : '';
      },
      
      handleEvent: function(){
         var self = this;
        $(window).on('resize', function(){ self.resize(); } );
        
        self.tabLinks.on((self.options.openOnhover)?'click, mouseenter' :'click' , function(event){										// when tab is clicked
        event.preventDefault();																			// prevent default behaviour	
        (typeof self.options.before === 'function') ? self.options.before.apply( this, arguments ) : '';		// call fxn before
        self.handleTabs.call(this, self);															// call handleEvent fxn; self.options - data values
        (typeof self.options.after === 'function') ? self.options.after.apply( this, arguments ) : '';		// call fxn after
        });

        if(self.options.responsive){																		// if accordion is enabled
        self.alinks.on('click', function(event){						// when accordain header is clicked
        event.preventDefault();									                            // prevent default behaviour
        (typeof self.options.before === 'function') ? self.options.before.apply( this, arguments ) : '';	// call fxn before
        self.handleAccordions.call(this, self); 									// call fxn to handle accordions
        (typeof self.options.after === 'function') ? self.options.after.apply( this, arguments ) : '';	// call fxn after
        });
        }
      },
      
      handleTabs: function(self){
        if($(this).parent().hasClass(self.activeClass)) return;												// do nothing when active tab is clicked
        
        var index = $(this).parent().index(),
            activeContent  = self.contents.eq(index);
        
                
        self.tabItems.removeClass(self.activeClass).eq(index).addClass(self.activeClass);										// add active class to this tab
        self.wrap.height(activeContent.outerHeight());
        self.reOrder(activeContent);
        if(self.options.responsive)
          self.alinks.removeClass(self.activeClass).eq(index).addClass(self.activeClass);												// add class to corresponding accordian header
        
        self.handleClasses(activeContent);
            
        (self.options.useCookie) ? self.setCookie.call(self, index) : '';										//if useCookie is true save the current tab index to cookie
      },
      
      handleAccordions: function(self){
        var $this           = $(this),
            index           = Math.floor(($this.next().index() -1)/2 ),
            intime          = self.options.accordionInTime,
            outtime         = self.options.accordionOutTime;
                
        if(($this.hasClass(self.activeClass)) && !self.options.collapsible) return;								// if active and not collapsible - do nothing
        
        else if( $this.hasClass(self.activeClass) && self.options.collapsible ){									// if active and collapsible
          self.alinks.removeClass(self.activeClass);											// 		remove active class from all accordian headers
          self.tabItems.removeClass(self.activeClass);										// 		remove active class from all tabs
          (self.options.accordionTransition ==='slide')	? self.contents.slideUp(outtime) : self.contents.fadeOut(outtime);				// else hide the visible content in specified time 
          
          (self.options.useCookie) ? self.setCookie.call(self, null) : '';										// 		delete the cookie
        }else{
          self.alinks.removeClass(self.activeClass).eq(index).addClass(self.activeClass);
          self.tabItems.removeClass(self.activeClass).eq(index).addClass(self.activeClass);									// add active class to the corresponding tab
          
          (self.options.accordionTransition ==='slide')												// if the transition is slide
            ? self.contents.slideUp(outtime).eq(index).slideDown(intime)				// 		slide down corresponding tab content
            : self.contents.fadeOut(outtime).eq(index).fadeIn(intime);					// 		show the corresponding tab content
          
          (self.options.useCookie) ? self.setCookie.call(self, index) : '';										// if useCookie is true	save the current tab index to cookie	
        }								
      },
      
      reOrder: function($ontop){
        var self = this,
            count = self.contents.length;
        $ontop.css('zIndex', count+1);
        self.contents.not($ontop).each(function(i){
            $(this).css('zIndex', count-i);
        });
      },
      
      getActiveTab: function(tab){
        var self = this, currentTab;
        
        if(typeof tab ==='number'){  return tab-1; }	// if tab specified return it immediately

        if(self.tabs.find('.'+self.activeClass).index() !==-1){
          return self.tabs.find('.'+self.activeClass).index();
        }
        
        currentTab =(self.options.useCookie)										// if remember last active tab is set to true
            ? (self.getCookie(self.options.cookieName)						// if $.cookie plugin is present & cookie is set
                ? self.getCookie(self.options.cookieName)				// 	set to  the value from cookie
                : self.options.initialTab-1                       // else set to specified tab or default open tab
                )																
            : self.options.initialTab-1;	

        if(window.location.hash) {
          var indexOfHash = self.tabLinks.index($('[href='+window.location.hash+']'));
          if(indexOfHash !== -1) currentTab = indexOfHash;
        }
        return currentTab;
      },
      
      setCookie: function(value){
        var self = this, expires, date, path, domain, secure;
        if (value === null) {
          value = '';
          date = new Date();
          date.setTime(date.getTime() + ((-1)*24*60*60*1000));
        }
        else if(typeof self.options.cookieExpires == 'number'){
          date = new Date();
          date.setTime(date.getTime() + (self.options.cookieExpires*24*60*60*1000));
        } else if( self.options.cookieExpires.toUTCString){
          date = self.options.cookieExpires;
        }
        expires = '; expires=' + date.toUTCString(); 
        path = self.options.cookiePath ? '; path=' + (self.options.cookiePath) : '';
        domain = self.options.cookieDomain ? '; domain=' + (self.options.cookieDomain) : '';
        secure = self.options.cookieSecure ? '; secure' : '';
        document.cookie = ''.concat(self.options.cookieName, '=', encodeURIComponent(value), expires, path, domain, secure);
      },
      
      getCookie: function(name){
        var name = name + "=";
        if (document.cookie && document.cookie != '') {
          var cookieArray = document.cookie.split(";");
          for(var i=0; i < cookieArray.length; i++){
            var cookie = jQuery.trim(cookieArray[i]);
            if(cookie.indexOf(name)==0) 
            return decodeURIComponent(cookie.substring(name.length, cookie.length));
          }
        }
        return null;
      },
  };
  /* initialize the jQueryTab plugin */
  $.fn.jQueryTab = function(options) {
    return this.each(function() {
      var container = $(this);
      if(container.data('jQueryTab')) return;
      var aT = new  jQueryTab(this, options);
      container.data('jQueryTab', aT);
    });
  };

  /* jQueryTab defaults */
  $.fn.jQueryTab.defaults = {
    
    //classes settings
    tabClass:'tabs',				// class of the tabs
    accordionClass:'accordion_tabs',	// class of the header of accordion on smaller screens
    contentWrapperClass:'tab_content_wrapper',		// class of content wrapper
    contentClass:'tab_content',		// class of container
    activeClass:'active',			// name of the class used for active tab

    //feature settings
    responsive:true,				// enable accordian on smaller screens
    responsiveBelow:600,    // the breakpoint
    collapsible:true,				// allow all tabs to collapse on accordians
    useCookie: true,				// remember last active tab using cookie
    openOnhover: false,			// open tab on hover
    initialTab: 1,					// tab to open initially; start count at 1 not 0

    //cookie settings
    cookieName: 'active-tab',		// name of the cookie set to remember last active tab
    cookieExpires: 365,				// when it expires in days or standard UTC time
    cookiePath: '',					// path on which cookie is accessible
    cookieDomain:'',				// domain of the cookie
    cookieSecure: false,			// enable secure cookie - requires https connection to transfer
    
    //tabs transition settings    fade|flip|scaleUp|slideLeft
    tabInTransition: 'fadeIn',  // classname for showing in the tab content
    tabOutTransition: 'fadeOut', // classname for hiding the tab content
    
    //accordion transition settings
    accordionTransition: 'slide',	// transitions to use - normal or slide
    accordionIntime:500,			// time for animation IN (1000 = 1s)
    accordionOutTime:400,			// time for animation OUT (1000 = 1s)
    
    //api functions
    before: function(){},			// function to call before tab is opened
    after: function(){}				// function to call after tab is opened
  };

})(jQuery, window, document); 


/* to dos */
/* 
1. fix bug when collapsible is true and resized
3. look into opentab function 

jQueryTab is back with unlimited  css3 transitions. Try out the few transitions already crafted for you. 
Want more,  make your own and go crazy!
*/