/*! * jQuery contextMenu - Plugin for simple contextMenu handling * * Version: git-master * * Authors: Rodney Rehm, Addy Osmani (patches for FF) * Web: http://medialize.github.com/jQuery-contextMenu/ * * Licensed under * MIT License http://www.opensource.org/licenses/mit-license * GPL v3 http://opensource.org/licenses/GPL-3.0 * */ (function($,undefined){$.support.htmlMenuitem=("HTMLMenuItemElement" in window);$.support.htmlCommand=("HTMLCommandElement" in window);$.support.eventSelectstart=("onselectstart" in document.documentElement);if(!$.ui||!$.ui.widget){var _cleanData=$.cleanData;$.cleanData=function(elems){for(var i=0,elem;(elem=elems[i])!=null;i++){try{$(elem).triggerHandler("remove")}catch(e){}}_cleanData(elems)}}var $currentTrigger=null,initialized=false,$win=$(window),counter=0,namespaces={},menus={},types={},defaults={selector:null,appendTo:null,trigger:"right",autoHide:false,delay:200,reposition:true,determinePosition:function($menu){if($.ui&&$.ui.position){$menu.css("display","block").position({my:"center top",at:"center bottom",of:this,offset:"0 5",collision:"fit"}).css("display","none")}else{var offset=this.offset();offset.top+=this.outerHeight();offset.left+=this.outerWidth()/2-$menu.outerWidth()/2;$menu.css(offset)}},position:function(opt,x,y){var $this=this,offset;if(!x&&!y){opt.determinePosition.call(this,opt.$menu);return}else{if(x==="maintain"&&y==="maintain"){offset=opt.$menu.position()}else{offset={top:y,left:x}}}var bottom=$win.scrollTop()+$win.height(),right=$win.scrollLeft()+$win.width(),height=opt.$menu.height(),width=opt.$menu.width();if(offset.top+height>bottom){offset.top-=height}if(offset.top<0){offset.top=0}if(offset.left+width>right){offset.left-=width}opt.$menu.css(offset)},positionSubmenu:function($menu){if($.ui&&$.ui.position){$menu.css("display","block").position({my:"left top",at:"right top",of:this,collision:"flipfit fit"}).css("display","")}else{var offset={top:0,left:this.outerWidth()};$menu.css(offset)}},zIndex:1,animation:{duration:50,show:"slideDown",hide:"slideUp"},events:{show:$.noop,hide:$.noop},callback:null,items:{}},hoveract={timer:null,pageX:null,pageY:null},zindex=function($t){var zin=0,$tt=$t;while(true){zin=Math.max(zin,parseInt($tt.css("z-index"),10)||0);$tt=$tt.parent();if(!$tt||!$tt.length||"html body".indexOf($tt.prop("nodeName").toLowerCase())>-1){break}}return zin},handle={abortevent:function(e){e.preventDefault();e.stopImmediatePropagation()},contextmenu:function(e){var $this=$(this);if(e.data.trigger=="right"){e.preventDefault();e.stopImmediatePropagation()}if(e.data.trigger!="right"&&e.originalEvent){return}if($this.hasClass("context-menu-active")){return}if(!$this.hasClass("context-menu-disabled")){$currentTrigger=$this;if(e.data.build){var built=e.data.build($currentTrigger,e);if(built===false){return}e.data=$.extend(true,{},defaults,e.data,built||{});if(!e.data.items||$.isEmptyObject(e.data.items)){if(window.console){(console.error||console.log).call(console,"No items specified to show in contextMenu")}throw new Error("No Items specified")}e.data.$trigger=$currentTrigger;op.create(e.data)}op.show.call($this,e.data,e.pageX,e.pageY)}},click:function(e){e.preventDefault();e.stopImmediatePropagation();$(this).trigger($.Event("contextmenu",{data:e.data,pageX:e.pageX,pageY:e.pageY}))},mousedown:function(e){var $this=$(this);if($currentTrigger&&$currentTrigger.length&&!$currentTrigger.is($this)){$currentTrigger.data("contextMenu").$menu.trigger("contextmenu:hide")}if(e.button==2){$currentTrigger=$this.data("contextMenuActive",true)}},mouseup:function(e){var $this=$(this);if($this.data("contextMenuActive")&&$currentTrigger&&$currentTrigger.length&&$currentTrigger.is($this)&&!$this.hasClass("context-menu-disabled")){e.preventDefault();e.stopImmediatePropagation();$currentTrigger=$this;$this.trigger($.Event("contextmenu",{data:e.data,pageX:e.pageX,pageY:e.pageY}))}$this.removeData("contextMenuActive")},mouseenter:function(e){var $this=$(this),$related=$(e.relatedTarget),$document=$(document);if($related.is(".context-menu-list")||$related.closest(".context-menu-list").length){return}if($currentTrigger&&$currentTrigger.length){return}hoveract.pageX=e.pageX;hoveract.pageY=e.pageY;hoveract.data=e.data;$document.on("mousemove.contextMenuShow",handle.mousemove);hoveract.timer=setTimeout(function(){hoveract.timer=null;$document.off("mousemove.contextMenuShow");$currentTrigger=$this;$this.trigger($.Event("contextmenu",{data:hoveract.data,pageX:hoveract.pageX,pageY:hoveract.pageY}))},e.data.delay)},mousemove:function(e){hoveract.pageX=e.pageX;hoveract.pageY=e.pageY},mouseleave:function(e){var $related=$(e.relatedTarget);if($related.is(".context-menu-list")||$related.closest(".context-menu-list").length){return}try{clearTimeout(hoveract.timer)}catch(e){}hoveract.timer=null},layerClick:function(e){var $this=$(this),root=$this.data("contextMenuRoot"),button=e.button,x=e.pageX,y=e.pageY,target,offset;e.preventDefault();e.stopImmediatePropagation();setTimeout(function(){var $window;var triggerAction=((root.trigger=="left"&&button===0)||(root.trigger=="right"&&button===2));if(document.elementFromPoint){root.$layer.hide();target=document.elementFromPoint(x-$win.scrollLeft(),y-$win.scrollTop());root.$layer.show()}if(root.reposition&&triggerAction){if(document.elementFromPoint){if(root.$trigger.is(target)||root.$trigger.has(target).length){root.position.call(root.$trigger,root,x,y);return}}else{offset=root.$trigger.offset();$window=$(window);offset.top+=$window.scrollTop();if(offset.top<=e.pageY){offset.left+=$window.scrollLeft();if(offset.left<=e.pageX){offset.bottom=offset.top+root.$trigger.outerHeight();if(offset.bottom>=e.pageY){offset.right=offset.left+root.$trigger.outerWidth();if(offset.right>=e.pageX){root.position.call(root.$trigger,root,x,y);return}}}}}}if(target&&triggerAction){root.$trigger.one("contextmenu:hidden",function(){$(target).contextMenu({x:x,y:y})})}root.$menu.trigger("contextmenu:hide")},50)},keyStop:function(e,opt){if(!opt.isInput){e.preventDefault()}e.stopPropagation()},key:function(e){var opt={};if($currentTrigger){opt=$currentTrigger.data("contextMenu")||{}}switch(e.keyCode){case 9:case 38:handle.keyStop(e,opt);if(opt.isInput){if(e.keyCode==9&&e.shiftKey){e.preventDefault();opt.$selected&&opt.$selected.find("input, textarea, select").blur();opt.$menu.trigger("prevcommand");return}else{if(e.keyCode==38&&opt.$selected.find("input, textarea, select").prop("type")=="checkbox"){e.preventDefault();return}}}else{if(e.keyCode!=9||e.shiftKey){opt.$menu.trigger("prevcommand");return}}case 40:handle.keyStop(e,opt);if(opt.isInput){if(e.keyCode==9){e.preventDefault();opt.$selected&&opt.$selected.find("input, textarea, select").blur();opt.$menu.trigger("nextcommand");return}else{if(e.keyCode==40&&opt.$selected.find("input, textarea, select").prop("type")=="checkbox"){e.preventDefault();return}}}else{opt.$menu.trigger("nextcommand");return}break;case 37:handle.keyStop(e,opt);if(opt.isInput||!opt.$selected||!opt.$selected.length){break}if(!opt.$selected.parent().hasClass("context-menu-root")){var $parent=opt.$selected.parent().parent();opt.$selected.trigger("contextmenu:blur");opt.$selected=$parent;return}break;case 39:handle.keyStop(e,opt);if(opt.isInput||!opt.$selected||!opt.$selected.length){break}var itemdata=opt.$selected.data("contextMenu")||{};if(itemdata.$menu&&opt.$selected.hasClass("context-menu-submenu")){opt.$selected=null;itemdata.$selected=null;itemdata.$menu.trigger("nextcommand");return}break;case 35:case 36:if(opt.$selected&&opt.$selected.find("input, textarea, select").length){return}else{(opt.$selected&&opt.$selected.parent()||opt.$menu).children(":not(.disabled, .not-selectable)")[e.keyCode==36?"first":"last"]().trigger("contextmenu:focus");e.preventDefault();return}break;case 13:handle.keyStop(e,opt);if(opt.isInput){if(opt.$selected&&!opt.$selected.is("textarea, select")){e.preventDefault();return}break}opt.$selected&&opt.$selected.trigger("mouseup");return;case 32:case 33:case 34:handle.keyStop(e,opt);return;case 27:handle.keyStop(e,opt);opt.$menu.trigger("contextmenu:hide");return;default:var k=(String.fromCharCode(e.keyCode)).toUpperCase();if(opt.accesskeys&&opt.accesskeys[k]){opt.accesskeys[k].$node.trigger(opt.accesskeys[k].$menu?"contextmenu:focus":"mouseup");return}break}e.stopPropagation();opt.$selected&&opt.$selected.trigger(e)},prevItem:function(e){e.stopPropagation();var opt=$(this).data("contextMenu")||{};if(opt.$selected){var $s=opt.$selected;opt=opt.$selected.parent().data("contextMenu")||{};opt.$selected=$s}var $children=opt.$menu.children(),$prev=!opt.$selected||!opt.$selected.prev().length?$children.last():opt.$selected.prev(),$round=$prev;while($prev.hasClass("disabled")||$prev.hasClass("not-selectable")){if($prev.prev().length){$prev=$prev.prev()}else{$prev=$children.last()}if($prev.is($round)){return}}if(opt.$selected){handle.itemMouseleave.call(opt.$selected.get(0),e)}handle.itemMouseenter.call($prev.get(0),e);var $input=$prev.find("input, textarea, select");if($input.length){$input.focus()}},nextItem:function(e){e.stopPropagation();var opt=$(this).data("contextMenu")||{};if(opt.$selected){var $s=opt.$selected;opt=opt.$selected.parent().data("contextMenu")||{};opt.$selected=$s}var $children=opt.$menu.children(),$next=!opt.$selected||!opt.$selected.next().length?$children.first():opt.$selected.next(),$round=$next;while($next.hasClass("disabled")||$next.hasClass("not-selectable")){if($next.next().length){$next=$next.next()}else{$next=$children.first()}if($next.is($round)){return}}if(opt.$selected){handle.itemMouseleave.call(opt.$selected.get(0),e)}handle.itemMouseenter.call($next.get(0),e);var $input=$next.find("input, textarea, select");if($input.length){$input.focus()}},focusInput:function(e){var $this=$(this).closest(".context-menu-item"),data=$this.data(),opt=data.contextMenu,root=data.contextMenuRoot;root.$selected=opt.$selected=$this;root.isInput=opt.isInput=true},blurInput:function(e){var $this=$(this).closest(".context-menu-item"),data=$this.data(),opt=data.contextMenu,root=data.contextMenuRoot;root.isInput=opt.isInput=false},menuMouseenter:function(e){var root=$(this).data().contextMenuRoot;root.hovering=true},menuMouseleave:function(e){var root=$(this).data().contextMenuRoot;if(root.$layer&&root.$layer.is(e.relatedTarget)){root.hovering=false}},itemMouseenter:function(e){var $this=$(this),data=$this.data(),opt=data.contextMenu,root=data.contextMenuRoot;root.hovering=true;if(e&&root.$layer&&root.$layer.is(e.relatedTarget)){e.preventDefault();e.stopImmediatePropagation()}(opt.$menu?opt:root).$menu.children(".hover").trigger("contextmenu:blur");if($this.hasClass("disabled")||$this.hasClass("not-selectable")){opt.$selected=null;return}$this.trigger("contextmenu:focus")},itemMouseleave:function(e){var $this=$(this),data=$this.data(),opt=data.contextMenu,root=data.contextMenuRoot;if(root!==opt&&root.$layer&&root.$layer.is(e.relatedTarget)){root.$selected&&root.$selected.trigger("contextmenu:blur");e.preventDefault();e.stopImmediatePropagation();root.$selected=opt.$selected=opt.$node;return}$this.trigger("contextmenu:blur")},itemClick:function(e){var $this=$(this),data=$this.data(),opt=data.contextMenu,root=data.contextMenuRoot,key=data.contextMenuKey,callback;if(!opt.items[key]||$this.is(".disabled, .context-menu-submenu, .context-menu-separator, .not-selectable")){return}e.preventDefault();e.stopImmediatePropagation();if($.isFunction(root.callbacks[key])&&Object.prototype.hasOwnProperty.call(root.callbacks,key)){callback=root.callbacks[key]}else{if($.isFunction(root.callback)){callback=root.callback}else{return}}if(callback.call(root.$trigger,key,root)!==false){root.$menu.trigger("contextmenu:hide")}else{if(root.$menu.parent().length){op.update.call(root.$trigger,root)}}},inputClick:function(e){e.stopImmediatePropagation()},hideMenu:function(e,data){var root=$(this).data("contextMenuRoot");op.hide.call(root.$trigger,root,data&&data.force)},focusItem:function(e){e.stopPropagation();var $this=$(this),data=$this.data(),opt=data.contextMenu,root=data.contextMenuRoot;$this.addClass("hover").siblings(".hover").trigger("contextmenu:blur");opt.$selected=root.$selected=$this;if(opt.$node){root.positionSubmenu.call(opt.$node,opt.$menu)}},blurItem:function(e){e.stopPropagation();var $this=$(this),data=$this.data(),opt=data.contextMenu;$this.removeClass("hover");opt.$selected=null}},op={show:function(opt,x,y){var $trigger=$(this),css={};$("#context-menu-layer").trigger("mousedown");opt.$trigger=$trigger;if(opt.events.show.call($trigger,opt)===false){$currentTrigger=null;return}op.update.call($trigger,opt);opt.position.call($trigger,opt,x,y);if(opt.zIndex){css.zIndex=zindex($trigger)+opt.zIndex}op.layer.call(opt.$menu,opt,css.zIndex);opt.$menu.find("ul").css("zIndex",css.zIndex+1);opt.$menu.css(css)[opt.animation.show](opt.animation.duration,function(){$trigger.trigger("contextmenu:visible")});$trigger.data("contextMenu",opt).addClass("context-menu-active");$(document).off("keydown.contextMenu").on("keydown.contextMenu",handle.key);if(opt.autoHide){$(document).on("mousemove.contextMenuAutoHide",function(e){var pos=$trigger.offset();pos.right=pos.left+$trigger.outerWidth();pos.bottom=pos.top+$trigger.outerHeight();if(opt.$layer&&!opt.hovering&&(!(e.pageX>=pos.left&&e.pageX<=pos.right)||!(e.pageY>=pos.top&&e.pageY<=pos.bottom))){opt.$menu.trigger("contextmenu:hide")}})}},hide:function(opt,force){var $trigger=$(this);if(!opt){opt=$trigger.data("contextMenu")||{}}if(!force&&opt.events&&opt.events.hide.call($trigger,opt)===false){return}$trigger.removeData("contextMenu").removeClass("context-menu-active");if(opt.$layer){setTimeout((function($layer){return function(){$layer.remove()}})(opt.$layer),10);try{delete opt.$layer}catch(e){opt.$layer=null}}$currentTrigger=null;opt.$menu.find(".hover").trigger("contextmenu:blur");opt.$selected=null;$(document).off(".contextMenuAutoHide").off("keydown.contextMenu");opt.$menu&&opt.$menu[opt.animation.hide](opt.animation.duration,function(){if(opt.build){opt.$menu.remove();$.each(opt,function(key,value){switch(key){case"ns":case"selector":case"build":case"trigger":return true;default:opt[key]=undefined;try{delete opt[key]}catch(e){}return true}})}setTimeout(function(){$trigger.trigger("contextmenu:hidden")},10)})},create:function(opt,root){if(root===undefined){root=opt}opt.$menu=$('
').addClass(opt.className||"").data({contextMenu:opt,contextMenuRoot:root});$.each(["callbacks","commands","inputs"],function(i,k){opt[k]={};if(!root[k]){root[k]={}}});root.accesskeys||(root.accesskeys={});$.each(opt.items,function(key,item){var $t=$('').addClass(item.className||""),$label=null,$input=null;$t.on("click",$.noop);item.$node=$t.data({contextMenu:opt,contextMenuRoot:root,contextMenuKey:key});if(item.accesskey){var aks=splitAccesskey(item.accesskey);for(var i=0,ak;ak=aks[i];i++){if(!root.accesskeys[ak]){root.accesskeys[ak]=item;item._name=item.name.replace(new RegExp("("+ak+")","i"),' ');break}}}if(typeof item=="string"){$t.addClass("context-menu-separator not-selectable")}else{if(item.type&&types[item.type]){types[item.type].call($t,item,opt,root);$.each([opt,root],function(i,k){k.commands[key]=item;if($.isFunction(item.callback)){k.callbacks[key]=item.callback}})}else{if(item.type=="html"){$t.addClass("context-menu-html not-selectable")}else{if(item.type){$label=$("").appendTo($t);$("").text(item._name||item.name).appendTo($label);$t.addClass("context-menu-input");opt.hasTypes=true;$.each([opt,root],function(i,k){k.commands[key]=item;k.inputs[key]=item})}else{if(item.items){item.type="sub"}}}switch(item.type){case"text":$input=$('').attr("name","context-menu-input-"+key).val(item.value||"").appendTo($label);break;case"textarea":$input=$('').attr("name","context-menu-input-"+key).val(item.value||"").appendTo($label);if(item.height){$input.height(item.height)}break;case"checkbox":$input=$('').attr("name","context-menu-input-"+key).val(item.value||"").prop("checked",!!item.selected).prependTo($label);break;case"radio":$input=$('').attr("name","context-menu-input-"+item.radio).val(item.value||"").prop("checked",!!item.selected).prependTo($label);break;case"select":$input=$('