Iterating over cue method with popcorn.js

I am trying to establish a few key points in a video. Instead of writing each entry, I would like to iterate over an object that has the data I need, such as the cue time and some information about what to do with the callback.

The problem is that when I try to iterate over the object, it overwrites all replicas except the last one.

var products = myVideo.products;
var video = Popcorn('#mainVideo');

    for (product in products){
        var obj   = products[product],
            start = obj.start,
            img   = obj.image,
            $targetDiv  = $("#"+obj.targetDiv);

        video.cue( start, function(){
            $('<img>', {
            class : "isImage",
            src : 'images/' + img
            }).prependTo( $targetDiv );
        })

    }

      

Any help would be greatly appreciated.

+3


source to share


1 answer


In this code, each function has its own callback function, but each function refers to the same variable img

and to the same $targetDiv

. By the time they run, these variables will be set to their respective values ​​for the last item in products

.

If you've ever run your code through jslint and saw a warning, don't do functions in a loop, that's why.A good way to do what you are trying to do is to put these variables inside a function that gets called immediately and returns another function that is your callback. Like this:

function makeCallback(obj) {
    return function() {
        $('<img>', {
        class : "isImage",
        src : 'images/' + obj.img
        }).prependTo( $("#"+obj.targetDiv) );
    };
}

for (var product in products) {
    var obj = products[product];
    video.cue( obj.start, makeCallback( obj ) );
}

      

Alternatively, you can use forEach , which does the same under the hood. (Popcorn provides its own version that handles both arrays and objects.)



Popcorn.forEach(products, function(obj) {
    video.cue( start, function(){
        $('<img>', {
        class : "isImage",
        src : 'images/' + obj.img
        }).prependTo( $("#"+obj.targetDiv) );
    });
});

      

I should note that you have another problem in this code, which is that Popcorn creates a new image every time you pass the cue point. So, if the user ever jumps back to play part of the video, the images will start piling up. Also, images do not start downloading until they are visible, so if there is a slow network connection, images may not display until they are too late.

The best way to deal with them is usually to create your images ahead of time, but make them invisible with CSS and then Popcorn events make them visible at the right time. You can use the image plugin which will do the most of your heavy lifting for you.

+3


source







All Articles