/* jjmenu - context menu jquery plugin
 * http://jursza.net/dev/jjmenu/
 *  
 * @author Jacek Jursza (okhan.pl@gmail.com)
 * @version 1.1.2
 * @date 2010-08-28
 * @category jQuery plugin
 * @copyright (c) 2009 Jacek Jursza (http://jursza.net/)
 * @licence MIT [http://www.opensource.org/licenses/mit-license.php]    
 */

(function($){  
   
	$.fn.jjmenu = function (clickEvent, param, myReplaces, effect) {  

		var global = this; 
		var acceptEvent = false;
		

		if ( clickEvent == "rightClick" || clickEvent == "both" )
		{
			global.mousedown(function(event) {
					if (event.button == 2 && (clickEvent == "rightClick" || clickEvent == "both")) { // right click
					    global.pageX = event.pageX;
                        global.pageY = event.pageY;
						event.preventDefault();
						event.stopPropagation();
						var mmain = new menu("main", param, myReplaces, this, effect);
						$(this)[0].oncontextmenu = function() {
									return false;
						}
          				$(this).unbind('mouseup');
          				$(this).blur();
          				return false;			
				    }
			});
			
    		document.body.oncontextmenu = function() {
                if ($("div[id^=jjmenu_main]").length) return false;
            }			
		}
		
		if ( clickEvent == "click" || clickEvent == "both" )
		{
			global.click( 
                    function(event) {
                        if (this == event.target) {
                            global.pageX = event.pageX;
                            global.pageY = event.pageY;
        					event.preventDefault();
        					event.stopPropagation();
        					var mmain = new menu("main", param, myReplaces, this, effect);
        					$(this).blur();
        					return false;			
    					}
	           		});
		}

		$(document).click(function(event) { if (event.button!=2) $("div[id^=jjmenu]").remove(); });

        /* Menu obeject */
		function menu(id,param,myReplaces,el,effect) {
		
			var effect = getEffect(id, effect);
			
			if (id == "main") window.triggerElement = el;
			$("div[id^=jjmenu_"+id+"]").remove();
			
            var m  = document.createElement('div');
			var ms = document.createElement('span');
			$(m).append(ms);
			
			m.className = "jjmenu";	m.id = "jjmenu_"+id;
			$(m).css({display:'none'});
			$(document.body).append(m);
			
			positionMenu();	

			var dynamicItems = false;
			
			for (var i in param) {
				
				if (param[i].get) {
					
					dynamicItems = true;
					$.getJSON(uReplace(param[i].get), function(data) {
						for (var ii in data) {
							putItem(data[ii]);
						}
						checkPosition();
					})
					$(this).ajaxError( function() {
						checkPosition();
					});
				}
				else if (param[i].getByFunction) {
					
					if  (typeof(param[i].getByFunction) == "function") {
						var uF = param[i].getByFunction;
					}
					else {
						var uF = eval(param[i].getByFunction);
					}
					var uItems = uF(myReplaces);
					for (var ii in uItems) {
						putItem(uItems[ii]);
					}
					checkPosition();
				}
				else {
					putItem(param[i]);
				}
			}
			
			if (!dynamicItems) checkPosition();
			showMenu();
			
			/* first position menu */
			function positionMenu() {
			
				var pos = $(el).offset();
				
				var t = pos.top;
				
				if (effect.xposition == "left") {
					 var l = pos.left;
				}
				else {
					 var l = pos.left+$(el).width()+10;
				}
				
				if (effect.xposition == "mouse") {
                    l = global.pageX;
                }
                if (effect.yposition == "mouse") {
                    t = global.pageY;
                }

				$(m).css({position:"absolute",top:t+"px",left:l+"px"});	         
			}
			
			/* correct menu position */
			function checkPosition() {

				var isHidden = $(m).css("display") == "none" ? true : false; 
				var noAuto = false;
				
				if (effect.orientation == "top" || effect.orientation == "bottom") {
					noAuto = true;
				}
			
				if (isHidden) $(m).show();
				    var positionTop = $(m).offset().top;
				    var positionLeft = $(m).offset().left;
				if (isHidden) $(m).hide(); 
			
				var xPos = positionTop - $(window).scrollTop();
	            
                $(m).css({left:"0px"});
                    var menuHeight = $(m).outerHeight();
                    var menuWidth = $(m).outerWidth();
				$(m).css({left:positionLeft+"px"});
                
                var nleft = positionLeft;
				if ( positionLeft + menuWidth > $(window).width() ) {
                    nleft = $(window).width() - menuWidth;
                }
                				
				var spaceBottom = true;
				if (effect.yposition == "auto" && effect.xposition == "left") {
					
                    if ( xPos + menuHeight + $(el).outerHeight() > $(window).height()) {
					    spaceBottom = false;
				    }				
				}				
				else {
    				
                    if ( xPos + menuHeight  > $(window).height()) {
    					spaceBottom = false;
    				}                
                }				

				var spaceTop = true;
				if (positionTop - menuHeight <  0) {
					spaceTop = false;
				}
				
				if (effect.yposition == "bottom") {
					positionTop = positionTop + $(el).outerHeight();
				 }
				
				if ( (effect.orientation == "auto" && spaceBottom == false && spaceTop == true) || effect.orientation == "top") {
					// top orientation
					var ntop = parseInt(positionTop,10) - parseInt(menuHeight,10);
					$(m).addClass("topOriented");

				} else {
					// bottom orientation
					$(m).addClass("bottomOriented");
					if (effect.yposition == "auto" && effect.xposition == "left") {
						positionTop = positionTop + $(el).outerHeight();
					}
					var ntop = parseInt(positionTop,10);
				}
				
				$(m).css({"top":ntop+"px", "left":nleft+"px"});
			}
			
			/* show menu depends to effect.show */
			function showMenu() {

				 if (!effect || effect.show == "default") {
					$(m).show();
					return false;
				 }
				 
				 var speed = parseInt(effect.speed);
				 speed = isNaN(speed) ? 500 : speed;
				   
				 switch (effect.show) 
				 {
					  case "fadeIn": 
						$(m).fadeIn(speed); 
					  break;
					  
					  case "slideDown": 
						$(m).slideDown(speed); 
					  break;
					  
					  default:
						$(m).show();
					  break;
				 }
			}
			
			/* put item to menu */
			function putItem(n) {
				
				var item = document.createElement('div');
				$(item).hover(function(){
								$(this).addClass("jj_menu_item_hover")
							  },
							  function(){
								$(this).removeClass("jj_menu_item_hover")
							  });
				
				$(item).click( function(event) {
					event.stopPropagation();
					doAction(n.action);	
				});	
				
				var span = document.createElement('span');
				$(item).append(span);
				  

				switch (n.type)
				{
					case "sub":
						item.className = "jj_menu_item jj_menu_item_more";
						$(item).click(function() {	 	
							if ($("#jjmenu_"+id+"_sub").length > 0) {
								$("div[id^=jjmenu_"+id+"_sub]").remove();
							}
							else {
								var sub = new menu(id+"_sub", n.src, myReplaces, this, effect);
							}	
						});
					break;
					
					default:
					  $(item).hover(function() { $("div[id^=jjmenu_"+id+"_sub]").remove(); });
						item.className = "jj_menu_item";
					break;
				}
				
				
				if (n.customClass && n.customClass.length>0) {
                    jQuery(span).addClass(n.customClass);
                }
				
				$(span).html(uReplace(n.title));
				$(ms).append(item);
			}
			
			/* do action on menu item */
			function doAction(act) {
			
				if (act) {
					
					switch (act.type) {
						
						case "gourl":
							if (act.target) {
								var newWindow = window.open(uReplace(act.url), act.target);
								newWindow.focus();
								return false;
							}
							else {
								document.location.href=uReplace(act.url);
							}
						break;
						
						case "ajax":
							$.getJSON(uReplace(act.url), function(data) {
							
								var cb = eval(act.callback);
								if (typeof(cb) == "function") {
									cb(data);
								}
							
							});
						break;
						
						case "fn":
                                var callfn = 'var cb = '+act.callback;
                                jQuery.globalEval(callfn);
                                if (typeof(cb) == "function") {
                                    cb(myReplaces);
                                }
						break;
					}
				}
			}
			
			/* replace string with user parameters */
			function uReplace(str) {
				if (myReplaces) {
					for (var u in myReplaces) {
						str = str.replace("#"+u+"#", eval("myReplaces."+u));
					}
				}
				return str;
			}

            /* get effect opbject */
			function getEffect(id, effect) {
			
				var defEffect = {
				  show:"default",
				  xposition:"right",
				  yposition:"auto",
				  orientation:"auto"
				};

				if (!effect) { return defEffect;  }      

				if (!effect.show) effect.show = "default";
						  
				var show = effect.show;

				if (!effect.xposition) effect.xposition = "right";
				if (!effect.yposition) effect.yposition = "auto";
				if (!effect.orientation) effect.orientation = "auto";

				if (id != "main") {
					var subeffect = defEffect;
					subeffect.show = show;
				}

				return ( id == "main" ) ? effect : subeffect;
			}
		} // !menu
	};  
   
 })(jQuery); 