/**
 * tools.tabs 1.0.1E - Tabs done rigth.
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/tabs.html
 * 
 * Edited:
 * Copyright (c) 2009 Ivan Vovnenko, Corporate Voice
 * http://www.corporatevoice.com
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Launch  : November 2008
 * Date: 2009-06-12 11:02:45 +0000 (Fri, 12 Jun 2009)
 * Revision: 1911 
 */ 
(function($) {
		
	// static constructs
	$.tools = $.tools || {version: {}};
	
	$.tools.version.tabs = '1.0.1E';
	
	$.tools.addTabEffect = function(name, fn) {
		effects[name] = fn;
	};		
	
	
	var effects = { 
		'default': function(i) { 
			this.getPanes().hide().eq(i).show(); 
		}, 
		
		// custom configuration variable: fadeInSpeed
		fade: function(i) {
			this.getPanes().hide().eq(i).fadeIn(this.getConf().fadeInSpeed);	
		},
		
		slide: function(i) {
			this.getCurrentPane().slideUp("fast");
			this.getPanes().eq(i).slideDown();			 
		},

		horizontal: function(i) {
			
			// store original width of a pane into memory
			if (!$._hW) { $._hW = this.getPanes().eq(0).width(); }
			
			// set current pane's width to zero
			this.getCurrentPane().animate({width: 0}, function() { $(this).hide(); });
			
			// grow opened pane to it's original width
			this.getPanes().eq(i).animate({width: $._hW}, function() { $(this).show(); });			 
		}		
	};   	
	 

	function Tabs(tabs, panes, opts) { 
		
		var self = this;
		var current;

		// generic binding function
		function bind(name, fn) {
			$(self).bind(name, function(e, args)  {
				if (fn && fn.call(this, args.index) === false && args) {
					args.proceed = false;	
				}	
			});
			return self;
		}
		
		// bind all callbacks from configuration
		$.each(opts, function(name, fn) {
			if ($.isFunction(fn)) { bind(name, fn); }
		});
		
		
		// public methods
		$.extend(this, {				
			click: function(i) {
				
				if (i === current) { return self; }
				
				var pane = self.getCurrentPane();				
				var tab = tabs.eq(i);												 
				
				if (typeof i == 'string') {
					tab = tabs.filter("[href=" +i+ "]");
					i = tabs.index(tab);
				}
				
				if (!tab.length) { 
					if (current >= 0) { return self; }
					i = opts.initialIndex;
					tab = tabs.eq(i);
				}				
				
				// possibility to cancel click action
				var args = {index: i, proceed: true};
				$(self).triggerHandler("onBeforeClick", args);				
				if (!args.proceed) { return self; }				
				
				tab.addClass(opts.current);
				
				// call the effect
				effects[opts.effect].call(self, i);
				
				// onClick callback
				$(self).triggerHandler("onClick", args);	
				
				tabs.removeClass(opts.current);	
				tab.addClass(opts.current);											
				current = i;
				return self;
			},
			
			getConf: function() {
				return opts;	
			},

			getTabs: function() {
				return tabs;	
			},
			
			getPanes: function() {
				return panes;	
			},
			
			getCurrentPane: function() {
				return panes.eq(current);	
			},
			
			getCurrentTab: function() {
				return tabs.eq(current);	
			},
			
			getIndex: function() {
				return current;	
			},
			
			next: function() {
				return self.click(current + 1);
			},
			
			prev: function() {
				return self.click(current - 1);	
			}, 
			
			onBeforeClick: function(fn) {
				return bind("onBeforeClick", fn);	
			},
			
			onClick: function(fn) {
				return bind("onClick", fn);	
			}			
		
		});
		
		
		// setup click actions for each tab
		tabs.each(function(i) { 
			$(this).bind(opts.event, function(e) {
				self.click(i);
				if (!opts.history) { 
					return e.preventDefault();
				}
			});			
		});
		
		// enable history plugin
		if (opts.history) {
			tabs.history(function(evt, hash) {
				if(hash){
					self.click(hash);
				}
			});
		}

		// if no pane is visible --> click on the first tab
		if (location.hash) {
			self.click(location.hash);	
		} else {
			self.click(opts.initialIndex);	
		}		
		
		// cross tab anchor link
		panes.find("a[href^=#]").click(function() {
			self.click($(this).attr("href"));		
		});
		
	}
	
	
	// jQuery plugin implementation
	$.fn.tabs = function(query, arg) {
		
		// return existing instance
		var el = this.eq(typeof conf == 'number' ? conf : 0).data("tabs");
		if (el) { return el; }

		
		// setup options
		var opts = {
			tabs: 'a',
			current: 'current',
			onBeforeClick: null,
			onClick: null, 
			effect: 'default',
			history: false,
			initialIndex: 0,			
			event: 'click',
			api:false
		};
		
		if ($.isFunction(arg)) {
			arg = {onBeforeClick: arg};
		}
		
		$.extend(opts, arg);
		
		// install tabs for each items in jQuery		
		this.each(function(i) {				
			var els = $(this).find(opts.tabs);
			
			if (!els.length) {
				els = $(this).children();	
			}

			var panes = null;
			if(query.jquery){
				panes=query;
			}else{
				var obj = $(query, this);
				if(obj.size()>0){
					panes = obj;
				}else{
					panes = $(this).siblings(query);
				}
			}

			el = new Tabs(els, panes, opts);
			$(this).data("tabs", el);	 
		});		
		
		return opts.api ? el: this;		
	};		
		
}) (jQuery); 


//{{{ history plugin

/**
 *	tools.history plugin. execute a callback when browser's 
 * back/forward buttons are pressed.
 *	
 *	Can be used as a separate tool. Example:
 *	
 *	$("ul.tabs a").history(function(hash) {		
 *		
 *	});	
 */
(function($) {
	
	var hash, iframe;		

	// jQuery plugin implementation
	$.prototype.history = function(fn) {
			
		var el = this;
		
		// IE
		if ($.browser.msie) {
			
			// create iframe that is constantly checked for hash changes
			if (!iframe) {
				iframe = $("<iframe />").attr('tabIndex','-1').attr('style','position: absolute; width: 0; height: 0; border: 0').get(0);
				$("body").append(iframe);
				
				setInterval(function() {
					var idoc = iframe.contentWindow.document;
					var h = idoc.location.hash;
				
					if (hash !== h) {						
						$.event.trigger("hash", h);
						hash = h;
					}
					
					// Fix for IE don't-react-on-hash-change behavior 
					var localHash = document.location.hash;
					if(localHash != h){
						idoc.open().close();
						idoc.location.hash = localHash;
					}
					
				}, 100);					
			}
			
			// when link is clicked the iframe hash updated
			el.bind("click.hash", function(e) {	
				var doc = iframe.contentWindow.document;
				doc.open().close();				
				doc.location.hash = $(this).attr("href");
			}); 
			
			// pseudoclick of the first item 
			//el.eq(0).triggerHandler("click.hash");
			
			
		// other browsers scans for location.hash changes directly withou iframe hack
		} else { 
			setInterval(function() {
				var h = location.hash;
				
				// ivan.vovnenko: trigger when any hash change
				if ((true || el.filter("[href*=" + h + "]").length) && h !== hash) {
					hash = h;
					$.event.trigger("hash", h);
				}						
			}, 100);
		}
		 
		// bind a history listener
		$(window).bind("hash", fn);
		
		// return jQuery
		return this;		
	};	
	

})(jQuery); 

//}}}

