YAHOO.namespace("YAHOO.mozmonkey");

/**
* Use this to animate in an element's hover state.  
* Do to Internet Explorer's event handling model, you'll have to define
* a hovering CSS class for this to work -- the code cannot hijaxk the :hover psuedo class styles.
* 
* How it works:
*
* 	Given the CSS:
* 		a:hover, a.hover { color: #f00; background: #dedede; }
*
*	The JavaScript:
*		YAHOO.util.Event.addListener(window, "load", function(){ YAHOO.mozmonkey.HoverHijax.addAllAncors('hover') });
*
*	Every anchor, when moused over, would fade into being red with a light grey background.
*	When moused off, the link will animate back to its original colors.  
* 
*	In this example the hover styles are grabbed from the a.hover selector and a:hover is present for non-JS browsers.
*
*
* Hovering Other Elements:
*
*	You can also use this API to animate hover on other elements
*	
*	The HTML:
*		<div id="testBtn">Try hovering me</div>
*
*	The CSS:
*		div#testBtn { background: #dedede; }
*		div#testBtn.hovering { background: #666; }
*
*	The JS:
*		YAHOO.mozmonkey.HoverHijax.addElement("testHover", "hovering");
*
* Animation Options:
*
*	You can specify custom options for the animation effects.
*		YAHOO.mozmonkey.HoverHijax.addElement("testHover", "hovering", { durationOn : .5, durationOn : 2 });
*
*	In this example, the hover will animate on (mouseover) in 500 milliseconds and will hover off (mouseout) in 2 seconds.
*	See the addElement() method documentation to get a full list of config parameter options.
*
* Important Limitations:
*
*	Background Color:
*	The background color will not animate if there is not a default background color set 
*	somewhere in the node's parent heirarchy.  Otherwise the backgroundColor style is specified as
* 	transparent, which is impossible to animate from.
*
*	Border Colors:
*	The border colors cannot be animated if a border is not set on the base (non-hovering) styles.
*	As a trick, you can set the border color to be the same as the background for the base style.
*	
*/
YAHOO.mozmonkey.HoverHijax = (function(){
	
	/**
	* Get all animatable colors from the element
	* @param {DomNode} el The elemnent to read the colors froma
	* @returns {Object}
	*/
	function getColors(el){
		var dom = YAHOO.util.Dom;
		var colors = {};
		colors.color = dom.getStyle(el, "color");
		colors.backgroundColor = dom.getStyle(el, "backgroundColor");
		colors.borderTopColor = dom.getStyle(el, "borderTopColor");
		colors.borderRightColor = dom.getStyle(el, "borderRightColor");
		colors.borderBottomColor = dom.getStyle(el, "borderBottomColor");
		colors.borderLeftColor = dom.getStyle(el, "borderLeftColor");
		
		// No background animation for images
		if(dom.getStyle(el, "backgroundImage") != "none"){
			colors.backgroundColor = null;
		}
		
		// Resolve transparency
		if(isTransparent(colors.backgroundColor)){
			colors.backgroundColor = resolveTransparency(el);
		}
		
		return colors;
	}
	
	/**
	* Detect if a color string means transparent
	* @param {String} color The color string
	* @returns boolean
	*/
	function isTransparent(color){
		return (color == "transparent" || color == "rgba(0, 0, 0, 0)");
	}
	
	/**
	* Resolve tranparent background.
	* Climb up node heirarcy until you find a defined background color
	* @param {DomNode} el The element to get the background for
	*/
	function resolveTransparency(el){
		var dom = YAHOO.util.Dom;
		var node = el;
		var bg = dom.getStyle(node, "backgroundColor");
		
		while(node && isTransparent(bg)){
			node = node.parentNode
			if(node == document){
				break;
			}
			bg = dom.getStyle(node, "backgroundColor");
			if(dom.getStyle(node, "backgroundImage") != "none"){
				bg = null;
				break;
			}
		}
		
		return bg;
	}
	
	/**
	* Get animation attributes
	* @param {DomNode} el The element that will be animated
	* @param {String} dir The hover direction ("on" or "off")
	* @param {Object} attributes The base custom attributes object
	* @return {Object} The attributes object
	*/
	function generateAttributes(el, dir, attributes){
		var attr = attributes;
		var dom = YAHOO.util.Dom;
		var from = el.hoverConfig.colorsOff;
		var to = el.hoverConfig.colorsOff;
		
		// Hover on
		if(dir == "on"){
			if(el.hoverConfig.colorsOn){
				to = el.hoverConfig.colorsOn;
			}
			else{
				dom.addClass(el, el.hoverConfig.className);
				to = getColors(el);
				el.hoverConfig.colorsOn = to;
				dom.removeClass(el, el.hoverConfig.className);
				
				// Reset colors
				for(prop in from){
					dom.setStyle(el, prop, from[prop]);
				}
			}
		}
		
		// Hover off
		else{
			from = el.hoverConfig.colorsOn;
		}
		
		// Diff and creat config
		for(prop in from){
			
			if(from[prop] && to[prop] && from[prop] != to[prop] && !isTransparent(to[prop]) && !isTransparent(from[prop])){
				attr[prop] = { 'to' : to[prop] };
			}
		}
		
		return attr;
		
	}
	
	/**
	* Start hover animation
	* @param {DomNode} el The element to hover
	*/
	function hoverOn(el, i){
		(new YAHOO.util.ColorAnim(el, generateAttributes(el, "on", el.hoverConfig.attrOn), el.hoverConfig.durationOn)).animate();
	}
	
	/**
	* Start over off animation
	* @param {DomNode} el The element to hover
	*/
	function hoverOff(el){
		(new YAHOO.util.ColorAnim(el, generateAttributes(el, "off", el.hoverConfig.attrOff), el.hoverConfig.durationOff)).animate();
	}
	
	
	return {
		
		/**
		* The animation duration (in seconds) when the element is hovered on.
		*/
		durationOn : .7,
		
		/**
		* The animation duration (in seconds) when the element is hovered off.
		*/
		durationOff : .7,
		
		/**
		* Setup element for hovering
		* @param {Object} el The element or element ID to setup
		* @param {String} className The CSS class to be added to envoke the hover colors (you can thank IE for this)
		* @param {Object} config Custom animation object.
		* 	<strong>durationOn</strong>: The animation duration (in seconds) when the element is hovered on.
		* 	<strong>durationOff</strong>: The animation duration (in seconds) when the element is hovered on.
		* 	<strong>methodOn</strong>: The animation method to use when the element is hovered on. (defaults YAHOO.util.Easing.easeNone)
		* 	<strong>methodOff</strong>: The animation method to use when the element is hovered off. (defaults YAHOO.util.Easing.easeNone)
		* 	<strong>attrOn:</style> Extra style attributes to be animated when the element is hoverd on (ie: height, width).
		* 	<strong>attrOff:</style> Extra style attributes to be animated when the element is hoverd off (ie: height, width).
		*/
		addElement : function(el, className, config){
					
			if(typeof el == "string"){
				el = document.getElementById(el);
			}
			
			if(!el){
				return;
			}
			
			// Set configuration
			el.hoverConfig = {};
			el.hoverConfig.colorsOff = getColors(el);
			el.hoverConfig.className = className
			el.hoverConfig.methodOn = config.methodOn;
			el.hoverConfig.methodOff = config.methodOff;
			el.hoverConfig.attrOn = config.attrOn || {};
			el.hoverConfig.attrOff = config.attrOff || {};
			el.hoverConfig.durationOn = config.durationOn || this.durationOn;
			el.hoverConfig.durationOff = config.durationOff || this.durationOff;
			
			// Add events
			YAHOO.util.Event.addListener(el, "mouseover", function(){ hoverOn(el) });
			YAHOO.util.Event.addListener(el, "mouseout", function(){ hoverOff(el) });
		},
		
		/**
		* Setup all <a> elements on the page for hovering
		* @param {Object} config The configuration object.
		*/
		addAllAncors : function(className, config){
			var a = document.getElementsByTagName("a");
			for(var i = 0; i < a.length; i++){
				this.addElement(a[i], className, config);
			}
			
		}		
	}
	
})();
