Web Dev Solutions

Catalin Mititiuc

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'; import sideShow from './assets/images/scenario-side_show.svg'; 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`, map = sideShow, 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.style.opacity = 1; next.data = data; mapPlaceholder.after(next); 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 useEls = svg.querySelectorAll('use[href*=".svg"]'); // console.log(useEls); // [...new Set([...useEls].map(el => el.getAttributeNS(null, 'href').match(/^(.*?)\.svg/g).at(0)))].forEach(f => { // const name = `../assets/images/${f}`; // import(name); // console.log(f); // }); // const linkEl = document.createElement('link'); // linkEl.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml'); // linkEl.setAttribute('rel', 'stylesheet'); // linkEl.setAttribute('href', '../../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', '../../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);