Last active
December 16, 2015 02:29
-
-
Save shogun70/5362893 to your computer and use it in GitHub Desktop.
Test-case for `<plaintext>` insertion and document rewrite. This would be the starting point for adding error recovery to Mobify.js.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<script> | |
(function(window, document, detector, timeout, scripts) { | |
var bootScript = $('script'); // bootScript is used in loadScript() | |
bootScript.setAttribute('onload', ';'); // old Safari will have a misleading ('onload' in bootScript) | |
if (typeof bootScript.onload !== 'function' || !detector()) { | |
alert('Browser not supported. No action'); // NOTE this alert pops-up twice on IE <= 8 - parsing restarts when charset is declared | |
return; | |
} | |
// Prevent the browser from downloading website resources | |
document.write('<plaintext style="display:none">'); | |
// read and write of document markup MUST use docProxy. | |
var docProxy = window.docProxy = { // NOTE: rewriting the page deletes window.docProxy (usually!?) | |
state: 'loading', // `state` transitions to 'loaded' at window.onload | |
getHTML: function() { | |
var plaintext = $('plaintext'); | |
if (!plaintext) throw 'Not captured'; // NOTE this shouldn't be necessary. | |
var html = plaintext.textContent || plaintext.innerText || plaintext.firstChild.nodeValue; | |
return html; | |
}, | |
setHTML: function(html) { | |
document.open('text/html', 'replace'); // replace current history entry (on IE and Firefox) | |
document.write(html); | |
document.close(); | |
}, | |
restore: function() { | |
var html = docProxy.getHTML(); | |
docProxy.setHTML(html); | |
delete window.docProxy; // WARN rewriting page should delete this anyway but doesn't seem to happen on old Safari | |
} | |
} | |
/* | |
Dead-man's page restore | |
If scripts fail to load, or | |
if there is an unhandled error that prevents scripts from rewriting the page, | |
this timeout function will restore the original HTML of the page, | |
that is, without the `<plaintext>` tag and any preceding markup. | |
FIXME: what if this occurs before `window.onload` or `scripts.onerror` | |
*/ | |
delay(function() { | |
if (!window.docProxy) return; // docProxy undefined means already rewritten | |
alert('Timed out waiting for document rewrite. Restoring page.'); | |
docProxy.restore(); | |
}, timeout); | |
var restoring = false; // `restoring` is set by queue(scripts).onerror | |
window.onload = function() { | |
docProxy.state = 'loaded'; | |
if (restoring) { | |
docProxy.restore(); | |
return; | |
} | |
if (docProxy.onload) delay(docProxy.onload); | |
} | |
queue(scripts, | |
function() { // oncomplete | |
alert('Scripts successfully loaded.'); | |
}, | |
function() { // onerror | |
alert('Scripts failed. Restoring page.'); | |
restoring = true; | |
if (docProxy.state == 'loaded') docProxy.restore(); | |
} | |
); | |
function queue(srcList, oncomplete, onerror) { | |
var list = srcList.slice(0); | |
delay(queueback); | |
function queueback() { | |
if (!list.length) { | |
oncomplete(); | |
return; | |
} | |
var src = list.shift(); | |
loadScript(src, queueback, onerror); | |
} | |
} | |
function loadScript(url, onload, onerror) { | |
var script = document.createElement('script'); | |
script.onload = onload; | |
script.onerror = onerror; | |
script.src = url; | |
bootScript.parentNode.insertBefore(script, bootScript); | |
return script; | |
} | |
function delay(fn, duration) { return window.setTimeout(fn, duration); } | |
function $(tag) { return document.getElementsByTagName(tag)[0]; } | |
})( window, document, | |
// detector function | |
function (){ | |
// WARN: The loader is enabled for | |
// - WebKit based browsers | |
// - IE 10+ | |
// - FireFox 4+ | |
// - Opera 13+ | |
// - 3DS | |
match = /webkit|(firefox)[\/\s](\d+)|(opera)[\s\S]*version[\/\s](\d+)|(msie)\s(\d+)|3ds/i.exec(navigator.userAgent); | |
if (!match) { | |
return false; | |
} | |
// match[1] == Firefox | |
if (match[1] && +match[2] < 4) { | |
return false; | |
} | |
// match[3] == Opera | |
if (match[3] && +match[4] < 13) { | |
return false; | |
} | |
// match[5] == IE | |
if (match[5] && +match[6] < 10) { | |
return false; | |
} | |
return true; | |
}, | |
3000, // Failsafe timeout | |
[ // NOTE: any number of startup scripts | |
'notfound.js' | |
] | |
); | |
</script> | |
<!DOCTYPE html> | |
<html lang="en" id="html"> | |
<head id="head"> | |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | |
<title>plaintext recovery test</title> | |
<style> | |
section { display: block; border: 1px solid red; } | |
section p { border: 1px solid green; } | |
</style> | |
</head> | |
<body id="body"> | |
<div> | |
<h1>plaintext recovery test</h1> | |
<section> | |
Narrative3 | |
<p>Paragraph</p> | |
<ul> | |
<li>One</li> | |
<li>Two</li> | |
</ul> | |
</section> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment