如何挂钩浏览器的contextmenu事件

Yan*_*Yan 1 javascript contextmenu list

我一直感到困惑,无法找到适合我的情境菜单.也许有人可以帮忙?

这是我需要将contextMenu添加到:

<ul id="list_{id}" class="list">
   <li id="Item_{id}"><a ondblclick=""><span>{title}</span></a></li>
</ul>
Run Code Online (Sandbox Code Playgroud)

这是动态列表,因此它将在页面上添加更多它们,并通过提供不同的ID来区分它们.所以我需要一个contextMenu,它将被添加到每个列表中,但每个列表都有一个唯一的contextMenu.通过向contextMenu的ID或类似内容添加动态{id}标记,每个列表中的contextMenu基本上不同的实例.

谢谢

T.J*_*der 6

很难说出你在问什么,但是如果你想要浏览浏览器的"上下文菜单"事件,你可以挂钩contextmenu事件,然后做你要做的任何事情(可能包括创建一个div,例如,有选项 - 例如,你自己的上下文菜单).您可以在列表本身上单独执行此操作,也可以getElementById按照您在问题中指示的方式执行此操作,或者您可以通过在包含所有列表的某个容器上挂起事件来执行此操作,然后确定事件何时触发哪个列表它被触发("事件委托").

有关事件委派方法,请参阅此答案的结尾.但假设您有一种方法可以知道所使用的实际ID,并且您希望专门为某些原因挂钩每个列表:

HTML:

<ul id='list_1'>
  <li>List 1 item 1</li>
  <li>List 1 item 2</li>
</ul>
<ul id='list_2'>
  <li>List 2 item 1</li>
  <li>List 2 item 2</li>
</ul>
Run Code Online (Sandbox Code Playgroud)

JavaScript的:

hookEvent(document.getElementById('list_1'), 'contextmenu', function(event) {
  event = event || window.event;
  if (event.preventDefault) {
    event.preventDefault();
  }
  display("List 1 context menu");
  return false;
});
hookEvent(document.getElementById('list_2'), 'contextmenu', function(event) {
  event = event || window.event;
  if (event.preventDefault) {
    event.preventDefault();
  }
  display("List 2 context menu");
  return false;
});

function hookEvent(element, event, handler) {
  if (element.addEventListener) {
    element.addEventListener( event, handler, false);
  }
  else if (element.attachEvent) {
    element.attachEvent('on' + event, handler);
  }
  else {
    element['on' + event] = handler;
  }
}
Run Code Online (Sandbox Code Playgroud)

实例

请注意,只有部分(大多数)浏览器允许您取消默认上下文菜单.


更新:重新启动"但如果ID可以绑定怎么办?" 问题如下:我担心我不知道"可绑定"是什么意思 - 你问题上的标签都没有表明具体的模板技术.您甚至没有提到模板是在服务器端还是在客户端发生,这使得很难提供帮助.但基本上,当JavaScript运行时,文档中的真实元素上会有真实的ID.你必须知道这些ID是什么才能使用getElementById.

服务器端模板:

如果这些ID将是完全动态的并且正在服务器上处理模板,则可以包含一些将这些ID传递给JavaScript的脚本.例如,您可能在文档顶部附近:

<script type='text/javascript'>
var mySpecialListIDs = [];
</script>
Run Code Online (Sandbox Code Playgroud)

...然后更新您的模板,以便在script每次扩展时添加一个小标记:

<ul id="list_{id}" class="list">
   <li id="Item_{id}"><a ondblclick=""><span>{title}</span></a></li>
</ul>
<script type='text/javascript'>
mySpecialListIDs.push("{id}");
</script>
Run Code Online (Sandbox Code Playgroud)

然后,您的客户端代码可以循环mySpecialLitIDs并在连接处理程序时使用每个ID.

客户端模板:

如果模板化是在客户端完成的,这会变得更简单:只需mySpecialListIDs在客户端脚本中的某个方便的位置设置列表,并在每次调用模板引擎时附加到它.


事件委派:无论您是在进行服务器端还是客户端模板,如果您要使用这样的动态列表,有时事件委派是处理它的最佳方式.该contextmenu事件(最喜欢的,但不是所有的事件)了DOM.因此,如果您将其挂钩到祖先元素(包含所有列表的内容,例如文档正文或其他类似内容),则可以通过检查事件对象来查看单击了哪个实际列表.像这样:

HTML:

<div id='list_container'>
  <ul id='list_1'>
    <li>List 1 item 1</li>
    <li>List 1 item 2</li>
  </ul>
  <ul id='list_2'>
    <li>List 2 item 1</li>
    <li>List 2 item 2</li>
  </ul>
</div>
Run Code Online (Sandbox Code Playgroud)

JavaScript(使用hookEvent上面的函数):

// Hook up the contextmenu event on the container, not
// on each list:
hookEvent(document.getElementById('list_container'),
          'contextmenu',
          handleListContextMenu);

// Our handler function
function handleListContextMenu(event) {
  var target;

  // Handle IE-vs-the-world difference
  event = event || window.event;

  // Find out what the actual target element clicked was
  target = event.target || event.srcElement;

  // See if it or an ancestor of it is one of our lists
  while (target &&
         (target.tagName !== "UL" || !target.id || target.id.substring(0, 5) !== "list_")) {
    target = target.parentNode;
  }

  // Did we find a list?
  if (target) {
    // Yes, handle this.
    if (event.preventDefault) {
      event.preventDefault();
    }
    display("List '" + target.id + "' context menu");
    return false;
  }
}
Run Code Online (Sandbox Code Playgroud)

实例