0

I am trying to create a slide show where I load the next slide before the current one is done. I have two prototypes for this. One for showing the current slide and then one for loading the next slide.

It worked fine until I put a setTimeout() for a delay between the slides. The NextSlide() function is calling itself after the setTimeout() however then the this.nextSlide is undefined even if it's loaded and added to this.nextSlide successfully in LoadNextSlide().

$(document).ready(function(){
    //Set width and height of canvas
    var width = $(document).width();
    var height = $(document).height();
    $("#MKslide").css({"width":width+"px","height":height+"px"});


    slideShow = new SlideShow(width, height, "2d");
    slideShow.LoadNextSlide(null);
    slideShow.NextSlide();
});

function SlideShow(canvasWidth, canvasHeight, dimension){
    //Creating the slideshow
}

SlideShow.prototype.LoadNextSlide = function(currentSlideNumber){

    var data = $.parseJSON($.ajax({
        type: "POST",
        url: "/cms/php/request.php",
        dataType: "json",
        data: {slideNumber : currentSlideNumber},
        async: false
    }).responseText);
    this.nextSlide = data;
    alert(this.nextSlide.id);
}

SlideShow.prototype.NextSlide = function(){
    alert(this.nextSlide.id);
    this.currentSlide = this.nextSlide; //Swap to next slide.
    if(beginsWithHTTP(this.currentSlide.data)){
        this.image.src = this.currentSlide.data;
    }
    else{
        this.image.src = "http://" + this.currentSlide.data; //Set the current slide.
    }
    this.LoadNextSlide(this.currentSlide.id); //Preload next slide
    window.setTimeout(this.NextSlide,this.currentSlide.duration * 1000);//wait x seconds before swapping
}
Olof
  • 776
  • 2
  • 14
  • 33

2 Answers2

3

Add bind(this) as follows:

window.setTimeout(this.NextSlide.bind(this),this.currentSlide.duration * 1000);

setTimeout schedules the function to execute later, and at that time the context in which it is executed will always be the global object (window), instead of your object. And this context is what this refers to. The bind method creates a new reference to your method that will override this behaviour and will always run with this set to what you pass to bind, independent of the context that it was called from.

An alternative, but less elegant solution is to pass setTimeout an anonymous function in which the method is called explicitly from your object's context:

var that = this; // keep a reference to your object
window.setTimeout(function () {
    that.NextSlide(); // use the reference to your object
}, this.currentSlide.duration * 1000);
trincot
  • 317,000
  • 35
  • 244
  • 286
0

You can use .bind or asign self=this and call a function anonymous with self.nextslide it is about scopes. Also you can use underscore bind as it would act as polyfill too.

juan garcia
  • 1,326
  • 2
  • 23
  • 56