/***
**  JQUERY MINIMENU PLUGIN
**	WRITTEN BY TOM ROMBAUT
**  Version 0.1
**  11/2009
**  DEPENDENCIES : JQUERY 1.3.1+ , JQUERY UI 1.7.2+
***/
var MiniMenu = function(options) {
	var conf = $.extend({}, $.fn.minimenu.defaults, options);
	var menu = $("<div class='minimenu'></div>");
	var status = "hidden";
	var pos = {};
	var loaded = false;
	var children = new Array();
	var cached = false;
	var timeout = false;
	var parent = false;
	var data = false;
	var menuItems = new Array();
	var intervalID = false;
	var ulheight = 0;
	var liheight = 0;
	
	var _initialize = function() {
		if(conf.data){
			data = conf.data;
		}
		if(conf.classname)
			menu.addClass(conf.classname);
		
		if(conf.showIcon)
			menu.addClass(conf.hasiconclass);
		if(conf.preload){
			_load(false);
		}
	};
	
	/** 
	***LOAD DATA
	**/
	
	var _load = function(show){
		if(data){
			loaded = true;
			_createMenuItems(data);
			if(show){
				_show();
			}
		}else{
			$.ajax({
				type		: conf.method,
				url			: conf.url,
				data		: conf.params,
				dataType	: conf.datatype,
				success		: function(data){
								_createMenuItems(data);
								if(show){
									loaded = true;
									_show();
								}
							  }
			});
		}
	};
	/** 
	**	CREATE MENU ITEMS 
	**/	
	var _createMenuItems = function(data){
		menu.append($("<ul></ul>"));
		
		for(i=0;i<data.length;i++){
			if(data[i].separator)
				$("ul",menu).append($('<li class="mm-separator"></li>'));
		
		
			var menuItem = new MiniMenuItem(data[i],conf,menu);
			$("ul",menu).append(menuItem);
			menuItems[menuItems.length] = menuItem;
		
		}
		_createEvents();
		if(conf.oddclass){
			for(i=0;i<menuItems.length;i++){
				if(i%2==0){
					menuItems[i].addClass(conf.oddclass);
				}
			}
		}
		if(conf.evenclass){
			for(i=0;i<menuItems.length;i++){
				if(i%2==1){
					menuItems[i].addClass(conf.evenclass);
				}
			}
		}
		
			
		$('body').append(menu);
		/*if(conf.width == "auto"){
			if($.browser.msie && $.browser.version < 8){
				for(i=0;i<menuItems.length;i++){
					menuItems[i].css("width",menu.width());
				}
			}
		}else{
			menu.css("width",conf.width);
		}*/
		
		if(conf.maxitems && conf.maxitems < menuItems.length){
			liheight = 0;
			ulheight = 0;
			
			for(i=0;i<conf.maxitems;i++){
				liheight += menuItems[i].outerHeight();
			}
			for(i=0;i<menuItems.length;i++){
				ulheight += menuItems[i].outerHeight();
			}
			$("ul",menu).css({
				height 		:	liheight,
				overflow	:	"hidden",
				padding		:	0
			});
			_initscrolling();
			
		}
		
	};
	/** 
	**	CREATE REGULAR EVENTS
	**/
	var _createEvents = function(){
		$("li",menu).mouseover(function(){
			//menu.hideChildren();
		});
		menu.hover(function(){
			menu.clearHideTimer();
		},function(){
			menu.setHideTimer();
		});
	};
	
	/** SHOW MENU **/
	var _show = function(){
		if(status == "hidden"){
			if(loaded){
				menu.css({left:pos.x,top:pos.y});
				menu.css("visibility","visible");
				status = "shown";
				if($.isFunction(conf.onshow)){
					conf.onshow(menu);
				}
			}else{
				_load(true);
			}
		}
	};
	/** HIDE MENU **/
	var _hide = function(all){
		if(status == "shown"){
			menu.hideChildren();
			if(all && parent)
				parent.hide(true);
			
			menu.css("visibility","hidden");
			status = "hidden";
			if($.isFunction(conf.onhide)){
				conf.onhide(menu);
			}
		}
	};
	var _initscrolling = function(){
		menu.prepend($("<div class='mm-scroller mm-s-up'></div>"));
		menu.append($("<div class='mm-scroller mm-s-down'></div>"));
		$(".mm-s-up",menu).mouseover(function(){
			_startscrolling("up");
		});
		$(".mm-s-up",menu).mouseout(function(){
			_endscrolling("up");
		});
		$(".mm-s-down",menu).mouseover(function(){
			_startscrolling("down");
		});
		$(".mm-s-down",menu).mouseout(function(){
			_endscrolling("down");
		});
		_checkscrollers();
	};
	var _startscrolling = function(type){
		if(!intervalID){
			intervalID = setInterval(function(){_scroll(type)},conf.scrollinterval);
		}
	};
	var _endscrolling = function(type){
		if(intervalID){
			clearInterval(intervalID);
			intervalID = false;
		}
	};
	var _scroll = function(type){
		var diff = $("ul li:first",menu).height();
		
		if(type == "up"){
			$("ul li:first",menu).animate({marginTop: (_getmargin() + diff)+"px"},100,function(){_checkscrollers();});
		}else if(type == "down"){
			$("ul li:first",menu).animate({marginTop: (_getmargin() - diff)+"px"},100,function(){_checkscrollers();});
		}
		_checkscrollers();
	};
	var _checkscrollers = function(){
		if(_getmargin() >= 0){
			if($(".mm-s-up",menu).css("display") != "none"){
				_endscrolling();
				$(".mm-s-up",menu).css("display","none");
			}
		}else{
			$(".mm-s-up",menu).css("display","block");
		}
		if(Math.abs(_getmargin()) >= (Math.abs(ulheight)-liheight) ){
			if($(".mm-s-down",menu).css("display") != "none"){
				$(".mm-s-down",menu).css("display","none");
				_endscrolling();
			}
		}else{
			$(".mm-s-down",menu).css("display","block");
		}
	}
	var _getmargin = function(){
		return ($("ul li:first",menu).css("marginTop").replace("px","")*1);
	};
	
	/** PUBLIC METHOD **/
	menu.getStatus = function(){
		return status;
	};
	menu.hide = function(all){
		_endscrolling();
		_hide(all);
	};
	menu.hideChildren = function(){
		/*for(key in children){
			if(children[key].getStatus() == "shown"){
				children[key].hide();
			}
		}*/
		for(var i=0;i<menuItems.length;i++){
			menuItems[i].hideChild();
		}
	}
	menu.show = function(){
		_show();
	};
	menu.setPosition = function(position){
		pos = position;
	};
	menu.getPosition = function(){
		return pos;
	};
	menu.clearHideTimer = function(){
		if(timeout){
			clearTimeout(timeout);
			timeout = false;
		}
		if(parent){
			parent.clearHideTimer();
		}
		
	};
	menu.setHideTimer = function(){
		if(!timeout){
			timeout = setTimeout(function(){menu.hide();},conf.timeToHide);
		}
		if(parent){
			parent.setHideTimer();
		}
	};
	menu.setParent = function(p){
		parent = p;
	}
	menu.setData = function(d){
		data = d;
	}
	menu.preload = function(){
		if(!loaded)
			_load(false);
	};
	menu.destroy = function(){
		if(children.length > 0){
			for(i=0;i<children.length;i++){
				children[i].destroy();
			}
		}
		menu.remove();
	}
	_initialize();
	return menu;
};

var MiniMenuItem = function(data,options,menu){
	var conf = $.extend({}, $.fn.minimenu.defaults, options);
	var item = $("<li></li>");
	var status = false;
	var type = false;
	var child = false;
	
	var _initialize = function(){
		if(data.id)
			item.attr("rel",data.id);
		
		/** FOR OTHER TYPES THEN REGULAR **/
		if(data.type){
			type = data.type;
			status = data.status;
			_initSpecialType();
		}else if(conf.showIcon){
			if(data.icon)
				item.append("<img src='"+data.icon+"' class='mm-icon'/>");
			else
				item.append("<img src='"+conf.blankimg+"' class='mm-icon'/>");
		}	
		
		if(data.label)
			item.append("<span>"+data.label+"</span><div class='mm-clear'></div>");
		
		if(data.children){
			item.addClass("mm-container");
			var ob = new MiniMenu(conf);
			ob.setData(data.children);
			ob.setParent(menu);
			child = ob;
		}else{
			item.addClass("mm-item");
		}
		
		if(data.classname){
			item.addClass(data.classname);
		}
		
		if(data.href){
			item.click(function(){
				window.location.href = data.href;
			});
		}
		
		if(data.onclick){
			if(!$.isFunction(data.onclick)){
				try{
					var customfunc = false;
					eval("customfunc = "+data.onclick+";");
					if($.isFunction(customfunc)){
						data.onclick = customfunc;
					}
				}catch(e){
					//alert(e);
				}
			}
			if($.isFunction(data.onclick)){
				item.click(function(){data.onclick(item)});
			}
		}
		
		_createEvents();
	};
	
	_createEvents = function(){
		item.hover(function(){
			menu.hideChildren(false);
			$(this).addClass("mm-hover");
		},function(){
			$(this).removeClass("mm-hover");
		});
		if(child){
			item.mouseover(function(){
				var npos = {};
				menu.preload();
				var itemWidth = $(this).width();
				var itemTop = $(this).position().top;
				var itemHeight = $(this).height();
				var wwidth = $("body").width();
				var left = menu.getPosition().x + itemWidth;
				var top = menu.getPosition().y + itemTop /*- itemHeight*/;
				
				if(left + menu.width() > wwidth){
					left = menu.getPosition().x - (itemWidth/2);
				}
				/*if(parent){
					npos.x = parent.getPosition().x + itemWidth;
					npos.y = parent.getPosition().y + itemTop;
				}else{*/
				npos.x = left;
				npos.y = top;
				//}
				child.setPosition(npos);
				child.addClass("mm-sub");
				child.show();	
			});
		}
		item.mousedown(function(){
			$(this).addClass("mm-down");
		});
		item.mouseup(function(){
			$(this).removeClass("mm-down");
		});
		
		if(conf.onclick){
			if(!$.isFunction(conf.onclick)){
				try{
					var customfunc = false;
					eval("customfunc = "+conf.onclick+";");
					if($.isFunction(customfunc)){
						conf.onclick = customfunc;
					}
				}catch(e){
					//alert(e);
				}
			}
			if($.isFunction(conf.onclick)){
				item.click(function(){conf.onclick(item)});
			}
		}
		item.click(function(){
			$(this).removeClass("mm-down");
			if(!type){
				menu.hide(true); 
			}
		});
	};
	
	_initSpecialType = function(){
		if(type == "check"){
			var icon = "";
			if(status == "checked"){
				icon = conf.iconchecked;
			}else{
				icon = conf.iconunchecked;
				status = "unchecked";
			}
			item.append("<img src='"+icon+"' class='mm-icon'/>");
			
			item.click(function(){
				var icon = conf.iconchecked;
				if(status == "checked"){
					icon = conf.iconunchecked;
					status = "unchecked";
				}else{
					status = "checked";
				}
				$("img",item).attr("src",icon);
			});
		}
		
	};
	
	item.setStatus = function(newStatus){
		status = newStatus;
	};
	item.getStatus = function(){
		return status;
	};
	item.hideChild = function(){
		if(child){
			child.hide(false);
		}
	};
	_initialize();
	return item;
};


/**
**	JQUERY EXTENSION
**/	
(function($) {	
	$.fn.minimenu = function(options) {
		return this.each(function() {
			var element = $(this);
			if (element.data('minimenu')) return;
			var w = new MiniMenu(this, options);
			element.data('minimenu', w);
		});
	};
	
})(jQuery);


$.fn.minimenu.defaults = {
	source			: "ajax",
	data			: false,		// FOR SUBITEMS
	method			: "POST",		// METHOD
	datatype		: "json",		// SOURCE DATATYPE - JSON / ELEMENT ($("ul")) - not yet implemented;
	url				: '/',			// AJAX URL
	params			: {},  			// PARAMS TO POST
	preload			: false,		// PRELOAD DATA - AJAX
	showIcon		: false,		// SHOW ICON
	timeToHide		: 500,			// Time needed before the menu hides on mouseout	
	parent			: false,
	evenclass		: "",
	oddclass		: "",
	classname		: "",
	hasiconclass	: "mm-hasicon",
	maxitems		: false,		//LIMIT NR OF VISIBLE MENU ITEMS
	scrollinterval	: 150,
	blankimg		: "/design/default/images/miniplugins/icons/blank.gif",
	iconchecked		: "/design/default/images/miniplugins/icons/ui-check-box-mix.png",
	iconunchecked	: "/design/default/images/miniplugins/icons/ui-check-box-uncheck.png",
	onshow			: false,		//FUNCTION TRIGGERED WHEN MENU IS SHOWN
	onhide			: false,		//FUNCTION TRIGGERED WHEN MENU IS HIDDEN
	width			: 'auto',		//OR PX OR TRIGGER
	appendTo		: $('body')
};

/** DATA ELEMENT OPTIONS 
button {
	id		:  "buttonid",
	label	:  "the label",
	onclick :  function(){ your action here },
	href	:  "Path/To/Url",
	icon	:  "Path/to/icon.gif",
	classname: "extraclass",
	type	:  "check",	  	   specialtypes not required
	status	:  "unchecked",  - or checked when is a specialtype 
}***/

