From b6f3f5628046c94a12ff70337a919e57f2385663 Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Mon, 25 Jan 2021 19:47:18 +1100 Subject: [PATCH] Basic ballot input prototype --- html/blt/index.html | 60 +++++++++++++++ html/blt/index.js | 178 ++++++++++++++++++++++++++++++++++++++++++++ html/main.css | 33 +++++++- 3 files changed, 269 insertions(+), 2 deletions(-) create mode 100644 html/blt/index.html create mode 100644 html/blt/index.js diff --git a/html/blt/index.html b/html/blt/index.html new file mode 100644 index 0000000..3768c76 --- /dev/null +++ b/html/blt/index.html @@ -0,0 +1,60 @@ + + + + + + pyRCV2 Ballot Input Tool + + + + + + +
+ +
+
+ + Ballot value: +
+
+ +
+
+ + + + + + diff --git a/html/blt/index.js b/html/blt/index.js new file mode 100644 index 0000000..44f90ca --- /dev/null +++ b/html/blt/index.js @@ -0,0 +1,178 @@ +/* + pyRCV2: Preferential vote counting + Copyright © 2020–2021 Lee Yingtong Li (RunasSudo) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +let candidates = ['Candidate 1', 'Candidate 2', 'Candidate 3']; +let ballots = []; + +let inpFile = document.getElementById('inpFile'); +let txtBallotValue = document.getElementById('txtBallotValue'); +let tblBallot = document.getElementById('tblBallot'); +let selBallots = document.getElementById('selBallots'); + +selBallots.value = 'new'; + +function initBallot() { + // Init ballot table + tblBallot.innerHTML = ''; + for (let candidate of candidates) { + let elTr = document.createElement('tr'); + + let elTd = document.createElement('td'); + let elInput = document.createElement('input'); + elInput.type = 'number'; + elInput.min = '1'; + elInput.style.width = '3em'; + elTd.appendChild(elInput); + elTr.appendChild(elTd); + + // Add listener + elInput.addEventListener('keyup', function(evt) { + if (evt.key === 'Enter') { + evt.preventDefault(); + clickSave(); + } + }); + + elTd = document.createElement('td'); + elTd.innerText = candidate; + elTr.appendChild(elTd); + + tblBallot.appendChild(elTr); + } +} + +function clickSave() { + // Save ballot + let ballot = {'value': txtBallotValue.value, 'preferences': []}; + for (let elInput of tblBallot.querySelectorAll('input')) { + ballot['preferences'].push(elInput.value); + } + + if (selBallots.value === 'new') { + // New ballot + ballots.push(ballot); + + // Add new ballot '; + selBallots.value = 'new'; + + for (let i = 0; i < ballots.length; i++) { + let elOption = document.createElement('option'); + elOption.innerText = 'Ballot ' + (i + 1); + selBallots.insertBefore(elOption, selBallots.selectedOptions[0]); + } + } + inpFile.value = ''; +} + +function clickSaveJSON() { + let result = { + 'candidates': candidates, + 'ballots': ballots, + }; + + let url = URL.createObjectURL(new File([JSON.stringify(result)], 'ballots.json', {type: 'application/json'})); + + let elA = document.createElement('a'); + elA.href = url; + elA.download = ''; + elA.click(); +} + +function clickEditCandidates() { + document.getElementById('bltMain').style.display = 'none'; + document.getElementById('divEditCandidates').style.display = 'block'; + document.getElementById('txtCandidates').value = candidates.join('\n'); +} + +function clickSaveCandidates() { + candidates = []; + for (let candidate of document.getElementById('txtCandidates').value.split('\n')) { + if (candidate.trim() !== '') { + candidates.push(candidate.trim()); + } + } + + // Update ballot entry + initBallot(); + + document.getElementById('bltMain').style.display = 'flex'; + document.getElementById('divEditCandidates').style.display = 'none'; +} + +// Init tasks + +initBallot(); +changeBallot(); diff --git a/html/main.css b/html/main.css index 92bdf77..268348a 100644 --- a/html/main.css +++ b/html/main.css @@ -58,7 +58,7 @@ body { table { border-collapse: collapse; } -td { +#result td { padding: 0px 8px; min-height: 1em; } @@ -69,7 +69,7 @@ td.count sup { font-size: 0.6rem; top: 0; } -tr:first-child td { +#result tr:first-child td { vertical-align: bottom; } td.excluded { @@ -88,6 +88,35 @@ tr.info td { -webkit-print-color-adjust: exact; } +/* BLT input tool */ + +#selBallots { + min-width: 10em; + margin-right: 1em; +} + +#bltMain { + display: flex; +} + +#tblBallot { + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +#tblBallot input { + margin-right: 0.5ex; +} + +#divEditCandidates div { + margin-bottom: 0.5em; +} + +#txtCandidates { + min-width: 20em; + min-height: 10em; +} + /* Print stylesheet */ #printWarning {