Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

一个函数搞定右键菜单 #12

Open
lzpong opened this issue Oct 30, 2017 · 4 comments
Open

一个函数搞定右键菜单 #12

lzpong opened this issue Oct 30, 2017 · 4 comments

Comments

@lzpong
Copy link
Owner

lzpong commented Oct 30, 2017

一个函数搞定右键菜单,不啰嗦:

function Menu(id,target,cbFunfun,beforeShowFun){
    if(typeof(target)!="object")
        target=document.querySelector(target)||document.querySelector("#"+target);
    if(!target)
        return null;
    //如果吧`this`和`self`去掉,则会共用同一个menu对象
    this.menu= document.createElement("div");//菜单 Dom Object
    this.menu.id = id;
    this.menu.classList.add("menu");
    this.menu.innerHTML = '<div class="menu-line"></div>';
    this.cbFun=cbFunfun;//回调函数,点击菜单项事件  fun(id,text,menuid);
    this.cbBefore=beforeShowFun;//显示之前回调,更改菜单项enable/disable  fun(menuid)
    //CSS
    var stls=document.getElementsByTagName("style");
    for(i in stls){
      if(stls[i].className=="menu_css"){
        stls=1;break;
      }
    }
    if(stls!=1){
       var stl=document.createElement("style")
       stl.className="menu_css";
       stl.innerHTML=".menu{position:absolute;margin:0;padding:2px;min-width:114px;border:1px solid #ddd;background-color:#fafafa;box-shadow:2px 3px 8px 1px #b3b2b2;z-index:9999999;display:none}.menu-line{position:absolute;left:26px;top:0;height:100%;font-size:1px;border-left:1px solid #ccc;border-right:1px solid #fff}.menu-item{cursor:default;height:20px;font-size:12px;line-height:20px;padding-left:28px;background-repeat:no-repeat}.menu-disable{color:gray;opacity:.3}.menu-sep{border-top:1px solid #ccc;border-bottom:1px solid #fff;font-size:1px;margin:3px 0 3px 25px}.menu-active{background-color:#b7d2ff}";
       document.head.appendChild(stl);
    }

    this.menu.onclick = onMenuClick;
    this.menu.onmouseout = onMenuMouseOn;
    this.menu.onmouseover = onMenuMouseOn;
    document.body.appendChild(this.menu);
    target.oncontextmenu = onContextMenu;
    this.target=null;//右键点击的对象
    var self=this;
    //show,,左/下边不超出
    function show(x,y){
        self.menu.style.opacity=0;
        self.menu.style.display = "block";
        if (document.body.offsetWidth < x + self.menu.offsetWidth)
            self.menu.style.left = document.body.offsetWidth-self.menu.offsetWidth + "px";
        else
            self.menu.style.left = x + "px";
        if (document.body.offsetHeight < y + self.menu.offsetHeight)
            self.menu.style.top = document.body.offsetHeight-self.menu.offsetHeight + "px";
        else
            self.menu.style.top = y + "px";
        self.menu.style.opacity=null;
    }
    //右键菜单
    function onContextMenu(e) {
        self.target=e.target;
        if(self.cbBefore)
            self.cbBefore(self.menu.id);
        show(e.clientX,e.clientY);
        document.addEventListener("click", OnDocClick, false);
        return false;
    }
    //控制菜单item高亮
    function onMenuMouseOn(e) {
        var cls = e.target.classList;
        //console.log(e.type,e.target);
        if (cls.contains("menu-item"))
        {
            if (e.type == "mouseover") {//进入
                cls.add("menu-active");
            } else if (e.type == "mouseout") {//移出
                cls.remove("menu-active")
            }
        }
    }
    //菜单item点击
    function onMenuClick(e) {
        cls = e.target.classList;
        if(self.cbFun && cls.contains("menu-item") && !cls.contains("menu-disable"))
            self.cbFun(e.target.id,e.target.innerText,self.menu.id,self.target);
    }
    //其他点击,关闭菜单
    function OnDocClick(e) {
        self.target=null;
        cls = e.target.classList;
        if (!(cls.contains("menu") || cls.contains("menu-line") || cls.contains("menu-sep")) && !cls.contains("menu-disable")){
            self.menu.style.display = "none";
            document.removeEventListener("click", OnDocClick);
        }
    }

    //text为空则插入间隔条,icon大小:20*20
    function insertItem(id,text,icon){
        var itm=document.createElement("div");
        if(text==null || text==""){
            itm.classList.add("menu-sep")
        }else{
            itm.id=id;
            if(icon && icon.length>3)
                itm.style.backgroundImage="url("+icon+")";
            itm.innerHTML=text;
            itm.classList.add("menu-item")
        }
        self.menu.appendChild(itm);
    }
    //设置item 可用/不可用
    function setAble(id,able){
      var itm=self.menu.querySelector("#"+id);
      if(itm){
        var disabled=itm.classList.contains("menu-disable");
        if(able && disabled)
            itm.classList.remove("menu-disable");
        else if(!able && !disabled)
            itm.classList.add("menu-disable");
      }
    }
    function clear(){
        var line=self.menu.firstElementChild;
        while(itm=line.nextElementSibling)
            itm.remove();
    }

    return {
        getID:function(){return self.menu.id;},
        insertItem:insertItem,
        clear:clear,
        setAble:setAble,
        show:show,
    }
}

使用方法:

<style>
.ddiv{
width:200px;
height:300px;
margin:10px;
display:inline-flex;
border: 1px solid rgb(204, 204, 204);
}
</style>
<div id="div1" class="ddiv">div1</div>
<div id="div2" class="ddiv">div2</div>
<div id="div3" class="ddiv">div3</div>
/*菜单回调函数参数:
 * id: 菜单选项ID
 * txt:菜单选项文字
 * menuid:菜单ID
 * target:右键点击的对象
*/
function onClick(id,txt,menuid,target){
console.log(id,txt,menuid,target);
}
//
var menu1=new Menu("menu1","div1",onClick);
menu1.insertItem("d1-1","item1m1放到","https://p.ssl.qhimg.com/t01f41d7d4e86418577.png");
menu1.insertItem("d1-2","item2m1范德萨范德萨","https://p.ssl.qhimg.com/t01f41d7d4e86418577.png");
menu1.insertItem("d1-3","item3m1按时");
menu1.insertItem();
menu1.insertItem("d1-4","item4m1按时");
menu1.setAble("d1-1",false);

//
var menu2=new Menu("menu2","div2",onClick);
menu2.insertItem("d2-1","item1m2");
menu2.insertItem("d2-2","item2m2");
menu2.insertItem("d2-3","item3m2");
menu2.insertItem();
menu2.insertItem("d2-4","item4m2");
menu2.setAble("d2-2",false);

//
var menu3=new Menu("menu3","div3",onClick);
menu3.insertItem("d3-1","item1m3");
menu3.insertItem("d3-2","item2m3");
menu3.insertItem("d3-3","item3m3");
menu3.insertItem();
menu3.insertItem("d3-4","item4m3");
menu3.setAble("d3-3",false);

直观图:
image

@lzpong
Copy link
Owner Author

lzpong commented Oct 31, 2017

如果去掉函数中的 thisself, 将只能共用同一个菜单(显示同一个菜单)

@408342494
Copy link

Uncaught ReferenceError: CreateElt is not defined

@lzpong
Copy link
Owner Author

lzpong commented Oct 19, 2018

Uncaught ReferenceError: CreateElt is not defined

function CreateElt(elm,cls){
    var e=document.createElement("style")
    e.className="menu_css";
    return e;
}

or

    var stl=document.createElement("style")
    stl.className="menu_css";

谢谢指出,,已修改!

@lzpong
Copy link
Owner Author

lzpong commented Dec 24, 2018

菜单回调函数增加一个参数: 右键点击的对象
菜单回调函数全部参数:

  • id: 菜单选项ID
  • txt:菜单选项文字
  • menuid:菜单ID
  • target:右键点击的对象

另外, body的高度要保证不为0哦, 不然, 菜单会看见的哟...
如:

html,body{
    height:100%;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants