+
tokens
-
-
-
+
+
sprites
-
+
diff --git a/static/map.js b/static/map.js
index ea631e5..0d8d6e6 100644
--- a/static/map.js
+++ b/static/map.js
@@ -8,18 +8,32 @@ function initializeMap(mapImgUrl) {
let init = false;
if (!map) {
init = true;
- map = L.map('map', { minZoom: 0, maxZoom: 4, crs: L.CRS.Simple, attributionControl: false, zoomControl: false });
- map.on("zoomend", ()=>{resizeMarkers();scaleSpritePreview();scaleAltSpritePreview();});
+ map = L.map("map", {
+ minZoom: 0,
+ maxZoom: 4,
+ crs: L.CRS.Simple,
+ attributionControl: false,
+ zoomControl: false
+ });
+ map.on("zoomend", () => {
+ resizeMarkers();
+ scaleSpritePreview();
+ scaleAltSpritePreview();
+ });
}
+
if (mapImg) {
mapImg.removeFrom(map);
}
+
mapImg = L.imageOverlay(mapImgUrl, worldBounds);
mapImg.addTo(map);
map.setMaxBounds(cameraBounds);
+
if (init) {
map.setView([0,0], 2);
}
+
resizeMarkers();
}
@@ -92,7 +106,6 @@ function toggleActive(tokenId) {
if (existing) {
const self = Object.assign({}, existing.t);
self.active = !self.active;
- console.log(self);
publish({token: stripToken(self)});
}
}
@@ -104,7 +117,6 @@ function moveToken(id) {
const realPos = existing.m.getLatLng();
self.x = realPos.lng;
self.y = realPos.lat;
-
publish({token: stripToken(self)});
}
}
@@ -131,7 +143,9 @@ function NewToken(token) {
draggable: true,
autoPan: true
});
+
marker.on("moveend", ()=>{moveToken(token.id)});
+
const node = document.createElement('div');
node.innerText = token.name;
marker.bindPopup(node);
diff --git a/static/socket.js b/static/socket.js
index 5963402..8c892d5 100644
--- a/static/socket.js
+++ b/static/socket.js
@@ -1,177 +1,18 @@
-let tableKey = {
+const tableKey = {
name: "",
passcode: ""
}
let conn = null;
let offline = false;
-let msgQ = [];
-
-const lagDiv = document.getElementById("lag");
-const secondaryPreviewZone = document.getElementById("tokenPreview_alt");
-const secondaryPreviewIdInput = document.getElementById("tokenPreview_alt_id");
-const dismissPreviewBtn = document.getElementById("tokenPreview_alt_clear");
-
-function showTableModal(show) {
- const modal = document.getElementById("table_modal");
- if (modal) {
- modal.style.display = show ? "block" : "none";
- }
-}
-
-function fmtLeading(n) {
- return n < 10 ? "0" + n : String(n);
-}
-
-function formatDice(r) {
- const date = new Date(r.timestamp)
- const p = document.createElement("p");
-
- const month = date.getMonth() + 1;
- const day = date.getDate();
- const hours = date.getHours();
- const minutes = date.getMinutes();
- const seconds = date.getSeconds();
-
- p.innerHTML = `${date.getFullYear()}-${fmtLeading(month)}-${fmtLeading(day)} ${fmtLeading(hours)}:${fmtLeading(minutes)}:${fmtLeading(seconds)} ${r.player} rolled ${r.roll.length}d${r.faces} ${(r.note ? "(" + r.note + ")" : "")}
[${r.roll}] (total ${r.roll.reduce((a,c)=>a+c,0)})`;
-
- return p;
-}
-
-function logDice(dice) {
- const diceLog = document.getElementById("dice_log");
- if (!Array.isArray(dice)) {
- dice = [ dice ];
- } else {
- if (diceLog) {
- diceLog.innerHTML = "";
- }
- }
- if (diceLog) {
- for(const r of dice) {
- try{
- const p = formatDice(r);
- diceLog.append(p);
- p.scrollIntoView();
- } catch{}
- }
- }
-}
-
-function setAuxMsg(msg) {
- const auxDiv = document.getElementById("aux");
- if (auxDiv) {
- auxDiv.innerText = msg;
- }
-}
-
-function updateTokens(tokens) {
- // update internal token array and map
- processTokens(tokens);
- // update token select window
- renderTokenSelect();
- // if admin, update token master list
- renderTokenMasterList();
-}
-
-function renderTokenSelect() {
- const tokenSelect = document.getElementById("token_select");
- let tokenSelectHTML = ""
- const scroll = tokenSelect.scrollTop;
- for (const t of tokens) {
- tokenSelectHTML += `
${t.t.name}\n`;
- }
- tokenSelect.innerHTML = tokenSelectHTML;
- tokenSelect.scrollTop = scroll;
-}
-
-// the following few functions aren't socket related but they directly relate to the previous function
-
-function initSpritePreviewById(id) {
- const token = tokens.find(t=>t.t.id == id);
- let img = null;
-
- if (token && id) {
-
- img = document.createElement("img");
- img.src = token.t.sprite;
- secondaryPreviewIdInput.value = id;
-
-
- img.onload = () => {
- scaleAltSpritePreview();
- }
- }
- dismissPreviewBtn.style.display = (token && id) ? "block" : "none";
- secondaryPreviewZone.innerHTML = "";
- if (img) {
- secondaryPreviewZone.appendChild(img);
- }
-}
-
-function dismissPreview() {
- initSpritePreviewById(null);
-}
-
-function scaleAltSpritePreview() {
- if (mapImg && mapImg._image) {
- const id = secondaryPreviewIdInput.value;
- const scaleFactor = mapImg._image.clientWidth / mapImg._image.naturalWidth;
- const img = secondaryPreviewZone.children[0];
- const token = tokens.find(t=>t.t.id == id);
- if (img && token) {
- img.width = token.t.w * scaleFactor;
- img.height = token.t.h * scaleFactor;
-
- }
- }
-}
-
-function makeUpToDate(msg) {
- if (msg) {
-
- // map image has to be set before tokens can be handled!
- if (msg.mapImg) {
- setMapImg(msg.mapImg);
- }
-
- if (msg.auxMsg) {
- setAuxMsg(msg.auxMsg);
- }
-
- if (msg.diceRolls) {
- logDice(msg.diceRolls);
- } else if (msg.diceRoll) {
- logDice(msg.diceRoll);
- }
-
- if (msg.tokens) {
- updateTokens(msg.tokens);
- } else if (msg.token) {
- updateTokens([msg.token]);
- }
- }
-}
-
-function setMapImg(url) {
- initializeMap(url);
-}
-
-function isTableKeyValid(name, passcode) {
- const r = /^[a-zA-Z0-9_]+$/;
- return r.test(name) && r.test(passcode);
-}
-
-function leave() {
- conn.close(1000);
-}
+const msgQ = [];
function dial() {
// get tableKey from UI
- const tblNameInput = document.getElementById("input_table_name");
- const tblPassInput = document.getElementById("input_table_pass");
- const joinTblBtn = document.getElementById("table_join");
- const leaveTblBtn = document.getElementById("table_leave");
+ const tblNameInput = $("input_table_name");
+ const tblPassInput = $("input_table_pass");
+ const joinTblBtn = $("table_join");
+ const leaveTblBtn = $("table_leave");
if (tblNameInput && tblPassInput && tblNameInput.value && tblPassInput.value) {
if (isTableKeyValid(tblNameInput.value, tblPassInput.value)) {
@@ -191,8 +32,11 @@ function dial() {
setErr("Table not found - check the name and passcode are correct");
} else if (e.code > 1001) {
- lagDiv.style.display = "block";
- setTimeout(dial, 1000)
+ const lagDiv = $("lag");
+ if (lagDiv) {
+ lagDiv.style.display = "block";
+ setTimeout(dial, 1000)
+ }
} else {
tblNameInput.readOnly = false;
@@ -200,7 +44,7 @@ function dial() {
joinTblBtn.style.display = adminToken ? "none" : "inline";
leaveTblBtn.style.display = "none";
- tabletop = document.getElementById("tabletop");
+ tabletop = $("tabletop");
if (tabletop) {
tabletop.style.display = "none";
}
@@ -218,22 +62,29 @@ function dial() {
});
conn.addEventListener("open", e => {
+
offline = false;
tblNameInput.readOnly = true;
tblPassInput.readOnly = true;
joinTblBtn.style.display = "none";
leaveTblBtn.style.display = adminToken ? "none" : "inline";
- lagDiv.style.display = "none";
+ lagDiv = $("lag");
+ if (lagDiv) {
+ lagDiv.style.display = "none";
+ }
+
while (msgQ.some(m=>m)) {
publish(msgQ[0]);
msgQ.shift();
}
+
closeErr();
- tabletop = document.getElementById("tabletop");
+ tabletop = $("tabletop");
if (tabletop) {
tabletop.style.display = "block";
}
});
+
conn.addEventListener("error", e => {
setErr(`Websocket error`);
conn.close(3000);
@@ -283,3 +134,163 @@ async function publish(msg) {
}
}
}
+
+function makeUpToDate(msg) {
+ if (msg) {
+ // map image has to be set before tokens can be handled!
+ if (msg.mapImg) {
+ setMapImg(msg.mapImg);
+ }
+
+ if (msg.auxMsg) {
+ setAuxMsg(msg.auxMsg);
+ }
+
+ if (msg.diceRolls) {
+ logDice(msg.diceRolls);
+ } else if (msg.diceRoll) {
+ logDice(msg.diceRoll);
+ }
+
+ if (msg.tokens) {
+ updateTokens(msg.tokens);
+ } else if (msg.token) {
+ updateTokens([msg.token]);
+ }
+ }
+}
+
+function fmtLeading(n) {
+ return n < 10 ? "0" + n : String(n);
+}
+
+function formatDice(r) {
+ const date = new Date(r.timestamp)
+ const p = document.createElement("p");
+
+ const month = date.getMonth() + 1;
+ const day = date.getDate();
+ const hours = date.getHours();
+ const minutes = date.getMinutes();
+ const seconds = date.getSeconds();
+
+ p.innerHTML = `${date.getFullYear()}-${fmtLeading(month)}-${fmtLeading(day)} ${fmtLeading(hours)}:${fmtLeading(minutes)}:${fmtLeading(seconds)} ${r.player} rolled ${r.roll.length}d${r.faces} ${(r.note ? "(" + r.note + ")" : "")}
[${r.roll}] (total ${r.roll.reduce((a,c)=>a+c,0)})`;
+
+ return p;
+}
+
+function logDice(dice) {
+ const diceLog = $("dice_log");
+ if (!Array.isArray(dice)) {
+ dice = [ dice ];
+ } else {
+ if (diceLog) {
+ diceLog.innerHTML = "";
+ }
+ }
+ if (diceLog) {
+ for(const r of dice) {
+ try{
+ const p = formatDice(r);
+ diceLog.append(p);
+ p.scrollIntoView();
+ } catch{}
+ }
+ }
+}
+
+function setAuxMsg(msg) {
+ const auxDiv = $("aux");
+ if (auxDiv) {
+ auxDiv.innerText = msg;
+ }
+}
+
+function updateTokens(tokens) {
+ // update internal token array and map
+ processTokens(tokens);
+ // update token select window
+ renderTokenSelect();
+ // if admin, update token master list
+ renderTokenMasterList();
+}
+
+function renderTokenSelect() {
+ const tokenSelect = $("token_select");
+
+ if (tokenSelect) {
+ const scroll = tokenSelect.scrollTop;
+ tokenSelect.innerHTML = tokens.reduce((s, t) => {
+ return s + `
${t.t.name}\n`;
+ }, "");
+ tokenSelect.scrollTop = scroll;
+ }
+}
+
+// the following few functions aren't socket related but they directly relate to the previous function
+
+function initSpritePreviewById(id) {
+ const token = tokens.find(t=>t.t.id == id);
+ let img = null;
+
+ if (token && id) {
+
+ img = document.createElement("img");
+ img.src = token.t.sprite;
+ const hdnTokenId = $("token_preview_id");
+ if (hdnTokenId) {
+ hdnTokenId.value = id;
+ }
+
+ img.onload = () => {
+ scaleAltSpritePreview();
+ }
+ }
+
+ const previewClearBtn = $("token_preview_clear");
+ if (previewClearBtn) {
+ previewClearBtn.style.display = (token && id) ? "block" : "none";
+ }
+ const tokenPreview = $("token_preview");
+ if (tokenPreview) {
+ tokenPreview.innerHTML = "";
+ if (img) {
+ tokenPreview.appendChild(img);
+ }
+ }
+}
+
+function dismissPreview() {
+ initSpritePreviewById(null);
+}
+
+function scaleAltSpritePreview() {
+ const hdnTokenId = $("token_preview_id");
+ const tokenPreview = $("token_preview");
+ if (tokenPreview && hdnTokenId && mapImg && mapImg._image) {
+ const id = hdnTokenId.value;
+ const scaleFactor = mapImg._image.clientWidth / mapImg._image.naturalWidth;
+ const img = tokenPreview.children[0];
+ const token = tokens.find(t=>t.t.id == id);
+ if (img && token) {
+ img.width = token.t.w * scaleFactor;
+ img.height = token.t.h * scaleFactor;
+ }
+ }
+}
+
+function setMapImg(url) {
+ initializeMap(url);
+}
+
+function isTableKeyValid(name, passcode) {
+ const r = /^[a-zA-Z0-9_]+$/;
+ return r.test(name) && r.test(passcode);
+}
+
+function leave() {
+ conn.close(1000);
+ tableKey.name = "";
+ tableKey.passcode = "";
+}
+
diff --git a/static/style.css b/static/style.css
index 5bccfd3..b98f4d6 100644
--- a/static/style.css
+++ b/static/style.css
@@ -66,7 +66,7 @@ button:hover {
background: var(--main_color);
}
-#errWrapper {
+#err_wrapper {
color: var(--err_color);
background: var(--bg_color);
border: solid 2px var(--err_color);
@@ -78,14 +78,14 @@ button:hover {
transform: translateX(-50%);
}
-#closeErr {
+#err_close {
display: inline;
border: none;
color: var(--err_color);
padding: 0 1ch;
margin-right: 1ch;
}
-#errDiv {
+#err_div {
display: inline;
}
@@ -130,15 +130,12 @@ pre {
overflow-y: auto;
}
-#auxMsgZone {
+#aux_msg_input {
width: 100%;
padding:0.2em;
height: 8em;
}
-#adminWrapper {
-}
-
summary {
cursor: pointer;
}
@@ -205,11 +202,11 @@ nav {
background: transparent;
}
-#tokenKeepAspect {
+#token_aspect_lock {
display: none;
}
-#tokenPreview_zone {
+#token_admin_preview {
position: relative;
}
diff --git a/static/util.js b/static/util.js
index dd1cd26..c4bbda7 100644
--- a/static/util.js
+++ b/static/util.js
@@ -1,26 +1,17 @@
-const errDiv = document.getElementById("errDiv");
-const errWrapper = document.getElementById("errWrapper");
-
const defaultTheme = [ "#000000cc", "#ccccccff", "#1f9b92ff", "#002b36ff", "#DC143Cff" ];
-const bgCol_input = document.getElementById("bg_col_input");
-const fgCol_input = document.getElementById("fg_col_input");
-const mainCol_input = document.getElementById("main_col_input");
-const subCol_input = document.getElementById("sub_col_input");
-const errCol_input = document.getElementById("err_col_input");
-
-const bgOp_input = document.getElementById("bg_col_opacity");
-const fgOp_input = document.getElementById("fg_col_opacity");
-const mainOp_input = document.getElementById("main_col_opacity");
-const subOp_input = document.getElementById("sub_col_opacity");
-const errOp_input = document.getElementById("err_col_opacity");
-
const saveData = {
username: "",
theme: defaultTheme,
}
+function $(id) {
+ return document.getElementById(id);
+}
+
function setErr(x) {
+ const errDiv = $("err_div");
+ const errWrapper = $("err_wrapper");
if (errDiv) {
errDiv.innerHTML = x;
}
@@ -30,6 +21,7 @@ function setErr(x) {
}
function closeErr() {
+ const errWrapper = $("err_wrapper");
if (errWrapper) {
errWrapper.style.display = "none";
}
@@ -39,14 +31,14 @@ function loadStorage() {
saveData.username = localStorage.getItem("username");
savedTheme = JSON.parse(localStorage.getItem("theme"));
saveData.theme = savedTheme || defaultTheme;
- const username = document.getElementById("name_entry");
+ const username = $("name_entry");
if (username) {
username.value = saveData.username;
}
}
function saveName() {
- const username = document.getElementById("name_entry");
+ const username = $("name_entry");
if (username) {
saveData.username = username.value;
localStorage.setItem("username", saveData.username);
@@ -54,22 +46,26 @@ function saveName() {
}
function setupDiceAutoScroll() {
- const diceWin = document.getElementById("dice_win");
+ const diceWin = $("dice_win");
+
if (diceWin) {
diceWin.addEventListener("toggle", e => {
if (diceWin.open) {
- const diceLog = document.getElementById("dice_log");
- diceLog.children[diceLog.children.length - 1].scrollIntoView();
+ const diceLog = $("dice_log");
+ if (diceLog && diceLog.children.length > 0) {
+ diceLog.children[diceLog.children.length - 1].scrollIntoView();
+ }
}
});
}
}
function hexToBytes(hex) {
- let bytes = [];
- for (let c = 0; c < hex.length; c += 2)
- bytes.push(parseInt(hex.substr(c, 2), 16));
- return bytes;
+ let bytes = [];
+ for (let c = 0; c < hex.length; c += 2) {
+ bytes.push(parseInt(hex.substr(c, 2), 16));
+ }
+ return bytes;
}
function toByte(v) {
@@ -97,31 +93,31 @@ function resetTheme(theme) {
let err_opacity = hexToBytes(err_col.substr(7));
err_col = err_col.substr(0,7);
- bgCol_input.value = bg_col;
- bgOp_input.value = bg_opacity;
- fgCol_input.value = fg_col;
- fgOp_input.value = fg_opacity;
- mainCol_input.value = main_col;
- mainOp_input.value = main_opacity;
- subCol_input.value = sub_col;
- subOp_input.value = sub_opacity;
- errCol_input.value = err_col;
- errOp_input.value = err_opacity;
+ $("bg_col_input").value = bg_col;
+ $("bg_col_opacity").value = bg_opacity;
+ $("fg_col_input").value = fg_col;
+ $("fg_col_opacity").value = fg_opacity;
+ $("main_col_input").value = main_col;
+ $("main_col_opacity").value = main_opacity;
+ $("sub_col_input").value = sub_col;
+ $("sub_col_opacity").value = sub_opacity;
+ $("err_col_input").value = err_col;
+ $("err_col_opacity").value = err_opacity;
} catch {}
}
function setTheme() {
- try{
- let bg_col = bgCol_input.value;
- let bg_opacity = toByte(bgOp_input.value);
- let fg_col = fgCol_input.value;
- let fg_opacity =(toByte(fgOp_input.value));
- let main_col = mainCol_input.value;
- let main_opacity = (toByte(mainOp_input.value));
- let sub_col = subCol_input.value;
- let sub_opacity = (toByte(subOp_input.value));
- let err_col = errCol_input.value;
- let err_opacity = (toByte(errOp_input.value));
+ try {
+ let bg_col = $("bg_col_input").value
+ let bg_opacity = toByte($("bg_col_opacity").value);
+ let fg_col = $("fg_col_input").value;
+ let fg_opacity = (toByte($("fg_col_opacity").value));
+ let main_col = $("main_col_input").value;
+ let main_opacity = (toByte($("main_col_opacity").value));
+ let sub_col = $("sub_col_input").value;
+ let sub_opacity = (toByte($("sub_col_opacity").value));
+ let err_col = $("err_col_input").value;
+ let err_opacity = (toByte($("err_col_opacity").value));
saveData.theme[0] = bg_col + bg_opacity;
saveData.theme[1] = fg_col + fg_opacity;