index : btroops | |
Virtual board game-aid for BattleTroops, an infantry combat simulator wargame published by FASA in 1989. |
aboutsummaryrefslogtreecommitdiff |
diff options
author | Catalin Mititiuc <webdevcat@proton.me> | 2024-04-30 16:58:12 -0700 |
---|---|---|
committer | Catalin Mititiuc <webdevcat@proton.me> | 2024-04-30 16:58:12 -0700 |
commit | d393934679290ab4e16aa0b4a73408273eb26596 (patch) | |
tree | 3b660a79ee2c9e062675b87f7bda9afa4a06f8ca /src | |
parent | 9c67c4a4a538c44fe8365536fa3dc4b1cc973b4b (diff) |
Refactor index.js
Diffstat (limited to 'src')
-rw-r--r-- | src/index.js | 169 | ||||
-rw-r--r-- | src/modules/gameboard.js | 2 | ||||
-rw-r--r-- | src/modules/map_select_dialog.js | 42 | ||||
-rw-r--r-- | src/modules/record_sheet.js | 60 |
4 files changed, 155 insertions, 118 deletions
diff --git a/src/index.js b/src/index.js index b6315f5..5c20a8e 100644 --- a/src/index.js +++ b/src/index.js @@ -1,91 +1,62 @@ import * as panzoom from './modules/pan-zoom.js'; import * as gameboard from './modules/gameboard.js'; import * as recordSheet from './modules/record_sheet.js'; +import * as mapSelectDialog from './modules/map_select_dialog.js'; globalThis.svgns = "http://www.w3.org/2000/svg"; const mapPlaceholder = document.querySelector('.map-placeholder'), distanceOutput = document.getElementById('status'), proneToggle = document.getElementById('toggle-prone-counter'), - object = document.querySelector('object'); + object = document.querySelector('object'), + contentVisToggleEl = document.querySelector('#content input[type="checkbox"].visible'), -object.addEventListener('load', function (e) { - mapPlaceholder.remove(); - this.style.opacity = 1; - - const svg = this.contentDocument.querySelector('svg'); - panzoom.start(svg); - gameboard.start(svg); - - recordSheet.clear(); - - const recordTemplate = document.querySelector('template#soldier-record-block'); - const startLoc = svg.querySelector('.start-locations'); - const forces = recordSheet.createRecords(gameboard.getUnits(), recordTemplate); - - for (const affiliation in forces) { - const container = document.querySelector(`#${affiliation}-record`); - const name = startLoc.dataset[`${affiliation}Name`]; - if (name) { - container.querySelector('.name').textContent = name; - } - forces[affiliation].forEach(r => container.appendChild(r)); - } - - document.querySelectorAll('.soldier-record').forEach(el => - el.addEventListener('click', () => { - if (el.classList.contains('selected')) { - el.classList.remove('selected'); - gameboard.unSelect(); - recordSheet.unSelect(); + toggleContentVis = (function () { + document.querySelectorAll('#content div').forEach(div => { + if (this.checked) { + div.style.display = div.id == 'record-sheet' ? 'flex' : 'block'; } else { - gameboard.select(el); + div.style.display = 'none'; } - }) - ); + }); - window.game = gameboard; -}); + localStorage.setItem('content-visibility', this.checked); + }).bind(contentVisToggleEl); -gameboard.setDistanceCallback((count = '-') => { - distanceOutput.querySelector('#hex-count').textContent = count; - distanceOutput.style.display = count === '-' ? 'none' : 'block'; -}); +function updateTurnCounter() { + const turnCounter = document.getElementById('turn-count'); -gameboard.setProneFlagCallback(checked => proneToggle.checked = checked); -gameboard.setSelectCallback(data => recordSheet.select(data)); + if (turnCounter.dataset.update === '1') { + turnCounter.children.namedItem('count').textContent++; + turnCounter.dataset.update = '0'; + } else { + turnCounter.dataset.update = '1'; + } +} -document.querySelectorAll('.end-move').forEach(el => el.addEventListener('click', () => { - recordSheet.endMove(); - gameboard.endMove(); -})); +function enableEndTurnButton(allegiance) { + document + .querySelector(`button.end-turn:not([data-allegiance="${allegiance}"])`) + .removeAttribute('disabled'); +} + +function clearMoveEndedIndicators(records) { + records.forEach(el => el.classList.remove('movement-ended')); +} 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.addEventListener('click', ({ target: { dataset: { allegiance: opponent }}}) => { + const dataSelector = `[data-allegiance="${opponent}"]`, + opponentRecords = Array.from(document.querySelectorAll(`.soldier-record${dataSelector}`)), + firstOpponentRecord = opponentRecords.sort((el1, el2) => el1.dataset.number > el2.dataset.number).at(0); el.setAttribute('disabled', ''); + updateTurnCounter(); + enableEndTurnButton(opponent); + clearMoveEndedIndicators(opponentRecords); - 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)); + gameboard.clearFiringArcs(opponent); + gameboard.select(firstOpponentRecord); }) ); @@ -104,47 +75,41 @@ document.getElementById('toggle-prone-counter').addEventListener('input', functi selected && gameboard.toggleProne(); }); -object.data = `${localStorage.getItem('map') || 'map1'}.svg`; - -const contentVisToggleEl = document.querySelector('#content input[type="checkbox"].visible'); -contentVisToggleEl.checked = (localStorage.getItem('content-visibility') !== 'false'); +contentVisToggleEl.addEventListener('input', toggleContentVis); -const toggleContentVis = (function () { - document.querySelectorAll('#content div').forEach(div => { - if (this.checked) { - div.style.display = div.id == 'record-sheet' ? 'flex' : 'block'; - } else { - div.style.display = 'none'; - } - }); +gameboard.setDistanceCallback((count = '-') => { + distanceOutput.querySelector('#hex-count').textContent = count; + distanceOutput.style.display = count === '-' ? 'none' : 'block'; +}); - localStorage.setItem('content-visibility', this.checked); -}).bind(contentVisToggleEl); +gameboard.setProneFlagCallback(checked => proneToggle.checked = checked); +gameboard.setSelectCallback(data => recordSheet.select(data)); -toggleContentVis(); -contentVisToggleEl.addEventListener('input', toggleContentVis); +document.querySelectorAll('.end-move').forEach(el => el.addEventListener('click', () => { + recordSheet.endMove(); + gameboard.endMove(); +})); -const showButton = document.getElementById('show-dialog'), - mapDialog = document.getElementById('map-dialog'), - selectEl = mapDialog.querySelector('select'), - confirmBtn = mapDialog.querySelector('#confirm-btn'); +object.addEventListener('load', function () { + mapPlaceholder.remove(); + this.style.opacity = 1; -mapDialog.querySelectorAll('option').forEach(option => - option.value === localStorage.getItem('map') && (option.selected = true) -); + const svg = this.contentDocument.querySelector('svg'), + startLocs = svg.querySelector('.start-locations'); -showButton.addEventListener('click', () => { - mapDialog.showModal(); + panzoom.start(svg); + gameboard.start(svg); + recordSheet.start(startLocs, gameboard.getUnits(), gameboard.unSelect, gameboard.select); }); -selectEl.addEventListener('change', () => { - confirmBtn.value = selectEl.value; -}); +contentVisToggleEl.checked = (localStorage.getItem('content-visibility') !== 'false'); +toggleContentVis(); -confirmBtn.addEventListener('click', e => { - e.preventDefault(); - localStorage.removeItem('pan-zoom'); - localStorage.setItem('map', selectEl.value); - document.querySelector('object').data = `${selectEl.value}.svg`; - mapDialog.close(); -}); +mapSelectDialog + .init() + .selectCurrentOptionOnPageLoad() + .showOnClick() + .updateValueOnSelection() + .changeMapOnConfirm(); + +object.data = `${localStorage.getItem('map') || 'map1'}.svg`; diff --git a/src/modules/gameboard.js b/src/modules/gameboard.js index 3c932d9..b7ef148 100644 --- a/src/modules/gameboard.js +++ b/src/modules/gameboard.js @@ -296,7 +296,7 @@ export function endMove() { } } -export function endTurn(allegiance) { +export function clearFiringArcs(allegiance) { firingArc.clear(svg, allegiance); } diff --git a/src/modules/map_select_dialog.js b/src/modules/map_select_dialog.js new file mode 100644 index 0000000..a9f8bc8 --- /dev/null +++ b/src/modules/map_select_dialog.js @@ -0,0 +1,42 @@ +export function init() { + const showButton = document.getElementById('show-dialog'), + mapDialog = document.getElementById('map-dialog'), + selectEl = mapDialog.querySelector('select'), + confirmBtn = mapDialog.querySelector('#confirm-btn'); + + return { + selectCurrentOptionOnPageLoad() { + mapDialog.querySelectorAll('option').forEach(option => + option.value === localStorage.getItem('map') && (option.selected = true) + ); + + return this; + }, + + showOnClick() { + showButton.addEventListener('click', () => { + mapDialog.showModal(); + }); + + return this; + }, + + updateValueOnSelection() { + selectEl.addEventListener('change', () => { + confirmBtn.value = selectEl.value; + }); + + return this; + }, + + changeMapOnConfirm() { + 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/record_sheet.js b/src/modules/record_sheet.js index 88c8e15..736ffb2 100644 --- a/src/modules/record_sheet.js +++ b/src/modules/record_sheet.js @@ -46,6 +46,39 @@ function createRecord({ dataset: { allegiance, number }}) { return div; } +function createRecords(units) { + const grouped = Array.from(units).reduce((acc, unit) => { + acc[unit.dataset.allegiance]?.push(unit) || (acc[unit.dataset.allegiance] = [unit]); + return acc; + }, {}); + + for (const al in grouped) { + grouped[al] = grouped[al].map(createRecord); + } + + return grouped; +} + +function clear() { + document.querySelectorAll('#attacker-record > div, #defender-record > div').forEach(el => el.remove()); + document.querySelector('#attacker-record .name').textContent = 'attacker'; + document.querySelector('#defender-record .name').textContent = 'defender'; +} + +function addEventListeners(unSelectCounter, selectCounter) { + document.querySelectorAll('.soldier-record').forEach(el => + el.addEventListener('click', () => { + if (el.classList.contains('selected')) { + el.classList.remove('selected'); + unSelectCounter(); + unSelect(); + } else { + selectCounter(el); + } + }) + ); +} + export function unSelect() { const selected = getSelected(); @@ -79,21 +112,18 @@ export function endMove() { unSelect(); } -export function createRecords(units, { content }) { - const grouped = Array.from(units).reduce((acc, unit) => { - acc[unit.dataset.allegiance]?.push(unit) || (acc[unit.dataset.allegiance] = [unit]); - return acc; - }, {}); - - for (const al in grouped) { - grouped[al] = grouped[al].map(createRecord); +export function start(startLoc, units, gbUnSelect, gbSelect) { + clear(); + const forces = createRecords(units); + + for (const affiliation in forces) { + const container = document.querySelector(`#${affiliation}-record`); + const name = startLoc.dataset[`${affiliation}Name`]; + if (name) { + container.querySelector('.name').textContent = name; + } + forces[affiliation].forEach(r => container.appendChild(r)); } - return grouped; -} - -export function clear() { - document.querySelectorAll('#attacker-record > div, #defender-record > div').forEach(el => el.remove()); - document.querySelector('#attacker-record .name').textContent = 'attacker'; - document.querySelector('#defender-record .name').textContent = 'defender'; + addEventListeners(gbUnSelect, gbSelect); } |