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

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

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


当前回答

根据这里和其他'流程的答案,我已经制作了一个看起来像谷歌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>

其他回答

一些漂亮的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%;}。你需要在某个地方加上一个边距之类的东西

你应该记住,如果你想使用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>

纯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>

你可以用这段代码来做。 访问这里获得完整的自动边缘检测教程http://www.voidtricks.com/custom-right-click-context-menu/

$(document).ready(function () {
 $("html").on("contextmenu",function(e){
        //prevent default context menu for right click
        e.preventDefault();

        var menu = $(".menu"); 

        //hide menu if already shown
        menu.hide(); 

        //get x and y values of the click event
        var pageX = e.pageX;
        var pageY = e.pageY;

        //position menu div near mouse cliked area
        menu.css({top: pageY , left: pageX});

        var mwidth = menu.width();
        var mheight = menu.height();
        var screenWidth = $(window).width();
        var screenHeight = $(window).height();

        //if window is scrolled
        var scrTop = $(window).scrollTop();

        //if the menu is close to right edge of the window
        if(pageX+mwidth > screenWidth){
        menu.css({left:pageX-mwidth});
        }

        //if the menu is close to bottom edge of the window
        if(pageY+mheight > screenHeight+scrTop){
        menu.css({top:pageY-mheight});
        }

        //finally show the menu
        menu.show();
 }); 

 $("html").on("click", function(){
 $(".menu").hide();
 });
 });

`