Web Dev Solutions

Catalin Mititiuc

aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--public/index.html21
-rw-r--r--public/map.css5
-rw-r--r--public/map1.svg (renamed from public/map.svg)0
-rw-r--r--public/map2.svg84
-rw-r--r--src/index.js169
-rw-r--r--src/modules/gameboard.js16
-rw-r--r--src/modules/record_sheet.js4
7 files changed, 214 insertions, 85 deletions
diff --git a/public/index.html b/public/index.html
index ef12273..d8a91f9 100644
--- a/public/index.html
+++ b/public/index.html
@@ -104,7 +104,7 @@
Loading...
</div>
- <object type="image/svg+xml" data="map.svg"></object>
+ <object type="image/svg+xml" data="map1.svg"></object>
<div id="status">
<span id="hex-counter">Distance: <span id="hex-count">-</span></span>
@@ -134,6 +134,25 @@
<span class="inning-top">◓</span>
<span class="inning-bottom">◒</span>
</span>
+
+ <dialog id="map-dialog">
+ <form>
+ <p>
+ <label>
+ Map:
+ <select>
+ <option value="map1">Map1</option>
+ <option value="map2">Map2</option>
+ </select>
+ </label>
+ </p>
+ <div>
+ <button value="cancel" formmethod="dialog">Cancel</button>
+ <button id="confirm-btn" value="default">Confirm</button>
+ </div>
+ </form>
+ </dialog>
+ <button id="show-dialog">Change map</button>
</div>
<div id="record-sheet">
diff --git a/public/map.css b/public/map.css
index 932d224..dbabab9 100644
--- a/public/map.css
+++ b/public/map.css
@@ -203,11 +203,11 @@ g.selected use {
transform: translate(19px, 31px) scale(4);
}
-g.start-locations > g:first-child {
+g.start-locations > g:first-child:not([data-y]) {
--i: -2;
}
-g.start-locations > g:last-child {
+g.start-locations > g:last-child:not([data-y]) {
--i: 52;
}
@@ -249,6 +249,7 @@ g[data-y]:nth-child(odd) {
transform: translateX(calc(var(--x-step) * var(--i))) scale(var(--scale));
}
+g[data-y="-2"] { --i: -2; }
g[data-y="0"] { --i: 0; }
g[data-y="1"] { --i: 1; }
g[data-y="2"] { --i: 2; }
diff --git a/public/map.svg b/public/map1.svg
index d927ae4..d927ae4 100644
--- a/public/map.svg
+++ b/public/map1.svg
diff --git a/public/map2.svg b/public/map2.svg
new file mode 100644
index 0000000..1d0f8c4
--- /dev/null
+++ b/public/map2.svg
@@ -0,0 +1,84 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg viewBox="-25 -150 400 570" xmlns="http://www.w3.org/2000/svg">
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="stylesheet" href="map.css" type="text/css"/>
+ <defs>
+ <polygon id="hex" points="0,10 8.66,5 8.66,-5 0,-10 -8.66,-5 -8.66,5"/>
+
+ <circle id="counter-base" cx="0" cy="0" r="5"/>
+
+ <g id="t-1" class="troop-counter-template"><use href="#counter-base"/><text>1</text></g>
+ <g id="t-2" class="troop-counter-template"><use href="#counter-base"/><text>2</text></g>
+ <g id="t-3" class="troop-counter-template"><use href="#counter-base"/><text>3</text></g>
+ <g id="t-4" class="troop-counter-template"><use href="#counter-base"/><text>4</text></g>
+ <g id="t-5" class="troop-counter-template"><use href="#counter-base"/><text>5</text></g>
+ <g id="t-6" class="troop-counter-template"><use href="#counter-base"/><text>6</text></g>
+ <g id="t-7" class="troop-counter-template"><use href="#counter-base"/><text>7</text></g>
+
+ <image id="counter-prone" href="counter_prone.jpg" width="10"/>
+ <image id="counter-grenade" href="counter_grenade.jpg" width="10"/>
+ </defs>
+
+ <rect id="background" x="-18" y="-10" width="386" height="322"/>
+
+ <g class="board">
+ <g id="firing-arcs">
+ <g id="shapes"/>
+ <g id="lines"/>
+ </g>
+ <g class="start-locations">
+ <g data-y="-2">
+ <g data-x="4" class="counter" data-allegiance="liao" data-number="1"><use href="#t-1"/></g>
+ <g data-x="3" class="counter" data-allegiance="liao" data-number="2"><use href="#t-2"/></g>
+ <g data-x="2" class="counter" data-allegiance="liao" data-number="3"><use href="#t-3"/></g>
+ <g data-x="1" class="counter" data-allegiance="liao" data-number="4"><use href="#t-4"/></g>
+ <g data-x="0" class="counter" data-allegiance="liao" data-number="5"><use href="#t-5"/></g>
+ </g>
+ <g data-y="6">
+ <g data-x="0" class="counter" data-allegiance="davion" data-number="1"><use href="#t-1"/></g>
+ <g data-x="1" class="counter" data-allegiance="davion" data-number="2"><use href="#t-2"/></g>
+ <g data-x="2" class="counter" data-allegiance="davion" data-number="3"><use href="#t-3"/></g>
+ <g data-x="3" class="counter" data-allegiance="davion" data-number="4"><use href="#t-4"/></g>
+ <g data-x="4" class="counter" data-allegiance="davion" data-number="5"><use href="#t-5"/></g>
+ </g>
+ </g>
+ <g class="grid">
+ <g data-y="0">
+ <g data-x="0"><use href="#hex"/></g>
+ <g data-x="1"><use href="#hex"/></g>
+ <g data-x="2"><use href="#hex"/></g>
+ <g data-x="3"><use href="#hex"/></g>
+ <g data-x="4"><use href="#hex"/></g>
+ </g>
+ <g data-y="1">
+ <g data-x="0"><use href="#hex"/></g>
+ <g data-x="1"><use href="#hex"/></g>
+ <g data-x="2"><use href="#hex"/></g>
+ <g data-x="3"><use href="#hex"/></g>
+ <g data-x="4"><use href="#hex"/></g>
+ </g>
+ <g data-y="2">
+ <g data-x="0"><use href="#hex"/></g>
+ <g data-x="1"><use href="#hex"/></g>
+ <g data-x="2"><use href="#hex"/></g>
+ <g data-x="3"><use href="#hex"/></g>
+ <g data-x="4"><use href="#hex"/></g>
+ </g>
+ <g data-y="3">
+ <g data-x="0"><use href="#hex"/></g>
+ <g data-x="1"><use href="#hex"/></g>
+ <g data-x="2"><use href="#hex"/></g>
+ <g data-x="3"><use href="#hex"/></g>
+ <g data-x="4"><use href="#hex"/></g>
+ </g>
+ <g data-y="4">
+ <g data-x="0"><use href="#hex"/></g>
+ <g data-x="1"><use href="#hex"/></g>
+ <g data-x="2"><use href="#hex"/></g>
+ <g data-x="3"><use href="#hex"/></g>
+ <g data-x="4"><use href="#hex"/></g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/src/index.js b/src/index.js
index 40ee397..a8b766a 100644
--- a/src/index.js
+++ b/src/index.js
@@ -6,13 +6,89 @@ globalThis.svgns = "http://www.w3.org/2000/svg";
const mapPlaceholder = document.querySelector('.map-placeholder'),
distanceOutput = document.getElementById('status'),
- proneToggle = document.getElementById('toggle-prone-counter');
+ proneToggle = document.getElementById('toggle-prone-counter'),
+ object = document.querySelector('object');
-document.querySelector('object').addEventListener('load', function () {
+object.addEventListener('load', function () {
mapPlaceholder.remove();
this.style.opacity = 1;
+
+ const svg = this.contentDocument.querySelector('svg');
+ panzoom.start(svg);
+ gameboard.start(svg);
+});
+
+gameboard.setDistanceCallback((count = '-') => {
+ distanceOutput.querySelector('#hex-count').textContent = count;
+ distanceOutput.style.display = count === '-' ? 'none' : 'block';
+});
+
+gameboard.setProneFlagCallback(checked => proneToggle.checked = checked);
+gameboard.setSelectCallback(data => recordSheet.select(data));
+
+document.querySelectorAll('.soldier-record').forEach(el =>
+ el.addEventListener('click', () => {
+ if (el.classList.contains('selected')) {
+ el.classList.remove('selected');
+ gameboard.unSelect();
+ recordSheet.unSelect();
+ } else {
+ gameboard.select(el);
+ }
+ })
+);
+
+document.querySelectorAll('.end-move').forEach(el => el.addEventListener('click', () => {
+ recordSheet.endMove();
+ gameboard.endMove();
+}));
+
+document.querySelectorAll('.end-turn').forEach(el =>
+ el.addEventListener('click', ({ target: { dataset: { allegiance }}}) => {
+ const dataSelector = `[data-allegiance="${allegiance}"]`,
+ records = Array.from(document.querySelectorAll(`.soldier-record${dataSelector}`)),
+ turnCounter = document.getElementById('turn-count'),
+ { dataset: { update }} = turnCounter;
+
+ el.setAttribute('disabled', '');
+
+ document
+ .querySelector(`button.end-turn:not([data-allegiance="${allegiance}"])`)
+ .removeAttribute('disabled');
+
+ if (update === '1') {
+ turnCounter.children.namedItem('count').textContent++
+ turnCounter.dataset.update = '0';
+ } else {
+ turnCounter.dataset.update = '1';
+ }
+
+ records
+ .sort((el1, el2) => el1.dataset.number > el2.dataset.number)
+ .forEach(el => el.classList.remove('movement-ended'));
+
+ gameboard.endTurn(allegiance);
+ gameboard.select(records.at(0));
+ })
+);
+
+document.querySelectorAll('.set-firing-arc').forEach(el =>
+ el.addEventListener('click', gameboard.setFiringArc)
+);
+
+document.querySelector('.set-grenade').addEventListener('click', gameboard.setGrenade);
+
+document.querySelectorAll('#toggle-firing-arc-vis input').forEach(el =>
+ el.addEventListener('input', gameboard.toggleFiringArcVisibility)
+);
+
+document.getElementById('toggle-prone-counter').addEventListener('input', function () {
+ const selected = recordSheet.getSelected();
+ selected && gameboard.toggleProne();
});
+object.data = `${localStorage.getItem('map') || 'map1'}.svg`;
+
document
.querySelector('#content input[type="checkbox"].visible')
.addEventListener('input', function () {
@@ -27,78 +103,27 @@ document
});
});
-window.addEventListener('load', () => {
- const svg = document.querySelector('object').contentDocument.querySelector('svg');
-
- gameboard.start(svg);
- panzoom.start(svg);
-
- gameboard.setDistanceCallback((count = '-') => {
- distanceOutput.querySelector('#hex-count').textContent = count;
- distanceOutput.style.display = count === '-' ? 'none' : 'block';
- });
-
- gameboard.setProneFlagCallback(checked => proneToggle.checked = checked);
- gameboard.setSelectCallback(data => recordSheet.select(data));
-
- document.querySelectorAll('.soldier-record').forEach(el =>
- el.addEventListener('click', () => {
- if (el.classList.contains('selected')) {
- el.classList.remove('selected');
- gameboard.unSelect();
- recordSheet.unSelect();
- } else {
- gameboard.select(el);
- }
- })
- );
-
- document.querySelectorAll('.end-move').forEach(el => el.addEventListener('click', () => {
- recordSheet.endMove();
- gameboard.endMove();
- }));
-
- document.querySelectorAll('.end-turn').forEach(el =>
- el.addEventListener('click', ({ target: { dataset: { allegiance }}}) => {
- const dataSelector = `[data-allegiance="${allegiance}"]`,
- records = Array.from(document.querySelectorAll(`.soldier-record${dataSelector}`)),
- turnCounter = document.getElementById('turn-count'),
- { dataset: { update }} = turnCounter;
-
- el.setAttribute('disabled', '');
-
- document
- .querySelector(`button.end-turn:not([data-allegiance="${allegiance}"])`)
- .removeAttribute('disabled');
-
- if (update === '1') {
- turnCounter.children.namedItem('count').textContent++
- turnCounter.dataset.update = '0';
- } else {
- turnCounter.dataset.update = '1';
- }
-
- records
- .sort((el1, el2) => el1.dataset.number > el2.dataset.number)
- .forEach(el => el.classList.remove('movement-ended'));
-
- gameboard.endTurn(allegiance);
- gameboard.select(records.at(0));
- })
- );
+const showButton = document.getElementById('show-dialog'),
+ mapDialog = document.getElementById('map-dialog'),
+ selectEl = mapDialog.querySelector('select'),
+ confirmBtn = mapDialog.querySelector('#confirm-btn');
- document.querySelectorAll('.set-firing-arc').forEach(el =>
- el.addEventListener('click', gameboard.setFiringArc)
- );
+mapDialog.querySelectorAll('option').forEach(option =>
+ option.value === localStorage.getItem('map') && (option.selected = true)
+);
- document.querySelector('.set-grenade').addEventListener('click', gameboard.setGrenade);
+showButton.addEventListener('click', () => {
+ mapDialog.showModal();
+});
- document.querySelectorAll('#toggle-firing-arc-vis input').forEach(el =>
- el.addEventListener('input', gameboard.toggleFiringArcVisibility)
- );
+selectEl.addEventListener('change', () => {
+ confirmBtn.value = selectEl.value;
+});
- document.getElementById('toggle-prone-counter').addEventListener('input', function () {
- const selected = recordSheet.getSelected();
- selected && gameboard.toggleProne();
- });
+confirmBtn.addEventListener('click', e => {
+ e.preventDefault();
+ localStorage.removeItem('pan-zoom');
+ localStorage.setItem('map', selectEl.value);
+ document.querySelector('object').data = `${selectEl.value}.svg`;
+ mapDialog.close();
});
diff --git a/src/modules/gameboard.js b/src/modules/gameboard.js
index 9f8723e..25db4ad 100644
--- a/src/modules/gameboard.js
+++ b/src/modules/gameboard.js
@@ -19,14 +19,14 @@ function getCellOccupant(cell) {
}
function getCells(svg) {
- return svg.querySelectorAll('g[data-y] > g[data-x]');
+ return svg.querySelectorAll('g.grid > g[data-y] > g[data-x]');
}
function getLockedSightLine(svg) {
return svg.querySelector('line.sight-line:not(.active)');
}
-function getSightLine(svg) {
+export function getSightLine(svg) {
return svg.querySelector('line.sight-line');
}
@@ -63,7 +63,7 @@ function getCellPosition(cell) {
}
function getCell(x, y) {
- return svg.querySelector(`g[data-y="${y}"] > g[data-x="${x}"]`);
+ return svg.querySelector(`g.grid > g[data-y="${y}"] > g[data-x="${x}"]`);
}
function getCounterAtGridIndex(x, y) {
@@ -85,7 +85,7 @@ function updateSightLine(cell) {
{ dataset: { x: tX }, parentElement: { dataset: { y: tY }}} = sightLine.getLockTarget();
const selector = sightLine.calcIndexes(+sX, +sY, +tX, +tY)
- .map(([x, y]) => `g[data-y="${y}"] g[data-x="${x}"] use[href="#hex"]`)
+ .map(([x, y]) => `g.grid g[data-y="${y}"] g[data-x="${x}"] use[href="#hex"]`)
.join(', ');
const hexes = svg.querySelectorAll(selector);
@@ -99,7 +99,7 @@ function drawSightLine(sourceCell, targetCell) {
{ dataset: { x: tX }, parentElement: { dataset: { y: tY }}} = targetCell;
const selector = sightLine.calcIndexes(+sX, +sY, +tX, +tY)
- .map(([x, y]) => `g[data-y="${y}"] g[data-x="${x}"] use[href="#hex"]`)
+ .map(([x, y]) => `g.grid g[data-y="${y}"] g[data-x="${x}"] use[href="#hex"]`)
.join(', ');
const hexes = svg.querySelectorAll(selector);
@@ -277,9 +277,9 @@ export function start(el) {
});
// debug
- const c = soldier.getCounter(svg, { dataset: { allegiance: 'davion', number: '1' }});
- soldier.place(svg, c, getCell(17, 25));
- select(c);
+ // const c = soldier.getCounter(svg, { dataset: { allegiance: 'davion', number: '1' }});
+ // soldier.place(svg, c, getCell(17, 25));
+ // select(c);
}
export function select(selected) {
diff --git a/src/modules/record_sheet.js b/src/modules/record_sheet.js
index 99af18f..e5e8de6 100644
--- a/src/modules/record_sheet.js
+++ b/src/modules/record_sheet.js
@@ -14,9 +14,9 @@ export function getSelected() {
export function select(data) {
const selector =
- `#record-sheet .soldier-record[data-number="${data.number}"][data-allegiance="${data.allegiance}"]`
+ `#record-sheet .soldier-record[data-number="${data.number}"][data-allegiance="${data.allegiance}"]`
- unSelect();
+ unSelect();
document.querySelector(selector).classList.add('selected');
document.getElementById('toggle-prone-counter').checked = data.prone;
}