let on_init = []
let on_modify = []
let on_setting_change = []
let on_debug = false
function set_cookie(k, v = null) {
if (v !== null) document.cookie = `${k}=${v}; path=/;`
else document.cookie = `${k}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`
}
function get_cookie(name) {
let res = document.cookie.match("(^|;)\\s*" + name + "\\s*=\\s*([^;]+)")?.pop() || ""
return res === "" ? null : res
}
// param > cookie > body
function get_setting(params, key) {
let res = params.get(key)
if (res === null) res = get_cookie(key)
if (res === null) res = document.querySelector("#settings").getAttribute(`data-${key}`)
if (res !== null) set_cookie(key, res)
return res
}
function get_site_identifier() {
let s = document.querySelector("#settings")
let res = window.location.hostname
if (s.getAttribute("data-project-id") !== "") res = s.getAttribute("data-project-id")
else if (window.location.hostname.endsWith("localhost")) res = s.getAttribute("data-local-mac")
return res
}
function node(...args) {
let node_str = "
"
let styles = {}
if (args.length == 1) {
if (typeof args[0] === "string") {
node_str = args[0]
} else {
styles = args[0]
}
} else if (args.length == 2) {
node_str = args[0]
styles = args[1]
}
const dummy = document.createElement("div")
dummy.innerHTML = node_str
const res = dummy.firstChild
for (let [k, v] of Object.entries(styles)) {
res.style[k.replaceAll("_", "-")] = v
}
return res
}
function get_webgl_texture_size() {
let n = node("", { border: "none", width: "1px", height: "1px" })
let gl = n.getContext("experimental-webgl")
let res = gl ? gl.getParameter(gl.MAX_TEXTURE_SIZE) : null
return res
}
function setup_side_nav(side_nav, targets, link_class_name = "side-nav-link") {
// cleanup side nav first
side_nav.textContent = ""
// create links
let links = []
for (let i = 0; i < targets.length; i++) {
targets[i].id = `side-nav-target-${i}`
let link = node(
`${targets[i].textContent}`
)
links.push(link)
side_nav.appendChild(link)
}
// define activation function
let prev_focus = null
let f_activate = x => {
if (x !== prev_focus) {
for (let item of links) item.classList.remove("activate")
x.classList.add("activate")
prev_focus = x
}
}
// observe targets
const observer = new IntersectionObserver(
items => {
if (items.length > 0 && items[0].isIntersecting) {
f_activate(side_nav.querySelector(`#link-${items[0].target.id}`))
}
},
{ root: null, rootMargin: "0px 0px -90% 0px", threshold: 0.95 }
)
for (let x of targets) observer.observe(x)
side_nav.addEventListener("click", e => setTimeout(() => f_activate(e.target), 100))
}
function setup_panorama_image(e) {
let texture_size = get_webgl_texture_size()
let src = e.getAttribute("data-src")
if (texture_size <= 8192) {
src = e.getAttribute("data-mobile-src")
e.style.width = "320px"
e.style.height = "320px"
}
if (texture_size === null) e.srcdoc = "WEBGL not supported"
else
e.srcdoc = `
`
}
function setup_album(e) {
let src = JSON.parse(e.getAttribute("data-items"))
let img = node("", { position: "relative", cursor: "pointer" })
e.append(img)
let text = node({
position: "absolute",
bottom: "5px",
right: "10px",
color: "white",
text_shadow: "1px 1px 0px black, -1px 1px 0px black, 1px -1px 0px black, -1px -1px 0px black",
z_index: 10
})
e.append(text)
text.textContent = `1/${src.length}`
let curr = 0
img.src = src[curr]
e.addEventListener("mousedown", () => {
curr += 1
if (curr >= src.length) curr = 0
img.src = src[curr]
text.textContent = `${curr + 1}/${src.length}`
})
}
function setup_settings() {
let params = new URLSearchParams(new URL(window.location.href).search)
let node_settings = document.querySelector("#settings")
// if lang is in cookie, switch to the same page of this lang
let lang = get_setting(params, "lang")
let language_options = JSON.parse(node_settings.getAttribute("data-language-options"))
if (lang !== null && lang in language_options) {
if (window.location.pathname !== language_options[lang][2]) {
window.location.replace(language_options[lang][2])
}
}
// set dark if dark is in cookie
let dark = get_setting(params, "dark")
let node_body = document.querySelector("body")
let node_lightbulb = node_settings.children[2]
let set_dark = inp => {
if (inp === "0") {
node_body.classList.remove("dark")
node_lightbulb.children[0].style.display = "none"
node_lightbulb.children[1].style.display = "block"
} else if (inp === "1") {
node_body.classList.add("dark")
node_lightbulb.children[0].style.display = "block"
node_lightbulb.children[1].style.display = "none"
}
dark = inp
set_cookie("dark", dark)
for (let f of on_setting_change) f()
}
set_dark(dark)
let node_lang_buttons = node_settings.children[0]
let node_lang_options = node_settings.children[1]
let open_lang_options = on => {
if (on) {
node_lang_buttons.children[0].style.display = "none"
node_lang_buttons.children[1].style.display = "block"
node_lang_options.style.display = "block"
} else {
node_lang_buttons.children[0].style.display = "block"
node_lang_buttons.children[1].style.display = "none"
node_lang_options.style.display = "none"
}
for (let f of on_setting_change) f()
}
node_lang_options.addEventListener("mousedown", e => {
let _lang = e.target.getAttribute("data-lang")
set_cookie("lang", _lang === "src" ? null : _lang)
})
node_lang_buttons.addEventListener("click", () => {
if (node_lang_options.style.display === "block") open_lang_options(false)
else {
open_lang_options(true)
let handler = e => {
if (!node_settings.contains(e.target)) {
open_lang_options(false)
document.removeEventListener(document, handler)
}
}
setTimeout(() => document.addEventListener("click", handler), 200)
}
})
node_lightbulb.addEventListener("click", () => set_dark(dark === "0" ? "1" : "0"))
}
addEventListener("DOMContentLoaded", () => {
setup_settings()
for (let e of document.querySelectorAll(".album")) setup_album(e)
for (let e of document.querySelectorAll(".panorama-image")) setup_panorama_image(e)
for (let f of on_init) f()
window.addEventListener("message", e => {
let d = e.data
if (typeof d === "object" && "to" in d) {
if (d.op === "modify") {
let target_e = document.querySelector(`#${d.args.target_id}`)
if (target_e !== null) {
target_e.innerHTML = d.args.html
for (let f of on_modify) f()
}
} else if (d.op === "debug") {
if (on_debug) {
for (let e of document.querySelectorAll("*")) e.classList.remove("debug")
} else {
for (let e of document.querySelectorAll("*")) e.classList.add("debug")
}
on_debug = !on_debug
}
}
})
})