我想添加一个自定义右键菜单到我的web应用程序。这可以在不使用任何预先构建的库的情况下完成吗?如果是这样,如何显示一个简单的自定义右键菜单,不使用第三方JavaScript库?

我的目标是像谷歌Docs做的东西。它允许用户右键单击并显示用户自己的菜单。

注意: 我想学习如何制作我自己的,而不是使用别人已经制作的东西,因为大多数时候,那些第三方库的功能都很臃肿,而我只想要我需要的功能,所以我希望它完全由我手工制作。


当前回答

一个简单的方法是使用onContextMenu返回一个JavaScript函数:

<input type="button" value="Example" onContextMenu="return RightClickFunction();">

<script>
 function RightClickFunction() {
  // Enter your code here;
  return false;
 }
</script>

7:13进入的时候,回的是虚假。您将取消上下文菜单。

如果你仍然想显示上下文菜单,你可以删除返回false;线。

其他回答

纯JS和css解决方案,一个真正的动态右键单击上下文菜单,尽管基于预定义的命名约定的元素id,链接等。 jsfiddle 你可以复制粘贴到单个静态HTML页面的代码:

var rgtClickContextMenu = document.getElementById('div-context-menu'); /** close the right click context menu on click anywhere else in the page*/ document.onclick = function(e) { rgtClickContextMenu.style.display = 'none'; } /** present the right click context menu ONLY for the elements having the right class by replacing the 0 or any digit after the "to-" string with the element id , which triggered the event */ document.oncontextmenu = function(e) { //alert(e.target.id) var elmnt = e.target if (elmnt.className.startsWith("cls-context-menu")) { e.preventDefault(); var eid = elmnt.id.replace(/link-/, "") rgtClickContextMenu.style.left = e.pageX + 'px' rgtClickContextMenu.style.top = e.pageY + 'px' rgtClickContextMenu.style.display = 'block' var toRepl = "to=" + eid.toString() rgtClickContextMenu.innerHTML = rgtClickContextMenu.innerHTML.replace(/to=\d+/g, toRepl) //alert(rgtClickContextMenu.innerHTML.toString()) } } .cls-context-menu-link { display: block; padding: 20px; background: #ECECEC; } .cls-context-menu { position: absolute; display: none; } .cls-context-menu ul, #context-menu li { list-style: none; margin: 0; padding: 0; background: white; } .cls-context-menu { border: solid 1px #CCC; } .cls-context-menu li { border-bottom: solid 1px #CCC; } .cls-context-menu li:last-child { border: none; } .cls-context-menu li a { display: block; padding: 5px 10px; text-decoration: none; color: blue; } .cls-context-menu li a:hover { background: blue; color: #FFF; } <!-- those are the links which should present the dynamic context menu --> <a id="link-1" href="#" class="cls-context-menu-link">right click link-01</a> <a id="link-2" href="#" class="cls-context-menu-link">right click link-02</a> <!-- this is the context menu --> <!-- note the string to=0 where the 0 is the digit to be replaced --> <div id="div-context-menu" class="cls-context-menu"> <ul> <li><a href="#to=0">link-to=0 -item-1 </a></li> <li><a href="#to=0">link-to=0 -item-2 </a></li> <li><a href="#to=0">link-to=0 -item-3 </a></li> </ul> </div>

你应该记住,如果你想使用Firefox唯一的解决方案,如果你想把它添加到整个文档,你应该把contextmenu="mymenu"添加到<html>标签,而不是body标签。 你应该注意这一点。

根据这里和其他'流程的答案,我已经制作了一个看起来像谷歌Chrome的版本,带有css3过渡。 JS小提琴

让我们开始简单,因为我们有上面的js在这个页面上,我们可以担心css和布局。我们将使用的布局是一个<a>元素和一个<img>元素或一个字体awesome图标(<i class="fa fa-flag"></i>)和一个<span>来显示键盘快捷键。这就是结构:

<a href="#" onclick="doSomething()">
  <img src="path/to/image.gif" />
  This is a menu option
  <span>Ctrl + K</span>
</a>

我们将把这些放在一个div中,并在右键菜单中显示该div。让我们风格他们像在谷歌Chrome浏览器,好吗?

#menu a {
  display: block;
  color: #555;
  text-decoration: no[...]

现在,我们将从接受的答案中添加代码,并获得游标的X和Y值。为此,我们将使用e.clientX和e. clienti。我们正在使用客户端,所以菜单div必须被修复。

var i = document.getElementById("menu").style;
if (document.addEventListener) {
  document.addEventListener('contextmenu', function(e) {
    var posX = e.clientX;
    var posY = e.client[...]

And that is it! Just add the css transisions to fade in and out, and done! var i = document.getElementById("menu").style; if (document.addEventListener) { document.addEventListener('contextmenu', function(e) { var posX = e.clientX; var posY = e.clientY; menu(posX, posY); e.preventDefault(); }, false); document.addEventListener('click', function(e) { i.opacity = "0"; setTimeout(function() { i.visibility = "hidden"; }, 501); }, false); } else { document.attachEvent('oncontextmenu', function(e) { var posX = e.clientX; var posY = e.clientY; menu(posX, posY); e.preventDefault(); }); document.attachEvent('onclick', function(e) { i.opacity = "0"; setTimeout(function() { i.visibility = "hidden"; }, 501); }); } function menu(x, y) { i.top = y + "px"; i.left = x + "px"; i.visibility = "visible"; i.opacity = "1"; } body { background: white; font-family: sans-serif; color: #5e5e5e; } #menu { visibility: hidden; opacity: 0; position: fixed; background: #fff; color: #555; font-family: sans-serif; font-size: 11px; -webkit-transition: opacity .5s ease-in-out; -moz-transition: opacity .5s ease-in-out; -ms-transition: opacity .5s ease-in-out; -o-transition: opacity .5s ease-in-out; transition: opacity .5s ease-in-out; -webkit-box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1); -moz-box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1); box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1); padding: 0px; border: 1px solid #C6C6C6; } #menu a { display: block; color: #555; text-decoration: none; padding: 6px 8px 6px 30px; width: 250px; position: relative; } #menu a img, #menu a i.fa { height: 20px; font-size: 17px; width: 20px; position: absolute; left: 5px; top: 2px; } #menu a span { color: #BCB1B3; float: right; } #menu a:hover { color: #fff; background: #3879D9; } #menu hr { border: 1px solid #EBEBEB; border-bottom: 0; } <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet"/> <h2>CSS3 and JAVASCRIPT custom menu.</h2> <em>Stephan Stanisic | Lisence free</em> <p>Right-click anywhere on this page to open the custom menu. Styled like the Google Chrome contextmenu. And yes, you can use <i class="fa fa-flag"></i>font-awesome</p> <p style="font-size: small"> <b>Lisence</b> <br /> "THE PIZZA-WARE LICENSE" (Revision 42): <br /> You can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a Pizza in return. <br /> <a style="font-size:xx-small" href="https://github.com/KLVN/UrbanDictionary_API#license">https://github.com/KLVN/UrbanDictionary_API#license</a> </p> <br /> <br /> <small>(The white body background is just because I hate the light blue editor background on the result on jsfiddle)</small> <div id="menu"> <a href="#"> <img src="http://puu.sh/nr60s/42df867bf3.png" /> AdBlock Plus <span>Ctrl + ?!</span> </a> <a href="#"> <img src="http://puu.sh/nr5Z6/4360098fc1.png" /> SNTX <span>Ctrl + ?!</span> </a> <hr /> <a href="#"> <i class="fa fa-fort-awesome"></i> Fort Awesome <span>Ctrl + ?!</span> </a> <a href="#"> <i class="fa fa-flag"></i> Font Awesome <span>Ctrl + ?!</span> </a> </div>

试试这个:

var cls = true; var ops; window.onload = function() { document.querySelector(".container").addEventListener("mouseenter", function() { cls = false; }); document.querySelector(".container").addEventListener("mouseleave", function() { cls = true; }); ops = document.querySelectorAll(".container td"); for (let i = 0; i < ops.length; i++) { ops[i].addEventListener("click", function() { document.querySelector(".position").style.display = "none"; }); } ops[0].addEventListener("click", function() { setTimeout(function() { /* YOUR FUNCTION */ alert("Alert 1!"); }, 50); }); ops[1].addEventListener("click", function() { setTimeout(function() { /* YOUR FUNCTION */ alert("Alert 2!"); }, 50); }); ops[2].addEventListener("click", function() { setTimeout(function() { /* YOUR FUNCTION */ alert("Alert 3!"); }, 50); }); ops[3].addEventListener("click", function() { setTimeout(function() { /* YOUR FUNCTION */ alert("Alert 4!"); }, 50); }); ops[4].addEventListener("click", function() { setTimeout(function() { /* YOUR FUNCTION */ alert("Alert 5!"); }, 50); }); } document.addEventListener("contextmenu", function() { var e = window.event; e.preventDefault(); document.querySelector(".container").style.padding = "0px"; var x = e.clientX; var y = e.clientY; var docX = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || document.body.offsetWidth; var docY = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || document.body.offsetHeight; var border = parseInt(getComputedStyle(document.querySelector(".container"), null).getPropertyValue('border-width')); var objX = parseInt(getComputedStyle(document.querySelector(".container"), null).getPropertyValue('width')) + 2; var objY = parseInt(getComputedStyle(document.querySelector(".container"), null).getPropertyValue('height')) + 2; if (x + objX > docX) { let diff = (x + objX) - docX; x -= diff + border; } if (y + objY > docY) { let diff = (y + objY) - docY; y -= diff + border; } document.querySelector(".position").style.display = "block"; document.querySelector(".position").style.top = y + "px"; document.querySelector(".position").style.left = x + "px"; }); window.addEventListener("resize", function() { document.querySelector(".position").style.display = "none"; }); document.addEventListener("click", function() { if (cls) { document.querySelector(".position").style.display = "none"; } }); document.addEventListener("wheel", function() { if (cls) { document.querySelector(".position").style.display = "none"; static = false; } }); .position { position: absolute; width: 1px; height: 1px; z-index: 2; display: none; } .container { width: 220px; height: auto; border: 1px solid black; background: rgb(245, 243, 243); } .container p { height: 30px; font-size: 18px; font-family: arial; width: 99%; cursor: pointer; display: flex; justify-content: center; align-items: center; background: rgb(245, 243, 243); color: black; transition: 0.2s; } .container p:hover { background: lightblue; } td { font-family: arial; font-size: 20px; } td:hover { background: lightblue; transition: 0.2s; cursor: pointer; } <div class="position"> <div class="container" align="center"> <table style="text-align: left; width: 99%; margin-left: auto; margin-right: auto;" border="0" cellpadding="2" cellspacing="2"> <tbody> <tr> <td style="vertical-align: middle; text-align: center;">Option 1<br> </td> </tr> <tr> <td style="vertical-align: middle; text-align: center;">Option 2<br> </td> </tr> <tr> <td style="vertical-align: middle; text-align: center;">Option 3<br> </td> </tr> <tr> <td style="vertical-align: middle; text-align: center;">Option 4<br> </td> </tr> <tr> <td style="vertical-align: middle; text-align: center;">Option 5<br> </td> </tr> </tbody> </table> </div> </div>

一些漂亮的CSS和一些没有外部库的非标准html标记的组合可以得到一个不错的结果(JSFiddle)

HTML

<menu id="ctxMenu">
    <menu title="File">
        <menu title="Save"></menu>
        <menu title="Save As"></menu>
        <menu title="Open"></menu>
    </menu>
    <menu title="Edit">
        <menu title="Cut"></menu>
        <menu title="Copy"></menu>
        <menu title="Paste"></menu>
    </menu>
</menu>

注意:菜单标签不存在,我是虚构的(你可以使用任何东西)

CSS

#ctxMenu{
    display:none;
    z-index:100;
}
menu {
    position:absolute;
    display:block;
    left:0px;
    top:0px;
    height:20px;
    width:20px;
    padding:0;
    margin:0;
    border:1px solid;
    background-color:white;
    font-weight:normal;
    white-space:nowrap;
}
menu:hover{
    background-color:#eef;
    font-weight:bold;
}
menu:hover > menu{
    display:block;
}
menu > menu{
    display:none;
    position:relative;
    top:-20px;
    left:100%;
    width:55px;
}
menu[title]:before{
    content:attr(title);
}
menu:not([title]):before{
    content:"\2630";
}

JavaScript只是为这个例子,我个人删除它在窗口上的持久菜单

var notepad = document.getElementById("notepad");
notepad.addEventListener("contextmenu",function(event){
    event.preventDefault();
    var ctxMenu = document.getElementById("ctxMenu");
    ctxMenu.style.display = "block";
    ctxMenu.style.left = (event.pageX - 10)+"px";
    ctxMenu.style.top = (event.pageY - 10)+"px";
},false);
notepad.addEventListener("click",function(event){
    var ctxMenu = document.getElementById("ctxMenu");
    ctxMenu.style.display = "";
    ctxMenu.style.left = "";
    ctxMenu.style.top = "";
},false);

还要注意,对于从右向左展开的菜单,您可能会将菜单> menu{left:100%;}修改为菜单> menu{right:100%;}。你需要在某个地方加上一个边距之类的东西