Remove select callbacks and use observable instead
This commit is contained in:
parent
cebf4ca548
commit
9d4952eaad
@ -116,7 +116,7 @@ function load() {
|
|||||||
|
|
||||||
panzoom.start(svg);
|
panzoom.start(svg);
|
||||||
gameboard.start(svg);
|
gameboard.start(svg);
|
||||||
recordSheet.start(startLocs, gameboard.getUnits(), gameboard.unSelect, gameboard.select);
|
recordSheet.start(startLocs, gameboard.getUnits());
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelectorAll('.end-turn').forEach(el =>
|
document.querySelectorAll('.end-turn').forEach(el =>
|
||||||
@ -158,14 +158,13 @@ gameboard.setDistanceCallback((count = '-') => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gameboard.setProneFlagCallback(checked => proneToggle.checked = checked);
|
gameboard.setProneFlagCallback(checked => proneToggle.checked = checked);
|
||||||
gameboard.setSelectCallback(data => recordSheet.select(data));
|
|
||||||
|
|
||||||
document.querySelectorAll('.end-move').forEach(el => el.addEventListener('click', () => {
|
document.querySelectorAll('.end-move').forEach(el => el.addEventListener('click', () => {
|
||||||
recordSheet.endMove();
|
recordSheet.endMove();
|
||||||
gameboard.endMove();
|
gameboard.endMove();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
document.querySelector('#fullscreen').addEventListener('click', e => {
|
document.querySelector('#fullscreen').addEventListener('click', () => {
|
||||||
if (!document.fullscreenElement) {
|
if (!document.fullscreenElement) {
|
||||||
document.documentElement.requestFullscreen();
|
document.documentElement.requestFullscreen();
|
||||||
} else if (document.exitFullscreen) {
|
} else if (document.exitFullscreen) {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import * as firingArc from './game/firing_arc.js';
|
import * as firingArc from './game/firing_arc.js';
|
||||||
import * as sightLine from './game/sight_line.js';
|
import * as sightLine from './game/sight_line.js';
|
||||||
import * as soldier from './game/soldier.js';
|
import * as soldier from './game/soldier.js';
|
||||||
|
import { Observable } from "./observable";
|
||||||
|
|
||||||
let svg, distanceCallback, proneFlagCallback, selectCallback,
|
let svg, distanceCallback, proneFlagCallback,
|
||||||
selected,
|
selected,
|
||||||
placing = [];
|
placing = [];
|
||||||
|
|
||||||
@ -74,6 +75,17 @@ function getSelected() {
|
|||||||
return svg.querySelector(`.counter.selected[data-allegiance][data-number]`);
|
return svg.querySelector(`.counter.selected[data-allegiance][data-number]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deselect() {
|
||||||
|
const selected = getSelected();
|
||||||
|
placing = [];
|
||||||
|
|
||||||
|
if (selected) {
|
||||||
|
selected.classList.remove(soldier.getSelectedClass());
|
||||||
|
clearSightLine();
|
||||||
|
firingArc.clipAll(svg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function clearSightLine() {
|
function clearSightLine() {
|
||||||
sightLine.setHexes([]);
|
sightLine.setHexes([]);
|
||||||
sightLine.clear();
|
sightLine.clear();
|
||||||
@ -159,7 +171,7 @@ function hasPreviousMoveInHistory(counter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function selectOffBoard() {
|
function selectOffBoard() {
|
||||||
this.classList.contains(soldier.getSelectedClass()) ? unSelect() : select(this);
|
Observable.notify('select', this);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUnits() {
|
export function getUnits() {
|
||||||
@ -174,10 +186,6 @@ export function setProneFlagCallback(callback) {
|
|||||||
proneFlagCallback = callback;
|
proneFlagCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setSelectCallback(callback) {
|
|
||||||
selectCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function start(el) {
|
export function start(el) {
|
||||||
svg = el;
|
svg = el;
|
||||||
|
|
||||||
@ -202,10 +210,10 @@ export function start(el) {
|
|||||||
placing.push(toPlace);
|
placing.push(toPlace);
|
||||||
getLockedSightLine(svg) ? updateSightLine(toPlace.parentElement) : drawSightLine(toPlace.parentElement, cell);
|
getLockedSightLine(svg) ? updateSightLine(toPlace.parentElement) : drawSightLine(toPlace.parentElement, cell);
|
||||||
} else {
|
} else {
|
||||||
unSelect();
|
deselect();
|
||||||
}
|
}
|
||||||
} else if (!occupant.classList.contains('clone')) {
|
} else if (!occupant.classList.contains('clone')) {
|
||||||
select(occupant);
|
Observable.notify('select', occupant);
|
||||||
} else {
|
} else {
|
||||||
if (isClone(occupant).of(toPlace)) {
|
if (isClone(occupant).of(toPlace)) {
|
||||||
if (hasPreviousMoveInHistory(occupant)) {
|
if (hasPreviousMoveInHistory(occupant)) {
|
||||||
@ -218,7 +226,7 @@ export function start(el) {
|
|||||||
placing.push(toPlace);
|
placing.push(toPlace);
|
||||||
}
|
}
|
||||||
} else if (!toPlace && occupant) {
|
} else if (!toPlace && occupant) {
|
||||||
select(occupant);
|
Observable.notify('select', occupant);
|
||||||
} else {
|
} else {
|
||||||
console.log('removing cell contents');
|
console.log('removing cell contents');
|
||||||
getCellContents(cell).forEach(el => el.remove());
|
getCellContents(cell).forEach(el => el.remove());
|
||||||
@ -234,7 +242,7 @@ export function start(el) {
|
|||||||
selector = `[data-allegiance="${allegiance}"][data-number="${number}"]`;
|
selector = `[data-allegiance="${allegiance}"][data-number="${number}"]`;
|
||||||
|
|
||||||
svg.querySelectorAll(selector).forEach(el => el.remove());
|
svg.querySelectorAll(selector).forEach(el => el.remove());
|
||||||
selectCallback();
|
Observable.notify('select');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -271,33 +279,23 @@ export function start(el) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Observable.subscribe('select', select);
|
||||||
console.log('gameboard.js loaded');
|
console.log('gameboard.js loaded');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function select(selected) {
|
export function select(data) {
|
||||||
unSelect();
|
if (!data) return;
|
||||||
let counter = soldier.getCounter(svg, selected);
|
|
||||||
|
|
||||||
if (counter) {
|
const counter = soldier.getCounter(svg, data) || soldier.createCounter(data);
|
||||||
firingArc.get(svg, counter).forEach(el => el.removeAttribute('clip-path'));
|
const isSelected = counter.classList.contains(soldier.getSelectedClass());
|
||||||
} else {
|
|
||||||
counter = soldier.createCounter(selected);
|
deselect();
|
||||||
}
|
|
||||||
|
if (isSelected) return;
|
||||||
|
|
||||||
placing.push(counter);
|
|
||||||
counter.classList.add(soldier.getSelectedClass());
|
counter.classList.add(soldier.getSelectedClass());
|
||||||
selectCallback && selectCallback({ prone: soldier.hasProne(counter), ...counter.dataset });
|
firingArc.get(svg, counter).forEach(el => el.removeAttribute('clip-path'));
|
||||||
}
|
placing.push(counter);
|
||||||
|
|
||||||
export function unSelect() {
|
|
||||||
const selected = getSelected();
|
|
||||||
placing = [];
|
|
||||||
|
|
||||||
if (selected) {
|
|
||||||
getSelected().classList.remove(soldier.getSelectedClass());
|
|
||||||
clearSightLine();
|
|
||||||
firingArc.clipAll(svg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function endMove() {
|
export function endMove() {
|
||||||
@ -305,7 +303,7 @@ export function endMove() {
|
|||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
soldier.endMove(svg, selected);
|
soldier.endMove(svg, selected);
|
||||||
unSelect();
|
deselect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
src/modules/observable.js
Normal file
19
src/modules/observable.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
const observers = {};
|
||||||
|
|
||||||
|
export const Observable = Object.freeze({
|
||||||
|
notify: (event, data) => {
|
||||||
|
observers[event].forEach((observer) => observer(data))
|
||||||
|
},
|
||||||
|
|
||||||
|
subscribe: (event, func) => {
|
||||||
|
(observers[event] ??= []).push(func);
|
||||||
|
},
|
||||||
|
|
||||||
|
unsubscribe: (event, func) => {
|
||||||
|
[...observers[event] || []].forEach((observer, index) => {
|
||||||
|
if (observer === func) {
|
||||||
|
observers[event].splice(index, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
@ -1,3 +1,5 @@
|
|||||||
|
import { Observable } from "./observable";
|
||||||
|
|
||||||
const weapons = {
|
const weapons = {
|
||||||
rifle: {
|
rifle: {
|
||||||
name: 'Rifle',
|
name: 'Rifle',
|
||||||
@ -98,27 +100,19 @@ function createRecords(units) {
|
|||||||
return grouped;
|
return grouped;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addEventListeners(unSelectCounter, selectCounter) {
|
function getRecord({ dataset: { allegiance: al, number: n }}) {
|
||||||
document.querySelectorAll('.soldier-record').forEach(el =>
|
const selector = `.soldier-record[data-number="${n}"][data-allegiance="${al}"]`;
|
||||||
el.addEventListener('click', () => {
|
|
||||||
if (el.classList.contains('selected')) {
|
return document.querySelector(selector);
|
||||||
el.classList.remove('selected');
|
|
||||||
unSelectCounter();
|
|
||||||
unSelect();
|
|
||||||
} else {
|
|
||||||
selectCounter(el);
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
function addEventListeners() {
|
||||||
|
document.querySelectorAll('.soldier-record').forEach(el =>
|
||||||
|
el.addEventListener('click', () => Observable.notify('select', el))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clear() {
|
function deselect() {
|
||||||
document.querySelectorAll('#record-sheet .soldier-record').forEach(el => el.remove());
|
|
||||||
document.querySelector('#attacker-record .name').textContent = 'attacker';
|
|
||||||
document.querySelector('#defender-record .name').textContent = 'defender';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function unSelect() {
|
|
||||||
const selected = getSelected();
|
const selected = getSelected();
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
@ -128,24 +122,28 @@ export function unSelect() {
|
|||||||
document.getElementById('toggle-prone-counter').checked = false;
|
document.getElementById('toggle-prone-counter').checked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clear() {
|
||||||
|
document.querySelectorAll('#record-sheet .soldier-record').forEach(el => el.remove());
|
||||||
|
document.querySelector('#attacker-record .name').textContent = 'attacker';
|
||||||
|
document.querySelector('#defender-record .name').textContent = 'defender';
|
||||||
|
}
|
||||||
|
|
||||||
|
function select(data) {
|
||||||
|
const record = data && getRecord(data);
|
||||||
|
const isSelected = record?.classList.contains('selected');
|
||||||
|
|
||||||
|
deselect();
|
||||||
|
|
||||||
|
if (isSelected || !data) return;
|
||||||
|
|
||||||
|
record.classList.add('selected');
|
||||||
|
document.querySelector('#toggle-prone-counter').checked = data.prone;
|
||||||
|
}
|
||||||
|
|
||||||
export function getSelected() {
|
export function getSelected() {
|
||||||
return document.querySelector('.soldier-record.selected');
|
return document.querySelector('.soldier-record.selected');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function select(data) {
|
|
||||||
unSelect();
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { allegiance: al, number: n } = data,
|
|
||||||
selector = `.soldier-record[data-number="${n}"][data-allegiance="${al}"]`;
|
|
||||||
|
|
||||||
document.querySelector(selector).classList.add('selected');
|
|
||||||
document.querySelector('#toggle-prone-counter').checked = data.prone;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function endMove() {
|
export function endMove() {
|
||||||
const selected = getSelected();
|
const selected = getSelected();
|
||||||
|
|
||||||
@ -153,10 +151,10 @@ export function endMove() {
|
|||||||
selected.classList.toggle('movement-ended');
|
selected.classList.toggle('movement-ended');
|
||||||
}
|
}
|
||||||
|
|
||||||
unSelect();
|
deselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function start(startLoc, units, gbUnSelect, gbSelect) {
|
export function start(startLoc, units) {
|
||||||
clear();
|
clear();
|
||||||
const forces = createRecords(units);
|
const forces = createRecords(units);
|
||||||
|
|
||||||
@ -171,5 +169,6 @@ export function start(startLoc, units, gbUnSelect, gbSelect) {
|
|||||||
forces[affiliation].forEach(r => records.appendChild(r));
|
forces[affiliation].forEach(r => records.appendChild(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
addEventListeners(gbUnSelect, gbSelect);
|
Observable.subscribe('select', select);
|
||||||
|
addEventListeners();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user