Basic router functionality
This commit is contained in:
commit
243217334a
11
index.html
Normal file
11
index.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Router</title>
|
||||||
|
</head>
|
||||||
|
<body id="router">
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
pages/index.html
Normal file
1
pages/index.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<h1>Index</h1>
|
||||||
152
router.js
Normal file
152
router.js
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
const router = document.querySelector("#router")
|
||||||
|
const path = typeof router.getAttribute('dir') === 'string' ? router.getAttribute('dir') : 'pages'
|
||||||
|
|
||||||
|
const page_404 = `
|
||||||
|
<h1>404</h1>
|
||||||
|
<p>Page not found</p>
|
||||||
|
`
|
||||||
|
|
||||||
|
window.addEventListener("DOMContentLoaded", onRouteChange)
|
||||||
|
window.addEventListener("hashchange", onRouteChange)
|
||||||
|
|
||||||
|
async function checkPath(link) {
|
||||||
|
let response = await fetch(link)
|
||||||
|
return !(response.status === 404)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPathname() {
|
||||||
|
let pathname = window.location.pathname
|
||||||
|
if (pathname.endsWith("index.html")) {
|
||||||
|
pathname = pathname.substring(0, pathname.length - 10)
|
||||||
|
}
|
||||||
|
return pathname
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRouteChange() {
|
||||||
|
let hashLocation
|
||||||
|
if (window.location.hash.substring(1, 2) == "/") {
|
||||||
|
hashLocation = window.location.hash.substring(2)
|
||||||
|
} else {
|
||||||
|
hashLocation = window.location.hash.substring(1)
|
||||||
|
}
|
||||||
|
if (!hashLocation) {
|
||||||
|
hashLocation = "index"
|
||||||
|
}
|
||||||
|
loadContent(hashLocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadContent(uri) {
|
||||||
|
if (!(await fetchData(`${path}/${uri}.html`))) {
|
||||||
|
updatePage(page_404)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchData(link) {
|
||||||
|
let response = await fetch(link)
|
||||||
|
if (!response.ok) { return false }
|
||||||
|
|
||||||
|
let content = await response.text()
|
||||||
|
|
||||||
|
// Get <style> tag from content
|
||||||
|
const styleStart = content.indexOf("<style>\n")
|
||||||
|
let styleText
|
||||||
|
if (styleStart !== -1) {
|
||||||
|
const styleEnd = content.indexOf("</style>", styleStart + 8)
|
||||||
|
styleText = content.substring(styleStart + 8, styleEnd)
|
||||||
|
content = content.replace("<style>\n" + styleText + "</style>", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get <script> tag from content
|
||||||
|
const scriptStart = content.indexOf("<script>\n")
|
||||||
|
let scriptText
|
||||||
|
if (scriptStart !== -1) {
|
||||||
|
const scriptEnd = content.indexOf("</script>", scriptStart + 9)
|
||||||
|
scriptText = content.substring(scriptStart + 9, scriptEnd)
|
||||||
|
content = content.replace("<script>\n" + scriptText + "</script>", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all linked stylesheets
|
||||||
|
const links = content.match(/<link[^>]+>/g) || ""
|
||||||
|
if (links) {
|
||||||
|
links.forEach((link) => {
|
||||||
|
let href = link.match(/href=".*"/g)
|
||||||
|
if (href.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
href = href[0]
|
||||||
|
if (href.length === 7) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const newLink = document.createElement("link")
|
||||||
|
newLink.href = href.substring(6, href.length - 1)
|
||||||
|
newLink.rel = "stylesheet"
|
||||||
|
router.appendChild(newLink)
|
||||||
|
content.replace(link, "")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all script tags with src attribute
|
||||||
|
const scripts = content.match(/<script[^>]+>[^>]*>/g) || ""
|
||||||
|
if (scripts) {
|
||||||
|
scripts.forEach((script) => {
|
||||||
|
const src = script.match(/src=".*"/g)[0]
|
||||||
|
if (src.length === 6) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const newScript = document.createElement("script")
|
||||||
|
newScript.src = src.substring(5, src.length - 1)
|
||||||
|
router.appendChild(newScript)
|
||||||
|
content.replace(script, "")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePage(content, styleText, scriptText)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePage(content, styleText='', scriptText='') {
|
||||||
|
removeStyle()
|
||||||
|
removeScript()
|
||||||
|
router.innerHTML = ""
|
||||||
|
router.insertAdjacentHTML("afterbegin", content)
|
||||||
|
if (styleText.length != 0) { injectStyle(styleText) }
|
||||||
|
if (scriptText.length != 0) { injectScript(scriptText) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dynamically inject <script>
|
||||||
|
function injectScript(scriptText) {
|
||||||
|
var script = document.createElement("script")
|
||||||
|
script.text = scriptText
|
||||||
|
document.body.appendChild(script)
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeScript() {
|
||||||
|
const scripts = [...document.querySelectorAll("script")].filter(
|
||||||
|
(script) => !script.src
|
||||||
|
)
|
||||||
|
let counter = 0
|
||||||
|
scripts.forEach((script) => {
|
||||||
|
counter++
|
||||||
|
if (counter !== scripts.length) {
|
||||||
|
script.remove()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dynamically inject <style>
|
||||||
|
function injectStyle(styleText) {
|
||||||
|
var style = document.createElement("style")
|
||||||
|
style.innerHTML = styleText
|
||||||
|
document.head.appendChild(style)
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeStyle() {
|
||||||
|
let counter = 0
|
||||||
|
const styles = document.querySelectorAll("style")
|
||||||
|
styles.forEach((style) => {
|
||||||
|
counter++
|
||||||
|
if (counter !== styles.length) {
|
||||||
|
style.remove()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user