import "../core/document"; import "../core/vendor"; var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, // is an interval (or frame) active? d3_timer_timeout; // is a timeout active? // The timer will continue to fire until callback returns true. d3.timer = function(callback, delay, then) { if (arguments.length < 3) { if (arguments.length < 2) delay = 0; else if (!isFinite(delay)) return; then = Date.now(); } var time = then + delay; // Add the callback to the tail of the queue. var timer = {callback: callback, time: time, next: null}; if (d3_timer_queueTail) d3_timer_queueTail.next = timer; else d3_timer_queueHead = timer; d3_timer_queueTail = timer; // Start animatin'! if (!d3_timer_interval) { d3_timer_timeout = clearTimeout(d3_timer_timeout); d3_timer_interval = 1; d3_timer_frame(d3_timer_step); } }; function d3_timer_step() { var now = d3_timer_mark(), delay = d3_timer_sweep() - now; if (delay > 24) { if (isFinite(delay)) { clearTimeout(d3_timer_timeout); d3_timer_timeout = setTimeout(d3_timer_step, delay); } d3_timer_interval = 0; } else { d3_timer_interval = 1; d3_timer_frame(d3_timer_step); } } d3.timer.flush = function() { d3_timer_mark(); d3_timer_sweep(); }; function d3_timer_mark() { var now = Date.now(), timer = d3_timer_queueHead; while (timer) { if (now >= timer.time) timer.flush = timer.callback(now - timer.time); timer = timer.next; } return now; } // Flush after callbacks to avoid concurrent queue modification. // Returns the time of the earliest active timer, post-sweep. function d3_timer_sweep() { var t0, t1 = d3_timer_queueHead, time = Infinity; while (t1) { if (t1.flush) { t1 = t0 ? t0.next = t1.next : d3_timer_queueHead = t1.next; } else { if (t1.time < time) time = t1.time; t1 = (t0 = t1).next; } } d3_timer_queueTail = t0; return time; } var d3_timer_frame = d3_window[d3_vendorSymbol(d3_window, "requestAnimationFrame")] || function(callback) { setTimeout(callback, 17); };