Skip to content

Instantly share code, notes, and snippets.

@billiegoose
Created January 20, 2017 02:58
Show Gist options
  • Save billiegoose/2e28e9d954ce496d33a0972adaf80e5f to your computer and use it in GitHub Desktop.
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
<!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>
@billiegoose
Copy link
Author

An experiment, heavily inspired by http://instantclick.io/

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