/*
 * TabControl - jQuery Plugin
 *
 * Progressive Computing LLC.
 * jQuery 1.4.x
 *
 * Date: August 5, 2010
 *
 * EXAMPLE INITIALIZATION:
 * ----------------------------------------------
 * $(document).ready(function() {
 *            var callBack = function(){
 *                   // callBack scope is the Tab Menu DIV
 *                   alert(this.innerHTML)
 *            }
 *
 *            $(".tabControl").TabControl({defaultIndex:0, callBack:callBack});    
 * });
 */
(function($) {

	$.fn.TabControl = function(options) {
		/**
		 * @options
		 * @defaultIndex {Number}The tab screen to display at runtime
		 * @menuImageClass {String}The UL menu class applied to a image menu
		 * @menuTextClass {String}The UL menu class applied to a text menu
		 * @selectedClass {String} The class name to apply to active anchor links and tab windows
		 * @animationIn {String} The type of animation when a slide gets focus
		 * @animationOut {String} The type of animation when a slide loses focus
		 * @slideTimer {Number} The number of seconds to display each slide. If null slide does not move
		 * @animationTimeIn {Number} The delay in milliseconds to animate screen to show
		 * @animationTimeOut {Number} The delay in milliseconds to animate screen to hide 
		 * @callBackOut {Function} The function to call once the screen animates out.
		 * @callBackIn {Function} The function to call once the screen animates in.
		 */
		$.fn.TabControl.defaultOptions = {
			   defaultIndex:0,
			   menuImageClass:'menuImage',
			   menuTextClass:'menuText',
			   selectedClass:'selected',
			   animationIn:'horizontalSlide',
			   animationOut:'horizontalSlide',
			   animationTimeIn:500,
			   animationTimeOut:500,
			   slideTimer:null,
			   callBackOut:null,
			   callBackIn:null
		}

		// Loop through each tabControl (i.e. DIV element ) on screen and 
		// initialze control
		this.each(function () {

			 // A member variable used to store the Tab container element. This will be the
			 // DIV element with the classname of 'tabControl' assigned.
			var m_tabContainer = this,

				// If an options object is sent at runtime merge default options with user specified
				// options into a single options object. If none specified use default options.
				m_options = (typeof(options) == 'object') ?
				$.extend({}, $.fn.TabControl.defaultOptions, options) :
				$.fn.TabControl.defaultOptions,

				// Slide Transition
				m_slideTransition,

				// Flag for animation
				m_isAnimating,

				// Flag for tab menu link decoration in images
				m_menuRollOver = false,

				// A jQuery reference to the first UL list which is expected to be the tab menu
				tabMenuUL = $('ul:first', this),

				// Check if Tab Menu's are Images or Text
				isTabMenuImg = (tabMenuUL[0].getElementsByTagName('img').length > 0);

			if(isTabMenuImg){

				// Apply Image Menu Class to UL element
				tabMenuUL.addClass(m_options.menuImageClass);

				// Check to see if navigation images have class 'imgRollOver' if so need to 
				// replace img with DIV tag to change image state for RollOver.
				if($('img:first', tabMenuUL).hasClass('imgRollOver')){

					// Default Tab Menu To Image Height / 2
					
					// The line below is not compatible with IE
					tabMenuUL.css('height', (tabMenuUL[0].getElementsByTagName('img')[0].height/2));

					$('img', tabMenuUL).each(function(i, e){

						var divElm = document.createElement('div');
							divElm.style.backgroundImage = 'url(' + e.src + ')';
							divElm.style.backgroundPosition = 'top';
							
							// The two lines below are not compatible with IE
							//divElm.style.width = e.width + 'px';
							//divElm.style.height = (e.height/2) + 'px';
							divElm.style.width = e.width + 'px';
							divElm.style.height = '28px';

						  $(e).replaceWith(divElm);
					});

					m_menuRollOver = true;
				}else{
					// Default Tab Menu To Native Image Height
					tabMenuUL.css('height', tabMenuUL[0].getElementsByTagName('img')[0].height);
				}

				// Apply a height value to li elements to alleviate larger offset height
				// Issue in FireFox & Chrome
				$('li', tabMenuUL).each(function(i, e){
					   e.style.height = '1em';
				});
				
			 }else{
				// Apply Text Menu Class to UL element
				tabMenuUL.addClass(m_options.menuTextClass);

				// Apply style to first li element of menu class UL
				$('li:first', tabMenuUL).addClass('firstItem');
			 }

			 // Insert a span tag to clear floats on li elements in main menu
			 $('<span style="display:block; clear:left;"></span>').insertAfter(tabMenuUL);

			 // Assign class to all tab windows which removes them from view
			 // Flag default tag by the options config and set to display
			$('.tabBodyWrapper > div', m_tabContainer).each(function(i, e){

				// Add tabBody class to all tab windows
				if(m_options.animationOut == "horizontalSlide"){
					  $(e).addClass('tabBodyHorizontalSlide');
				}else{
					  $(e).addClass('tabBody');
				}

				if(i == m_options.defaultIndex){
					  $(e).addClass(m_options.selectedClass);
				}
			 });                  

			 // Assign 'click' event and data to anchor link tab menus. Pass the tab menu
			 // to ensure we only get results within the selected tabControl menu.
			 $('li a', tabMenuUL).each(function(i, e){

				// reference the jQuery object
				var $el = $(e);

				// Assign the event to the anchor link
				$el.click(function(p_event){

					// ensure tab is not currently selected.
					if(this.className.indexOf(m_options.selectedClass) == -1){

						if(!m_isAnimating){
							// Setup Events based on Tab Transition
							if(m_options.slideTimer != null){
								// Stop transition for focus
								if(m_options.slideTimer){
									  stopTabTransition();
								}
							}

							switchTab(this);
						}
					}
				});

				if(m_menuRollOver){
					$el.hover(
						function () {
							if(!$(this).hasClass(m_options.selectedClass)){
								this.firstChild.style.backgroundPosition = 'bottom';
							}
						},

						function () {
							this.firstChild.style.backgroundPosition = 'top';
						}
					)
						 
				}

				// Assign the tab index to the anchor link using jQuery's data method
				$el.data('index', i);

				if(i == m_options.defaultIndex){
					$(e).addClass(m_options.selectedClass);
				}
			});
			
			// Set Display of Navigation Bars			
			$(".tabBodyWrapper").slideDown(1000, function(){
				$(".tabBodyWrapper").prev().prev().css('visibility','visible');
			});

			if(m_options.slideTimer != null){
				// Setup Interval and Events to manage automatic tab transition
				setTabTransition();
			}

			function switchTab(p_index){

				// Set animation flag
				m_isAnimating = true;

				if(m_options.slideTimer != null){
					stopTabTransition();
				}
				
				// Get the chosen tab index
				var chosenTabIndex = $(p_index).data('index'),

					// Get jQuery object of active window. Get the current displayed DIV element (i.e. tab window) 
					// and fade out. The ':first' selector ensures only one result is returned.
					activeWindow = $('.tabBodyWrapper > div.' + m_options.selectedClass + ':first', m_tabContainer),

					// Declare callBack event for animation end
					callBack = function(){
						// Call function if callBackOut is specified
						if(m_options.callBackOut != null){
								m_options.callBackOut.apply(m_tabContainer, arguments);
						}

						// Animation is complete. Show selected tab
						showTab(chosenTabIndex);
					};

				switch(m_options.animationOut){
					case "slideUp":
						activeWindow.slideUp(m_options.animationTimeOut, callBack);
						break;
					case "horizontalSlide":
						var activeWindowIndex = $('.tabBodyWrapper > div', m_tabContainer).index(activeWindow),
							chosenWindow = $('.tabBodyWrapper > div:eq(' + chosenTabIndex + ')', m_tabContainer),
							removeWindow = function(){
								$(this).css('display','none');
							}

						 if(chosenTabIndex < activeWindowIndex){
							// Navigating right to left
							chosenWindow.css('display','block').css('left', '571px').animate({left:'0px'}, 'normal', callBack);
							activeWindow.animate({left:'-571px'}, 'normal', removeWindow);
						 }else{
							// Navigating left to right
							chosenWindow.css('display','block').css('left', '-571px').animate({left:'0px'}, 'normal', callBack);
							activeWindow.animate({left:'571px'}, 'normal', removeWindow);
						 }
						 break;
					default:
							activeWindow.fadeOut(m_options.animationTimeOut, callBack);
						 break;
				}
				
			 };

			 function showTab(p_tabIndex){

				// Remove the m_options.selectedClass class from previously selected anchor link
				// and DIV element tab window.
				$('.' + m_options.selectedClass, m_tabContainer).removeClass(m_options.selectedClass);

				// Add m_options.selectedClass class to new selected anchor link. The 'eq' selector
				// allows us to select the anchor link by the index value of the returned result.
				$('a:eq('+ p_tabIndex  +')', tabMenuUL).addClass(m_options.selectedClass);

				// Add m_options.selectedClass class to new DIV element tab window
				var chosenWindow = $('.tabBodyWrapper > div:eq('+ p_tabIndex  +')', m_tabContainer).addClass(m_options.selectedClass),

					// callBack function for animation end event
					callBack = function(){
						// Call function if callBackIn is specified
						if(m_options.callBackIn != null){
								m_options.callBackIn.apply(m_tabContainer, arguments);
						}
						
						if(m_options.slideTimer != null){
							setTabTransition();
						}

						// Set animation flag
						m_isAnimating = false;
					}

				switch(m_options.animationIn){
					case "slideDown":
						chosenWindow.hide().slideDown(m_options.animationTimeIn, callBack);
						break;
					case "horizontalSlide":
						// We Do Nothing Here Since It was Already Done with Switch Tab
						// Call function if callBackIn is specified
						if(m_options.callBackIn != null){
							m_options.callBackIn.apply(m_tabContainer, arguments);
						}
						
						if(m_options.slideTimer != null){
							setTabTransition();
						}
						
						// Set animation flag
						m_isAnimating = false;						
						break;
					default:
						chosenWindow.hide().fadeIn(m_options.animationTimeIn, callBack);
						break;
				}
			 };

			 function setTabTransition(){

				var intervalFunction = function(){

					// Get the current index of the tab being displayed
					var currentTabIndex = $('li a', tabMenuUL).index($('li a.' + m_options.selectedClass, tabMenuUL));

					// Incrament Tab to Next One
					currentTabIndex++;

					// Make sure we have tab ceiling                
					if(currentTabIndex == tabMenuUL.children().length){
						 currentTabIndex = 0;
					}

					// Switch to next tab
					switchTab($('li:eq(' +  currentTabIndex + ') a', tabMenuUL));
				}

				m_slideTransition = setTimeout(intervalFunction, m_options.slideTimer);
			 }

			 function stopTabTransition(){
				clearTimeout(m_slideTransition);
			 }
		});
	}
})(jQuery);

