/*******************************************************************************

 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.8.5rc5

 *

 * added: boxMenu menu modality by: Sven Dowideit http://trunk.fosiki.com/Sandbox/WebSubMenu

 */

// 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.8.5rc5",

    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:400,

      openOnRight:false,

      containment:"window",

      iconPath:"images/graphicsdemo6/",

      hasImages:true,

      fadeInTime:100,

      fadeOutTime:200,

      menuTop:0,

      menuLeft:0,

      submenuTop:0,

      submenuLeft:4,

      opacity:1,

      openOnClick:false,

      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.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);

              if ($(this).metadata().disabled) $(this).attr("isDisable",$(this).metadata().disabled);

            });

          }



          thisMenu.menuvoice=$(this).find("[menu]").add($(this).filter("[menu]"));

          thisMenu.menuvoice.filter("[isDisable]").addClass("disabled");



          $(thisMenu.menuvoice).css("white-space","nowrap");



          if(openOnClick){

            $(thisMenu.menuvoice).bind("click",function(){

              $(document).unbind("click.closeMbMenu");                              

              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){

                  $("[isOpen]").removeAttr("isOpen");

                }

                $(this).removeMbMenu(thisMenu);

              }

              $(document).unbind("click.closeMbMenu");

            });

          }

          var mouseOver=$.browser.msie?"mouseenter":"mouseover";

          var mouseOut=$.browser.msie?"mouseleave":"mouseout";



          $(thisMenu.menuvoice).mb_hover(

                  this.options.hoverIntent,

                  function(){

                    if(!$(this).attr("isOpen"))

                      $("[isOpen]").removeAttr("isOpen");

                    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")){

                      $(this).removeMbMenu(thisMenu);

                      $(this).buildMbMenu(thisMenu,$(this).attr("menu"));

                      if ($(this).attr("menu")=="empty"){

                        $(this).removeMbMenu(thisMenu);

                      }

                      $(this).attr("isOpen","true");

                    }

                  },

                  function(){

                    if (closeOnMouseOut)

                      $.mbMenu.deleteOnMouseOut= setTimeout(function(){

                        $(this).removeMbMenu(thisMenu,true);

                        $(document).unbind("click.closeMbMenu");

                      },$(root)[0].options.closeAfter);



                    if ($(this).attr("menu")=="empty"){

                      $(this).removeClass("selected");

                    }

                    if(!thisMenu.clicked)

                      $(this).removeClass("selected");

                    $(document).one("click.closeMbMenu",function(){

                      $("[isOpen]").removeAttr("isOpen");

                      $(this).removeClass("selected");

                      $(this).removeMbMenu(thisMenu,true);

                      thisMenu.rootMenu=false;thisMenu.clicked=false;

                    });

                  }

                  );

        });

      });

    },

    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.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({"-webkit-user-select":"none","-moz-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");

          $("[isOpen]").removeAttr("isOpen");

        }

        op.clicked=true;

        op.actualOpenedMenu=this;

        $(op.actualOpenedMenu).attr("isOpen","true");

        $(op.actualOpenedMenu).addClass("selected");

      }



      //empty

      if($(this).attr("menu")=="empty"){

        return;

      }



      var opener=this;

      var where=(!type|| type=="cm")?$(document.body):$(this).parent().parent();



      var menuClass= op.options.menuSelector.replace(".","");



      if(op.rootMenu) menuClass+=" submenuContainer";

      if(!op.rootMenu && $(opener).attr("isDisable")) menuClass+=" disabled";



      where.append("<div class='menuDiv'><div class='"+menuClass+" '></div></div>");

      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();



      //LITERAL MENU SUGGESTED BY SvenDowideit

      var isBoxmenu=$("#"+m).hasClass("boxMenu");



      if (isBoxmenu) {

        this.voices = $("#"+m).clone(true);

        this.voices.css({display: "block"});

        this.voices.attr("id", m+"_clone");

      } else {

        //TODO this will break <a rel=text> - if there are nested a's

        this.voices= $("#"+m).find("a").clone(true);

      }



      /*

       *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("isdisable",$(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);

        });

      }





      // 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("[isdisable]");

        if(!op.rootMenu && $(opener).attr("isDisable"))

          isDisabled=true;



        var isSeparator=$(voice).attr("rel")=="separator";



        // boxMenu SUGGESTED by Sven Dowideit

        if (op.options.hasImages && !isText && !isBoxmenu){



          var imgPath=$(voice).attr("img")?$(voice).attr("img"):"blank.gif";

          imgPath=(imgPath.length>3 && imgPath.indexOf(".")>-1)?"<img class='imgLine' src='"+op.options.iconPath+imgPath+"'>":imgPath;

          imgPlace="<td class='img'>"+imgPath+"</td>";

        }



        var line="<table id='"+m+"_"+i+"' class='line"+(isTitle?" title":"")+"' cellspacing='0' cellpadding='0' border='0' style='width:100%;' width='100%'><tr>"+imgPlace+"<td class='voice' nowrap></td></tr></table>";



        if(isSeparator)

          line="<p class='separator' style='width:100%;'></p>";



        if(isText)

          line="<div style='width:100%; display:table' class='line' id='"+m+"_"+i+"'><div class='voice'></div></div>";



        // boxMenu SUGGESTED by Sven Dowideit

        if(isBoxmenu)

          line="<div style='width:100%; display:inline' class='' id='"+m+"_"+i+"'><div class='voice'></div></div>";



        $(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") && !isDisabled){

            menuLine.find(".voice a").wrap("<div class='menuArrow'></div>");

            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 ||isBoxmenu)){

            menuLine.css({cursor:"pointer"});



            menuLine.bind("mouseover",function(){

              clearTimeout($.mbMenu.deleteOnMouseOut);

              $(this).addClass("selected");

            });



            menuLine.bind("mouseout",function(){

              $(this).removeClass("selected");

            });



            menuLine.mb_hover(

                    op.options.submenuHoverIntent,

                    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;

                      }

                    },

                    function(){}

                    );

          }

          if(isDisabled || isTitle || isText || isBoxmenu){

            $(this).removeAttr("href");

            menuLine.bind(mouseOver,function(){

              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 &&  !isBoxmenu && !isText){

              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+"')";

              $(voice).removeAttr("href");

              eval(link);

              $(this).removeMbMenu(op,true);

            }else{

              $(document).unbind("click.closeMbMenu");

            }

          });

        }

      });



      // 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);$(document).unbind("click.closeMbMenu");},$(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.closeMbMenu",function(){$(document).removeMbMenu(op,true);});

      });



      if (op.options.fadeInTime>0) $(this.menuContainer).fadeIn(op.options.fadeInTime);

      else $(this.menuContainer).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=$(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){

            l-=((op.options.menuWidth*2)-(op.options.submenuLeft*2));

          }

          break;

        case "cm":

          if ((actualX+(op.options.menuWidth*1.5))>= ww && mw<ww){

            l-=((op.options.menuWidth)-(op.options.submenuLeft));

          }

          break;

        default:

          if ((actualX+mw)>= ww && mw<ww){

            l-=($(this.menuContainer).offset().left+mw)-ww+18;

          }

          break;

      }

      if ((actualY+mh)>= wh-10 && mh<wh){

        t-=((actualY+mh)-wh)+10;

      }



      $(this.menu).css({

        top:t,

        left:l

      });

    },



    removeMbMenu: function(op,fade){

      if(!op)op=$.mbMenu.options.actualMenuOpener;

      if(!op) return;

      if (op.rootMenu) {

        $(op.actualOpenedMenu)

                .removeAttr("isOpen")

                .removeClass("selected");

        $("[isOpen]").removeAttr("isOpen");

        $(op.rootMenu).css({width:1, height:1});

        if (fade) $(op.rootMenu).fadeOut(op.options.fadeOutTime,function(){$(this).remove();});

        else $(op.rootMenu).remove();

        op.rootMenu=false;

        op.clicked=false;

      }

    },



    //mouse  Position

    getMouseX : function (e){

      var mouseX;

      if ($.browser.msie)mouseX = e.clientX + document.documentElement.scrollLeft;

      else mouseX = e.pageX;

      if (mouseX < 0) mouseX = 0;

      return mouseX;

    },

    getMouseY : function (e){

      var mouseY;

      if ($.browser.msie)	mouseY = e.clientY + document.documentElement.scrollTop;

      else mouseY = e.pageY;

      if (mouseY < 0)	mouseY = 0;

      return mouseY;

    },

    //get max z-inedex of the page

    mb_bringToFront: function(){

      var zi=10;

      $('*').each(function() {

        if($(this).css("position")=="absolute" || $(this).css("position")=="fixed" ){

          var cur = parseInt($(this).css('zIndex'));

          zi = cur > zi ? parseInt($(this).css('zIndex')) : zi;

        }

      });



      $(this).css('zIndex',zi+=10);

    },

    mb_hover:function(hoverIntent, fn1, fn2){

      if(hoverIntent==0)

        $(this).hover(fn1,fn2);

      else

        $(this).hoverIntent({

          sensitivity: 30,

          interval: hoverIntent,

          timeout: 0,

          over:fn1,

          out:fn2

        });

    }

  });

  $.fn.buildMenu = $.mbMenu.buildMenu;

  $.fn.buildContextualMenu = $.mbMenu.buildContextualMenu;

})(jQuery);
