是否有可能检测到一个特定的DOM事件是否有任何事件处理程序绑定到它(包括浏览器默认事件处理) -在Firefox的Greasemonkey代码(EcmaScript 5.1严格模式)?
到目前为止,我设法取消我的点击事件处理时,文本被选中,但我想取消我的事件处理在所有以下情况点击事件触发默认操作:
- 在 页面上选择文本显示
- 上下文菜单(即右键单击)
- 后面是一个链接(左键点击
<a>
) - 表单元素被操纵(文本框获得焦点,光标开始闪烁,单选按钮被选中,…)
- 处理事件的其他JavaScript代码(例如:弹出帮助对话框)
是否有一个捕获所有机制,或者我需要在我的代码中显式拼写所有情况?
下面的代码是我如何检测选择发生的:
var toggleHighlight = function(){
var oldTargt;
return function(e){
targt = e.target;
sel = window.getSelection();
if (!sel.isCollapsed && sel.containsNode(targt, true)) {
return;
}
...
oldTargt = targt;
}()
document.addEventListener('click', toggleHighlight);
<子>指出:
-我不想用我的脚本停止传播,如果事件将传播到其他处理程序,我想停止我的脚本。
-我对只有jquery事件处理程序的解决方案不感兴趣,如果他们不捕获默认的浏览器事件处理程序。
-如果这个功能确实不存在,请引用一些文章或博客,而不仅仅是你自己的观点。
-特别的建议是欢迎的,但我主要感兴趣的是一个普遍的解决方案的存在。子>
更新:可接受的解决方案包括:
- 我需要检查 的
- 非javascript的方式从Firefox插件访问
- 解释Firefox如何知道点击一个有效的
<a>
元素应该触发重新加载新的URL +这个逻辑如何不能从javascript/plugins访问
if
条件的详尽(ish)列表这个问题几乎是"如何在Javascript/jQuery中没有默认值的情况下执行操作?"的重复,除了作为Greasemonkey脚本器,还有一个(复杂的)选项可供您使用。
从你的问题来看,看起来你想要为没有默认操作的节点设置默认操作,然后在任何其他事件处理程序为给定事件触发时中止该默认操作。对此没有"万能机制",您尝试的任何技术都有可能破坏某些页面。原因:
-
javascript和Greasemonkey API都没有提供任何机制来列出给定节点的事件。有一个老的建议,但它从来没有实施过。
然而, Firefox插件可以通过nsIEventListenerService列出事件,所以有一个可能性你可以为那部分编写一个helper插件,它与Greasemonkey接口。
-
同样,没有机制可以从event对象检测事件链中的先前事件,除非设置了
event.defaultPrevented
。(通常不会) -
即使可以列出节点X的事件侦听器,也无法帮助父节点上的回退侦听器。现代JS库可以(有时确实可以)使任何旧节点都可点击。并且/或者他们可以在
document
上设置侦听器,例如获取所有单击事件,但实际上不做任何事情,除非原始目标是某个特定节点。
一个好的折衷策略是遵循另一个问题的引导,不对具有默认操作的节点做任何事情。
要处理右键单击,或单击中心,请检查event.which
。
因此,您可以在检查中添加以下代码片段:
return function(e){
targt = e.target;
sel = window.getSelection();
if (e.which != 1) {
return; //-- Abort on anything that is not a left-click.
}
if (e.defaultPrevented) {
return; //-- The one time we know that some other handler fired.
}
if (isInteractiveElement (targt) ) {
// Do nothing for elements that trigger browser actions
return;
}
...
地点:
function isInteractiveElement (node) {
var intElems = [
//-- Must be uppercase
"A", "BUTTON", "INPUT", "TEXTAREA", "VIDEO", "MAP", "OBJECT"
];
if (intElems.indexOf (node.nodeName) >= 0) {
return true;
}
else if (node.nodeName === "BODY") {
return false;
}
return isInteractiveElement (node.parentNode);
}