Skip to content

Instantly share code, notes, and snippets.

@ammarfaizi2
Created April 14, 2023 23:12
Show Gist options
  • Save ammarfaizi2/3f1e6cfa6eb52da79488c1c364a3864b to your computer and use it in GitHub Desktop.
Save ammarfaizi2/3f1e6cfa6eb52da79488c1c364a3864b to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2023 Ammar Faizi <[email protected]>
*/
class GWRouter {
parse_title(body)
{
let m = body.match(/<title>(.*?)<\/title>/s);
if (m)
return m[1];
return null;
}
parse_content(body)
{
let m = body.match(/<body id="gwrouter">(.*?)<\/body>.+?<\/html>/s);
if (m)
return m[1];
return null;
}
apply_page(e)
{
if (!e || !("body" in e))
return;
let title = this.parse_title(e.body);
let content = this.parse_content(e.body);
if (content !== null)
this.frame.innerHTML = content;
else
this.frame.innerHTML = e.body;
if (title !== null)
document.title = title;
this.install_events();
}
handle_pop_state(e)
{
this.apply_page(e.state);
}
navigate_onload(url, body)
{
if (url != this.cur_url)
return;
window.history.pushState({body: body}, "", url);
this.apply_page(window.history.state);
}
navigate(url)
{
if (this.cur_xhr) {
this.cur_xhr.abort();
this.cur_xhr = null;
}
let that = this;
let xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.withCredentials = true;
xhr.setRequestHeader("X-GWRouter-State", "1");
xhr.onload = function() {
that.navigate_onload(url, this.responseText);
};
xhr.onerror = function() {
window.location = url;
};
this.cur_url = url;
this.cur_xhr = xhr;
xhr.send();
}
install_a_href_event(e)
{
let href = e.getAttribute("href");
if (!href || href[0] == '#')
return;
let that = this;
e.onclick = function(e) {
e.preventDefault();
that.navigate(href);
};
}
install_a_href_events()
{
let a = document.getElementsByTagName("a");
for (let i = 0; i < a.length; i++)
this.install_a_href_event(a[i]);
}
install_events()
{
this.install_a_href_events();
let that = this;
window.onpopstate = function(e) {
that.handle_pop_state(e);
};
}
install()
{
this.cur_url = null;
this.cur_xhr = null;
this.frame = document.getElementById("gwrouter");
if (!this.frame) {
alert("Cannot find gwrouter frame!");
return;
}
this.install_events();
}
};
const gwrouter = new GWRouter;
document.addEventListener("DOMContentLoaded", function(event) {
gwrouter.install();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment