1

What I want to happen is when the ".slick-next" button is clicked, the browser waits 3 seconds, and then runs the loadPHP() function. Below is my code, which seems like it theoretically should work, but doesn't. What happens is that the setTimeout function runs once when the page loads, but after that clicking the next button doesn't do anything.

var timeout = null;

$(".slick-next").click(nextButton(timeout));

var nextButton = (function(timeout) {
    window.clearTimeout(timeout);
    timeout = setTimeout(function() {
        loadPHP();  
    }, 3000);
});

I tried wrapping the whole jQuery expression in a setTimeout, but that doesn't work either. What happens is that you can't click the button for 3 seconds, but then can click it endlessly.

setTimeout(function() {
    $(".slick-next").click(nextButton(timeout));
}, 3000));

Why is this behavior happening?

Cœur
  • 37,241
  • 25
  • 195
  • 267
  • `click` expects a function, not `undefined`, which is what `nextButton` returns. You probably want `.click(nextButton)`, and note also that there is no pass-by-reference in JS. – elclanrs Jan 11 '15 at 03:18
  • @elclanrs Can you expand on this? –  Jan 11 '15 at 03:27
  • http://jsfiddle.net/0y1gzf94/ –  Jan 11 '15 at 03:42
  • @elclanrs, "... no pass-by-reference in JS" - since when? Read the top answer [here](http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language). – Roamer-1888 Jan 11 '15 at 03:46

4 Answers4

1

That's because you're already invoking the function while doing .click(nextButton(timeout)) and thus starting the timer.

Instead, pass a reference:

var timeout = null;
var clickCount = 0;

var loadPHP = function() {
  $('#output').text(clickCount + ': Loading from server ...');
};

var nextButton = function() {
  clickCount++;
  window.clearTimeout(timeout);
  timeout = setTimeout(loadPHP, 3000);
  $('#output').text('Timeout ' + timeout + ' set. Waiting 3s.');
};

$(".slick-next").click(nextButton);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="slick-next">Run</button>
<div id="output"></div>

... or use function.prototype.bind as suggested in one of the comments but it's not really required for what's desired here and it is a ECMA script 5.1 feature, thus not available in older JavaScript browser implementations.

Also of note: When assigning function expressions to variables, this must be done before the variable is used; otherwise one is passing an undefined value. To avoid this need, use declaration hoisting.

Community
  • 1
  • 1
Rainer Rillke
  • 1,281
  • 12
  • 24
  • A little bit of an off-topic question, but how did you include that "run code snippet" in your answer? –  Jan 11 '15 at 03:32
  • There is a [blog post](http://blog.stackoverflow.com/2014/09/introducing-runnable-javascript-css-and-html-code-snippets/) about that. Comments are for discussing the answer so your question is perfectly fine :) @featherlight53 Don't forget to mark an answer as accepted. – Rainer Rillke Jan 11 '15 at 03:34
0

You want to attach nextButton as a click handler, not execute it immediately.

You could write :

$(".slick-next").click(nextButton);

except for the need to pass an argument. That's what .bind() is for :

$(".slick-next").click(nextButton.bind(null, timeout));

Also, the setTimeout expression will simplify :

timeout = setTimeout(loadPHP, 3000);
Roamer-1888
  • 19,138
  • 5
  • 33
  • 44
  • This has gotten me the furthest. Now it doesn't load automatically, and clicking the button runs the loadPHP() function once. But I can only run it once, and clicking the button doesn't run the function again.. –  Jan 11 '15 at 03:45
  • It sounds like a side-effect of `loadPHP` destroys something that the process depends on. Does `.slick-next` get replaced for example? – Roamer-1888 Jan 11 '15 at 03:51
  • You're right it was messing something up. Though some of the other answers would have worked, this worked best for what I'm doing. –  Jan 12 '15 at 03:48
0

What I want to happen is when the ".slick-next" button is clicked, the browser waits 3 seconds and then runs the loadPHP() function

We could do this easily by setting a function as event handler bound to event click:

$(".slick-next").on("click",function(){
    setTimeout(function() {
        loadPHP();  
    }, 3000);
});

The problem with your code was that you were firing the click event by calling the click function $(".slick-next").click()

ZakiMak
  • 2,072
  • 2
  • 17
  • 26
-1

Drop the enclosing parens around the function because the expression on the right hand side is being evaluated for a value:

var nextButton = function(timeout) {
    window.clearTimeout(timeout);
    timeout = setTimeout(function() {
        loadPHP();  
    }, 3000);
};
maurice
  • 171
  • 1
  • 6
  • `var x = (function(){});` and `var x = function(){};` yields in the same result: Two times, an anonymous function is assigned to `x`. – Rainer Rillke Jan 11 '15 at 03:35