Question

I am attempting to set multiple cue points in a video. Instead of writing each cue out, I would like to iterate over an object that has the data I need, such as the time of the cue and some info about what to do with the call back.

The problem is when I try to iterate over the object it overwrites all the cues except for 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.

Was it helpful?

Solution

In this code, every cue has its own callback function, but every function refers to the same variable img and the same $targetDiv. By the time they run, those variables will be set to their respective values for the last item in products.

If you've ever run code through jslint and seen the warning, don't make functions in a loop, this is why. A good way to do what you're trying to do is to put those variables inside of a function that gets called immediately and returns another function, which 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 thing under the hood. (Popcorn provides its own version, which 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 you have Popcorn creating a new image every time you pass through the cue point. So, if the user ever skips back to replay some of the video, the images will start to pile up. Also, the images don't start loading until right when they become visible, so if there's a slow-ish network connection, the images may not show up until it's too late.

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top