Skip to content

Instantly share code, notes, and snippets.

@adrianjost
Last active November 4, 2018 12:29
Show Gist options
  • Save adrianjost/c67e125fbf93b0d3fd3647849573dc36 to your computer and use it in GitHub Desktop.
Save adrianjost/c67e125fbf93b0d3fd3647849573dc36 to your computer and use it in GitHub Desktop.
turbonav inspired by turbolinks & swup
import diffDom from 'diff-dom'; // node-module: "npm i diff-dom"
const diffDOM = new diffDom();
const defaultOptions = {
clickTarget: `a[href*='${window.location.hostname}'], a[href^='#'], a[href^='/']`,
saveHeaders: `.turbonav-keep`,
imitateBrowserEvents: true
};
var options;
function newPage(html){
const dom = parser.parseFromString(html, "text/html");
/*dom.querySelectorAll("script").forEach((script) => {
script.addEventListener("load", () => {
console.log("loaded script");
});
});*/
if(options.imitateBrowserEvents){
window.dispatchEvent(new Event('unload'));
}
const head = document.querySelector("head");
const headDiff = diffDOM.diff(head, dom.querySelector("head"));
diffDOM.apply(head, headDiff);
/*
// clear head
head.querySelectorAll(`*:not(${options.saveHeaders})`).forEach((elem) => {
elem.remove();
});
// add new head
dom.querySelectorAll(`head > *`).forEach((newNode) => {
const isNew = Array.from(head.children).every((existingNode) => {
return !newNode.isEqualNode(existingNode);
});
if(isNew){
head.appendChild(newNode);
}
});
*/
// replace body
document.querySelector("html").replaceChild(document.querySelector("body").cloneNode(), document.querySelector("body"));
const body = document.querySelector("body");
const bodyDiff = diffDOM.diff(body, dom.querySelector("body"));
diffDOM.apply(body, bodyDiff);
if(options.imitateBrowserEvents){
document.dispatchEvent(new Event('DOMContentLoaded'));
window.dispatchEvent(new Event('load'));
}
/*
// execute script tags
document.querySelectorAll("script").forEach(scriptTag => {
eval(scriptTag.innerHTML);
});
*/
document.dispatchEvent(new Event('turbonav:load'));
}
function navigate(event){
if(!history.pushState){return false;}
event.preventDefault();
event.stopPropagation();
if(options.imitateBrowserEvents){
window.dispatchEvent(new Event('beforeunload'));
}
document.dispatchEvent(new Event('turbonav:visit'));
const navTarget = this.getAttribute("href");
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.dispatchEvent(new Event('turbonav:request-end'));
history.pushState(null, null, navTarget);
newPage(xhttp.responseText);
}
};
xhttp.open("GET", navTarget, true);
document.dispatchEvent(new Event('turbonav:request-start'));
xhttp.send();
}
const parser = new DOMParser();
export default function init(userOptions){
options = Object.assign(defaultOptions, userOptions);
// add click handler
document.querySelectorAll(options.clickTarget).forEach((target) => {
target.addEventListener("click", navigate);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment