0

I'm creating video objects via jquery from an array of urls that point to mp4 files. I want to have the first video autoplay then once its finished pick up on the "ended" function and play the next video in the sequence.

 $(document).ready(function () {

            var urls = ["https://s3-us-west-1.amazonaws.com/linkto.mp4", "https://s3-us-west-1.amazonaws.com/linktoother.mp4"]
            var videos = [];

            for (var i = 0; i < urls.length; i++) {

                var path = urls[i];

                var video = $('<video></video>');
                var source = $('<source></source>');

                source.attr('src', path);
                source.appendTo(video);

                if (i === 0) {
                    video.attr('autoplay', 'true');
                }
                video.attr('id', 'video_' + i);
                video.attr('preload', 'true');
                video.attr('width', '100%');

                videos.push(video);

                video.on('ended', function () {
                    console.log('Video has ended!' + i);
//                        playNext(video);
                });

                $('#movie').append(video);

            }

I can see the movies generated and the first one plays fine. The problem is when 'ended' function the variable i == 2 because thats how many videos are in the array and the for loop increased i. I've been away from javascript for a while. I can think of workarounds like adding an index attribute to the video element or something but basically how do I get the correct index in the "ended" function.

Brian
  • 4,328
  • 13
  • 58
  • 103

1 Answers1

1

The problem here is the wrong use of a closure variable in a loop.

In your case you can create a local closure by using $.each() to iterate over the array

$(document).ready(function () {

    var urls = ["https://s3-us-west-1.amazonaws.com/linkto.mp4", "https://s3-us-west-1.amazonaws.com/linktoother.mp4"]
    var videos = [];

    $.each(urls, function (i, path) {
        var video = $('<video></video>');
        var source = $('<source></source>');

        source.attr('src', path);
        source.appendTo(video);

        if (i === 0) {
            video.attr('autoplay', 'true');
        }
        video.attr('id', 'video_' + i);
        video.attr('preload', 'true');
        video.attr('width', '100%');

        videos.push(video);

        video.on('ended', function () {
            console.log(i)
        });

        $('#movie').append(video);
    })

})

You really don't want to have the index, since all the video elements are siblings you can just find the next sibling of the currently ended video element

    video.on('ended', function () {
        console.log('Video has ended!' + $(this).index());
        var $current = $(this),
            $next = $this.next();
        console.log($next.find('source').attr('src'))
        //playNext($(this));
    });
Community
  • 1
  • 1
Arun P Johny
  • 384,651
  • 66
  • 527
  • 531