/**
* Over 'n Out is essentially like hoverIntent by Brian Cherne except that this one can truely have no delay on mouseover
*
* //Usage
* $("ul#top_nav li.dropdown").overNOut({
*		over: function(e) { },	//The function to be called on mouseover 
*		overDelay: 0,             //The delay for the mouseover function call
*		out: function(e) { },	   //The function to be called on mouseout 
*		outDelay: 300,           //The delay for the mouseout function call (give the user a chance to bring the mouse back into the elements space) 
*		mouseOutOnLast: true		    //Calls mouseout on the last element when the user hovers over a new one
*	});
*
* @Author Alex Howard
*/

(function($) {
	$.fn.overNOut = function(passedOptions) {
		// default configuration options
		var options = {
			overDelay: 0,
			outDelay: 300,
			over: false,
			out: false,
			mouseOutOnLast: true
		};
		
		var lastOver;
		
		var handleHover = function(e) {
			var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
			while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
			if ( p == this ) { return false; }
			
			var ob = this;
			
			switch (e.type) {
				case "mouseover":
					if (this.overNOutTimer) { clearTimeout(this.overNOutTimer); }
					
					if (options.mouseOutOnLast) {
						if (lastOver) { 
							lastOver.overNOutOptions.out.apply(lastOver);
							clearTimeout(lastOver.overNOutTimer);
						}
					}
					
					lastOver = this;
					
					if (options.over) {
						if (options.overDelay > 0) {
							this.overNOutTimer = setTimeout(function() {
								options.over.apply(ob, [e]);
							}, options.overDelay);
						} else {
							options.over.apply(this, [e]);
						}
					}
					break;
				
				case "mouseout":
					//if (this.overNOutTimer) { clearTimeout(this.overNOutTimer); }
					if (options.out) {
						if (options.outDelay > 0) {
							this.overNOutTimer = setTimeout(function() {
								options.out.apply(ob, [e]);
							}, options.outDelay);
						} else {
							options.out.apply(this, [e]);
						}
					}
					break;
					
				default:
					break;
			}
		};

		return this.each(function() {        
			// If options exist, lets merge them
			// with our default settings
			if ( passedOptions ) { 
				$.extend(options, passedOptions);
			}
			
			this.overNOutOptions = options;
			this.overNOutTimer = false;
			
			$(this).mouseover(handleHover).mouseout(handleHover);
		});
	};
})(jQuery);
