1

I wrote a script to load video with JSON requests to improve performance, but I can't get it to work correctly. The weird thing is that console.log(currentvid1) returns correct value, but the function keeps saying that currentvid1 is undefined.

I guess the trick should be in order of parts of code, but after trying moving them here and there I've got confused even more. Here is the code in the current state:

$(document).ready(function(){
    var videosArr = [];
    var vidIndex = 0;

    $.getJSON("js/videos.json", function(data) {
        $.each( data, function( key, val ) {
            videosArr.push('<iframe width="315" height="236" src="'+val+'" frameborder="0" allowfullscreen></iframe>');
        });

        var currentvid1 = videosArr[vidIndex];
        var currentvid2 = videosArr[vidIndex+1];
        var currentvid3 = videosArr[vidIndex+2];

        $('#showmorebtn').click(function(){
            if (currentvid1.length > 0 && currentvid2.length > 0 && currentvid3.length > 0){
                $('#inputvids').append(currentvid1 + currentvid2 + currentvid3);
                vidIndex += 3;
            }else if(currentvid1.length > 0 && currentvid2.length > 0 && currentvid3.length == 0){
                $('#inputvids').append(currentvid1 + currentvid2 + currentvid3);
                $('#showmorebtn').remove();
            }else if(currentvid1.length > 0 && currentvid2.length == 0){
                $('#inputvids').append(currentvid1);
                $('#showmorebtn').remove();
            }else if(currentvid1.length > 0){
                $('#inputvids').append(currentvid1);
                $('#showmorebtn').remove();
            }else if(currentvid1.length == 0){
                $('#showmorebtn').remove();
            }
        });
    });

});

Probably this code is not as close to the correct one as some of those I tried before, but anyway... I just need to figure out the logic with JSON...

PS: Also the code might look terribly long for its purpose. I need to load only next 3 or fewer videos with each click. I guess it can be written better, but I'll work on that only after I figure out why the variable returns undefined.

EDIT: By the way, the entire code is inside of $(document).ready function. I've changed the code abode accordingly.

1
  • 3
    Function scope. Commented Jan 21, 2014 at 12:06

1 Answer 1

1

The best solution is not only to break out of your function scope (the variables you define are not usable outside the function), but also to keep in mind that getJSON is asynchronous and will not return a result immediately.

My advice: attach the click-handler in the getJSON response:

EDIT: since you added you don't always have 3 videos, i simplified it for you: now it checks if the video exists and appends it if true, else it's omitted.

var videosArr = [];
var vidIndex = 0;

$.getJSON("js/videos.json", function(data) {
    $.each( data, function( key, val ) {
        videosArr.push('<iframe width="315" height="236" src="'+val+'" frameborder="0" allowfullscreen></iframe>');
    });

    var currentvid1 = videosArr[vidIndex];
    var currentvid2 = videosArr[vidIndex+1];
    var currentvid3 = videosArr[vidIndex+2];

    $('#showmorebtn').click(function(){
        if (currentvid1 && currentvid2 && currentvid3){
            $('#inputvids').append(currentvid1 + currentvid2 + currentvid3);
            vidIndex += 3;
        }else if(currentvid1 && currentvid2){
            $('#inputvids').append(currentvid1 + currentvid2);
            $('#showmorebtn').remove();
        }else if(currentvid1){
            $('#inputvids').append(currentvid1);
            $('#showmorebtn').remove();
        }else {
            $('#showmorebtn').remove();
        }
    }); 
});

An even better version of your code actually would work when you click multiple times: (globals are now function scoped, locals were removed, vidIndex updates actually make a change on the click - the old script just appends the three next videos again and again)

$.getJSON("js/videos.json", function(data) {
    var videosArr = [];
    var vidIndex = 0;

    $.each( data, function( key, val ) {
        videosArr.push('<iframe width="315" height="236" src="'+val+'" frameborder="0" allowfullscreen></iframe>');
    });

    $('#showmorebtn').click(function(){
        if (videosArr[vidIndex] && videosArr[vidIndex+1] && videosArr[vidIndex+2]){
            $('#inputvids').append(videosArr[vidIndex] + videosArr[vidIndex+1] + videosArr[vidIndex+2]);
            vidIndex += 3;
        }else if(videosArr[vidIndex] && videosArr[vidIndex+1]){
            $('#inputvids').append(videosArr[vidIndex] + videosArr[vidIndex+1]);
            $('#showmorebtn').remove();
        }else if(videosArr[vidIndex]){
            $('#inputvids').append(videosArr[vidIndex]);
            $('#showmorebtn').remove();
        }else {
            $('#showmorebtn').remove();
        }
    }); 
});
Sign up to request clarification or add additional context in comments.

5 Comments

Nota that in this case the showmorebtn will always be displayed and will not have any behavior at the beginning. You can always hide the button in the beginning and add a $('#showmorebtn').show() in order to show it after attaching the behaviour
It still returns the same "Cannot read property 'length' of undefined". By the way, the entire code is inside of $(document).ready function.
If it still returns undefined property, that would be because you go out of bounds on your array when assigning the currentvid-variables. are you sure videosArr[vidIndex+2] exists? (or haven't made a typo)
Yeah, that's probably the reason. videosArr[vidIndex+2] not always exists. That's why I made all these checks for the length, but I didn't consider that such a definition itself would cause issues. Gonna try to fix it now.
Thank you a lot for this! It works perfectly now! You are my hero!

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.