Skip to content
This repository has been archived by the owner on Aug 5, 2020. It is now read-only.

Commit

Permalink
Add iOS 8.0 scroll fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Justin Vaillancourt committed Sep 23, 2014
1 parent f043040 commit d70cdc2
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 0 deletions.
5 changes: 5 additions & 0 deletions api/cont.js
Expand Up @@ -226,6 +226,11 @@
return Async(this, function(cont, async) {
if (args.length == 1) data = cont.all();
dust.render(template, data, function(err, out) {
// Apply scroll fix to iOS 8.0
if (out && Mobify.isIOS8_0()) {
out = Mobify.ios8_0ScrollFix(out);
}

if (err) {
async.finish(out);
debug.die(err);
Expand Down
62 changes: 62 additions & 0 deletions api/util.js
Expand Up @@ -81,6 +81,68 @@
return i18nlookup;
};

Mobify.isIOS8_0 = function() {
var IOS8_REGEX = /ip(hone|od|ad).*OS 8_0/i;

return IOS8_REGEX.test(window.navigator.userAgent);
};

/**
* iOS 8.0 has a bug where dynamically switching the viewport (by swapping the
* viewport meta tag) causes the viewport to automatically scroll. When
* capturing, the initial document never has an active meta viewport tag.
* Then, the rendered document injects one causing the aforementioned scroll.
*
* This patches HTML to hide the body until the first paint (and hopefully after
* the initial viewport is calculated). By the time we show the body the new
* viewport should have already taken effect.
*
* JIRA: https://mobify.atlassian.net/browse/GOLD-883
* Open Radar: http://www.openradar.me/radar?id=5516452639539200
* WebKit Bugzilla: https://bugs.webkit.org/show_bug.cgi?id=136904
*/
Mobify.ios8_0ScrollFix = function(htmlString) {
var BODY_REGEX = /<body(?:[^>'"]*|'[^']*?'|"[^"]*?")*>/i;

var openingBodyTag = BODY_REGEX.exec(htmlString);
// Do nothing if we can't find an opening `body` tag.
if (!openingBodyTag) {
return htmlString;
}
openingBodyTag = openingBodyTag[0];

// Use DOM methods to manipulate the attributes on the `body` tag. This
// lets us rely on the browser to set body's style to `display: none`.
// We create a containing element to be able to set an inner HTML string.
var divEl = document.createElement('div');

// The `div`'s inner string can't be a `body` tag, so we temporarily change
// it to a `div`..
var openingBodyTagAsDiv = openingBodyTag.replace(/^<body/, '<div');
divEl.innerHTML = openingBodyTagAsDiv;

// ..so that we can set it to be hidden..
divEl.firstChild.style.display = 'none';

// ..and change it back to a `body` string!
openingBodyTagAsDiv = divEl.innerHTML.replace(/<\/div>$/, '');
openingBodyTag = openingBodyTagAsDiv.replace(/^<div/, '<body');

// Append the script to show the body after two paints. This needs to be
// inside the body to ensure that `document.body` is available when it
// executes.
var script =
"<script>" +
" window.requestAnimationFrame(function() {" +
" window.requestAnimationFrame(function() {" +
" document.body.style.display = '';" +
" });" +
" });" +
"<\/script>";

return htmlString.replace(BODY_REGEX, openingBodyTag + script);
};

// ###
// # SERVICES
// ###
Expand Down
25 changes: 25 additions & 0 deletions test/util-test.html
Expand Up @@ -232,6 +232,31 @@ <h2 id="qunit-userAgent"></h2>
equal(Mobify.getImageURL('http://test/1.jpg', {maxWidth: 320}), '//ir3.mobify.com/320/http://test/1.jpg')
});

test("Mobify.ios8_0ScrollFix", function() {
var html =
"<html>" +
"<head>" +
" <title>Scroll Fix Test</title>" +
"</head>" +
"<body style='font-size: 13px' class='x-test'>" +
" <ul>" +
" <li>Woohoo</li>" +
" </ul>" +
"</body>" +
"</html>";

html = Mobify.ios8_0ScrollFix(html);

ok(html.indexOf('font-size: 13px') !== -1,
'`font-size: 13px` on the body tag is still present');
ok(html.indexOf('display: none') !== -1,
'`display: none` was set on the body tag');
ok(html.indexOf("document.body.style.display = '';") !== -1,
'there is a script to show the body');
ok(html.indexOf('x-test') !== -1,
'`x-test` body class tag is still present');
});

test('$.fn.resizeImages', function() {
var $resized = Mobify.$('#test-resizeImages').resizeImages()
equal($resized.length, 3)
Expand Down

0 comments on commit d70cdc2

Please sign in to comment.