在 Firefox 中单击 HTML5 视频控件时如何防止事件冒泡

Posted

技术标签:

【中文标题】在 Firefox 中单击 HTML5 视频控件时如何防止事件冒泡【英文标题】:How to prevent event bubbling when clicking on HTML5 video controls in Firefox 【发布时间】:2014-09-14 23:43:57 【问题描述】:

在 Firefox 中,当视频标记包含在 a 标记中时,在单击视频暂停时使用标准视频控件也会重定向。我怎样才能让它像其他浏览器一样运行,例如点击暂停只会暂停视频,也不会重定向。这就是我需要的。

这是一个简单的演示:http://jsfiddle.net/me2loveit2/cSTGM/

<a href="http://www.google.com" target="_blank">
    <video controls="" muted="" preload="auto" id="testid" >
        <source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4"/>
        <source src="http://www.w3schools.com/html/mov_bbb.ogg" type="video/ogg"/>
        <source src="http://www.w3schools.com/html/mov_bbb.webm" type="video/webm"/>
        <img src="http://dummyimage.com/1044x585/000/fff"/>
    </video>
</a>

【问题讨论】:

【参考方案1】:

你得到的标记是无效的,HTML5 spec 明确指出

a 元素可以围绕整个段落、列表、表格等,甚至整个部分,只要其中没有交互内容(例如按钮或其他链接)。 em>

视频导航实际上是包含按钮的交互式内容。

由于某种原因,在 Chrome 中单击控件不会触发锚点,而在 Firefox 中会触发。 这取决于浏览器如何使用 Shadow DOM 构造控件,并且由于标记是无效的并且对此没有真正的标准,这是任何人的猜测。

你应该做的是删除锚点并在点击视频时使用javascript重定向,像这样

$('#testid').on('click', function() 
    var win = window.open('http://www.google.com', '_blank');
    win.focus();
);

这会给你有效的标记,因为你可以删除包装锚,但它也不能解决单击控件时不重定向的问题,它完全相同,因为控件仍在视频中并且在 Firefox 中触发点击处理程序,但在 Chrome 中不触发。

在 webkit 中,这些控件可能以某种方式被 -webkit-media-controls 伪类作为目标,但是 Firefox 似乎没有任何此类伪类,所以这也不起作用。

您所剩下的是依赖于控件似乎始终位于底部的事实,并且它们大约 30 像素高,因此您可以将锚点覆盖在视频顶部并省略一点底部的一部分。 这适用于所有浏览器,并且您将拥有有效的标记。

<video controls="" muted="" autoplay preload="auto" id="testid" >
    <!-- stuff -->
</video>
<a href="http://www.google.com" class="overlay" target="_blank"></a>

为确保锚点放置正确并具有正确的大小,可以使用一点 javascript

$('.overlay').each(function() 
    var vid = $(this).prev('video');
    $(this).css(
        position : 'fixed',
        top      : vid.offset().top + 'px',
        left     : vid.offset().left + 'px',
        width    : vid.width() + 'px',
        height   : (vid.height() - 30) + 'px',
    );
);

FIDDLE

【讨论】:

感谢 adeneo。如果我希望正确完成覆盖,似乎没有办法绕过覆盖......和自定义控件,因为它们在悬停在覆盖上时不会淡入。此外,有时控件可能具有圆形边缘,因此为了使其完美,我必须制作自定义控件并将它们放在顶部。 是的,我认为这是要走的路,我也在考虑启动一些自定义控件并将悬停事件附加到叠加层,但认为答案有点过分,据我所知,覆盖基本上是答案,也是使其跨浏览器工作的唯一方法。谢谢采纳!【参考方案2】:

考虑到视频事件(playpause 等)在之后触发

,除了使用自定义控件之外,我不确定是否有可能以真正优雅的方式绕过控件行为em> 点击事件。这是一个硬编码默认控件的近似高度的解决方案。我不喜欢硬编码,但在其他方面我认为还可以。它适用于所有avideo 元素,并且不会对元素进行任何过度迭代。 setTimeout 位是 event.preventDefault() 杀死链接行为和播放/暂停行为的解决方法。
$(document).on('click', 'a', function(event) 
    var video = $('video:hover').first();
    if (video.length && video.offset().top + video.height() - event.pageY < 35) 
        var anchor = $(this);
        var href = anchor.attr('href');
        var target = anchor.attr('target');
        anchor.attr('href', 'javascript:;');
        anchor.attr('target', null);
        setTimeout(function() 
            anchor.attr('href', href);
            anchor.attr('target', target);
        , 1);
    
);

【讨论】:

【参考方案3】:

您可以通过为您的视频创建自定义控件并仅将video 标记与a 标记而不是控件包装来实现此目的。这使您可以选择跨浏览器对视频进行一致的外观控制,但您必须对 CSS 有很好的理解才能使其在浏览器中看起来良好且一致。我已经包含了您想要的 CodePen 项目,以及一些自定义控件。这些控件在浏览器中看起来不太好,但我认为您可以理解。

http://codepen.io/anon/pen/dtHsb

【讨论】:

【参考方案4】:

非常难看,但通常的解决方案不起作用,因为 event.stropPropagation() 仅适用于事件处理程序,而 event.preventDefault() 会破坏控件。

http://jsfiddle.net/cSTGM/28/

$('#testid').click(function() 
    link = $(this).parent();
    originalHref = link.attr('href');
    originalTarget = link.attr('target');
    link.attr('href', 'javascript:void(0)');
    link.attr('target', '_self');
    setTimeout(function() 
        link.attr('href', originalHref);
        link.attr('target', originalTarget);        
    , 0);
);

【讨论】:

很好的解决方法,但现在 a 标签完全没用了,我一开始就可以把它去掉。所以当我点击视频而不是控件时,我仍然需要它来重定向我。 是的,抱歉,我无法在 Chrome 上进行测试,所以我无法理解要求。我会尝试自定义控件,因为它们似乎不允许使用默认值编写脚本。【参考方案5】:

如果是VIDEO标签,我们只需要防止重定向

$('#testid').click(function() 
    if (event.target.tagName !=== 'VIDEO') 
        //redirect
    
);

【讨论】:

请详细说明您的代码。仅代码答案很少有帮助。

以上是关于在 Firefox 中单击 HTML5 视频控件时如何防止事件冒泡的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 视频无法在 Firefox 中播放

在 HTML5 视频上全屏显示时,自定义控件仍然适用吗?

HTML5 视频播放/暂停控件仅在 Safari 浏览器中不起作用

HTML5:在带有控件的视频上放置画布

html5 视频中的单独播放/暂停按钮

Firefox 冻结的 HTML5 视频不会降级为 Flash