From 1f141ccbadecf5b0ccb1eba65da0f93a22f0c8f4 Mon Sep 17 00:00:00 2001 From: dogeystamp Date: Mon, 2 Jan 2023 14:05:53 -0500 Subject: [PATCH] interface.js: refactored API to be more concise --- scripts/aes.js | 55 ++++------------- scripts/interface.js | 143 +++++++++++++++++++------------------------ 2 files changed, 75 insertions(+), 123 deletions(-) diff --git a/scripts/aes.js b/scripts/aes.js index 903e859..e5e14d6 100644 --- a/scripts/aes.js +++ b/scripts/aes.js @@ -1,56 +1,23 @@ let encForm = new Form({id: "encryption", tag: document.getElementById("encryption")}); -let encMsg = new FormElement({ - id: "msg", - type: "textarea", - label: "Message", - form: encForm -}); -let encPass = new FormElement({ - id: "password", - type: "password", - label: "Password", - form: encForm -}); -let encButton = new FormElement({ - id: "button", - type: "button", - label: "Encrypt", - form: encForm -}); -let encOut = new FormElement({ - id: "output", - type: "output", + +let encMsg = encForm.createTextArea({label: "Message"}); +let encPass = encForm.createPasswordInput({label: "Password"}); +let encButton = encForm.createButton({label: "Encrypt"}); +let encOut = encForm.createOutput({ label: "Output", dataType: "json-b64", - form: encForm }); let decForm = new Form({id: "decryption", tag: document.getElementById("decryption")}); -let decMsg = new FormElement({ - id: "msg", - type: "textarea", + +let decMsg = decForm.createTextArea({ label: "Encrypted message", dataType: "json-b64", - form: decForm -}); -let decPass = new FormElement({ - id: "password", - type: "password", - label: "Password", - form: decForm -}); -let decButton = new FormElement({ - id: "button", - type: "button", - label: "Decrypt", - form: decForm -}); -let decOut = new FormElement({ - id: "output", - type: "output", - label: "Output", - form: decForm }); +let decPass = decForm.createPasswordInput({label: "Password"}); +let decButton = decForm.createButton({label: "Decrypt"}); +let decOut = decForm.createOutput({label: "Output"}); + function getKeyMaterial(password) { let enc = new TextEncoder(); diff --git a/scripts/interface.js b/scripts/interface.js index 5128253..0e83c80 100644 --- a/scripts/interface.js +++ b/scripts/interface.js @@ -1,6 +1,5 @@ class InterfaceElement { - constructor({id, tag}) { - this.id = id; + constructor({tag}) { if (tag !== undefined) { this.handle = tag; } @@ -23,15 +22,24 @@ class InterfaceElement { } +function dataTypeSupports(params, validTypes) { + if (params.dataType === undefined) { + params.dataType = validTypes[0]; + } + if (!validTypes.includes(params.dataType)) { + throw `Element can not support '${params.dataType}' data type`; + } +} + class Form extends InterfaceElement { - constructor({id, tag}) { - super({id, tag}); + constructor({tag}) { + super({tag}); if (tag === undefined) { this.handle = document.createElement("div"); } - this.elements = new Map(); + this.elements = []; this.clearAlerts = this.clearAlerts.bind(this); } @@ -42,7 +50,7 @@ class Form extends InterfaceElement { } set advanced(x) { this.#advanced = x; - for (const [id, element] of this.elements.entries()) { + for (const element of this.elements) { if (element.advanced === true) { if (this.advanced === true) { element.hidden = false; @@ -54,10 +62,49 @@ class Form extends InterfaceElement { } clearAlerts() { - for (const [id, element] of this.elements.entries()) { + for (const element of this.elements) { element.clearAlerts(); } } + + appendElement(elem) { + this.handle.append(elem.fragment); + return elem; + } + + createTextBox(params) { + params.tag = document.createElement("input"); + dataTypeSupports(params, ["plaintext", "b64", "json-b64"]); + return this.appendElement(new FormElement(params)); + } + + createPasswordInput(params) { + params.tag = document.createElement("input"); + params.tag.setAttribute("type", "password"); + dataTypeSupports(params, ["plaintext"]); + return this.appendElement(new FormElement(params)); + } + + createTextArea(params) { + params.tag = document.createElement("textarea"); + dataTypeSupports(params, ["plaintext", "b64", "json-b64"]); + return this.appendElement(new FormElement(params)); + } + + createButton(params) { + params.tag = document.createElement("button"); + params.tag.appendChild(document.createTextNode(params.label)); + params.label = ""; + dataTypeSupports(params, ["none"]); + return this.appendElement(new FormElement(params)); + } + + createOutput(params) { + params.tag = document.createElement("textarea"); + params.tag.setAttribute("readonly", true); + dataTypeSupports(params, ["plaintext", "b64", "json-b64"]); + return this.appendElement(new FormElement(params)); + } } function b64ToBuf (b64) { @@ -89,40 +136,13 @@ class FormElement extends InterfaceElement { this.handle.disabled = !this.#enabled; } - constructor({id, type, form, tag, label="", dataType="plaintext", advanced=false, enabled=true}) { - super({id}); - this.id = id; + constructor({form, tag, label="", dataType, advanced=false, enabled=true}) { + super({tag}); this.advanced = advanced; - this.type = type; this.clearAlerts = this.clearAlerts.bind(this); - switch (type) { - case "textbox": - this.handle = document.createElement("input"); - break; - case "password": - this.handle = document.createElement("input"); - this.handle.setAttribute("type", "password"); - break; - case "textarea": - this.handle = document.createElement("textarea"); - break; - case "button": - this.handle = document.createElement("button"); - this.handle.appendChild(document.createTextNode(label)); - label = ""; - dataType = "none" - break; - case "output": - this.handle = document.createElement("textarea"); - this.handle.setAttribute("readonly", true); - break; - default: - throw `Unknown input type: ${type}`; - } - if (label !== "") { this.label = document.createElement("label"); this.label.appendChild(document.createTextNode(label)); @@ -131,53 +151,18 @@ class FormElement extends InterfaceElement { this.dataType = dataType; this.enabled = enabled; - this.handle.id = this.id; if (this.advanced === true) this.hidden = true; - if (form !== undefined) { - this.form = form; - if (this.label !== undefined) { - this.label.setAttribute("for", this.id); - form.handle.appendChild(this.label); - } - form.handle.appendChild(this.handle); - form.elements.set(id, this); - - if (this.advanced === true) this.hidden = !form.advanced; + this.fragment = new DocumentFragment(); + if (this.label !== undefined) { + this.fragment.appendChild(this.label); } + this.fragment.appendChild(this.handle); + + if (this.advanced === true) this.hidden = !form.advanced; } - // plaintext is string data - // b64 is raw ArrayBuffer data - // json-b64 is Object data - // or none, which gives undefined - #dataType = "none"; - get dataType() { - return this.#dataType; - } - set dataType(x) { - function err(type, x) { - throw `'${type}' element can not support '${x}' data type`; - } - - switch (x) { - case "plaintext": - case "b64": - case "json-b64": - let valid = ["textbox", "password", "textarea", "output"]; - if (!valid.includes(this.type)) err(this.type, x); - break; - case "none": - if (this.type !== "button") err(this.type, x); - break; - default: - throw `Unknown data type: ${x}`; - } - - this.#dataType = x; - } - get value() { this.clearAlerts(); switch (this.dataType) { @@ -227,11 +212,11 @@ class FormElement extends InterfaceElement { // type is alert-error or alert-info if (this.handle === undefined) { - throw `can not add alert for '${this.id}': still undefined`; + throw `can not add alert: still undefined`; } if (this.hidden === true) { - throw `can not add alert for '${this.id}': hidden`; + throw `can not add alert: hidden`; } if (title === undefined) {