Web Dev Solutions

Catalin Mititiuc

import counters from './assets/images/counters.svg'; import mapsheets from './assets/images/mapsheets.svg'; async function loadScript(scenario, svg, script) { return new Promise((resolve, reject) => { const scriptEl = document.createElementNS("http://www.w3.org/2000/svg", 'script'); scriptEl.onload = () => { console.log(`${script}.js loaded`); resolve(); }; scriptEl.onerror = () => { reject(Error('Script failed to load.')); }; const dataset = scenario.querySelector('script')?.dataset || {}; Object.entries(dataset).forEach(([k, v]) => scriptEl.dataset[k] = v); scriptEl.setAttributeNS(null, 'href', `../../${script}.js`); svg.append(scriptEl); }); } export async function requestResource(url) { return new Promise((resolve, reject) => { const request = new XMLHttpRequest(); request.open('GET', url, true); request.responseType = 'document'; request.onload = function() { if (request.status === 200) { resolve(request.response); } else { reject(Error('Image didn\'t load successfully; error code:' + request.statusText)); } }; request.onerror = function() { reject(Error('There was a network error.')); }; request.send(); }); } export async function build(svg, request) { const defs = svg.querySelector('defs'); const gb = svg.querySelector('.gameboard'); const grid = svg.querySelector('.grid'); const scenario = await request; const startLocs = scenario.querySelector('.start-locations'); const externalResourceEls = Array.from(scenario.querySelectorAll('use[href*=".svg"')); scenario.querySelectorAll('defs > *').forEach(el => defs.append(svg.ownerDocument.importNode(el, true))); const refs = externalResourceEls.reduce((acc, el) => { const href = el.getAttributeNS(null, 'href'); const [filename] = href.match(/.+\.svg/); const fragmentIdentifier = href.split('.svg').pop(); (acc[filename] ??= new Set()).add(fragmentIdentifier); el.setAttributeNS(null, 'href', fragmentIdentifier); return acc; }, {}); const hashedFilenames = { 'counters.svg': counters, 'mapsheets.svg': mapsheets } await Promise.all( Object.keys(refs).map(filename => requestResource(hashedFilenames[filename])) ).then(result => { Object.keys(refs).forEach((filename, index) => { const external = result[index]; refs[filename].forEach(fragmentIdentifier => { external .querySelectorAll(`${fragmentIdentifier} use`) .forEach(el => refs[filename].add(el.getAttributeNS(null, 'href'))); }); const refsQuery = [...refs[filename]].join(', '); external.querySelectorAll(refsQuery).forEach(node => defs.append(svg.ownerDocument.importNode(node, true)) ); }); }); //if (startLocs) grid.before(svg.ownerDocument.importNode(startLocs, true)); const scenarioGrid = scenario.querySelector('.grid'); const scenarioBuildings = scenario.querySelector('.gameboard .buildings'); if (scenarioGrid) { const frontmost = grid.querySelector('.frontmost'); [...scenarioGrid.children].forEach(child => frontmost.before(svg.ownerDocument.importNode(child, true))); } if (scenarioBuildings) svg.querySelector('.gameboard .buildings').replaceWith(svg.ownerDocument.importNode(scenarioBuildings, true)); await loadScript(scenario, svg, 'radial') return loadScript(scenario, svg, 'map'); }