summaryrefslogtreecommitdiff
path: root/public/common/client.js
diff options
context:
space:
mode:
Diffstat (limited to 'public/common/client.js')
-rw-r--r--public/common/client.js193
1 files changed, 108 insertions, 85 deletions
diff --git a/public/common/client.js b/public/common/client.js
index 8aa1f65..1c0892d 100644
--- a/public/common/client.js
+++ b/public/common/client.js
@@ -1,5 +1,7 @@
"use strict"
+// TODO: hide more functions and globals in anonymous function scope
+
let params = {
mode: "play",
title_id: window.location.pathname.split("/")[1],
@@ -272,7 +274,7 @@ function init_notepad() {
notepad_window.innerHTML = `
<div id="notepad_header">Notepad: ${player}</div>
<div id="notepad_x" onclick="toggle_notepad()">\u274c</div>
- <textarea id="notepad_input" cols="55" rows="10" maxlength="16000" oninput="dirty_notepad()"></textarea>
+ <textarea id="notepad_input" maxlength="16000" oninput="dirty_notepad()"></textarea>
<div id="notepad_footer"><button id="notepad_save" onclick="save_notepad()" disabled>Save</button></div>
`
document.querySelector("body").appendChild(notepad_window)
@@ -350,19 +352,17 @@ window.addEventListener("keyup", (evt) => {
/* REMATCH BUTTON */
-function add_icon_button(where, id, img, title, fn) {
+function add_icon_button(where, id, img, fn) {
let button = document.getElementById(id)
if (!button) {
- button = document.createElement("div")
+ button = document.createElement("button")
button.id = id
- button.title = title
- button.className = "icon_button"
button.innerHTML = '<img src="/images/' + img + '.svg">'
button.addEventListener("click", fn)
if (where)
- document.getElementById("toolbar").appendChild(button)
+ document.querySelector("#toolbar").appendChild(button)
else
- document.querySelector(".menu").after(button)
+ document.querySelector("#toolbar details").after(button)
}
return button
}
@@ -383,9 +383,9 @@ function goto_replay() {
}
function on_game_over() {
- add_icon_button(1, "replay_button", "sherlock-holmes-mirror", "Watch replay", goto_replay)
+ add_icon_button(1, "replay_button", "sherlock-holmes-mirror", goto_replay)
if (player !== "Observer")
- add_icon_button(1, "rematch_button", "cycle", "Propose a rematch!", goto_rematch)
+ add_icon_button(1, "rematch_button", "cycle", goto_rematch)
remove_resign_menu()
}
@@ -713,54 +713,41 @@ function init_replay() {
document.body.appendChild(script)
}
-window.addEventListener("load", function () {
- zoom_map()
- if (params.mode === "debug")
- init_replay()
- else if (params.mode === "replay")
- init_replay()
- else if (params.mode === "play")
- connect_play()
- else
- document.getElementById("prompt").textContent = "Invalid mode: " + params.mode
-})
-
/* MAIN MENU */
-add_icon_button(0, "chat_button", "chat-bubble", "Open chat", toggle_chat).classList.add("hide")
-add_icon_button(0, "zoom_button", "magnifying-glass", "Zoom", () => toggle_zoom())
-add_icon_button(0, "log_button", "scroll-quill", "Hide log", toggle_log)
-add_icon_button(0, "fullscreen_button", "expand", "Fullscreen", toggle_fullscreen)
+add_icon_button(0, "chat_button", "chat-bubble", toggle_chat).classList.add("hide")
+add_icon_button(0, "zoom_button", "magnifying-glass", () => toggle_zoom())
+add_icon_button(0, "log_button", "scroll-quill", toggle_log)
+add_icon_button(0, "fullscreen_button", "expand", toggle_fullscreen)
-function init_main_menu() {
- let popup = document.querySelector(".menu_popup")
- let sep = document.createElement("div")
- sep.className = "menu_separator"
- sep.id = "main_menu_separator"
+function add_main_menu_separator() {
+ let popup = document.querySelector("#toolbar details menu")
+ let sep = document.createElement("li")
+ sep.className = "separator"
popup.insertBefore(sep, popup.firstChild)
}
function add_main_menu_item(text, onclick) {
- let popup = document.querySelector(".menu_popup")
- let sep = document.getElementById("main_menu_separator")
- let item = document.createElement("div")
- item.className = "menu_item"
+ let popup = document.querySelector("#toolbar details menu")
+ let sep = popup.querySelector(".separator")
+ let item = document.createElement("li")
item.onclick = onclick
item.textContent = text
popup.insertBefore(item, sep)
}
function add_main_menu_item_link(text, url) {
- let popup = document.querySelector(".menu_popup")
- let sep = document.getElementById("main_menu_separator")
- let item = document.createElement("a")
- item.className = "menu_item"
- item.href = url
- item.textContent = text
+ let popup = document.querySelector("#toolbar details menu")
+ let sep = popup.querySelector(".separator")
+ let item = document.createElement("li")
+ let a = document.createElement("a")
+ a.href = url
+ a.textContent = text
+ item.appendChild(a)
popup.insertBefore(item, sep)
}
-init_main_menu()
+add_main_menu_separator()
if (params.mode === "play" && params.role !== "Observer") {
add_main_menu_item_link("Go home", "/games/active")
add_main_menu_item_link("Go to next game", "/games/next")
@@ -768,6 +755,20 @@ if (params.mode === "play" && params.role !== "Observer") {
add_main_menu_item_link("Go home", "/")
}
+function close_menus(self) {
+ for (let node of document.querySelectorAll("#toolbar > details"))
+ if (node !== self)
+ node.removeAttribute("open")
+}
+
+for (let node of document.querySelectorAll("#toolbar > details")) {
+ node.onclick = function () { close_menus(node) }
+ node.onmouseleave = function () { node.removeAttribute("open") }
+}
+for (let node of document.querySelectorAll("#toolbar > details > menu")) {
+ node.onclick = function () { close_menus(null) }
+}
+
function toggle_fullscreen() {
if (document.fullscreenElement)
document.exitFullscreen()
@@ -857,45 +858,21 @@ function on_snap_stop() {
function toggle_log() {
document.querySelector("aside").classList.toggle("hide")
- zoom_map()
+ update_layout()
}
var toggle_zoom = function () {}
-
-function zoom_map() {
- let mapwrap = document.getElementById("mapwrap")
- if (mapwrap) {
- let main = document.querySelector("main")
- let map = document.getElementById("map")
- map.style.transform = null
- mapwrap.style.width = null
- mapwrap.style.height = null
- if (mapwrap.classList.contains("fit")) {
- let { width: gw, height: gh } = main.getBoundingClientRect()
- let { width: ww, height: wh } = mapwrap.getBoundingClientRect()
- let { width: cw, height: ch } = map.getBoundingClientRect()
- let scale = Math.min(ww / cw, gh / ch)
- if (scale < 1) {
- map.style.transform = "scale(" + scale + ")"
- mapwrap.style.width = (cw * scale) + "px"
- mapwrap.style.height = (ch * scale) + "px"
- }
- }
- }
-}
-
-window.addEventListener("resize", zoom_map)
+var update_layout = function () {}
/* PAN & ZOOM GAME BOARD */
;(function panzoom_init() {
- const MIN_ZOOM = 0.5
- const MAX_ZOOM = 1.5
+ var MIN_ZOOM = Number(document.querySelector("main").dataset.minZoom) || 0.5
+ var MAX_ZOOM = Number(document.querySelector("main").dataset.maxZoom) || 1.5
+
const THRESHOLD = 0.0625
const DECELERATION = 125
- console.log("DPX", window.devicePixelRatio)
-
const e_scroll = document.querySelector("main")
e_scroll.style.touchAction = "none"
@@ -914,11 +891,11 @@ window.addEventListener("resize", zoom_map)
e_scroll.appendChild(e_outer)
const mapwrap = document.getElementById("mapwrap")
- const map = document.getElementById("map") || e_inner.firstChild
+ const map = document.getElementById("map") || e_inner.querySelector("div")
const map_w = mapwrap ? mapwrap.clientWidth : map.clientWidth
const map_h = mapwrap ? mapwrap.clientHeight : map.clientHeight
- console.log("MAP", map_w, map_h)
+ console.log("INIT MAP", map, map_w, map_h, window.devicePixelRatio)
var transform0 = { x: 0, y: 0, scale: 1 }
var transform1 = { x: 0, y: 0, scale: 1 }
@@ -940,14 +917,9 @@ window.addEventListener("resize", zoom_map)
var mom_vx = 0
var mom_vy = 0
- try {
- new ResizeObserver(update_transform_resize).observe(document.getElementById("log"))
- } catch (err) {
- window.addEventListener("resize", function (evt) {
- old_scale = 0
- update_transform()
- })
- }
+ // set globals to our scoped functions
+ toggle_zoom = toggle_zoom_imp
+ update_layout = update_layout_imp
function clamp_scale(scale) {
let win_w = e_scroll.clientWidth
@@ -981,10 +953,10 @@ window.addEventListener("resize", zoom_map)
function toggle_zoom_imp() {
if (transform1.scale === 1) {
- if (window.innerWidth >= 800) {
+ if (window.innerWidth > 800) {
if (mapwrap) {
mapwrap.classList.toggle("fit")
- zoom_map()
+ update_map_fit()
return
}
}
@@ -998,10 +970,38 @@ window.addEventListener("resize", zoom_map)
return false
}
+ function update_layout_imp() {
+ update_map_fit()
+ update_transform_resize()
+ scroll_log_to_end()
+ }
+
+ function update_map_fit() {
+ let mapwrap = document.getElementById("mapwrap")
+ if (mapwrap) {
+ let main = document.querySelector("main")
+ let map = document.getElementById("map")
+ map.style.transform = null
+ mapwrap.style.width = null
+ mapwrap.style.height = null
+ if (mapwrap.classList.contains("fit")) {
+ let { width: gw, height: gh } = main.getBoundingClientRect()
+ let { width: ww, height: wh } = mapwrap.getBoundingClientRect()
+ let { width: cw, height: ch } = map.getBoundingClientRect()
+ let scale = Math.min(ww / cw, gh / ch)
+ if (scale < 1) {
+ map.style.transform = "scale(" + scale + ")"
+ mapwrap.style.width = (cw * scale) + "px"
+ mapwrap.style.height = (ch * scale) + "px"
+ }
+ }
+ }
+ }
+
function disable_map_fit() {
if (mapwrap && mapwrap.classList.contains("fit")) {
mapwrap.classList.remove("fit")
- zoom_map()
+ update_map_fit()
}
}
@@ -1048,6 +1048,12 @@ window.addEventListener("resize", zoom_map)
}
}
+ function update_transform_resize() {
+ old_scale = 0
+ anchor_transform()
+ update_transform()
+ }
+
function start_measure(time) {
mom_last_t = [ time, time, time ]
mom_last_x = [ transform1.x, transform1.x, transform1.x ]
@@ -1213,6 +1219,23 @@ window.addEventListener("resize", zoom_map)
},
{ passive: false }
)
-
- toggle_zoom = toggle_zoom_imp
})()
+
+/* INITIALIZE */
+
+window.addEventListener("resize", () => update_layout())
+
+window.addEventListener("load", function () {
+ if (window.innerWidth <= 800)
+ document.querySelector("aside").classList.add("hide")
+ update_layout()
+
+ if (params.mode === "debug")
+ init_replay()
+ else if (params.mode === "replay")
+ init_replay()
+ else if (params.mode === "play")
+ connect_play()
+ else
+ document.getElementById("prompt").textContent = "Invalid mode: " + params.mode
+})