Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching all audio end events from dynamic content in jquery

I have seen similar questions - but not that fix my problem!

I have audio on my page and when one ends, I want the next to start, but I can't even get the ended to trigger...

I cut the code down to this:

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

This is called from my page/code (and is executed, setting a break point shows that).

As far as I understand this should set the handler at the document level, so any 'ended' events from any 'audio' tag (even if added dynamically) should be trapped and show me that alert...

But it never fires.

edit

With some borrowing from Çağatay Gürtürk's suggestion so far have this...

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');
        });
    });
}

I'd still like to set this at the document level so I don't need to worry about adding it when dynamic elements are added...

like image 427
pperrin Avatar asked Apr 19 '15 09:04

pperrin


1 Answers

The reason it does not fire is, media events( those specifically belonging to audio or video like play, pause, timeupdate, etc) do not get bubbled. you can find the explanation for that in the answer to this question.

So using their solution, I captured the ended event, and this would allow setting triggers for dynamically added audio elements.

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

JSFiddle demo

the code for event capturing( taken from the other SO answer):

    $.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);
                    }
                });
            });
        };
    })();
like image 76
mido Avatar answered Sep 29 '22 14:09

mido