Skip to content

Instantly share code, notes, and snippets.

@shogun70
Last active December 16, 2015 02:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shogun70/5362893 to your computer and use it in GitHub Desktop.
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.
<!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