Joshua Moerman
12 years ago
1 changed files with 132 additions and 0 deletions
@ -0,0 +1,132 @@ |
|||
(function (window) { |
|||
|
|||
// This library re-implements setTimeout, setInterval, clearTimeout, clearInterval for iOS6.
|
|||
// iOS6 suffers from a bug that kills timers that are created while a page is scrolling.
|
|||
// This library fixes that problem by recreating timers after scrolling finishes (with interval correction).
|
|||
// This code is free to use by anyone (MIT, blabla).
|
|||
// Author: rkorving@wizcorp.jp
|
|||
|
|||
var timeouts = {}; |
|||
var intervals = {}; |
|||
var orgSetTimeout = window.setTimeout; |
|||
var orgSetInterval = window.setInterval; |
|||
var orgClearTimeout = window.clearTimeout; |
|||
var orgClearInterval = window.clearInterval; |
|||
|
|||
|
|||
function createTimer(set, map, args) { |
|||
var id, cb = args[0], repeat = (set === orgSetInterval); |
|||
|
|||
function callback() { |
|||
if (cb) { |
|||
cb.apply(window, arguments); |
|||
|
|||
if (!repeat) { |
|||
delete map[id]; |
|||
cb = null; |
|||
} |
|||
} |
|||
} |
|||
|
|||
args[0] = callback; |
|||
|
|||
id = set.apply(window, args); |
|||
|
|||
map[id] = { args: args, created: Date.now(), cb: cb, id: id }; |
|||
|
|||
return id; |
|||
} |
|||
|
|||
|
|||
function resetTimer(set, clear, map, virtualId, correctInterval) { |
|||
var timer = map[virtualId]; |
|||
|
|||
if (!timer) { |
|||
return; |
|||
} |
|||
|
|||
var repeat = (set === orgSetInterval); |
|||
|
|||
// cleanup
|
|||
|
|||
clear(timer.id); |
|||
|
|||
// reduce the interval (arg 1 in the args array)
|
|||
|
|||
if (!repeat) { |
|||
var interval = timer.args[1]; |
|||
|
|||
var reduction = Date.now() - timer.created; |
|||
if (reduction < 0) { |
|||
reduction = 0; |
|||
} |
|||
|
|||
interval -= reduction; |
|||
if (interval < 0) { |
|||
interval = 0; |
|||
} |
|||
|
|||
timer.args[1] = interval; |
|||
} |
|||
|
|||
// recreate
|
|||
|
|||
function callback() { |
|||
if (timer.cb) { |
|||
timer.cb.apply(window, arguments); |
|||
if (!repeat) { |
|||
delete map[virtualId]; |
|||
timer.cb = null; |
|||
} |
|||
} |
|||
} |
|||
|
|||
timer.args[0] = callback; |
|||
timer.created = Date.now(); |
|||
timer.id = set.apply(window, timer.args); |
|||
} |
|||
|
|||
|
|||
window.setTimeout = function () { |
|||
return createTimer(orgSetTimeout, timeouts, arguments); |
|||
}; |
|||
|
|||
|
|||
window.setInterval = function () { |
|||
return createTimer(orgSetInterval, intervals, arguments); |
|||
}; |
|||
|
|||
window.clearTimeout = function (id) { |
|||
var timer = timeouts[id]; |
|||
|
|||
if (timer) { |
|||
delete timeouts[id]; |
|||
orgClearTimeout(timer.id); |
|||
} |
|||
}; |
|||
|
|||
window.clearInterval = function (id) { |
|||
var timer = intervals[id]; |
|||
|
|||
if (timer) { |
|||
delete intervals[id]; |
|||
orgClearInterval(timer.id); |
|||
} |
|||
}; |
|||
|
|||
window.addEventListener('scroll', function () { |
|||
// recreate the timers using adjusted intervals
|
|||
// we cannot know how long the scroll-freeze lasted, so we cannot take that into account
|
|||
|
|||
var virtualId; |
|||
|
|||
for (virtualId in timeouts) { |
|||
resetTimer(orgSetTimeout, orgClearTimeout, timeouts, virtualId); |
|||
} |
|||
|
|||
for (virtualId in intervals) { |
|||
resetTimer(orgSetInterval, orgClearInterval, intervals, virtualId); |
|||
} |
|||
}); |
|||
|
|||
}(window)); |
Reference in new issue