如何挂钩浏览器的contextmenu事件

时间:2010-12-11 22:45:28

标签: javascript list contextmenu

我一直感到困惑,无法找到对我有用的情境菜单。也许有人可以提供帮助?

以下是我需要将contextMenu添加到:

<ul id="list_{id}" class="list">
   <li id="Item_{id}"><a ondblclick=""><span>{title}</span></a></li>
</ul>

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

由于

1 个答案:

答案 0 :(得分:6)

很难说出你在问什么,但是如果你想要浏览浏览器的“上下文菜单”事件,你可以挂钩contextmenu事件,然后做你想做的事情。 do(可能包括创建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>

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;
  }
}

Live example

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


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

服务器端模板

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

<script type='text/javascript'>
var mySpecialListIDs = [];
</script>

...然后更新您的模板,以便在每次展开时添加一个小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>

然后您的客户端代码可以遍历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>

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;
  }
}

Live example