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