2

So I am trying to setup a timer to hide some overlays at work. This is a super basic timer, but the timer never starts or runs....I am not really sure what am I missing here. http://jsfiddle.net/deadlychambers/sEn7X/

JavaScript

$(document).ready(function () {
  CreateFrameTimer("timey", 30);
});
var FrameTimer;
var FrameTimerTotalSeconds;
var FrameTimerOn = false;

function CreateFrameTimer(TimerId, Time) {
    FrameTimerOn = true;
    FrameTimer = document.getElementById(TimerId);
    FrameTimerTotalSeconds = Time;
    UpdateFrameTimer();
    window.setTimeout("TickTock();", 1000);
}
function TickTock() {
    FrameTimerTotalSeconds -= 1;
    UpdateFrameTimer();
    if (FrameTimerTotalSeconds <= 0 || FrameTimerOn == false)
    {
        this.HideFrameOverlays();
        return;
    }
    window.setTimeout("TickTock();", 1000);
}
function UpdateFrameTimer(){
  $("#me").html(FrameTimerTotalSeconds);
}

HTML

<div id="me"></div>
RobG
  • 142,382
  • 31
  • 172
  • 209
DeadlyChambers
  • 5,217
  • 4
  • 44
  • 61
  • start with replacing "TickTock();" with TickTock, and you should be able to add a count variable inside of TickTock to track how's the function get executed – Yang Apr 10 '14 at 00:19
  • 1
    What are you trying to do with `this.HideFrameOverlays()` because `this` will be set to the `window` object or `undefined` (in strict mode). – jfriend00 Apr 10 '14 at 00:19
  • 1
    Also, isn't your **id** `timey` supposed to match with the **id** in your HTML (currently `me`)? – Sunny Patel Apr 10 '14 at 00:54
  • 2
    Here's a much cleaned up version that only used one global symbol: http://jsfiddle.net/jfriend00/HXd5s/. – jfriend00 Apr 10 '14 at 00:57

2 Answers2

1

window.setTimeout(TickTock, 1000); is the correct line. See Updated JSFiddle.

The JSFiddle also changes to Javascript loading to onDomReady which allows the Javascript pane to function on a global level. There's a similar SO answer which helps decipher the reason for changing that first parameter from a string to the function reference.

Community
  • 1
  • 1
Sunny Patel
  • 7,830
  • 2
  • 31
  • 46
  • 1
    Issue caused by the jsFiddle set to onload which makes your functions not be global. – jfriend00 Apr 10 '14 at 00:19
  • 2
    Sure, I fixed that already, but that alone didn't solve the root problem. If he implemented my answer on its own page, there would be no issues. – Sunny Patel Apr 10 '14 at 00:21
  • "correct" by what criterion? While passing a function reference is preferred for various reasons, `setTimeout(TickTock,1000)` and `setTimeout('TickTock()',1000)` will have identical results. – RobG Apr 10 '14 at 00:51
  • This is a cargo-cult sort of answer. It explains nothing. It just says, "I dunno why, but when I do this some things work." – Wayne Apr 10 '14 at 01:03
  • Well, @RobG, not identical in this case. See my answer. – Wayne Apr 10 '14 at 01:06
  • @lwburk—then that is an issue with JSFIDDLE, and perhaps the question should be tagged as such (done). It has nothing to do with JavaScript *per se*. The poster of this answer should update it to answer the OPs question. – RobG Apr 10 '14 at 01:11
  • I see what you're saying, but it *does* have to do with JavaScript *per se*. It is still the case that eval'ing a string in global context is not identical to executing a function based on a reference to it. In this case, the difference is highlighted by jsfiddle's wrapping of the code, but you could demonstrate the same thing anywhere. – Wayne Apr 10 '14 at 01:15
1

There are two separate things to understand here. First, when you pass a string to setTimeout that code is simply executed in the global context. When you pass it a reference to a function, then that specific function is executed in the global context.

Second, jsfiddle allows you to choose whether your code is wrapped in another function, which determines whether your variables and functions are global.

Therefore:

  • As your code is written, the fiddle is trying to execute a global function called TickTock but no such function exists (because you've instructed jsfiddle to wrap your code in another function and JavaScript variables are scoped to their nearest containing function). So, passing a reference to the particular function you want to execute works.

  • On the other hand, you can also fix your problem by selecting one of the "no wrap" jsfiddle options, which makes your functions global and as a side-effect causes the code you pass to setTimeout to succeed.

Fixing the issue is one thing, but it's better to understand why it's happening.

Wayne
  • 59,728
  • 15
  • 131
  • 126