如何挂钩浏览器的上下文菜单事件

发布于 2024-10-07 01:21:57 字数 441 浏览 0 评论 0原文

我一直很困惑,找不到适合我的上下文菜单。也许有人可以帮忙?

这是我需要添加 contextMenu 的内容:

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

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

谢谢

I keep getting puzzled, can't find a contextmenu that will work for me. Maybe someone can help?

Here's to what I need contextMenu to be added to:

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

This is dynamic list, so it will add many more of them on the page and differ them by giving different ID's. So I need a contextMenu which will be added to every list but for each list an unique contextMenu. Basically different instances of contextMenu in every list, by adding dynamic {id} tag to the ID of contextMenu or something like that.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

许一世地老天荒 2024-10-14 01:21:57

很难说出你在问什么,但如果你想挂钩浏览器的“上下文菜单”事件,你可以挂钩 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>

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示例

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


更新:回复你的“但是如果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;
  }
}

实时示例

It's kind of hard to tell what you're asking, but if you want to hook into the "context menu" event of a browser, you hook the contextmenu event and then do whatever you're going to do (which could include creating a div, for instance, with options on it — e.g., your own context menu). You can either do that on the lists themselves, individually, via getElementById as you indicated in your question, or you can do it by hooking the event on some container that holds all of the lists, and then figuring out when the event is triggered which list it was triggered on ("event delegation").

See the end of this answer for the event delegation approach. But assuming you have a way of knowing the actual IDs used and you want to hook each list specifically for some reason:

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

Note that only some (most) browsers let you cancel the default context menu.


Update: Re your "but what if the ID is bindable?" question below: I'm afraid I don't know what you mean by "bindable" — none of the tags on your question indicates a specific templating technology. You haven't even mentioned whether the templating is happening server-side or client-side, which makes it hard to help. But basically, by the time the JavaScript is running, there will be real IDs on real elements in the document. You'll have to know what those IDs are in order to use getElementById.

Server-side templating:

If those IDs are going to be completely dynamic and the template is being handled on the server, you can include a small bit of script that passes those IDs on to JavaScript. For instance, near the top of your document you might have:

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

...and then update your template to add a small script tag each time it's expanded:

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

Then your client-side code can loop through mySpecialLitIDs and use each ID when hooking up the handler.

Client-side templating:

If the templating is being done client-side, this gets a bit simpler: Just set up your mySpecialListIDs list at some convenient place in your client-side script, and the append to it each time you call the templating engine.


Event Delegation: Whether you're doing server- or client-side templating, if you're going to have dynamic lists like this, sometimes event delegation is the best way to handle it. The contextmenu event (like most, but not all, events) bubbles up the DOM. So if you hook it on an ancestor element (something that contains all of your lists, like the document body itself or some such), you can then see which actual list was clicked by examining the event object. Like this:

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 (using the hookEvent function from above):

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文