我希望实现类似于Google文档的功能。它允许用户右键单击并显示他们自己的菜单。
注意:我想学习如何制作自己的自定义右键菜单,而不是使用别人已经制作好的东西,因为大多数时候,这些第三方库都有很多功能,而我只需要我需要的功能,所以我想完全手工制作。
回答你的问题 - 使用 contextmenu
事件, 如下所示:
if (document.addEventListener) {
document.addEventListener('contextmenu', function(e) {
alert("You've tried to open context menu"); //here you draw your own menu
e.preventDefault();
}, false);
} else {
document.attachEvent('oncontextmenu', function() {
alert("You've tried to open context menu");
window.event.returnValue = false;
});
}
<body>
Lorem ipsum...
</body>
但你应该问问自己,你真的想要覆盖默认的右键行为吗 - 这取决于你正在开发的应用程序。
e.preventDefault();
。这就是为什么常规菜单没有显示的原因。您可以创建一些条件逻辑进行检查,如果在右键单击时按下了按键并且不调用e.preventDefault()
- 那么您将获得常规浏览器菜单。 - Radek Benkel这对我非常有用。为了像我这样的人,期望绘制菜单,我在这里放置我用来创建右键菜单的代码:
$(document).ready(function() {
if ($("#test").addEventListener) {
$("#test").addEventListener('contextmenu', function(e) {
alert("You've tried to open context menu"); //here you draw your own menu
e.preventDefault();
}, false);
} else {
//document.getElementById("test").attachEvent('oncontextmenu', function() {
//$(".test").bind('contextmenu', function() {
$('body').on('contextmenu', 'a.test', function() {
//alert("contextmenu"+event);
document.getElementById("rmenu").className = "show";
document.getElementById("rmenu").style.top = mouseY(event) + 'px';
document.getElementById("rmenu").style.left = mouseX(event) + 'px';
window.event.returnValue = false;
});
}
});
// this is from another SO post...
$(document).bind("click", function(event) {
document.getElementById("rmenu").className = "hide";
});
function mouseX(evt) {
if (evt.pageX) {
return evt.pageX;
} else if (evt.clientX) {
return evt.clientX + (document.documentElement.scrollLeft ?
document.documentElement.scrollLeft :
document.body.scrollLeft);
} else {
return null;
}
}
function mouseY(evt) {
if (evt.pageY) {
return evt.pageY;
} else if (evt.clientY) {
return evt.clientY + (document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop);
} else {
return null;
}
}
.show {
z-index: 1000;
position: absolute;
background-color: #C0C0C0;
border: 1px solid blue;
padding: 2px;
display: block;
margin: 0;
list-style-type: none;
list-style: none;
}
.hide {
display: none;
}
.show li {
list-style: none;
}
.show a {
border: 0 !important;
text-decoration: none;
}
.show a:hover {
text-decoration: underline !important;
}
<!-- jQuery should be at least version 1.7 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="contextmenu.js"></script>
<link rel="stylesheet" href="contextmenu.css" />
<div id="test1">
<a href="www.google.com" class="test">Google</a>
<a href="www.google.com" class="test">Link 2</a>
<a href="www.google.com" class="test">Link 3</a>
<a href="www.google.com" class="test">Link 4</a>
</div>
<!-- initially hidden right-click menu -->
<div class="hide" id="rmenu">
<ul>
<li>
<a href="http://www.google.com">Google</a>
</li>
<li>
<a href="http://localhost:8080/login">Localhost</a>
</li>
<li>
<a href="C:\">C</a>
</li>
</ul>
</div>
mouseY(event)
和 mouseX(event)
像预期的那样工作,需要在它们后面添加 px
。示例链接:http://jsfiddle.net/a6w7n64o/。 - zanetujQuery
实际上并没有太多额外的东西,不会拖慢任何速度。它非常有用,这个答案中使用的相同jQuery
可以轻松转换为标准的JavaScript
命令。它可能不完全符合原始问题的要求,但绝对是95%符合要求的。 - The Duke Of Marshall שלום一些漂亮的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>
注意: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只是这个例子中使用的,我个人会在Windows上保留它以获得持久性菜单。
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 > menu{left:100%;}
为menu > menu{right:100%;}
来创建一个从右到左展开的菜单。不过您需要在某处添加一些边距或其他东西。
return false;
以支持更多的浏览器版本。 - stackprotectormenu[title]:before
是将标题注入标签的魔法,因此您不必使用它,可以根据需要在标签中填写内容。 - Isaac<i class="fa fa-flag"></i>
) 以及一个用于显示快捷键的 <span>
元素的 <a>
元素来构建布局。因此,结构如下:<a href="#" onclick="doSomething()">
<img src="path/to/image.gif" />
This is a menu option
<span>Ctrl + K</span>
</a>
我们将把它们放在一个div中,并在右键单击时显示该div。让我们像Google Chrome一样对其进行样式设置,好吗?
#menu a {
display: block;
color: #555;
text-decoration: no[...]
现在我们将添加来自已接受答案的代码,并获取鼠标指针的X和Y值。为此,我们将使用e.clientX
和e.clientY
。我们正在使用client,因此菜单div必须是fixed。
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>
简单的启动函数,在光标位置创建一个上下文菜单,在鼠标离开时销毁它自己。
oncontextmenu = (e) => {
e.preventDefault()
let menu = document.createElement("div")
menu.id = "ctxmenu"
menu.style = `top:${e.pageY-10}px;left:${e.pageX-40}px`
menu.onmouseleave = () => ctxmenu.outerHTML = ''
menu.innerHTML = "<p>Option1</p><p>Option2</p><p>Option3</p><p>Option4</p><p onclick='alert(`Thank you!`)'>Upvote</p>"
document.body.appendChild(menu)
}
#ctxmenu {
position: fixed;
background: ghostwhite;
color: black;
cursor: pointer;
border: 1px black solid
}
#ctxmenu > p {
padding: 0 1rem;
margin: 0
}
#ctxmenu > p:hover {
background: black;
color: ghostwhite
}
isDisplayed = true/false
,而不是解析。 - NVRMtop:${e.pageY-10}px;left:${e.pageX-40}px
menu.onmouseleave = () => ctxmenu.outerHTML = ''
menu.innerHTML = "<p>选项1</p><p>选项2</p><p>选项3</p><p>选项4</p><p onclick='alert(`谢谢!`)'>点赞</p>"
document.body.appendChild(menu);
}
} - Murat Kezli这是一个纯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>
您可以尝试通过将以下代码添加到 body 标签来简单地阻止上下文菜单:
```html oncontextmenu="return false;" ```<body oncontextmenu="return false;">
这将阻止所有对上下文菜单的访问(不仅是通过鼠标右键,还包括通过键盘)。
P.S. 您可以将此添加到任何标签中以禁用上下文菜单
例如:
<div class="mydiv" oncontextmenu="return false;">
将仅禁用特定div中的上下文菜单
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<head>
<title>Context menu - LabLogic.net</title>
</head>
<body>
<script language="javascript" type="text/javascript">
document.oncontextmenu=RightMouseDown;
document.onmousedown = mouseDown;
function mouseDown(e) {
if (e.which===3) {//righClick
alert("Right-click menu goes here");
}
}
function RightMouseDown() { return false; }
</script>
</body>
</html>
已在Opera 11.6、Firefox 9.01、Internet Explorer 9和Chrome 17中进行了测试并且能够正常工作。
试试这个:
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>
这里有一个非常好的 自定义右键菜单教程,附带完整的工作代码示例(不需要 JQuery 或其他库)。
你也可以在他们的 GitHub 上找到演示代码。
他们提供了详细的逐步说明,让你可以跟着构建自己的右键菜单(包括 html、css 和 javascript 代码),并在最后通过给出完整的示例代码进行总结。
你可以轻松地跟着操作,并根据自己的需求进行调整。而且没有必要使用 JQuery 或其他库。
这是他们示例菜单代码的样子:
<nav id="context-menu" class="context-menu">
<ul class="context-menu__items">
<li class="context-menu__item">
<a href="#" class="context-menu__link" data-action="View"><i class="fa fa-eye"></i> View Task</a>
</li>
<li class="context-menu__item">
<a href="#" class="context-menu__link" data-action="Edit"><i class="fa fa-edit"></i> Edit Task</a>
</li>
<li class="context-menu__item">
<a href="#" class="context-menu__link" data-action="Delete"><i class="fa fa-times"></i> Delete Task</a>
</li>
</ul>
</nav>