|
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); |
|
}); |
|
} |