1

For context, I am writing a plugin for omniture (adobe) sitecatalyst for video tracking. Before I write the plugin in the sitecatalyst format, I want to confirm it is working. I have tested the same code but using jQuery, and it works fine with how jQuery handles variables/scope. But doing it with Javascript directly is proving to be a little more difficult. Here is where I am at:

var vsa = new Array();
var vp = new Array(); 
vsa = document.getElementsByTagName('video');
if(vsa.length>0){
for(var vvv=0;vvv<vsa.length;vvv++) {
    vsa[vvv].addEventListener('seeked',function () { if(vp[vsa[vvv].id]) { s.Media.play(vsa[vvv].id,vsa[vvv].currentTime); }},false);
    vsa[vvv].addEventListener('seeking',function () { if(vp[vsa[vvv].id]) { s.Media.play(vsa[vvv].id,vsa[vvv].currentTime); }},false);
    vsa[vvv].addEventListener('play',function () { 
        if(!vp[vsa[vvv].id]) { 
            vp[vsa[vvv].id] = true; 
            s.Media.open(vsa[vvv].id,vsa[vvv].duration,s.Media.playerName);
            s.Media.play(vsa[vvv].id,vsa[vvv].currentTime); 
        } else {
            s.Media.play(vsa[vvv].id,vsa[vvv].currentTime);
        }},false);
    vsa[vvv].addEventListener('pause',function () { if(vp[vsa[vvv].id]) { s.Media.stop(vsa[vvv].id,vsa[vvv].currentTime); }},false);
    vsa[vvv].addEventListener('ended',function () { vp[vsa[vvv].id] = false; s.Media.stop(vsa[vvv].id,vsa[vvv].currentTime); s.Media.close(vsa[vvv].id); },false);

    if (typeof vsa[vvv].error != 'undefined' && vsa[vvv].error) {
        var scvt_msg = 'Error Not Captured';
        if(typeof vsa[vvv].error.code != 'undefined') {
            switch (vsa[vvv].error.code) {
                case MEDIA_ERR_ABORTED:
                    scvt_msg = 'vsa[vvv]eo stopped before load.';
                    break;
                case MEDIA_ERR_NETWORK:
                    scvt_msg = 'Network error';
                    break;
                case MEDIA_ERR_DECODE:
                    scvt_msg = 'vsa[vvv]eo is broken';
                    break;  
                case MEDIA_ERR_SRC_NOT_SUPPORTED:
                    scvt_msg = 'Codec is unsupported by this browser';
                    break;
            }
        }
        s.tl(this,'o','video: ' + scvt_msg);
    }

}
}

On load, there is no error (meaning the eventlisteners are attaching correctly). When I press play on the video, I get a "vsa[vvv] is undefined". on the line of code that starts with

if(!vp[vsa[vvv].id]) 

Any ideas how to get the "global" vars of vsa, vp, and s accessible from the event listener function?

Thank you!

1
  • BTW, use array literal notation [] instead of new Array. It is prettier and has less evil corner cases. Commented May 2, 2012 at 5:00

1 Answer 1

3

The variables are accessible. The problem is that you fell into the (very common) closures inside for loops trap.

Basically, all the event listeners are sharing the same vvv variable. By the time the event listeners run, vvv has gone through all the loop and is set to vsa.length, making vsa[vvv] undefined. (Check this out by adding a console.log(vvv) call to your event listeners)

The usual fix for this is creating the event listeners in a function outside the loop, to make each event listener get its own reference to a videotag variable.

function addMyEvents(node){
    //the inner functions here get their own separate version of "node"
    // instead of sharing the vvv
    node.addEventListener('seeked',function () { if(vp[node.id]) { s.Media.play(node.id, node.currentTime); }},false);
    node.addEventListener('seeking',function () { if(vp[node.id]) { s.Media.play(node.id, node.currentTime); }},false);
    //...
}

for(var vvv=0;vvv<vsa.length;vvv++) {
    addMyEvents(vsa[vvv]);
}

By the way, you don't need the if(vsa.length) test in the beginning since the loop wont run if the length is zero anyway...


To aboid this error in the future, run your code through a linter like JSHint or JSLint. They give warnings if you create functions inside a for loop.

Sign up to request clarification or add additional context in comments.

2 Comments

@missingno Thank you. This worked perfectly (as I'm sure you already knew). I appreciate your time to reply. Thank you.
@Domenic :) Totally agree. the way the plugins end up getting written ends up requiring as much "short hand" as possible. But in principle, I totally agree with you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.