从 jquery 中的动态内容捕获所有音频结束事件

Catching all audio end events from dynamic content in jquery

我见过类似的问题 - 但不能解决我的问题!

我的页面上有音频,当一个结束时,我想开始下一个,但我什至无法触发结束...

我把代码缩减为:

function DaisyChainAudio() {
    $().on('ended', 'audio','' ,function () {
        alert('done');
    });
}

这是从我的 page/code 调用的(并执行,设置断点显示)。

据我所知,这应该在文档级别设置处理程序,因此来自任何 'audio' 标记(即使是动态添加)的任何 'ended' 事件都应该被捕获并向我显示警报...

但它永远不会触发。

编辑

从 Çağatay Gürtürk 的建议中借用了一些东西,到目前为止有了这个...

function DaisyChainAudio() {
        $(function () {
        $('audio').on('ended', function (e) {
            $(e.target).load();
            var next = $(e.target).nextAll('audio');
            if (!next.length) next = $(e.target).parent().nextAll().find('audio');
            if (!next.length) next = $(e.target).parent().parent().nextAll().find('audio');
            if (next.length) $(next[0]).trigger('play');
        });
    });
}

我仍然想在文档级别设置它,这样我就不必担心在添加动态元素时添加它...

试试这个:

$('audio').on('ended', function (e) {
        alert('done');
        var endedTag=e.target; //this gives the ended audio, so you can find the next one and play it.
});

请注意,当您动态创建新音频时,您应该分配事件。一个快速而肮脏的解决方案是:

function bindEvents(){
$('audio').off('ended').on('ended', function (e) {
            alert('done');
            var endedTag=e.target; //this gives the ended audio, so you can find the next one and play it.
    });
}

和 运行 bindEvents 每当你 create/delete 一个音频元素时。

它不触发的原因是,媒体事件(那些特别属于 audiovideo 的媒体事件,例如 playpausetimeupdate 等)不要起泡。您可以在 this question 的答案中找到对此的解释。

所以使用他们的解决方案,我捕获了 ended 事件,这将允许为动态添加的音频元素设置触发器。

$.createEventCapturing(['ended']);  // add all the triggers for which you like to catch.
$('body').on('ended', 'audio', onEnded); // now this would work.

JSFiddle demo

事件捕获代码(取自另一个SO答案):

    $.createEventCapturing = (function () {
        var special = $.event.special;
        return function (names) {
            if (!document.addEventListener) {
                return;
            }
            if (typeof names == 'string') {
                names = [names];
            }
            $.each(names, function (i, name) {
                var handler = function (e) {
                    e = $.event.fix(e);

                    return $.event.dispatch.call(this, e);
                };
                special[name] = special[name] || {};
                if (special[name].setup || special[name].teardown) {
                    return;
                }
                $.extend(special[name], {
                    setup: function () {
                        this.addEventListener(name, handler, true);
                    },
                    teardown: function () {
                        this.removeEventListener(name, handler, true);
                    }
                });
            });
        };
    })();