我想添加一个自定义右键菜单到我的web应用程序。这可以在不使用任何预先构建的库的情况下完成吗?如果是这样,如何显示一个简单的自定义右键菜单,不使用第三方JavaScript库?
我的目标是像谷歌Docs做的东西。它允许用户右键单击并显示用户自己的菜单。
注意: 我想学习如何制作我自己的,而不是使用别人已经制作的东西,因为大多数时候,那些第三方库的功能都很臃肿,而我只想要我需要的功能,所以我希望它完全由我手工制作。
我想添加一个自定义右键菜单到我的web应用程序。这可以在不使用任何预先构建的库的情况下完成吗?如果是这样,如何显示一个简单的自定义右键菜单,不使用第三方JavaScript库?
我的目标是像谷歌Docs做的东西。它允许用户右键单击并显示用户自己的菜单。
注意: 我想学习如何制作我自己的,而不是使用别人已经制作的东西,因为大多数时候,那些第三方库的功能都很臃肿,而我只想要我需要的功能,所以我希望它完全由我手工制作。
当前回答
对于那些使用bootstrap 5和jQuery 3寻找一个非常简单的自定义上下文菜单的自包含实现的人来说,这里是…
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<title>Custom Context Menu</title>
</head>
<style>
#context-menu {
position: absolute;
display: none;
}
</style>
<body>
<div class="container-fluid p-5">
<div class="row p-5">
<div class="col-4">
<span id="some-element" class="border border-2 border-primary p-5">Some element</span>
</div>
</div>
<div id="context-menu" class="dropdown clearfix">
<ul class="dropdown-menu" style="display:block;position:static;margin-bottom:5px;">
<li><a class="dropdown-item" href="#" data-value="copy">Copy</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#" data-value="select-all">Select All</a></li>
</ul>
</div>
<script src="https://code.jquery.com/jquery-3.6.1.min.js" integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
<script>
$('body').on('contextmenu', '#some-element', function(e) {
$('#context-menu').css({
display: "block",
left: e.pageX,
top: e.pageY
});
return false;
});
$('html').click(function() {
$('#context-menu').hide();
});
$("#context-menu li a").click(function(e){
console.log('in context-menu item, value = ' + $(this).data('value'));
});
</script>
</body>
</html>
改编自https://codepen.io/anirugu/pen/xjjxvG
其他回答
我使用类似于下面jsfiddle的东西
function onright(el, cb) {
//disable right click
document.body.oncontextmenu = 'return false';
el.addEventListener('contextmenu', function (e) { e.preventDefault(); return false });
el.addEventListener('mousedown', function (e) {
e = e || window.event;
if (~~(e.button) === 2) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
return false;
}
});
// then bind Your cb
el.addEventListener('mousedown', function (e) {
e = e || window.event;
~~(e.button) === 2 && cb.call(el, e);
});
}
如果你的目标浏览器是旧的IE浏览器,你应该用' attachEvent;情况下
试试这个
$(function() {
var doubleClicked = false;
$(document).on("contextmenu", function (e) {
if(doubleClicked == false) {
e.preventDefault(); // To prevent the default context menu.
var windowHeight = $(window).height()/2;
var windowWidth = $(window).width()/2;
if(e.clientY > windowHeight && e.clientX <= windowWidth) {
$("#contextMenuContainer").css("left", e.clientX);
$("#contextMenuContainer").css("bottom", $(window).height()-e.clientY);
$("#contextMenuContainer").css("right", "auto");
$("#contextMenuContainer").css("top", "auto");
} else if(e.clientY > windowHeight && e.clientX > windowWidth) {
$("#contextMenuContainer").css("right", $(window).width()-e.clientX);
$("#contextMenuContainer").css("bottom", $(window).height()-e.clientY);
$("#contextMenuContainer").css("left", "auto");
$("#contextMenuContainer").css("top", "auto");
} else if(e.clientY <= windowHeight && e.clientX <= windowWidth) {
$("#contextMenuContainer").css("left", e.clientX);
$("#contextMenuContainer").css("top", e.clientY);
$("#contextMenuContainer").css("right", "auto");
$("#contextMenuContainer").css("bottom", "auto");
} else {
$("#contextMenuContainer").css("right", $(window).width()-e.clientX);
$("#contextMenuContainer").css("top", e.clientY);
$("#contextMenuContainer").css("left", "auto");
$("#contextMenuContainer").css("bottom", "auto");
}
$("#contextMenuContainer").fadeIn(500, FocusContextOut());
doubleClicked = true;
} else {
e.preventDefault();
doubleClicked = false;
$("#contextMenuContainer").fadeOut(500);
}
});
function FocusContextOut() {
$(document).on("click", function () {
doubleClicked = false;
$("#contextMenuContainer").fadeOut(500);
$(document).off("click");
});
}
});
http://jsfiddle.net/AkshayBandivadekar/zakn7Lwb/14/
你可以试着通过在body标签中添加以下内容来阻止上下文菜单:
<body oncontextmenu="return false;">
这将阻止对上下文菜单的所有访问(不仅从鼠标右键,而且从键盘)。
附注:你可以把它添加到任何你想禁用上下文菜单的标签上
例如:
<div class="mydiv" oncontextmenu="return false;">
将禁用上下文菜单在特定的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>
一些漂亮的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%;}。你需要在某个地方加上一个边距之类的东西