/*
 * jQuery UI Imagemenu 1.1
 *
 * Based on phatfusion Image Menu by Samuel Birch
 *
 * Copyright 2010, Sebastian Possner
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://www.possner.de/imagemenu
 *
 * Depends:
 *   jquery.ui.core.js
 *   jquery.ui.widget.js
 */
(function( $, undefined ) {

$.widget("ui.imagemenu", {
	options: {
		openWidth: 200,
		duration: 300,
		easing: "swing",
		open: null,
		animateOpen: false,
		fadeOutCollapsed: null,
		border: 0,
		interval: null
	},
	
	/**
	 * Create the imagemenu by decorating all <a..>-child elements.
	 * Called by widget framework.
	 */
	 _create: function() {
		this.elements = this.element.find("a");
		
		//no imagemenu when no menu items were found
		if (this.elements.length == 0) return;
		
		this.widths = {};
		this.widths.closed = this.elements.eq(0).width();
		this.widths.openSelected = this.options.openWidth;
		this.widths.openOthers = Math.round(((this.widths.closed*this.elements.length) - (this.widths.openSelected+this.options.border)) / (this.elements.length-1));
				
		var self = this;
		var options = this.options;

		//bind all mouse events
		this.elements.each(function(i,el) {
			$(el)
				.mouseenter(function(evt) {
					self.stopAutoswitcher().expandMenu(i)._trigger('menuenter',evt,el);
				})
				.mouseleave(function(evt) {
					self.expandMenu(options.open).startAutoswitcher()._trigger('menuleave',evt,el);
				})
				.click(function(evt) {
					options.open = (i == options.open ? null : i);
					self.expandMenu(i)._trigger(options.open == null ? 'clickclose' : 'clickopen',evt,el);
				});
		});
		
		//open default menu
		if (this.options.open != null) {
			//when no index was given, find the index
			if ($.type(this.options.open) !== 'number') {
				//preset to null (no index was found)
				this.elements.each(function(i,el) {
					if (el.id == options.open) {
						//overwrite open with the id
						options.open = i;
					}
				});
			}
			if ($.type(this.options.open) === 'number') {
				this._setMenu(this.options.open, this.options.animateOpen === true);
			} else {
				//id not found
				this.options.open = null;
			}
		}
		
		//start autorotation of menu items
		this.startAutoswitcher();
	},
	
	/**
	 * Expands animated the menu item with the specified index (0 = first).
	 * If no num is given (null), all items will be resetted to initial size
	 */
 	expandMenu: function(num) {
		return this._setMenu(num,true);
	},
	
	/**
	 * Expands the menu item with the specified index (0 = first).
	 * If no num is given (null), all items will be resetted to initial size
	 * animated: true to animate the expanding/collapsing effect; false otherwise
	 */
	_setMenu: function(num, animated) {
		var expanding = ($.type(num) === 'number'),
			width = (expanding ? this.widths.openOthers : this.widths.closed), 
			newSizes = {}, 
			self = this;

		if (animated) {
			//setup array of start and end sizes (one for each menu item)
			this.elements.each(function(i,el){
				newSizes[i] = {
					start: $(el).stop().width(), 
					//give some extra width on last element to avoid flickering when rounding (especially in IE )
					end: (i == self.elements.length-1 ? width+self.options.border : width)
				};
			});
			
			// set new open width of specified element for animation
			if (expanding) {
				newSizes[num] = {'width': this.widths.openSelected};
			} else {
				//animate any - e.g. the first one
				num = 0;
				//transform start,end in animateable map
				newSizes[0] = {'width': newSizes[0].end};
			}

			//animate the item and sync the others with the step method
			$(this.elements[num]).animate(newSizes[num], {
				duration: self.options.duration,
				easing:	self.options.easing,
				queue: false,
				step: function(current, fx) {
					//expand/shrink other elements
					self.elements.each(function(i,el){
						if (i != num) {
							$(el).width((newSizes[i].end-newSizes[i].start)*fx.pos + newSizes[i].start);
						}
					});
				}
			});
		} else {
			this.elements.each(function(i,el){
				if (expanding) {
					if (i == num) {
						$(el).width(self.widths.openSelected);
					} else {
						$(el).width(i == self.elements.length-1 ? width+self.options.border : width);
					}
				} else {
					$(el).width(width);	
				}
			});
												   
		}
		
		//fade in and out the menu items if configured
		if ($.type(this.options.fadeOutCollapsed) === 'number' && this.options.fadeOutCollapsed > 0) {
			this.elements.each(function(i,el){
				$(el).fadeTo(self.options.duration, (expanding && i != num ? self.options.fadeOutCollapsed : 1));
			});
		}
				
		//return this in otder to be chainable
		return this;
	},
	
	/**
	 * Starts the window interval to switch to the next menu item.
	 */
	startAutoswitcher: function() {
		if ($.type(this.options.interval) === 'number' && this.options.interval > 0) {
			this.stopAutoswitcher();
			var self = this,
				options = this.options;
			this.autoswitcher = setInterval(function() {
				self.expandMenu(options.open = (options.open + 1) % self.elements.length);
			}, this.options.interval);
		}
		return this;
	},
	
	/**
	 * Stops the current auto switcher interval if there is any.
	 */
	stopAutoswitcher: function() {
		if (this.autoswitcher != null) {
			clearInterval(this.autoswitcher);
			this.autoswitcher = null;
		}
		return this;
	}
	
});
})( jQuery );
