Loren Wolsiffer
Loren Wolsiffer

Reputation: 167

JavaScript setTimeout will not die.

I made a photogallery and is AJAX powered. Below are the relevant pieces of code.

    if (isset($_POST['stopss'])){
    echo'<script type="text/javascript">
    clearTimeout(setss);
    </script>';
    }

    if (isset($_POST['startss'])){
    ?>
    <script type="text/javascript">
    var setss = window.setTimeout('delayer(\''+src+'\',\''+dir+'\',\''+title+'\',\''+width+'\',\''+height+'\',\''+img+'\')',5000);
    </script>
    <?
    }

The delayer function passes params for a new modal box window (new AJAX request). The problem as I see it. The timeout gets started when a user clicks the Slideshow button. Even though they press the Stop Slideshow button (this reloads the AJAX page), the timer is still running (in the background) and in clearTimeout(setss), setss is no longer available (because of the new AJAX page request) so the clearTimeout fails to clear.

Is there any way to kill the timeout running in the background? Even if the modalbox window is closed, 5 seconds later it opens and happily keeps playing the slide show.

btw, this is the modalbox call. Modalbox.show('../b-gal-scripts/ajaxgal.php', {title: title, overlayOpacity: .1, width: width, height: height, method: 'post', params: {src: next, dir: dir, img: img, ssimg: next} }); return false;

Upvotes: 0

Views: 1220

Answers (2)

Paul Butcher
Paul Butcher

Reputation: 6956

I'm having a little difficulty understanding your problem, but I hope this helps.

  1. When a page is reloaded, the previous instance of the page, and any state associated with it ceases to exist. As a result, the timeout has been stopped. Essentially, if the global setSS doesn't exist, then neither does the timeout to which it refers, therefore, that timeout cannot be responsible for starting the slideshow.

  2. When an active page is served from something like PHP, the work of the server (WRT the creation of any content of the page) is done. No more content can subsequently be written to the page. Your clearTimeout is essentially useless, as it could only clear a timeout that is set during the load of the page. It won't write a new script element into the existing page.

  3. Variables are not shared across pages, so if you are setting the timeout in one page, and clearing it in another, that will not work.

So, in order to clear the timeout, you need to call clearTimeout in the same page (and instance of that page) as the setTimeout, and that call must be executed after the setTimeout.

If none of the above apply to your situation, then is it possible that $_POST['startss'] and $_POST['stopss'] are set in the same request? If so, the new page will create a new timeout after the attempt to clear it, and will therefore display the slideshow.

(as an aside, using a closure to create a function to pass to setTimeout will be more readable than compiling a string that calls a function).

Upvotes: 1

Tadeck
Tadeck

Reputation: 137440

The problem

When you reload the page, the old JavaScript code (for the previous request) stops running and the new one is executed.

The problem is that you first call clearTimeout(setss) and later define what setss really is.

A couple additional problems

A few tips:

  1. Do not mix quoting styles, you are creating a mess this way.
  2. If you want quotes within quotes, just use the fact there are different quotes like that:

    var setss = window.setTimeout("delayer('"+src+'","'+dir+'","'+title+'","'+width+'","'+height+'","'+img+'")',5000);
    
  3. ...and preferably get used to event-based programming and closures when coding JavaScript, like that:

    var sets = window.setTimeout(function(){
        delayer(src, dir, title, width, height, img);
    }, 5000);
    

Final version of your code

Your code should look like the following:

if (isset($_POST['startss']) && !isset($_POST['stopss'])){
    ?>
    <script type="text/javascript">
        var setss = window.setTimeout(function(){
            delayer(src, dir, title, width, height, img);
        }, 5000);
    </script>
    <?
}

It makes use of the fact, that you do not need to first output a script that is executed only to immediately stop it if not needed. Just make PHP condition to check if you want it to be executed, the output it.

Second, the JS has been changed from using strings (which is totally messy) to using anonymous functions. Take a closer look into that.

Did it help?

Upvotes: 2

Related Questions