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