Skip to content

Instantly share code, notes, and snippets.

@kTmnh
Forked from ronkorving/ios6-timers.js
Last active April 27, 2022 21:24
Show Gist options
  • Star 32 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save kTmnh/3798925 to your computer and use it in GitHub Desktop.
Save kTmnh/3798925 to your computer and use it in GitHub Desktop.
iOS6 webkit timer bug workaround
(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).
// Original Author: rkorving@wizcorp.jp
var timeouts = {};
var intervals = {};
var orgSetTimeout = window.setTimeout;
var orgSetInterval = window.setInterval;
var orgClearTimeout = window.clearTimeout;
var orgClearInterval = window.clearInterval;
// To prevent errors if loaded on older IE.
if (!window.addEventListener) return false;
// This fix needs only for iOS 6.0 or 6.0.1, continue process if the version matched.
if (!navigator.userAgent.match(/OS\s6_0/)) return false;
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);
}
};
//check and add listener on the top window if loaded on frameset/iframe
var win = window;
while (win.location != win.parent.location) {
win = win.parent;
}
win.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));
@kTmnh
Copy link
Author

kTmnh commented Nov 1, 2012

All you need to work this fix is just load the file on the head with script tag.
This fix may affect other non-bug devices, though, load & append it
if (iOS6) { // check iOS6 with your custom flag
$('head').append('<script type="text/javascript" src="ios6-timers.js"></script>');
}

I have checked this bug on iOS 6.0.1, but the problem is still remaining.

@ejtb
Copy link

ejtb commented Dec 4, 2012

This worked for me! touchswipe froze when resizing (scrolling/zooming) a page on iphone4 with iOS6. I saved this code as a js file and included it in my page in which i use a SudoSlider with TouchSwipe. Now i can resize and scroll the page and the swiping on the slider keeps working.

@netpoetica
Copy link

Ur a hero. Thank u

@AndyArcher63
Copy link

I seem to be getting this error in console:
TypeError: 'undefined' is not a function (evaluating 'timer.cb.apply(window, arguments)')

any ideas?

edit

nasty work around with browser sniffing wrap the above in:
if((navigator.userAgent.match(/(iPhone|iPod|iPad)/i))) {
}

@kTmnh
Copy link
Author

kTmnh commented Jan 29, 2013

Apparently, Apple fixed this problem on iOS 6.1 released today.
You can check whether fixed or not by the page below

https://gist.github.com/4661261

@sarathrajan
Copy link

Hi.. I have added the fix.js in my header and issue seems to be fixed. But my images are inside a link (anchor tag), while clicking the image, its not redirecting. Just showing the loading icon and nothing happens after that. Please, need help on this :(

@kTmnh
Copy link
Author

kTmnh commented Feb 4, 2013

Added useragent check in order to fix the issue only on iOS 6 or 6.0.1.

@sarathrajan
Copy link

Hi.. Thanks for your valuable help and sorry for the late response from my end. I have updated the code, but still its not working for me. Redirection is not working. I am using iOS 6.0.1. Same issue in android 4.0.4 also. Please need help :(

@kTmnh
Copy link
Author

kTmnh commented Feb 28, 2013

@sarathrajan HI, I think you should post your comment on https://github.com/malsup/cycle2/issues this project's issues section, not here.

This is my own gist post, and have no relation with malsup/cycle2 project.
And, I guess your problem is not caused my gist. I hope you could find the answer there :)

@sarathrajan
Copy link

Hi kTmnh, Thanks for your response. But I am getting this link issue only after adding this ios6-timers.js. So can you suggest me a solution for this. Thanks in advance for all your help :)

@kTmnh
Copy link
Author

kTmnh commented Mar 5, 2013

@sarathrajan I see. Is there anywhere I can review your code? Please let me know the page you have error you mention, I think I could help you.

@sarathrajan
Copy link

@kTmnh, My site is not yet live. So unfortunately cant review my code now. What I am having is a slideshow of images. I am using cycle 2 for this slideshow. All my images are given links to their respective pages. But I am getting issue in the slideshow after a 'L' shaped swipe. And I added this js to fix this. It worked fine after adding ur js. But unfortunately when i click the image, its not redirecting to its page. I am in a critical situation :( .If its not working, i need to use some other plugin for this slideshow. :( But I would like to use the awesome cycle 2 itself. Is there any way to fix this issue?

@sarathrajan
Copy link

Hi kTmnh, Can you give me a solution for this please :(

@sarathrajan
Copy link

Not able to fix this issue.. :( I am planning to use another plugin. :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment