检测默认事件处理



是否有可能检测到一个特定的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事件处理程序的解决方案不感兴趣,如果他们不捕获默认的浏览器事件处理程序。
-如果这个功能确实不存在,请引用一些文章或博客,而不仅仅是你自己的观点。
-特别的建议是欢迎的,但我主要感兴趣的是一个普遍的解决方案的存在。

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

  • 我需要检查
  • if条件的详尽(ish)列表
  • 非javascript的方式从Firefox插件访问
  • 解释Firefox如何知道点击一个有效的<a>元素应该触发重新加载新的URL +这个逻辑如何不能从javascript/plugins访问

这个问题几乎是"如何在Javascript/jQuery中没有默认值的情况下执行操作?"的重复,除了作为Greasemonkey脚本器,还有一个(复杂的)选项可供您使用。

从你的问题来看,看起来你想要为没有默认操作的节点设置默认操作,然后在任何其他事件处理程序为给定事件触发时中止该默认操作。对此没有"万能机制",您尝试的任何技术都有可能破坏某些页面。原因:

  1. javascript和Greasemonkey API都没有提供任何机制来列出给定节点的事件。有一个老的建议,但它从来没有实施过。

    然而, Firefox插件可以通过nsIEventListenerService列出事件,所以有一个可能性你可以为那部分编写一个helper插件,它与Greasemonkey接口。

  2. 同样,没有机制可以从event对象检测事件链中的先前事件,除非设置了event.defaultPrevented。(通常不会)

  3. 即使可以列出节点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);
}

相关内容

  • 没有找到相关文章

最新更新