从DOM中删除事件目标时的跨浏览器事件传播行为

时间:2014-02-07 22:11:35

标签: javascript jquery html cross-browser

我们遇到了包含跨度的Bootstrap增强锚点行为的跨浏览器问题。看了Bootstrap js后,我设法将问题提炼到下面的代码(这不依赖于Bootstrap):

HTML:

<a href="http://doc.jsfiddle.net">
    <span>Glyph</span> Download
</a>

JS:

$(document).ready(function () {
    $(document).on('click', 'a', function () {
        var $anchor = $(this)
        $anchor['html']('Downloading');        
    });
});

http://jsfiddle.net/VV767/1/

在IE 10中单击span(带有文本“Glyph”),将禁止链接到锚点URL。单击锚点内的任何其他位置(即文本“下载”)并激活链接(所需行为)。在Chrome 32中,单击锚点中的任意位置(span内外)和锚点URL均已正确激活。我没有测试过Firefox。

js代码(简化自Bootstrap的button.js代码)在单击时将锚内容切换为“下载”文本。 (这是使用Bootstrap的实际示例:http://jsfiddle.net/M4DuJ/10/。单击IE 10中的字形不会激活链接。)

问题似乎源于事件目标span在被文本“下载”替换时从DOM中删除的事实(在button.js中存储原始html锚点内容使用jquery data() api,以便稍后重置它。)

我的问题是,这是否是一个已知的问题/怪癖,是否有一个更优雅/简化的解决方案,我提供的?

2 个答案:

答案 0 :(得分:0)

目前我们有这个解决方法:

$(document).on('click', 'a > span', function (event) {
    event.preventDefault();
    event.stopPropagation();

    var $anchor = $(this).parent();
    var e = document.createEvent('MouseEvents');
    e.initEvent('click', true, true);
    $anchor[0].dispatchEvent(e);
});

即截取span上的点击,阻止事件传播,然后调用父锚点击。这适用于Chrome 32和IE 10。

http://jsfiddle.net/87KXy/

答案 1 :(得分:0)

好吧,如果你正在寻找一种不那么不优雅的解决方法(是否可能存在于旁观者眼中),我会选择这样的事情:

$(document).ready(function () {
    $(document).on('click', 'a', function (e) {
        e.preventDefault();
        var $anchor = $(this);
        $anchor['html']('Downloading');
        window.location.href = $anchor.attr('href');
    });
});

http://jsfiddle.net/VV767/3/

这是一种更直接的导航到链接目标的方式,并且可以帮助您创建和调度事件......

警告:只有当链接的目标是同一窗口时,这才会起作用。在框架环境中,可以通过首先读取链接目标属性来修改另一个框架的位置;但是,如果目标是_blank,则可能涉及打开一个新窗口,弹出窗口拦截器可能会阻止该窗口。