// #@(#)jquery.animatedMenu.js	1.1 13:51:26,11/09/20 (yy/mm/dd)
(function ($) {
	/**
	 * Private Objects/Methods
	 */
	
	var menu = {
		
		/**
		 * Change to attempt to change the image/text
		 * If successful then calls the update method.
		 * Also queues up changes should they already be happening
		 */
		change:function(inThis, inData) {
			var currentIndex	= $(inThis).data("currentIndex"),
				options			= $(inThis).data("options"),
				timeoutID;
			if($(inThis).data("currentIndex") != inData.index && menu.inFade !== true) {
				$(inThis).data("tempIndex", inData.index);
				
				timeoutID = setTimeout(function(e) {
					menu.update(inThis, inData);
				},options.hoverPause);
				
				$(inThis).data("timerID", timeoutID);
			} else if(menu.inFade === true) {
				menu.queueFade = {menuThis:inThis, menuData:inData};
			}
		},
		
		/**
		 * Changes the actual image and text
		 * Ensures the image is fully loaded before changing
		 */
		update:function(inThis, inData) {
			var foreground	= $(inThis).find(".jq_animatedMenu_foreground"),
				background	= $(inThis).find(".jq_animatedMenu_background"),
				options		= $(inThis).data("options"),
				cacheImage	= document.createElement('img');
			
			menu.inFade = true;
			
			// Swap foreground to background
			$(background).html($(foreground).html());
			$(background).fadeIn(0);
		
			$(cacheImage).load(function(){
				// Set the current index of the item so that we don't try and keep
				// loading should we already be on it.
				$(inThis).data("currentIndex", $(inThis).data("tempIndex"));
				
				// Apply the image and the text to the foreground
				$(foreground).find("img:first").attr("src", inData.image);
				$(foreground).find(".jq_animatedMenu_text").html(inData.text);
				$(background).fadeOut(options.fadeDuration, function() {
					menu.inFade = false;
					if(menu.queueFade !== undefined) {
						menu.change(menu.queueFade.menuThis, menu.queueFade.menuData);
						menu.queueFade = undefined;
					}
				});
			
			});
			cacheImage.src = inData.image;
		},
		
		stop:function(inThis, inData) {
			clearTimeout($(inThis).data("timerID"));
		}
	};
	
	/**
	 * Public methods
	 */
	var methods = {
		
		/**
		 * The main/default constructor of the plugin
		 */
		init : function(inOptions) {
			var options = $.extend({}, $.fn.animatedMenu.defaults, inOptions);		// Combine the options and defaults into a new object
			// Set up each menu here
			return this.each(function() {
				var defaultDiv		= $(this).find(".jq_animatedMenu_default"),
					foregroundDiv	= {},
					backgroundDiv	= {},
					classes			= $(defaultDiv).attr("class"),
					cArray			= classes.split(" "),
					cLength			= cArray.length,
					cCount			= 0,
					menuItems		= $(this).find(".jq_animatedMenu_list ul:first > li"),
					mainThis		= this;
				
				// Give defaults for the menu checking
				$(this).data("index",	-1);
				$(this).data("options", options);
				
				$(defaultDiv).before("<div class='jq_animatedMenu_foreground'></div>");
				$(defaultDiv).before("<div class='jq_animatedMenu_background'></div>");
				
				foregroundDiv = $(this).find(".jq_animatedMenu_foreground");
				backgroundDiv = $(this).find(".jq_animatedMenu_background"); 
				
				for(cCount = cLength; cCount > 0; cCount--) { if(cArray[cCount] == "jq_animatedMenu_default") { cArray.splice(cCount, 1); }}
				
				classes = cArray.join(" ");
				// Add the existing content to the foreground and background and copy across the classes
				$(foregroundDiv).html($(defaultDiv).html()).addClass(classes);
				$(backgroundDiv).html($(defaultDiv).html()).addClass(classes);
				
				// Hide it as we still need the data
				$(defaultDiv).hide();
				
				// Find the images and the text and add them to the hover function for the over state of each menu
				$(menuItems).each(function(index) {
					var menuData	= {},
						menuItem	= $(this).find(".jq_animatedMenu_data");
					
					menuItem.hide();
					
					menuData.image	= $(menuItem).attr("rel");
					menuData.text	= $(menuItem).html();
					menuData.index	= index;
					$(this).hover(
						function() {
							menu.change(mainThis, menuData);
						}, 
						function() {
							menu.stop(mainThis, menuData);
						}
					);
				});
				
				$(this).bind("mouseleave", function() {
					var defaultImage	= $(defaultDiv).find("img:first").attr("src"),
						defaultText		= $(defaultDiv).find(".jq_animatedMenu_text").html();
					
					// Stop the current
					menu.stop(mainThis, null);
					
					// Clear the Queue
					menu.queueFade = undefined;
					
					// Revert back
					menu.change(mainThis, {image:defaultImage, text:defaultText, index:-1});	
					
				});
				
			});
		}
	};
	
	/**
	 * Main Constructor which then goes on to use the method object.
	 */
	$.fn.animatedMenu = function (method) {
		if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
	    } else if (typeof method === 'object' || !method ) {
			return methods.init.apply(this, arguments);
	    } else {
			$.error('Method ' +  method + ' does not exist on jQuery.animatedMenu');
	    }
	};
	
	/**
	 * Public Properties contained within defaults object
	 */ 
	$.fn.animatedMenu.defaults = {
		hoverPause:500,
		fadeDuration:3000
	};
	
	/**
	 * Default automated method
	 */
	$(document).ready(function() {
		$('.jq_animatedMenu').animatedMenu();
	});
})(jQuery);

