【问题标题】:How to open anchor context menu with JavaScript?如何使用 JavaScript 打开锚上下文菜单?
【发布时间】:2020-10-07 17:45:34
【问题描述】:

我正在尝试仅使用 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 }))

【问题讨论】:

标签: javascript html mouseevent anchor


【解决方案1】:

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

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

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 sn-ps 中被阻止,原因很明显。试试这个CodePen 进行工作演示。

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

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

【讨论】:

  • 这是迄今为止我找到的最有帮助的答案。据我所知,无法打开本机浏览器上下文菜单,因此打开自定义上下文菜单似乎是唯一的选择。 (对于好奇的我,我需要一个 div,它不能是锚,但里面有一个锚,它接收点击事件。我想将 div 上的所有点击事件“转发”到其中的锚并且无法计算了解如何“转发”右键单击事件。有点像这样,但也适用于右键单击:eng.wealthfront.com/2020/10/01/…
  • 感谢您的精彩评论 ;) --- 现在,opening the native browser contextmenu isn't possible - 是真的(据我所知)。 --- 关于“转发”事件...您的意思是处理在parent 上发生的事件并使用它的处理程序child?不...我不知道为什么要这样做。很容易想象会有不止一个child 会尝试处理那个“转发的事件”。我看起来不是个好主意。 ;)
【解决方案2】:
document.getElementById("anchor-el").addEventListener("click", function() {
    var link = document.getElementById('anchor-el').getAttribute("href");
    window.open(link,'_blank');
});

相信会对你有所帮助。

【讨论】:

    【解决方案3】:

    如果我理解正确,您必须创建一个自定义 contextmenu。所以这里是一个例子。

    const menu = document.querySelector('[data-id=anchor-el]')
    const anchor = document.getElementById('anchor-el');
    
    anchor.addEventListener('contextmenu', e => {
      e.preventDefault();
      menu.style.top = e.pageX;
      menu.style.top = e.pageY;
      menu.style.display = 'block';
    });
    
    menu.querySelector('li#newTab').addEventListener('click', (evt) => {
      evt.preventDefault();
      console.log('clicked open in new tab');
      window.open(anchor.href);
    });
    menu.querySelector('li#newWin').addEventListener('click', (evt) => {
      evt.preventDefault();
      console.log('clicked open in new window');
      window.open(anchor.href, '_blank', 'toolbar=0,location=0,menubar=0');
    });
    
    document.body.addEventListener('click', (evt) => {
      evt.preventDefault();
      evt.stopPropagation();
      menu.style.display = 'none';
    });
    [data-id="anchor-el"] {
      width: 15rem;
      display: flex;
      margin: 0;
      padding: 0;
      align-items: stretch;
      align-content: space-evenly;
      flex-direction: column;
      justify-content: space-evenly;
      box-shadow: 0 0.25rem 0.325rem 0.175rem rgba(0, 0, 0, 0.2);
      position: relative;
      display: none;
    }
    
    [data-id="anchor-el"] ul li {
      width: 100%;
      list-style: none;
      margin: 0;
      padding: 0.5rem;
      position: relative;
      color: #000;
      font-weight: 500;
      font-size: 1rem;
      cursor: pointer;
    }
    
    [data-id="anchor-el"] ul li:hover {
      color: #f00;
    }
    <a href="https://stackoverflow.com" id="anchor-el"> Anchor </a>
    
    <div>
    
      <div type="context" data-id="anchor-el">
        <ul>
          <li label="Open in new tab" id="newTab">Open in new tab</li>
          <li label="Open in new window" id="newWin">Open in new window</li>
        </ul>
      </div>
    
    </div>

    【讨论】:

      【解决方案4】:

      如果你想在菜单中有在新选项卡中打开和在新窗口中打开选项,为什么只使用 HTML?

      <html>
        <head></head>
        <body>
          <a href="https://stackoverflow.com" id="anchor-el" target="_blank" title="If you run this snippet and click on this link, it won't work because you need to run it in your own editor"> Anchor </a>
        </body>
      </html>

      只要点击上述代码,就会在新标签页中打开。右键单击时,还会有在新选项卡中打开和在新窗口中打开的选项。

      属性“target”指定链接的打开位置;下面是一些例子:

      target="_blank" - "Opens in new tab"
      target="_self" - "Opens in the same tab"
      target="_parent" - "Opens in the parent frame"
      target="_top" - "Opens in the full body of the window"
      

      【讨论】:

        【解决方案5】:

        打开本机系统上下文菜单,例如。 G。无法使用默认的右键单击上下文菜单。
        您当然可以使用 jQuery 创建自己的上下文菜单,例如:
        https://swisnl.github.io/jQuery-contextMenu/

        作为如何使用该库的示例:

         $(function() {
                $.contextMenu({
                    selector: '#example', 
                    trigger: 'left',
                    callback: function(key, options) {
                        var m = "clicked: " + key;
                        window.console && console.log(m) || alert(m); 
                    },
                    items: {
                        "edit": {name: "Edit", icon: "edit"},
                        "cut": {name: "Cut", icon: "cut"},
                       copy: {name: "Copy", icon: "copy"},
                        "paste": {name: "Paste", icon: "paste"},
                        "delete": {name: "Delete", icon: "delete"},
                        "sep1": "---------",
                        "quit": {name: "Quit", icon: function(){
                            return 'context-menu-icon context-menu-icon-quit';
                        }}
                    }
                });
                
                /* prevent the default switching to the target site */
                $("#example").on("click", function(event) { 
                    event.preventDefault(); 
                });
            });
        <link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.1/jquery.contextMenu.min.css" rel="stylesheet"/>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.1/jquery.contextMenu.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-contextmenu/2.7.1/jquery.ui.position.js"></script>
        
        <a href="https://google.com" id="example">click me</a>

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-18
          相关资源
          最近更新 更多