1 // Mock setTimeout, clearTimeout
  2 // Contributed by Pivotal Computer Systems, www.pivotalsf.com
  3 
  4 var Clock = {
  5     timeoutsMade: 0,
  6     scheduledFunctions: {},
  7     nowMillis: 0,
  8     reset: function() {
  9         this.scheduledFunctions = {};
 10         this.nowMillis = 0;
 11         this.timeoutsMade = 0;
 12     },
 13     tick: function(millis) {
 14         var oldMillis = this.nowMillis;
 15         var newMillis = oldMillis + millis;
 16         this.runFunctionsWithinRange(oldMillis, newMillis);
 17         this.nowMillis = newMillis;
 18     },
 19     runFunctionsWithinRange: function(oldMillis, nowMillis) {
 20         var scheduledFunc;
 21         var funcsToRun = [];
 22         for (var timeoutKey in this.scheduledFunctions) {
 23             scheduledFunc = this.scheduledFunctions[timeoutKey];
 24             if (scheduledFunc != undefined &&
 25                 scheduledFunc.runAtMillis >= oldMillis &&
 26                 scheduledFunc.runAtMillis <= nowMillis) {
 27                 funcsToRun.push(scheduledFunc);
 28                 this.scheduledFunctions[timeoutKey] = undefined;
 29             }
 30         }
 31 
 32         if (funcsToRun.length > 0) {
 33             funcsToRun.sort(function(a, b) {
 34                 return a.runAtMillis - b.runAtMillis;
 35             });
 36             for (var i = 0; i < funcsToRun.length; ++i) {
 37                 try {
 38                     this.nowMillis = funcsToRun[i].runAtMillis;
 39                     funcsToRun[i].funcToCall();
 40                     if (funcsToRun[i].recurring) {
 41                         Clock.scheduleFunction(funcsToRun[i].timeoutKey,
 42                                 funcsToRun[i].funcToCall,
 43                                 funcsToRun[i].millis,
 44                                 true);
 45                     }
 46                 } catch(e) {
 47                 }
 48             }
 49             this.runFunctionsWithinRange(oldMillis, nowMillis);
 50         }
 51     },
 52     scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
 53         Clock.scheduledFunctions[timeoutKey] = {
 54             runAtMillis: Clock.nowMillis + millis,
 55             funcToCall: funcToCall,
 56             recurring: recurring,
 57             timeoutKey: timeoutKey,
 58             millis: millis
 59         };
 60     }
 61 };
 62 
 63 function setTimeout(funcToCall, millis) {
 64     Clock.timeoutsMade = Clock.timeoutsMade + 1;
 65     Clock.scheduleFunction(Clock.timeoutsMade, funcToCall, millis, false);
 66     return Clock.timeoutsMade;
 67 }
 68 
 69 function setInterval(funcToCall, millis) {
 70     Clock.timeoutsMade = Clock.timeoutsMade + 1;
 71     Clock.scheduleFunction(Clock.timeoutsMade, funcToCall, millis, true);
 72     return Clock.timeoutsMade;
 73 }
 74 
 75 function clearTimeout(timeoutKey) {
 76     Clock.scheduledFunctions[timeoutKey] = undefined;
 77 }
 78 
 79 function clearInterval(timeoutKey) {
 80     Clock.scheduledFunctions[timeoutKey] = undefined;
 81 }
 82