From edff19fb5b4d1998ef19d13f1bb82935595444d8 Mon Sep 17 00:00:00 2001 From: Wolvan Date: Tue, 4 Jan 2022 22:25:05 +0100 Subject: [PATCH] Create voting page This page displays all options that have been set on creation. Thanks to `textFit` the texts in the title and options automatically get sized correctly. The create poll button has also been renamed to submit-button to make it more universal on other pages. --- README.md | 7 +++- frontend/html/index.html | 2 +- frontend/html/poll.html | 50 +++++++++++++++++++++++- frontend/static/css/main.css | 71 +++++++++++++++++++++++++++++++++-- frontend/static/js/textfit.js | 1 + src/frontend.ts | 16 +++++++- 6 files changed, 137 insertions(+), 10 deletions(-) create mode 100644 frontend/static/js/textfit.js diff --git a/README.md b/README.md index 2fd412e..3585e42 100644 --- a/README.md +++ b/README.md @@ -30,4 +30,9 @@ Execute the scripts with `npm run + -

Welcome to poll.horse!

-

{{ POLL_TITLE }}

+
+

Poll.horse

+

Make voting on things simpler

+
+
+
+ {{ FORM_SUBMISSION_ERROR }} +
+
ID: {{ POLL_ID }}
+
+
+
+
+ {{ POLL_TITLE }} +
+
+ {{ POLL_OPTION_DIVS }} +
+
+
+
+ \ No newline at end of file diff --git a/frontend/static/css/main.css b/frontend/static/css/main.css index cc119c7..3d24fe9 100644 --- a/frontend/static/css/main.css +++ b/frontend/static/css/main.css @@ -76,6 +76,16 @@ main .error.error-visible { display: block; } /* #endregion Error */ +/* #region ID */ +main .poll-id { + position: absolute; + right: 30%; + top: 20px; + font-family: Arial, sans-serif; + color: #fff; + font-size: 1.75em; +} +/* #endregion ID */ /* #region notepad */ main .notepad { position: relative; @@ -88,6 +98,7 @@ main .notepad { } main .notepad .poll-title { height: 70px; + font-size: 0.9em; } main .notepad .poll-title input { font-size: 2em; @@ -112,6 +123,58 @@ main .notepad .poll-footer { padding-left: 10%; padding-right: 5px; width: calc(90% - 5px); + position: relative; +} + +main .notepad .poll-options .poll-option .input-container { + position: relative; + width: 25px; + height: 25px; + display: inline-block; + vertical-align: top; + top: 13px; +} + +main .notepad .poll-options .poll-option input[type="checkbox"], +main .notepad .poll-options .poll-option input[type="radio"] { + appearance: none; + position: absolute; + vertical-align: top; + top: 0; + left: 0; + width: 25px; + height: 25px; + border: 1px solid #b1b874; + border-radius: 5px; + margin-right: 5px; +} +main .notepad .poll-options .poll-option svg.checkmark { + width: 50px; + height: 50px; + border-radius: 50%; + display: block; + stroke-width: 2; + stroke: #cf2828; + stroke-miterlimit: 10; + stroke-dashoffset: 0; + margin: 10% auto; +} +main .notepad .poll-options .poll-option div.checkmark { + position: absolute; + top: -25px; + left: -20px; + display: none; + pointer-events: none; +} +main .notepad .poll-options .poll-option input[type="checkbox"]:checked ~ div.checkmark, +main .notepad .poll-options .poll-option input[type="radio"]:checked ~ div.checkmark { + display: block; +} +main .notepad .poll-options .poll-option .text { + display: inline-block; + vertical-align: top; + width: calc(100% - 25px - 5px); + height: 100%; } main .notepad-border { @@ -119,8 +182,8 @@ main .notepad-border { left: 5%; height: 100%; width: 5px; - border-left: 2px solid red; - border-right: 2px solid red; + border-left: 2px solid #cf2828; + border-right: 2px solid #cf2828; } /* #endregion notepad */ /* #region notepad-footer */ @@ -142,10 +205,10 @@ main .notepad .poll-footer button:hover { background-color: #b6b6b6; } -#create-poll { +#submit-button { background-color: #cf2828; } -#create-poll:hover { +#submit-button:hover { background-color: #e94747; } main .notepad .poll-footer input[type="checkbox"] { diff --git a/frontend/static/js/textfit.js b/frontend/static/js/textfit.js new file mode 100644 index 0000000..27a9642 --- /dev/null +++ b/frontend/static/js/textfit.js @@ -0,0 +1 @@ +(function(root,factory){"use strict";if(typeof define==="function"&&define.amd){define([],factory)}else if(typeof exports==="object"){module.exports=factory()}else{root.textFit=factory()}})(typeof global==="object"?global:this,function(){"use strict";var defaultSettings={alignVert:false,alignHoriz:false,multiLine:false,detectMultiLine:true,minFontSize:6,maxFontSize:80,reProcess:true,widthOnly:false,alignVertWithFlexbox:false};return function textFit(els,options){if(!options)options={};var settings={};for(var key in defaultSettings){if(options.hasOwnProperty(key)){settings[key]=options[key]}else{settings[key]=defaultSettings[key]}}if(typeof els.toArray==="function"){els=els.toArray()}var elType=Object.prototype.toString.call(els);if(elType!=="[object Array]"&&elType!=="[object NodeList]"&&elType!=="[object HTMLCollection]"){els=[els]}for(var i=0;i=parseInt(window.getComputedStyle(innerSpan)["font-size"],10)*2){multiLine=true}if(!multiLine){el.style["white-space"]="nowrap"}low=settings.minFontSize;high=settings.maxFontSize;var size=low;while(low<=high){mid=high+low>>1;innerSpan.style.fontSize=mid+"px";if(innerSpan.scrollWidth<=originalWidth&&(settings.widthOnly||innerSpan.scrollHeight<=originalHeight)){size=mid;low=mid+1}else{high=mid-1}}if(innerSpan.style.fontSize!=size+"px")innerSpan.style.fontSize=size+"px";if(settings.alignVert){addStyleSheet();var height=innerSpan.scrollHeight;if(window.getComputedStyle(el)["position"]==="static"){el.style["position"]="relative"}if(!hasClass(innerSpan,"textFitAlignVert")){innerSpan.className=innerSpan.className+" textFitAlignVert"}innerSpan.style["height"]=height+"px";if(settings.alignVertWithFlexbox&&!hasClass(el,"textFitAlignVertFlex")){el.className=el.className+" textFitAlignVertFlex"}}}function innerHeight(el){var style=window.getComputedStyle(el,null);return el.clientHeight-parseInt(style.getPropertyValue("padding-top"),10)-parseInt(style.getPropertyValue("padding-bottom"),10)}function innerWidth(el){var style=window.getComputedStyle(el,null);return el.clientWidth-parseInt(style.getPropertyValue("padding-left"),10)-parseInt(style.getPropertyValue("padding-right"),10)}function isElement(o){return typeof HTMLElement==="object"?o instanceof HTMLElement:o&&typeof o==="object"&&o!==null&&o.nodeType===1&&typeof o.nodeName==="string"}function hasClass(element,cls){return(" "+element.className+" ").indexOf(" "+cls+" ")>-1}function addStyleSheet(){if(document.getElementById("textFitStyleSheet"))return;var style=[".textFitAlignVert{","position: absolute;","top: 0; right: 0; bottom: 0; left: 0;","margin: auto;","display: flex;","justify-content: center;","flex-direction: column;","}",".textFitAlignVertFlex{","display: flex;","}",".textFitAlignVertFlex .textFitAlignVert{","position: static;","}"].join("");var css=document.createElement("style");css.type="text/css";css.id="textFitStyleSheet";css.innerHTML=style;document.body.appendChild(css)}}); \ No newline at end of file diff --git a/src/frontend.ts b/src/frontend.ts index 68dd7b5..b46e0b0 100644 --- a/src/frontend.ts +++ b/src/frontend.ts @@ -121,10 +121,22 @@ export default function init(router: Router): void { (program.opts().backendBaseUrl || "http://localhost:" + program.opts().port) + "/_backend/poll/" + id ).then(r => r.json()) as Poll; if (!poll || poll.error) return res.redirect("/"); + + const pollOptions = poll.options.map(option => + `
+
+
+
${option}
+
` + ).join(""); + await displayPage(req, res, "poll.html", { - "POLL_ID": id, + "POLL_ID": poll.id, "POLL_TITLE": poll.title, - + "POLL_OPTION_DIVS": pollOptions, + "BACKEND_BASE_PATH": (program.opts().backendBaseUrl || ""), + "FORM_SUBMISSION_ERROR": req.query.error, + "FORM_SUBMISSION_ERROR_SHOWN_CLASS": req.query.error ? "error-visible" : "", }); } catch (error) { console.log(error);