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';
import { Observable } from './modules/observable.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'),
contentVisToggleEl = document.querySelector('#content input[type="checkbox"].visible'),
// fileName = localStorage.getItem('map') || (env === 'test' ? 'test_map' : 'map1'),
fileName = localStorage.getItem('map') || 'scenario-side_show',
map = `assets/images/${fileName}.svg`,
fileInputEl = document.querySelector('input[type="file"]'),
dice = document.querySelectorAll('.die'),
d6 = {
1: 'one',
2: 'two',
3: 'three',
4: 'four',
5: 'five',
6: 'six'
},
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';
}
});
localStorage.setItem('content-visibility', this.checked);
}).bind(contentVisToggleEl);
let mapResourceEl = document.querySelector('object');
function loadScenario(data) {
const current = document.querySelector('object');
const next = document.createElement('object');
next.setAttribute('type', 'image/svg+xml');
next.style.opacity = 0;
next.addEventListener('load', load);
mapPlaceholder.after(next);
mapPlaceholder.style.opacity = 1;
next.data = data;
current.remove();
}
function updateTurnCounter() {
const turnCounter = document.getElementById('turn-count');
if (turnCounter.dataset.update === '1') {
turnCounter.children.namedItem('count').textContent++;
turnCounter.dataset.update = '0';
} else {
turnCounter.dataset.update = '1';
}
}
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'));
}
function distance(count = '-') {
distanceOutput.querySelector('#hex-count').textContent = count;
distanceOutput.style.display = count === '-' ? 'none' : 'block';
}
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#getting_a_random_integer_between_two_values_inclusive
function getRandomIntInclusive(min, max) {
const minCeiled = Math.ceil(min);
const maxFloored = Math.floor(max);
return Math.floor(Math.random() * (maxFloored - minCeiled + 1) + minCeiled); // The maximum is inclusive and the minimum is inclusive
}
// ⚀ ⚁ ⚂ ⚃ ⚄ ⚅
function roll(die) {
const numsAsWords = Object.values(die);
return numsAsWords[getRandomIntInclusive(0, numsAsWords.length - 1)];
}
function load() {
const svg = this.contentDocument.querySelector('svg'),
startLocs = svg.querySelector('.start-locations')
// , scriptEl = this.contentDocument.querySelector('script')
;
// const linkEl = document.createElement('link');
// linkEl.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
// linkEl.setAttribute('rel', 'stylesheet');
// linkEl.setAttribute('href', 'http://localhost:8080/assets/css/map.css');
// linkEl.setAttribute('type', 'text/css');
// linkEl.onload = function (e) {
// console.log('map.css loaded');
// if (scriptEl) {
// scriptEl.onload = function () {
// console.log('map.js loaded');
// };
// scriptEl.setAttribute('href', 'http://localhost:8080/map.js');
// }
// };
// svg.prepend(linkEl);
this.style.opacity = 1;
mapPlaceholder.style.opacity = 0;
URL.revokeObjectURL(this.data);
panzoom.start(svg);
gameboard.start(svg);
recordSheet.start(startLocs, gameboard.getUnits());
}
document.querySelectorAll('.end-turn').forEach(el =>
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);
gameboard.clearFiringArcs(opponent);
Observable.notify('select', firstOpponentRecord);
})
);
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();
});
document.querySelectorAll('.end-move').forEach(el =>
el.addEventListener('click', () => Observable.notify('endmove'))
);
document.querySelector('#fullscreen').addEventListener('click', () => {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen();
} else if (document.exitFullscreen) {
document.exitFullscreen();
}
});
document.querySelector('#download-save').addEventListener('click', e => {
const data = document.querySelector('object').contentDocument.documentElement.outerHTML;
const element = document.createElement('a');
element.setAttribute('download', 'save.svg');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(data));
// element.style.display = 'none';
// document.body.appendChild(element);
element.click();
// document.body.removeChild(element);
});
document.querySelector('#upload-save').addEventListener('click', () => {
fileInputEl.click();
});
document.querySelector('input[type="file"]').addEventListener('change', e => {
const [file] = fileInputEl.files;
loadScenario(URL.createObjectURL(file))
});
document.querySelector('#roll-dice').addEventListener('click', () => {
dice.forEach(el => {
el.classList.remove('roll-in');
el.classList.add('roll-out');
});
});
contentVisToggleEl.addEventListener('input', toggleContentVis);
contentVisToggleEl.checked = (localStorage.getItem('content-visibility') !== 'false');
toggleContentVis();
mapSelectDialog
.init()
.selectCurrentOptionOnPageLoad()
.showOnClick()
.updateValueOnSelection()
.changeMapOnConfirm(loadScenario);
mapResourceEl.addEventListener('load', load);
mapResourceEl.data = map;
mapResourceEl = null;
dice.forEach(el => {
el.classList.add(roll(d6));
el.addEventListener('animationend', e => {
if (e.animationName === 'roll-out') {
el.classList.remove('roll-out');
el.classList.replace(el.classList.item(1), roll(d6));
el.classList.add('roll-in');
}
});
});
Observable.subscribe('distance', distance);
Observable.subscribe('proneflag', checked => proneToggle.checked = checked);