add prompt with number counter

This commit is contained in:
Araxeus
2021-04-17 20:30:06 +03:00
parent ff6a486daf
commit 341a06aae7
8 changed files with 140 additions and 47 deletions

View File

@ -45,3 +45,8 @@ body {
background-color: rgb(0, 0, 0);
color: whitesmoke;
}
.minus,
.plus {
background:rgb(0, 0, 0);
}

View File

@ -6,7 +6,9 @@ const url = require("url");
const path = require("path");
const DEFAULT_WIDTH = 370;
const DEFAULT_COUNTER_WIDTH = 300;
const DEFAULT_HEIGHT = 160;
const DEFAULT_COUNTER_HEIGHT= 150;
function electronPrompt(options, parentWindow) {
return new Promise((resolve, reject) => {
@ -18,8 +20,6 @@ function electronPrompt(options, parentWindow) {
{
width: DEFAULT_WIDTH,
height: DEFAULT_HEIGHT,
minWidth: DEFAULT_WIDTH,
minHeight: DEFAULT_HEIGHT,
resizable: false,
title: "Prompt",
label: "Please input a value:",
@ -40,6 +40,11 @@ function electronPrompt(options, parentWindow) {
options || {}
);
options_.minWidth = options.minWidth || options.width ||
options_.type === "counter" ? DEFAULT_COUNTER_WIDTH : DEFAULT_WIDTH;
options_.minHeight = options.minHeight || options.height ||
options_.type === "counter" ? DEFAULT_COUNTER_HEIGHT : DEFAULT_HEIGHT;
if (options_.type === "select" && (options_.selectOptions === null || typeof options_.selectOptions !== "object")) {
reject(new Error('"selectOptions" must be an object'));
return;
@ -136,6 +141,13 @@ function electronPrompt(options, parentWindow) {
reject(new Error("prompt.html did-fail-load, log:\n", + log.toString()));
});
const promptUrl = url.format({
protocol: 'file',
slashes: true,
pathname: path.join(__dirname, 'page', 'prompt.html'),
hash: id
});
//Finally, load prompt
promptWindow.loadURL(promptUrl);
});

View File

@ -78,3 +78,35 @@ select#data {
background-color: #ddd;
color: black;
}
/* Counter mode css */
span {
cursor: pointer;
}
.number {
margin: 100px;
}
.minus,
.plus {
user-select: none;
width: 20px;
height: 20px;
background: #f2f2f2;
border-radius: 4px;
padding: 8px 5px 8px 5px;
border: 1px solid #ddd;
display: inline-block;
vertical-align: middle;
text-align: center;
}
.inputt {
height: 34px;
width: 100px;
text-align: center;
font-size: 26px;
border: 1px solid #ddd;
border-radius: 4px;
display: inline-block;
vertical-align: middle;
}

View File

@ -1,13 +1,13 @@
const fs = require("fs");
const {ipcRenderer} = require("electron");
const docReady = require("doc-ready");
let promptId = null;
let promptOptions = null;
function $(selector) {return document.querySelector(selector)}
document.addEventListener( 'DOMContentLoaded', promptRegister);
docReady(promptRegister);
//start here
function promptRegister() {
//get custom session id
promptId = document.location.hash.replace("#", "");
@ -21,18 +21,18 @@ function promptRegister() {
//set label
if (promptOptions.useHtmlLabel) {
document.querySelector("#label").innerHTML = promptOptions.label;
$("#label").innerHTML = promptOptions.label;
} else {
document.querySelector("#label").textContent = promptOptions.label;
$("#label").textContent = promptOptions.label;
}
//set button label
if (promptOptions.buttonLabels && promptOptions.buttonLabels.ok) {
document.querySelector("#ok").textContent = promptOptions.buttonLabels.ok;
$("#ok").textContent = promptOptions.buttonLabels.ok;
}
if (promptOptions.buttonLabels && promptOptions.buttonLabels.cancel) {
document.querySelector("#cancel").textContent = promptOptions.buttonLabels.cancel;
$("#cancel").textContent = promptOptions.buttonLabels.cancel;
}
//inject custom stylesheet from options
@ -51,26 +51,40 @@ function promptRegister() {
}
//add button listeners
document.querySelector("#form").addEventListener("submit", promptSubmit);
document.querySelector("#cancel").addEventListener("click", promptCancel);
$("#form").addEventListener("submit", promptSubmit);
$("#cancel").addEventListener("click", promptCancel);
//create input/select
const dataContainerElement = document.querySelector("#data-container");
const dataContainerElement = $("#data-container");
let dataElement;
if (promptOptions.type === "input") {
dataElement = promptCreateInput();
} else if (promptOptions.type === "select") {
dataElement = promptCreateSelect();
} else {
return promptError(`Unhandled input type '${promptOptions.type}'`);
}
dataContainerElement.append(dataElement);
switch (promptOptions.type) {
case "counter":
case "input":
dataElement = promptCreateInput();
break;
case "select":
dataElement = promptCreateSelect();
break;
default:
return promptError(`Unhandled input type '${promptOptions.type}'`);
}
if (promptOptions.type === "counter") {
dataElement.classList.add("input");
dataElement.style.width = "unset";
dataElement.style["text-align"] = "center";
//dataElement.style["min-height"] = "1.5em";
dataContainerElement.append(createMinus(dataElement));
dataContainerElement.append(dataElement);
dataContainerElement.append(createPlus(dataElement));
} else {
dataContainerElement.append(dataElement);
}
dataElement.setAttribute("id", "data");
dataElement.focus();
if (promptOptions.type === "input") {
if (promptOptions.type === "input" || promptOptions.type === "counter") {
dataElement.select();
}
@ -87,7 +101,8 @@ function promptRegister() {
window.addEventListener("error", error => {
if (promptId) {
promptError("An error has occured on the prompt window: \n" + error);
promptError("An error has occured on the prompt window: \n" + JSON.stringify(error, ["message", "arguments", "type", "name"])
);
}
});
@ -107,15 +122,23 @@ function promptCancel() {
//transfer input data to back
function promptSubmit() {
const dataElement = document.querySelector("#data");
const dataElement = $("#data");
let data = null;
if (promptOptions.type === "input") {
data = dataElement.value;
} else if (promptOptions.type === "select") {
data = promptOptions.selectMultiple ?
dataElement.querySelectorAll("option[selected]").map(o => o.getAttribute("value")) :
dataElement.value;
switch (promptOptions.type) {
case "input":
data = dataElement.value;
break;
case "counter":
data = validateCounterInput(dataElement.value);
break;
case "select":
data = promptOptions.selectMultiple ?
dataElement.querySelectorAll("option[selected]").map(o => o.getAttribute("value")) :
dataElement.value;
break;
default: //will never happen
return promptError(`Unhandled input type '${promptOptions.type}'`);
}
ipcRenderer.sendSync("prompt-post-data:" + promptId, data);
@ -127,6 +150,9 @@ function promptCreateInput() {
dataElement.setAttribute("type", "text");
if (promptOptions.value) {
if (promptOptions.type === "counter") {
promptOptions.value = validateCounterInput(promptOptions.value);
}
dataElement.value = promptOptions.value;
} else {
dataElement.value = "";
@ -150,11 +176,11 @@ function promptCreateInput() {
}
});
//Confrim on 'Enter'
//Confirm on 'Enter'
dataElement.addEventListener("keypress", event => {
if (event.key === "Enter") {
event.preventDefault();
document.querySelector("#ok").click();
$("#ok").click();
}
});
@ -184,5 +210,35 @@ function promptCreateSelect() {
return dataElement;
}
function createMinus(dataElement) {
const minus = document.createElement("span");
minus.textContent = "-";
minus.classList.add("minus");
minus.onmousedown = () => {
dataElement.value = validateCounterInput(parseInt(dataElement.value) - 1);
};
return minus;
}
function createPlus(dataElement) {
const plus = document.createElement("span");
plus.textContent = "+";
plus.classList.add("plus");
plus.onmousedown = () => {
dataElement.value = validateCounterInput(parseInt(dataElement.value) + 1);
};
return plus;
}
//validate counter
function validateCounterInput(input) {
const min = promptOptions.counterOptions?.minimum,
max = promptOptions.counterOptions?.maximum;
if (min !== undefined && input < min) {
return min;
}
if (max !== undefined && input > max) {
return max;
}
return input;
}

View File

@ -43,8 +43,9 @@ prompt({
| label | (optional, string) The label which appears on the prompt for the input field. Defaults to 'Please input a value:'. |
| buttonLabels | (optional, object) The text for the OK/cancel buttons. Properties are 'ok' and 'cancel'. Defaults to null. |
| value | (optional, string) The default value for the input field. Defaults to null. |
| type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input. Defaults to 'input'. |
| inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> `<input type="text" required>`. Used if the type is 'input' |
| type | (optional, string) The type of input field, either 'input' for a standard text input field or 'select' for a dropdown type input or 'counter' for a number counter with buttons. Defaults to 'input'. |
| inputAttrs | (optional, object) The attributes of the input field, analagous to the HTML attributes: `{type: 'text', required: true}` -> `<input type="text" required>`. Used if the type is 'input'
| counterOptions | (optional, object) minimum and maximum of counter in format: `{minimum: %int%, maximum: %int%} ` |
| selectOptions | (optional, object) The items for the select dropdown if using the 'select' type in the format 'value': 'display text', where the value is what will be given to the then block and the display text is what the user will see. |
| useHtmlLabel | (optional, boolean) Whether the label should be interpreted as HTML or not. Defaults to false. |
| width | (optional, integer) The width of the prompt window. Defaults to 370. |