/* 
	dg_tabs jQuery Plugin v1.2.1 Docs:
	
	Created by Stuart Elmore 24th June 2009 (last edited 24th July 2009)
	
	options:
		tabLinks: 			[css selector]			The id/class of the list of links (can be the id / class of the parent div)
		tabPanel: 			[css selector]			The id/class of the panel (holding div) where the tab content resides
		selected: 			[css selector]			The id of the first selected tab (default: first in sequence)
		selectedClass: 		[class name (string)]	The class name that you want on the selected object (default: 'selected')
		applySelectedTo: 	[css object selector]	The object (li/div/a) that you want the selected class applied to (default: 'a');
		transition: 		[string]				Option for trasition ('slide','fade')(default: false [none])
		transitionSpeed:	[int]					The speed for the transition in msec (default: 500)
		fixedHeight: 		[boolean]				Boolean for the tab area to keep the greatest height (default: false)
		hidePosition: 		['hide' / 'position']	Positions the tabs rather than hiding them to allow for rendering off screen (needed for Google Maps etc.) (default: 'hide')
		AJAXparams			[array]					Optional parameters for AJAX requests
			[method,dataType,username,password]
		selectCallBack:		[function]				Function for callback to fire on each tab event. Returns the tab ID (#)
*/

(function($) { 
	var self = null;
	$.fn.dg_tabs = function() {
		var args = arguments[0] || {}; 	
		return this.each(function() {
			new $.dg_tabs(this, args);
		});
	};
	
	$.dg_tabs = function (e, args) {
		var tabData = new Object();
		this.tabObject = $(e);
		this.tabLinks = args.tabLinks || "#" + $(e.id);
		this.tabPanel = args.tabPanel || "#" + $(e).siblings('div').attr('id'); 
		this.selected = args.selected || false;
		this.transition = args.transition || false;
		this.transitionSpeed = (args.transitionSpeed/2) || 250;
		this.fixedHeight = args.fixedHeight || false
		this.selectedClass = args.selectedClass || 'selected';
		this.applySelectedTo = args.applySelectedTo || 'a';
		this.hidePosition = args.hidePosition || 'hide';
		this.fixedHeightVal = 0;
		this.fixedWidthVal = 0;
		this.callBack = args.selectCallBack || function(){};
		this.callBackEnabled = true;
		this.callBackOn = [];
		this.AJAXparams = args.AJAXparams || ['','','',''];
		this.debugBool = args.debug || false;
		this.debug("Line 47: this.tabPanel = "+this.tabPanel);
		this.debug("Line 48: Calling 'init'");
		this.init(tabData);
	};
	
	$.dg_tabs.prototype = {
		init: function(tabData){
			var self = this;
			this.hrefCache=[];
			this.linkCache=[];
			this.hashCache=[];
			this.currentlyOpen = '';
			this.transitionRunning=false;
			tabData.AJAX = new Object();
			tabData.AJAX.method = this.AJAXparams[0] || 'GET';
			tabData.AJAX.dataType = this.AJAXparams[1] || 'html';
			tabData.AJAX.username = this.AJAXparams[2] || '';
			tabData.AJAX.password = this.AJAXparams[3] || '';
			tabData.links = [];
			tabCounter = -1;
			$(this.tabLinks+' a[rel^="tabs"]').each(function(){
				hashID = '';
				tabCounter++;
				self.debug('search result: '+$(this).attr('href').search(/#/))
				if($(this).attr('href').search(/#/)<1){
					self.linkCache.push($(this).attr('href'));
					self.hrefCache.push($(this).attr('href'));
					self.debug("Line 73: self.linkCache["+tabCounter+"] = "+$(this).attr('href'));
					tabData.links.push('local');
					self.debug("Line 75: tabData.links["+tabCounter+"] = 'local'");
					if (self.callBackEnabled == true){
						self.callBackOn[tabCounter] = 'tabs';
					}
				}else{
					tabData.AJAX.hasAJAX = true; 
					linkRefOrig = $(this).attr('href').split("#");
					linkRef=[];
					linkRef[0]= linkRefOrig[0];
					linkRef[1]= '#'+linkRefOrig[1];
					if($(this).attr('rel').search(/\[/)>0){
						self.debug('Line 99: Link has an ID in the rel: '+$(this).attr('rel')+' = ' +$(this).attr('rel').search(/\[/));
						if(!tabData.AJAX.sourceID){
							tabData.AJAX.sourceID = [];
						}
						thisSourceID = $(this).attr('rel').split("[");
						thisSourceID = thisSourceID[1].split("]");
						tabData.AJAX.sourceID[tabCounter] = thisSourceID[0];
						self.debug('Line 106: RelID commit to memory: '+tabData.AJAX.sourceID[tabCounter]);
					}
					self.linkCache.push(linkRef[1]);
					self.debug("Line 109: self.linkCache["+tabCounter+"] = "+linkRef[1]);
					tabData.links.push(linkRef[0]);
					self.debug("Line 111: tabData.links["+tabCounter+"] = "+linkRef[0]);
					if (self.callBackEnabled == true){
						self.callBackOn[tabCounter] = 'ajax';
					}
					self.hrefCache.push($(this).attr('href'));
				}
				self.hashCache[$(this).attr('href')] = tabCounter;
				$(this).click(function(){
					self.invokeTab($(this).attr('href'),tabData);
					return false;
				});
			});
			this.debug("Line 109: tabCounter = "+tabCounter);
			for (i=0; i<self.linkCache.length; i++){
				if(self.fixedHeight==true){
					if($(self.tabPanel + ' ' + self.linkCache[i]).height()>self.fixedHeightVal){
						self.fixedHeightVal=$(self.tabPanel + ' ' + self.linkCache[i]).height();
					}
					if($(self.tabPanel + ' ' + self.linkCache[i]).width()>self.fixedWidthVal){
						self.fixedWidthVal=$(self.tabPanel + ' ' + self.linkCache[i]).width();
					}
				}
				if(self.selected==false){
					if (i!=0){
						if (self.hidePosition=='hide'){
							$(self.tabPanel + ' ' + self.linkCache[i]).hide();
							self.debug("Line 124: ("+self.tabPanel + ' ' + self.linkCache[i]+").hide(); ");
						}
					}else{
						self.currentlyOpen = self.linkCache[i];
						self.applySelectedToToggle(self.linkCache[i]);
						self.invokeTab(self.hrefCache[i],tabData);
					}
				}else{
					if (self.selected!=self.linkCache[i]){
						if (self.hidePosition=='hide'){
							$(self.tabPanel + ' ' + self.linkCache[i]).hide();
						}
					}else{
						self.currentlyOpen = self.linkCache[i];
						self.applySelectedToToggle(self.linkCache[i]);
						self.debug('Line 145: self.linkCache['+i+'] = '+self.linkCache[i]);
						self.invokeTab(self.hrefCache[i],tabData);
					}
				}
			}
			if(this.fixedHeight==true){
				$(this.tabPanel)
					.height(this.fixedHeightVal)
					.width(this.fixedWidthVal);
						if (this.hidePosition=='position'){
							$(this.tabPanel).css('overflow','hidden');
						}
			}
		},
		
		applySelectedToToggle: function(aHref){
			var self = this;
			switch(this.applySelectedTo){
				case 'a':
					$(this.tabLinks+' a[href*="#"]').removeClass(self.selectedClass);
					$(this.tabLinks+' a[href$="'+aHref+'"]').addClass(this.selectedClass);
				default:
					$(this.tabLinks+' a[href*="#"]').closest(this.applySelectedTo).removeClass(self.selectedClass);
					$('a[href$="'+aHref+'"]').closest(this.applySelectedTo).addClass(this.selectedClass);
				break;
			}
		},
		
		invokeTab: function(targetHash,tabData){
			this.debug('line 167: targetHash = '+targetHash);
			var self = this;
			if (targetHash == false){return;}
			this.debug('Line 178: does this.hashCache[] exist? = '+this.hashCache);
			this.debug('targetID = this.hashCache['+targetHash+'] = '+this.hashCache[targetHash]);
			targetID = this.hashCache[targetHash];
			target = this.linkCache[targetID]
			if (tabData.links[targetID] != 'local'){
				this.debug('line 173: tabData.links['+targetID+'] = '+tabData.links[targetID]);
				if(tabData.AJAX.ajaxStore){
					if(!tabData.AJAX.ajaxStore[targetID]){
						this.storeAJAX(tabData.links[targetID],targetID,tabData);
					}
				}else{
					this.storeAJAX(tabData.links[targetID],targetID,tabData);
				}
			}
			if(this.currentlyOpen == target) {
				return;
			}
			if(this.transition==false){
				$(this.currentlyOpen).hide();
				$(target).show();
				this.applySelectedToToggle(target);
				if (self.callBackEnabled == true){
					self.debug('calling callBack... self.callBackOn[targetID] ='+self.callBackOn[targetID]);
					if (self.callBackOn[targetID] == 'tabs'){
						self.invokeCallBack(targetID);
					}else{
						self.callBackOn[targetID] = 'tabs'
					}
				}
			}else{
				switch(this.transition){
					case 'slide':
						$(this.currentlyOpen).slideUp(this.transitionSpeed);
						$(target).slideDown(this.transitionSpeed,function(){self.applySelectedToToggle(target);});
						if (self.callBackEnabled == true){
							self.debug('calling callBack... self.callBackOn[targetID] ='+self.callBackOn[targetID]);
							if (self.callBackOn[targetID] == 'tabs'){
								self.invokeCallBack(targetID);
							}else{
								self.callBackOn[targetID] = 'tabs'
							}
						}
					break;
					case 'fade':
						if(this.transitionRunning==true){
							return;
						}else{
							this.transitionRunning=true;
							$(this.currentlyOpen)
								.stop(true,true)
								.fadeOut(this.transitionSpeed,function(){
									$(target).fadeIn(self.transitionSpeed,function(){
										self.transitionRunning=false;
										self.applySelectedToToggle(target);
										if (self.callBackEnabled == true){
											self.debug('calling callBack... self.callBackOn[targetID] ='+self.callBackOn[targetID]);
											if (self.callBackOn[targetID] == 'tabs'){
												self.invokeCallBack(targetID);
											}else{
												self.callBackOn[targetID] = 'tabs'
											}
										}
									});
								});
						}
					break;
					default:
						$(this.currentlyOpen).hide(this.transitionSpeed);
						$(target).show(this.transitionSpeed,function(){
							self.applySelectedToToggle(target);
							if (self.callBackEnabled == true){
								self.debug('calling callBack... self.callBackOn[targetID] ='+self.callBackOn[targetID]);
								if (self.callBackOn[targetID] == 'tabs'){
									self.invokeCallBack(targetID);
								}else{
									self.callBackOn[targetID] = 'tabs'
								}
							}
						});
					break;
				}
			}
			this.currentlyOpen = target;
		},
		
		storeAJAX: function(linkData,targetID,tabData){
			if(tabData.AJAX.ajaxStore){
				this.callAJAX(linkData,targetID,tabData);
			}else{
				tabData.AJAX.ajaxStore = [];
				this.callAJAX(linkData,targetID,tabData);
			}
		},
		
		callAJAX: function(linkData,targetID,tabData){
			var self = this;
			$.ajax({
			   type: tabData.AJAX.method,
			   dataType: tabData.AJAX.dataType,
			   username: tabData.AJAX.username,
			   password: tabData.AJAX.password,
			   url: linkData,
			   success: function(response){
			     self.debug('AJAX linkData = '+linkData);
				 tabData.AJAX.ajaxStore[targetID]=response;
			     self.debug('AJAX insert data to = '+self.linkCache[targetID]);
				 strResponse='';
				 if (tabData.AJAX.sourceID){
					 if (tabData.AJAX.sourceID[targetID]){
						 self.debug('tabData.AJAX.sourceID = '+tabData.AJAX.sourceID[targetID]);
						 response= "<div>"+response+"</div>";
						 strResponse = $(response).wrap('<div></div>').find(tabData.AJAX.sourceID[targetID]).html();
						 self.debug('strResponse = $('+response+').find('+tabData.AJAX.sourceID[targetID]+').html()');
						 self.debug('strResponse = '+strResponse);
					 }else{
						 strResponse = response;
					 }
				 }else{
					 strResponse = response;
				 }
				 $(self.linkCache[targetID]).html(strResponse);
				 self.invokeCallBack(targetID);			   
			   },
			   error: function(XMLHttpRequest, textStatus, errorThrown){
				   switch(XMLHttpRequest.status){
					   	case 404:
					   	 	response='<p title="statusCode=404">Sorry, there was an error retrieving <em>'+linkData+'</em>. Please try again later.</p>';
							tabData.AJAX.ajaxStore[targetID]=response;
						break;
						default:
					   	 	response='<p title="statusCode='+XMLHttpRequest.status+'">Sorry, there was an error retrieving <em>'+linkData+'</em>. Please try again later.</p>';
						break;
				   }
			   	 $(self.linkCache[targetID]).html(response);
			   }
			});
		},
		
		invokeCallBack: function(targetID){
			if (this.callBackEnabled == true){
				this.debug('callBack called on '+targetID);
				this.debug('callBack: '+this.callBack[targetID]);
				this.callBack(this.linkCache[targetID]);
			}
		},
		
		debug: function(data){
			if(this.debugBool==true){
				console.log('dg_tabs: '+data);
			}
		}
	}
})(jQuery);
