首页 > 解决方案 > 如何使用 JavaScript 打开锚上下文菜单?

问题描述

我正在尝试仅使用 JavaScript 打开一个锚上下文菜单,例如对于这个 HTML:

<html>
  <head></head>
  <body>
    <a href="https://stackoverflow.com" id="anchor-el"> Anchor </a>
  </body>
</html>

我想仅使用 JavaScript 使用原生的“在链接新选项卡中打开”和“在新窗口中打开链接”选项打开上下文菜单。

到目前为止,我已经尝试过了,它似乎成功地将一个contextmenu事件发送到锚点,但上下文菜单实际上并没有显示......

document.getElementById('anchor-el').dispatchEvent(new MouseEvent('contextmenu', { bubbles: true }))

标签: javascripthtmlmouseeventanchor

解决方案


根据我对您的问题的理解,您希望用结果“替换”正常click事件contextmenu结果......但只有该上下文菜单的前两个项目。

这使它成为您必须定义的自定义菜单。所以这里有一些东西......

let contextElements = document.querySelectorAll(".context-anchor")
let myContext = document.querySelector(".context")
let contextItems = document.querySelectorAll(".context-item")
let contextHref

// To add event a listener on each .context-anchor element in order to show a "simulated context menu"
contextElements.forEach(function(ce){
  ce.addEventListener("click", function(e){
    e.preventDefault()
    
    // Get the click coord to open the context menu at the right place
    let clickCoords = {x: e.pageX, y: e.pageY}
    // Get the href of the clicked link
    contextHref = ce.href
    
    // Create a mouse event
    let event = document.createEvent('MouseEvents');
    event.initEvent('mycontextmenu', false, true);
    
    // Be ready to handle it
    this.addEventListener('mycontextmenu', function (e) {
      myContext.style.top = clickCoords.y
      myContext.style.left = clickCoords.x
      myContext.style.display= "block"
    }, false);
    
    // Dispatch it
    this.dispatchEvent(event);
  })
})

// Listener for the options of that "simulated context menu"
contextItems.forEach(function(ci){
  ci.addEventListener("click", function(e){
    if(this.getAttribute("data-destination") === "tab"){
      window.open(contextHref,"_blank")
    }else{
      window.open(contextHref,"custom",`width=${0.99*screen.width},height=${0.94*screen.height}`)
    }
  })
})

// To hide the "simulated context menu" when there is a click anywhere else than on a .context-anchor element
document.addEventListener("click", function(e){
  if(myContext.style.display==="block" && e.target.classList.toString().split(" ").indexOf("context-anchor")<0){
    myContext.style.display= "none"
  }
})
.context{
  display: none;
  position: absolute;
  top: 0;
  left: 0;
  border: 1px solid lightgrey;
  background: white;
  margin: 1em;
  box-shadow: 2px 2px 2px grey;
  min-width: 15em;
}

.context-item{
  font-family: "arial";
  padding: 0.5em 2em;
}

.context-item:hover{
  background: lightgrey;
}
<a href="https://stackoverflow.com" class="context-anchor"> Anchor </a><br>
<br>
<a href="http://hmpg.net/" > Normal anchor </a>

<!-- The simulated context menu -->
<div class="context">
  <div class="context-item" data-destination="tab">Open link in a new tab</div>
  <div class="context-item" data-destination="window">Open link in a new window</div>
</div>

注意window.open由于明显的原因,在 SO 片段中被阻止。试试这个CodePen的工作演示。

这绝对是创建奇怪和不常见的浏览器行为的大量代码。所以我不会推荐任何人使用它。

我发布这个是因为这是一个赏金挑战。oO(哈哈!)


推荐阅读