Created
January 20, 2017 02:58
-
-
Save billiegoose/2e28e9d954ce496d33a0972adaf80e5f to your computer and use it in GitHub Desktop.
Replace internal links with history.pushState based navigation but leave external links unmodified
This file contains 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> | |
<html> | |
<head> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title></title> | |
</head> | |
<body> | |
<a href="/app.html">app.html</a> | |
<br> | |
These should use the instantaneous single page app navigation: | |
<ul> | |
<li><a href="/page/1">App Page 1</a></li> | |
<li><a href="/page/2">App Page 2</a></li> | |
<li><a href="/page/3">App Page 3</a></li> | |
<li><a href="/page/3#downabit">Page 3 with anchor</a> (doesn't quite work as intended)</li> | |
</ul> | |
These should use normal link navigation: | |
<ul> | |
<li><a href="#downabit">Relative anchor</a></li> | |
<li><a href="/page/3" target="_blank">App Page 3 (new tab)</a></li> | |
<li><a href="http://google.com">External link</a></li> | |
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> | |
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> | |
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> | |
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> | |
<div id="downabit">Here is this bit</div> | |
</ul> | |
<script> | |
(function () { | |
window.HijackLinks = hijackLinks | |
function hijackLinks () { | |
for (let node of document.getElementsByTagName('a')) { | |
console.log(node, node.nodeName, node.href) | |
node.addEventListener('click', singlePageAppNavigate, false) | |
} | |
} | |
function singlePageAppNavigate (e) { | |
if (isLocalHref(e.target)) { | |
e.preventDefault() | |
let node = e.target | |
history.pushState({}, '', node.href) | |
// Firefox on my phone does not show the new URL in the URL bar. :-( | |
// But if I tap the address bar to edit it it does. | |
emitNavigateEvent() | |
} | |
} | |
function emitNavigateEvent () { | |
let event = new Event('navigate') | |
window.dispatchEvent(event) | |
} | |
window.addEventListener('popstate', function (e) { | |
emitNavigateEvent() | |
}) | |
// I'd like to acknowledge Alexandre Dieulot (github.com/dieulot/instantclick) | |
// @link https://github.com/dieulot/instantclick/blob/master/src/instantclick.js#L98 | |
function isLocalHref (a) { | |
if (a.host !== window.location.host | |
|| a.protocol !== window.location.protocol | |
|| a.target | |
|| a.hasAttribute('download') | |
// This one is subtle. This (re)enables the hash to be used for it's original in-page navigation behavior. | |
|| (a.pathname === window.location.pathname && a.search === window.location.search) | |
) { | |
return false | |
} | |
return true | |
} | |
})(window) | |
</script> | |
<script> | |
// User code | |
window.HijackLinks() | |
window.addEventListener('navigate', function(){ | |
// Bizarrely enough, doing this "fixes" the URL bar in Firefox on my phone. | |
// But not if I do it in singlePageAppNavigate(). | |
document.title = window.location.pathname | |
}) | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
An experiment, heavily inspired by http://instantclick.io/