From d0df27a55c77d47a809958ecd4448df38a10c526 Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Sun, 6 Jun 2021 17:31:20 +1000 Subject: [PATCH] Implement print view --- html/index.html | 17 +++-- html/index.js | 171 ++++++++++++++++++++++++++++++++++++++++++++++++ html/main.css | 6 +- 3 files changed, 182 insertions(+), 12 deletions(-) diff --git a/html/index.html b/html/index.html index 2a1a5b2..019d98b 100644 --- a/html/index.html +++ b/html/index.html @@ -225,11 +225,13 @@ -
- -
- -
+
+
+ +
+ +
+
- -
Printing directly from this page is not supported. Use the ‘Print result’ button to generate a printer-friendly report.
+
Printing directly from this page is not supported. Use the ‘Print result’ button to generate a printer-friendly report.
+ diff --git a/html/index.js b/html/index.js index e9ab7cb..78bc267 100644 --- a/html/index.js +++ b/html/index.js @@ -69,6 +69,7 @@ worker.onmessage = function(evt) { } else if (evt.data.type === 'finalResultSummary') { divLogs2.insertAdjacentHTML('beforeend', evt.data.summary); + document.getElementById('printPane').style.display = 'block'; } } @@ -114,6 +115,176 @@ async function clickCount() { }); } +// Print logic + +async function printResult() { + let printableWidth; // Printable width in CSS pixels + let paperSize = document.getElementById('selPaperSize').value; + if (paperSize === 'A4') { + printableWidth = (29.7 - 2) * 96 / 2.54; + } else if (paperSize === 'A3') { + printableWidth = (42.0 - 2) * 96 / 2.54; + } else if (paperSize === 'letter') { + printableWidth = (27.9 - 2) * 96 / 2.54; + } + printableWidth = Math.round(printableWidth); + + let wprint = window.open(''); + wprint.document.title = 'OpenTally Report'; + + // Add stylesheets + let numToLoad = 0; + let numLoaded = -1; + + function onLoadStylesheet() { + numLoaded++; + if (numLoaded == numToLoad) { + wprint.print(); + } + } + + for (let elCSSBase of document.querySelectorAll('head link')) { + numToLoad++; + let elCSS = wprint.document.createElement('link'); + elCSS.rel = elCSSBase.rel; + elCSS.type = elCSSBase.type; + if (elCSSBase.href.endsWith('?v=GITVERSION')) { + elCSS.href = elCSSBase.href.replace('?v=GITVERSION', '?v=' + Math.random()); + } else { + elCSS.href = elCSSBase.href; + } + + elCSS.onload = onLoadStylesheet; + wprint.document.head.appendChild(elCSS); + } + + // Configure printing + let elStyle = wprint.document.createElement('style'); + elStyle.innerHTML = '@page { size: ' + paperSize + ' landscape; margin: 1cm; } @media print { body { padding: 0; } }'; + wprint.document.head.appendChild(elStyle); + + let elContainer = wprint.document.createElement('div'); + elContainer.id = 'printContainer'; + elContainer.style.width = printableWidth + 'px'; + wprint.document.body.appendChild(elContainer); + + // Copy result logs 1 + let divResultLogs1 = document.getElementById('resultLogs1'); + let divResultLogs2 = wprint.document.createElement('div'); + divResultLogs2.innerHTML = divResultLogs1.innerHTML; + elContainer.appendChild(divResultLogs2); + + // Parse table, accounting for rowspan + let elTrs1 = document.querySelector('#result').rows; + let rows = []; + for (let elTr1 of elTrs1) { + rows.push([]); + } + for (let r = 0; r < elTrs1.length; r++) { + for (let c = 0; c < elTrs1[r].cells.length; c++) { + let elTd1 = elTrs1[r].cells[c]; + rows[r].push(elTd1); + + let rowspan = elTd1.getAttribute('rowspan'); + // NB: Only works for rowspan in first column + if (rowspan !== null && c == 0) { + rowspan = parseInt(rowspan); + // Add ghost cells + for (let i = 1; i < rowspan; i++) { + rows[r + i].push(null); + } + } + } + } + + function copyColumn(c, elTrs2) { + let tdsAdded = []; + for (let r = 0; r < rows.length; r++) { + if (c < rows[r].length) { + let elTd1 = rows[r][c]; + if (elTd1 !== null) { + let elTd2 = wprint.document.createElement('td'); + elTd2.innerHTML = elTd1.innerHTML; + elTd2.className = elTd1.className; + elTd2.setAttribute('rowspan', elTd1.getAttribute('rowspan')); + elTd2.setAttribute('style', elTd1.getAttribute('style')); + elTrs2[r].appendChild(elTd2); + tdsAdded.push(elTd2); + } + } + } + return tdsAdded; + } + + async function copyTableColumns(startCol) { + // Add table + let elTable2 = wprint.document.createElement('table'); + elTable2.className = 'result'; + if (startCol > 1) { + elTable2.style.pageBreakBefore = 'always'; + } + elContainer.appendChild(elTable2); + + // Add rows + let elTrs2 = []; + for (let elTr1 of elTrs1) { + let elTr2 = wprint.document.createElement('tr'); + elTr2.className = elTr1.className; + elTrs2.push(elTr2); + elTable2.appendChild(elTr2); + } + + // Copy first column + copyColumn(0, elTrs2); + + // How many columns to copy? + let totalWidth = rows[0][0].clientWidth; + let endCol; + for (endCol = startCol; endCol < rows[0].length; endCol++) { + if (totalWidth + rows[0][endCol].clientWidth > printableWidth) { + break; + } + totalWidth += rows[0][endCol].clientWidth; + } + + // Copy columns + for (let c = startCol; c < endCol; c++) { + copyColumn(c, elTrs2); + } + + // Copy stage comments + elContainer.insertAdjacentHTML('beforeend', '

Stage comments:

'); + let olStageComments2 = wprint.document.createElement('ol'); + olStageComments2.start = startCol; + elContainer.append(olStageComments2); + for (let c = startCol; c < endCol && c < rows[0].length - 1; c++) { + olStageComments2.insertAdjacentHTML('beforeend', olStageComments.children[c-1].outerHTML); + } + + if (endCol < rows[0].length) { + // Start new table if columns remain + copyTableColumns(endCol); + } else { + // Copy winning candidates + elContainer.insertAdjacentHTML('beforeend', '

Count complete. The winning candidates are, in order of election:

'); + elContainer.insertAdjacentHTML('beforeend', divLogs2.lastElementChild.outerHTML); + } + } + + // Adjust results table to width + document.getElementById('resultsDiv').style.width = printableWidth + 'px'; + await new Promise(window.requestAnimationFrame); // Allow DOM to update + + // Copy table + await copyTableColumns(1); + + // Restore original view + document.getElementById('resultsDiv').style.width = 'auto'; + + // Trigger print when ready + onLoadStylesheet(); +} + // Presets function changePreset() { diff --git a/html/main.css b/html/main.css index c3d03f9..0105049 100644 --- a/html/main.css +++ b/html/main.css @@ -153,11 +153,7 @@ tr.info:last-child td, .bb { } @media print { - body.interactive > * { - display: none; - } - #divAdvancedOptions, #printPane { - /* Override inline style */ + #divUI { display: none !important; } #printWarning {