/******************************************************************************* jquery.mb.components copyright (c) 2001-2010. matteo bicocchi (pupunzi); open lab srl, firenze - italy email: info@pupunzi.com site: http://pupunzi.com licences: mit, gpl http://www.opensource.org/licenses/mit-license.php http://www.gnu.org/licenses/gpl.html ******************************************************************************/ /* * name:jquery.mb.menu * version: 2.7.6 */ // to get the element that is fireing a contextmenu event you have $.mbmenu.lastcontextmenuel that returns an object. (function($) { $.mbmenu = { name:"mbmenu", author:"matteo bicocchi", version:"2.7.6", actualmenuopener:false, options: { template:"yourmenuvoicetemplate",// the url that returns the menu voices via ajax. the data passed in the request is the "menu" attribute value as "menuid" additionaldata:"", menuselector:".menucontainer", menuwidth:150, openonright:false, containment:"window", iconpath:"ico/", hasimages:true, fadeintime:100, fadeouttime:200, menutop:0, menuleft:0, submenutop:0, submenuleft:4, opacity:1, shadow:false, shadowcolor:"transparent", shadowopacity:.2, openonclick:true, closeonmouseout:false, closeafter:500, minzindex:"auto", // or number hoverintent:0, //if you use jquery.hoverintent.js set this to time in milliseconds; 0= false; submenuhoverintent:200, //if you use jquery.hoverintent.js set this to time in milliseconds; 0= false; oncontextualmenu:function(){} //it pass 'o' (the menu you clicked on) and 'e' (the event) }, buildmenu : function (options){ return this.each (function () { var thismenu =this; thismenu.id = !this.id ? "menu_"+math.floor (math.random () * 1000): this.id; this.options = {}; $.extend (this.options, $.mbmenu.options); $.extend (this.options, options); $(".mbmenu").hide(); thismenu.clicked = false; thismenu.rootmenu=false; thismenu.clearclicked=false; thismenu.actualopenedmenu=false; thismenu.menuvoice=false; var root=$(this); var openonclick=this.options.openonclick; var closeonmouseout=this.options.closeonmouseout; //build roots $(root).each(function(){ /* *using metadata plugin you can add attribute writing them inside the class attr with a json sintax * for ex: class="rootvoice {menu:'menu_2'}" */ if ($.metadata){ $.metadata.settype("class"); thismenu.menuvoice=$(this).find(".rootvoice"); $(thismenu.menuvoice).each(function(){ if ($(this).metadata().menu) $(this).attr("menu",$(this).metadata().menu); }); } thismenu.menuvoice=$(this).find("[menu]").add($(this).filter("[menu]")); $(thismenu.menuvoice).each(function(){ $(this).addclass("rootvoice"); $(this).attr("nowrap","nowrap"); }); if(openonclick){ $(thismenu.menuvoice).bind("click",function(){ if (!$(this).attr("isopen")){ $(this).buildmbmenu(thismenu,$(this).attr("menu")); $(this).attr("isopen","true"); }else{ $(this).removembmenu(thismenu,true); $(this).addclass("selected"); } //empty if($(this).attr("menu")=="empty"){ if(thismenu.actualopenedmenu){ $(thismenu.actualopenedmenu).removeclass("selected"); thismenu.clicked=true; $(this).removeattr("isopen"); cleartimeout(thismenu.clearclicked); } $(this).removembmenu(thismenu); } return false; }); } var mouseover=$.browser.msie?"mouseenter":"mouseover"; var mouseout=$.browser.msie?"mouseleave":"mouseout"; if (this.options.hoverintent==0){ $(thismenu.menuvoice).bind(mouseover,function(){ if (closeonmouseout) cleartimeout($.mbmenu.deleteonmouseout); if (!openonclick) $(thismenu).find(".selected").removeclass("selected"); if(thismenu.actualopenedmenu){ $(thismenu.actualopenedmenu).removeclass("selected");} $(this).addclass("selected"); if((thismenu.clicked || !openonclick) && !$(this).attr("isopen")){ cleartimeout(thismenu.clearclicked); $(this).buildmbmenu(thismenu,$(this).attr("menu")); if ($(this).attr("menu")=="empty"){ $(this).removembmenu(thismenu); $(this).removeattr("isopen"); } } }); $(thismenu.menuvoice).bind(mouseout,function(){ if (closeonmouseout) $.mbmenu.deleteonmouseout= settimeout(function(){$(this).removembmenu(thismenu,true);},$(root)[0].options.closeafter); if ($(this).attr("menu")=="empty"){ $(this).removeclass("selected"); thismenu.clearclicked= settimeout(function(){thismenu.rootmenu=false;thismenu.clicked=false;},$(root)[0].options.closeafter); } if(!thismenu.clicked) $(this).removeclass("selected"); $(document).one("click",function(){ if ($(this).attr("menu")=="empty"){ cleartimeout(thismenu.clearclicked); return; } $(this).removeclass("selected"); $(this).removembmenu(thismenu,true); }); }); }else{ // hoverhintent $(thismenu.menuvoice).hoverintent({ over:function(){ if (closeonmouseout) cleartimeout($.mbmenu.deleteonmouseout); if (!openonclick) $(thismenu).find(".selected").removeclass("selected"); if(thismenu.actualopenedmenu){ $(thismenu.actualopenedmenu).removeclass("selected");} $(this).addclass("selected"); if((thismenu.clicked || !openonclick) && !$(this).attr("isopen")){ cleartimeout(thismenu.clearclicked); $(this).buildmbmenu(thismenu,$(this).attr("menu")); if ($(this).attr("menu")=="empty"){ $(this).removembmenu(thismenu); $(this).removeattr("isopen"); } } }, sensitivity: 30, interval: this.options.hoverintent, timeout: 0, out:function(){ if (closeonmouseout) $.mbmenu.deleteonmouseout= settimeout(function(){$(this).removembmenu(thismenu,true);},$(root)[0].options.closeafter); if ($(this).attr("menu")=="empty"){ $(this).removeclass("selected"); thismenu.clearclicked= settimeout(function(){thismenu.rootmenu=false;thismenu.clicked=false;},$(root)[0].options.closeafter); } if(!thismenu.clicked) $(this).removeclass("selected"); $(document).one("click",function(){ if ($(this).attr("menu")=="empty"){ cleartimeout(thismenu.clearclicked); return; } $(this).removeclass("selected"); $(this).removembmenu(thismenu,true); }); } }); } }); }); }, buildcontextualmenu : function (options){ return this.each (function () { var thismenu = this; thismenu.options = {}; $.extend (thismenu.options, $.mbmenu.options); $.extend (thismenu.options, options); $(".mbmenu").hide(); thismenu.clicked = false; thismenu.rootmenu=false; thismenu.clearclicked=false; thismenu.actualopenedmenu=false; thismenu.menuvoice=false; /* *using metadata plugin you can add attribut writing them inside the class attr with a json sintax * for ex: class="rootvoice {menu:'menu_2'}" */ var cmenuels; if ($.metadata){ $.metadata.settype("class"); cmenuels= $(this).find(".cmvoice"); $(cmenuels).each(function(){ if ($(this).metadata().cmenu) $(this).attr("cmenu",$(this).metadata().cmenu); }); } cmenuels= $(this).find("[cmenu]").add($(this).filter("[cmenu]")); $(cmenuels).each(function(){ $(this).css("-khtml-user-select","none"); var cm=this; cm.id = !cm.id ? "menu_"+math.floor (math.random () * 100): cm.id; $(cm).css({cursor:"default"}); $(cm).bind("contextmenu","mousedown",function(event){ event.preventdefault(); event.stoppropagation(); event.cancelbubble=true; $.mbmenu.lastcontextmenuel=cm; if ($.mbmenu.options.actualmenuopener) { $(thismenu).removembmenu($.mbmenu.options.actualmenuopener); } /*add custom behavior to contextmenuevent passing the el and the event *you can for example store to global var the obj that is fireing the event *mbactualcontextualmenuobj=cm; * * you can for example create a function that manipulate the voices of the menu * you are opening according to a certain condition... */ thismenu.options.oncontextualmenu(this,event); $(this).buildmbmenu(thismenu,$(this).attr("cmenu"),"cm",event); $(this).attr("isopen","true"); }); }); }); } }; $.fn.extend({ buildmbmenu: function(op,m,type,e){ var msie6=$.browser.msie && $.browser.version=="6.0"; var mouseover=$.browser.msie?"mouseenter":"mouseover"; var mouseout=$.browser.msie?"mouseleave":"mouseout"; if (e) { this.mousex=$(this).getmousex(e); this.mousey=$(this).getmousey(e); } if ($.mbmenu.options.actualmenuopener && $.mbmenu.options.actualmenuopener!=op) $(op).removembmenu($.mbmenu.options.actualmenuopener); $.mbmenu.options.actualmenuopener=op; if(!type || type=="cm") { if (op.rootmenu) { $(op.rootmenu).removembmenu(op); $(op.actualopenedmenu).removeattr("isopen"); } op.clicked=true; op.actualopenedmenu=this; $(op.actualopenedmenu).attr("isopen","true"); $(op.actualopenedmenu).addclass("selected"); } var opener=this; var where=(!type|| type=="cm")?$(document.body):$(this).parent().parent(); //empty if($(this).attr("menu")=="empty"){ return; } var menuclass= op.options.menuselector.replace(".",""); where.append(""); this.menu = where.find(".menudiv"); $(this.menu).css({width:0, height:0}); if (op.options.minzindex!="auto"){ $(this.menu).css({zindex:op.options.minzindex++}); }else{ $(this.menu).mb_bringtofront(); } this.menucontainer = $(this.menu).find(op.options.menuselector); $(this.menucontainer).bind(mouseover,function(){ $(opener).addclass("selected"); }); $(this.menucontainer).css({ position:"absolute", opacity:op.options.opacity }); if (!$("#"+m).html()){ $.ajax({ type: "post", url: op.options.template, cache: false, async: false, data:"menuid="+m+(op.options.additionaldata!=""?"&"+op.options.additionaldata:""), success: function(html){ $("body").append(html); $("#"+m).hide(); } }); } $(this.menucontainer).attr("id", "mb_"+m).hide(); this.voices= $("#"+m).find("a").clone(); if (op.options.shadow) { var shadow = $("").hide(); if(msie6) shadow = $("").hide(); } /* *using metadata plugin you can add attribut writing them inside the class attr with a json sintax * for ex: class="rootvoice {menu:'menu_2'}" */ if ($.metadata){ $.metadata.settype("class"); $(this.voices).each(function(){ if ($(this).metadata().disabled) $(this).attr("disabled",$(this).metadata().disabled); if ($(this).metadata().img) $(this).attr("img",$(this).metadata().img); if ($(this).metadata().menu) $(this).attr("menu",$(this).metadata().menu); if ($(this).metadata().action) $(this).attr("action",$(this).metadata().action); if ($(this).metadata().disabled) $(this).attr("disabled",$(this).metadata().disabled); }); } // build each voices of the menu $(this.voices).each(function(i){ var voice=this; var imgplace=""; var istext=$(voice).attr("rel")=="text"; var istitle=$(voice).attr("rel")=="title"; var isdisabled=$(voice).is("[disabled]"); var isseparator=$(voice).attr("rel")=="separator"; if (op.options.hasimages && !istext){ var imgpath=$(voice).attr("img")?$(voice).attr("img"):"blank.gif"/*tpa=http://www.major.com.cn/widgets/jquery-plugin/blank.gif*/; imgpath=(imgpath.length>3 && imgpath.indexof(".")>-1)?"":imgpath; imgplace=""+imgpath+""; } var line=""+imgplace+"
"; if(isseparator) line="
"; if(istext) line="
"; $(opener.menucontainer).append(line); var menuline = $(opener.menucontainer).find("#" + m + "_" + i); var menuvoice = menuline.find(".voice"); if(!isseparator){ menuvoice.append(this); if($(this).attr("menu")){ menuline.find(".voice a").wrap(""); menuline.find(".menuarrow").addclass("submenuopener"); menuline.css({cursor:"default"}); this.isopener=true; } if(istext){ menuvoice.addclass("textbox"); if ($.browser.msie) menuvoice.css({maxwidth:op.options.menuwidth}); this.isopener=true; } if(isdisabled){ menuline.addclass("disabled").css({cursor:"default"}); } if(!(istext || istitle || isdisabled)){ menuline.css({cursor:"pointer"}); if (op.options.submenuhoverintent==0){ menuline.bind("mouseover",function(event){ cleartimeout($.mbmenu.deleteonmouseout); $(this).addclass("selected"); if(opener.menucontainer.actualsubmenu && !$(voice).attr("menu")){ $(opener.menu).find(".menudiv").remove(); $(opener.menucontainer.actualsubmenu).removeclass("selected"); opener.menucontainer.actualsubmenu=false; //return false; } if ($(voice).attr("menu")){ if(opener.menucontainer.actualsubmenu && opener.menucontainer.actualsubmenu!=this){ $(opener.menu).find(".menudiv").remove(); $(opener.menucontainer.actualsubmenu).removeclass("selected"); opener.menucontainer.actualsubmenu=false; } if (!$(voice).attr("action")) $(opener.menucontainer).find("#"+m+"_"+i).css("cursor","default"); if (!opener.menucontainer.actualsubmenu || opener.menucontainer.actualsubmenu!=this){ $(opener.menu).find(".menudiv").remove(); opener.menucontainer.actualsubmenu=false; $(this).buildmbmenu(op,$(voice).attr("menu"),"sm",event); opener.menucontainer.actualsubmenu=this; } $(this).attr("isopen","true"); return false; } }); }else{ // hoverhintent menuline.bind("mouseover",function(){ cleartimeout($.mbmenu.deleteonmouseout); $(this).addclass("selected"); }); menuline.hoverintent({ over:function(event){ if(opener.menucontainer.actualsubmenu && !$(voice).attr("menu")){ $(opener.menu).find(".menudiv").remove(); $(opener.menucontainer.actualsubmenu).removeclass("selected"); opener.menucontainer.actualsubmenu=false; } if ($(voice).attr("menu")){ if(opener.menucontainer.actualsubmenu && opener.menucontainer.actualsubmenu!=this){ $(opener.menu).find(".menudiv").remove(); $(opener.menucontainer.actualsubmenu).removeclass("selected"); opener.menucontainer.actualsubmenu=false; } if (!$(voice).attr("action")) $(opener.menucontainer).find("#"+m+"_"+i).css("cursor","default"); if (!opener.menucontainer.actualsubmenu || opener.menucontainer.actualsubmenu!=this){ $(opener.menu).find(".menudiv").remove(); opener.menucontainer.actualsubmenu=false; $(this).buildmbmenu(op,$(voice).attr("menu"),"sm",event); opener.menucontainer.actualsubmenu=this; } $(this).attr("isopen","true"); return false; } }, out:function(){}, sensitivity: 30, interval: op.options.submenuhoverintent, timeout: 0 }); } menuline.bind(mouseout,function(){ $(this).removeclass("selected"); }); } if(isdisabled || istitle || istext){ $(this).removeattr("href"); menuline.bind(mouseover,function(){ $(document).unbind("click"); if (closeonmouseout) cleartimeout($.mbmenu.deleteonmouseout); if(opener.menucontainer.actualsubmenu){ $(opener.menu).find(".menudiv").remove(); opener.menucontainer.actualsubmenu=false; } }).css("cursor","default"); } menuline.bind("click",function(){ if (($(voice).attr("action") || $(voice).attr("href")) && !isdisabled){ var target=$(voice).attr("target")?$(voice).attr("target"):"_self"; if ($(voice).attr("href") && $(voice).attr("href").indexof("javascript:")>-1){ $(voice).attr("action",$(voice).attr("href").replace("javascript:","")); } var link=$(voice).attr("action")?$(voice).attr("action"):"window.open('"+$(voice).attr("href")+"', '"+target+"')"; if (!$(voice).attr("href") || ($(voice).attr("href") && $(voice).attr("href").indexof("javascript:")>-1)){ $(voice).removeattr("href"); eval(link); } $(this).removembmenu(op,true); }else if($(voice).attr("menu")) return false; }); } }); // close on mouseout var closeonmouseout=$(op)[0].options.closeonmouseout; if (closeonmouseout){ $(opener.menucontainer).bind("mouseenter",function(){ cleartimeout($.mbmenu.deleteonmouseout); }); $(opener.menucontainer).bind("mouseleave",function(){ var menutoremove=$.mbmenu.options.actualmenuopener; $.mbmenu.deleteonmouseout= settimeout(function(){$(this).removembmenu(menutoremove,true);},$(op)[0].options.closeafter); }); } //positioning opened var t=0,l=0; $(this.menucontainer).css({ minwidth:op.options.menuwidth }); if ($.browser.msie) $(this.menucontainer).css("width",$(this.menucontainer).width()+2); switch(type){ case "sm": t=$(this).position().top+op.options.submenutop; l=$(this).position().left+$(this).width()-op.options.submenuleft; break; case "cm": t=this.mousey-5; l=this.mousex-5; break; default: if (op.options.openonright){ t=$(this).offset().top-($.browser.msie?2:0)+op.options.menutop; l=$(this).offset().left+$(this).outerwidth()-op.options.menuleft-($.browser.msie?2:0); }else{ t=$(this).offset().top+$(this).outerheight()-(!$.browser.mozilla?2:0)+op.options.menutop; l=$(this).offset().left+op.options.menuleft; } break; } $(this.menu).css({ position:"absolute", top:t, left:l }); if (!type || type=="cm") op.rootmenu=this.menu; $(this.menucontainer).bind(mouseout,function(){ $(document).one("click",function(){$(document).removembmenu(op,true);}); }); if (op.options.fadeintime>0) $(this.menucontainer).fadein(op.options.fadeintime); else $(this.menucontainer).show(); if (op.options.shadow) { $(this.menu).prepend(shadow); shadow.css({ width:$(this.menucontainer).outerwidth(), height:$(this.menucontainer).outerheight()-1, position:'absolute', backgroundcolor:op.options.shadowcolor, border:0, opacity:op.options.shadowopacity }).show(); } var wh= (op.options.containment=="window")?$(window).height():$("#"+op.options.containment).offset().top+$("#"+op.options.containment).outerheight(); var ww=(op.options.containment=="window")?$(window).width():$("#"+op.options.containment).offset().left+$("#"+op.options.containment).outerwidth(); var mh=$(this.menucontainer).outerheight(); var mw=shadow?shadow.outerwidth():$(this.menucontainer).outerwidth(); var actualx=$(where.find(".menudiv:first")).offset().left-$(window).scrollleft(); var actualy=$(where.find(".menudiv:first")).offset().top-$(window).scrolltop(); switch(type){ case "sm": if ((actualx+mw)>= ww && mw= ww && mw= ww && mw= wh-10 && mh zi ? parseint($(this).css('zindex')) : zi; } }); $(this).css('zindex',zi+=10); } }); $.fn.buildmenu = $.mbmenu.buildmenu; $.fn.buildcontextualmenu = $.mbmenu.buildcontextualmenu; })(jquery);