Web Dev Solutions

Catalin Mititiuc

const selectedClass = 'selected'; function dataSelector({ dataset: { allegiance, number }}) { return `[data-number="${number}"][data-allegiance="${allegiance}"]`; } function traceSelector(counter) { return `polyline.move-trace${dataSelector(counter)}`; } function getCellPosition(cell) { let pt = new DOMPoint(0, 0), transform = getComputedStyle(cell).transform.match(/-?\d+\.?\d*/g), mtx = new DOMMatrix(transform); pt = pt.matrixTransform(mtx); transform = getComputedStyle(cell.parentElement).transform.match(/-?\d+\.?\d*/g); mtx = new DOMMatrix(transform); pt = pt.matrixTransform(mtx); return pt; } function getClones(svg, counter) { return svg.querySelectorAll(`.counter.clone${dataSelector(counter)}`); } function addMoveToHistory(selected) { const clone = selected.cloneNode(true); clone.classList.remove(selectedClass); clone.classList.add('clone'); selected.parentElement.appendChild(clone); return clone; } function updatePlacement(cell, selected, clone) { const prevCoords = [ clone.parentElement.dataset.x, clone.parentElement.parentElement.dataset.y ] selected.dataset.previous = prevCoords; cell.appendChild(selected); selected.childNodes.forEach(n => { if (n.classList.contains('removed')) { n.remove(); } else if ('preexisting' in n.dataset) { delete n.dataset.preexisting; } }); } function createTrace(previous, current, selected) { const trace = document.createElementNS(svgns, 'polyline'); trace.dataset.number = selected.dataset.number; trace.dataset.allegiance = selected.dataset.allegiance; trace.classList.add('move-trace'); trace.setAttributeNS(null, 'points', `${previous.x},${previous.y} ${current.x},${current.y}`); return trace; } export function handleTrace(svg, selected, clone, current) { let trace = getTrace(svg, selected); if (!trace) { trace = createTrace(getCellPosition(clone.parentElement), current, selected); svg.querySelector('.gameboard').prepend(trace); } else { const points = `${trace.getAttribute('points')} ${current.x},${current.y}`; trace.setAttributeNS(null, 'points', points); } } export function getAllCounters(container) { return container.querySelectorAll('g.counter[data-allegiance][data-number]'); } export function getCounter(svg, selected) { return svg.querySelector(`.counter${dataSelector(selected)}:not(.clone)`); } export function getTrace(svg, counter) { return svg.querySelector(traceSelector(counter)); } export function place(svg, selected, cell) { if (svg.querySelector('.grid').contains(selected)) { const clone = addMoveToHistory(selected); updatePlacement(cell, selected, clone) handleTrace(svg, selected, clone, getCellPosition(cell)); } else { selected.removeAttribute('data-x'); cell.appendChild(selected); } } export function removeClones(svg, counter) { getClones(svg, counter).forEach(c => c.remove()); } export function endMove(svg, counter) { const proneCounter = counter.querySelector('[href="#counter-prone"]'); if (proneCounter) { proneCounter.dataset.preexisting = ''; } svg.querySelector(traceSelector(counter))?.remove(); delete counter.dataset.previous; removeClones(svg, counter); } export function hasProne(counter) { return !!counter.querySelector('[href="#counter-prone"]'); } export function toggleProne(counter) { let proneCounter = counter.querySelector('[href="#counter-prone"]'); if (!proneCounter) { proneCounter = document.createElementNS(svgns, 'use'); proneCounter.setAttributeNS(null, 'href', '#counter-prone'); counter.appendChild(proneCounter); } else if ('preexisting' in proneCounter.dataset) { proneCounter.classList.toggle('removed'); } else { proneCounter.remove(); } } export function getSelectedClass() { return selectedClass; }