HTMLCollection.prototype.forEach = Array.prototype.forEach; HTMLCollection.prototype.slice = Array.prototype.slice; initTouchkey = (keepPattern, svgid, formid, formfieldid) => { let svg = document.getElementById(svgid); let form; if (formid !== null) { form = document.getElementById(formid); } let formfield = document.getElementById(formfieldid); let currentStroke = null; let strokeId = 0; let doneMap = {}; let enteredKey = ''; let drawLine = (fromX, fromY, toX, toY) => { let line = document.createElementNS('http://www.w3.org/2000/svg', 'line'); let id = 'l-' + (strokeId++); let idAttr = document.createAttribute('id'); let classAttr = document.createAttribute('class'); let x1attr = document.createAttribute('x1'); let y1attr = document.createAttribute('y1'); let x2attr = document.createAttribute('x2'); let y2attr = document.createAttribute('y2'); let styleAttr = document.createAttribute('style'); idAttr.value = id; classAttr.value = 'l'; x1attr.value = fromX; y1attr.value = fromY; x2attr.value = toX; y2attr.value = toY; styleAttr.value = 'stroke: grey; stroke-width: 5%; stroke-linecap: round'; line.setAttributeNode(idAttr); line.setAttributeNode(classAttr); line.setAttributeNode(x1attr); line.setAttributeNode(y1attr); line.setAttributeNode(x2attr); line.setAttributeNode(y2attr); line.setAttributeNode(styleAttr); svg.appendChild(line); return id; }; let endPath = () => { svg.removeChild(svg.getElementById(currentStroke)); currentStroke = null; }; let clearTouchkey = () => { doneMap = {}; enteredKey = ''; svg.getElementsByClassName('l').slice().reverse().forEach((line) => { svg.removeChild(line); }); }; svg.onmousedown = (ev) => { clearTouchkey(); let svgrect = svg.getBoundingClientRect(); let minId = ''; let minDist = Infinity; let minx = 0; let miny = 0; doneMap = {}; document.getElementsByClassName('c').forEach((circle) => { let x = parseFloat(circle.getAttribute('cx')) / 100.0 * svgrect.width; let y = parseFloat(circle.getAttribute('cy')) / 100.0 * svgrect.height; let dist = Math.pow(ev.offsetX - x, 2) + Math.pow(ev.offsetY - y, 2); if (dist < minDist) { minDist = dist; minId = circle.id; minx = x; miny = y; } }); currentStroke = drawLine(minx, miny, ev.offsetX, ev.offsetY); doneMap[minId] = 1; enteredKey += minId; }; svg.onmouseup = (ev) => { endPath(); formfield.value = enteredKey; if (keepPattern !== true) { clearTouchkey(); } if (formid !== null) { form.submit(); } }; svg.onmousemove = (ev) => { if (currentStroke != null) { let svgrect = svg.getBoundingClientRect(); let minId = ''; let minDist = Infinity; let minx = 0; let miny = 0; document.getElementsByClassName('c').forEach((circle) => { let x = parseFloat(circle.getAttribute('cx')) / 100.0 * svgrect.width; let y = parseFloat(circle.getAttribute('cy')) / 100.0 * svgrect.height; let dist = Math.pow(ev.offsetX - x, 2) + Math.pow(ev.offsetY - y, 2); if (dist < minDist) { minDist = dist; minId = circle.id; minx = x; miny = y; } }); if (minDist < 2000 && !(minId in doneMap)) { let line = svg.getElementById(currentStroke); line.setAttribute('x2', minx); line.setAttribute('y2', miny); currentStroke = drawLine(minx, miny, ev.offsetX, ev.offsetY); doneMap[minId] = 1; enteredKey += minId; } let line = svg.getElementById(currentStroke); line.setAttribute('x2', ev.offsetX); line.setAttribute('y2', ev.offsetY); } }; };