javascript – 检测默认事件处理

是否有可能在Firefox的Greasemonkey代码(
EcmaScript 5.1 strict mode)中检测特定DOM事件是否具有绑定到它的任何事件处理程序(包括浏览器默认事件处理)?

到目前为止,当我选择了一个文本时,我设法取消了我的点击事件处理,但是我希望在以下所有情况下取消我的事件处理,其中click事件触发默认操作:

>在页面上选择文字
>显示上下文菜单(即右键单击)
>遵循一个链接(左键单击< 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-event-handlers-only解决方案不感兴趣.
– 如果此功能确实不存在,请引用一些文章或博客,而不仅仅是您自己的观点.
– 欢迎提出具体建议,但我主要对存在一般解决方案感兴趣.

更新:可接受的解决方案包

>穷举(ish)我需要检查的条件列表
>从Firefox插件可以访问的非JavaScript方式
>解释Firefox如何知道点击有效的< a>元素应该触发重新加载新URL如何从javascript / plugins无法访问此逻辑

最佳答案 这个问题几乎与
“How to do an action only when there is no default in Javascript / jQuery?”重复,除了作为Greasemonkey脚本编写者,还有一个(复杂)选项可用.

从您的问题来看,您似乎想为没有一个节点的节点设置default action,然后在任何其他事件处理程序触发给定事件时中止该默认操作.对此没有“全能机制”,你尝试过的任何技术都可能会破坏一些页面.原因如下:

> javascript和Greasemonkey API都没有提供列出给定节点事件的任何机制.有an old proposal,但它从未实施过.

但是,Firefox附加组件可以通过nsIEventListenerService列出事件,因此您可以为该部件编写一个帮助程序附件,该附件与Greasemonkey接口.详细信息(方式)超出了本问题的范围.
>同样,除非设置了event.defaultPrevented,否则没有机制可以检测来自Event object的事件链中的先前事件. (通常不会.)
>即使您可以列出节点X的事件侦听器,也无法帮助父节点上的后备侦听器.现代JS库可以(有时可以)使任何旧节点可点击.和/或他们可以设置一个监听器,例如,获取所有点击事件的文档,但除了原始目标是某个特定节点之外,实际上并没有做任何事情.

一个好的折衷策略是跟随另一个问题的引导而不对具有默认操作的节点做任何事情.
要处理右键单击或中心点击,请检查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);
}
点赞