如何在网页中添加自定义右键菜单?

415
我想在我的网络应用程序中添加一个自定义右键菜单。是否可以在不使用任何预制库的情况下完成?如果可以,如何显示一个简单的自定义右键菜单,而不使用第三方JavaScript库?
我希望实现类似于Google文档的功能。它允许用户右键单击并显示他们自己的菜单。
注意:我想学习如何制作自己的自定义右键菜单,而不是使用别人已经制作好的东西,因为大多数时候,这些第三方库都有很多功能,而我只需要我需要的功能,所以我想完全手工制作。

5
刚刚偶然发现了这个网站:http://davidwalsh.name/html5-context-menu,喜欢HTML5。 - Nijboer IT
5
这绝对不是重复的问题。因为这个问题要求没有第三方库的答案,而另一个问题很可能使用Jquery *(我想写一个用户脚本中类似于Google驱动器的上下文菜单的上下文)*。 - user2284570
1
今天我找到了两个关于这个问题的好例子(我认为):DEMO 1 // DEMO 2(这个演示需要 jquery UI)。希望对大家有所帮助,再见。 - Drako
3
只是想指出,HTML5上下文菜单只在某些Firefox版本中受支持,据我所知其他浏览器都不支持。Chrome自版本61起就不再支持它。 - Dan Willett
4
针对使用React的人 - native-menu 复制了 所有 现有功能(复制、在新标签页中打开、在Google上搜索等),同时外观看起来更符合本地化(根据浏览器应用不同的样式)。演示 - Sam Denty
22个回答

7

我知道这个问题已经有答案了,但是我花了一些时间来解决第二个答案,使原生上下文菜单消失并在用户点击的位置出现。

HTML

<body>
    <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 class="White">White</li>
            <li>Green</li>
            <li>Yellow</li>
            <li>Orange</li>
            <li>Red</li>
            <li>Blue</li>
        </ul>
    </div>
</body>

CSS

.hide {
  display: none;
}

#rmenu {
  border: 1px solid black;
  background-color: white;
}

#rmenu ul {
  padding: 0;
  list-style: none;
}
#rmenu li
{
  list-style: none;
  padding-left: 5px;
  padding-right: 5px;
}

JavaScript

if (document.getElementById('test1').addEventListener) {
    document.getElementById('test1').addEventListener('contextmenu', function(e) {
            $("#rmenu").toggleClass("hide");
            $("#rmenu").css(
              {
                position: "absolute",
                top: e.pageY,
                left: e.pageX
              }
            );
            e.preventDefault();
     }, false);
}

// this is from another SO post...  
$(document).bind("click", function(event) {
  document.getElementById("rmenu").className = "hide";
});

CodePen 示例


6

试一下

$(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/


代码很好,但请包括一些关于OP的问题实际上是什么以及如何解决它的描述。 - Rory McCrossan
我喜欢这个解决方案,但是在Firefox 39中,菜单在弹出后会自动消失。 - Matt
如果你强制页面滚动(比如添加一堆<br>标签),并且在底部的某个位置,那么这个解决方案实际上是不起作用的。 - DanielM
你应该使用clientX和clientY而不是pageX和pageY以使其工作; 查看这个很棒的回答: https://dev59.com/r2ox5IYBdhLWcg3wWjDQ - DanielM
是的,DanielM,在滚动时右键菜单存在问题,但通过使用clientX和clientY代替pageX和pageY来解决了这个问题,我已经对代码进行了更改。感谢您的帮助... - AkshayBandivadekar

3
你可以使用这段代码来实现。 访问此处以获取完整教程,包括自动边缘检测: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();
 });
 });

`


1
<script>
function fun(){
document.getElementById('menu').style.display="block";
}

</script>
<div id="menu" style="display: none"> menu items</div>

<body oncontextmenu="fun();return false;">

我在这里做什么:
  1. 创建自定义的div菜单,并将其位置设置为绝对定位,同时在不需要时将其显示设置为none。

  2. 在要被点击的页面或元素上添加oncontextmenu事件。

  3. 使用return false取消默认浏览器操作。

  4. 使用js来调用您自己的操作。


1

对于那些寻求使用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


我想知道Bootstrap的弹出框组件是否可以使用? - Phillip Senn

1

在Opera 12.17,Firefox 30,Internet Explorer 9和Chrome 26.0.1410.64中测试并有效。

document.oncontextmenu =function( evt ){
        alert("OK?");
        return false;
        }

1
这只会在上下文菜单出现时显示一个警报,我不知道它如何自定义。 - Stephen Ostermiller
你好@StephenOstermiller!return false会隐藏正常的上下文菜单 - 因此我们可以将警报更改为其他内容,例如使用element.style.display =“block”显示自定义警报。 - corn on the cob

1

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

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

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

通过输入 return false;,您将取消上下文菜单。

如果您仍想显示上下文菜单,只需删除 return false; 行即可。


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

3
你知道有一个oncontextmenu事件会被触发(通常在右键单击时)。 - megawac

0
<html>
<head>
<style>
.rightclick {
    /* YOUR CONTEXTMENU'S CSS */
    visibility: hidden;
    background-color: white;
    border: 1px solid grey;
    width: 200px;
    height: 300px;
}
</style>
</head>
<body>
  <div class="rightclick" id="ya">
    <p onclick="alert('choc-a-late')">I like chocolate</p><br><p onclick="awe-so-me">I AM AWESOME</p>
  </div>
  <p>Right click to get sweet results!</p>
</body>
<script>
    document.onclick = noClick;
    document.oncontextmenu = rightClick;
    function rightClick(e) {
        e = e || window.event;
        e.preventDefault();
        document.getElementById("ya").style.visibility = "visible";
        console.log("Context Menu v1.3.0 by IamGuest opened.");
   }
function noClick() {
    document.getElementById("ya").style.visibility = "hidden";
    console.log("Context Menu v1.3.0 by IamGuest closed.");
}
</script>
<!-- Coded by IamGuest. Thank you for using this code! -->
</html>

您可以调整和修改此代码,以创建外观更好、更高效的上下文菜单。至于修改现有的上下文菜单,我不确定如何操作...请查看这个fiddle,以获得一个有组织的视角。另外,请尝试点击我的上下文菜单中的项目。它们应该会提示您一些很棒的信息。如果它们不起作用,请尝试更复杂的操作。


0

你说得没错,但这并没有回答最初的问题。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接