aboutsummaryrefslogtreecommitdiff
path: root/input/select.js
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2024-09-15 14:32:48 +0700
committerShulhan <ms@kilabit.info>2024-09-15 14:32:48 +0700
commitd1e96e09438b4a5c7580b86c469e817a61be991f (patch)
tree4d81fb2fd62207bbb9162b81083c721ec8fd8e29 /input/select.js
parent1cc9c9dd68a3a59c685505228336430624608852 (diff)
downloadpakakeh.ts-d1e96e09438b4a5c7580b86c469e817a61be991f.tar.xz
all: commit all generate JavaScript files
This is to simplify development on third party where they can clone and include the file directly without installing or running anything to build the files.
Diffstat (limited to 'input/select.js')
-rw-r--r--input/select.js152
1 files changed, 152 insertions, 0 deletions
diff --git a/input/select.js b/input/select.js
new file mode 100644
index 0000000..ba8b919
--- /dev/null
+++ b/input/select.js
@@ -0,0 +1,152 @@
+// SPDX-FileCopyrightText: 2021 M. Shulhan <ms@kilabit.info>
+// SPDX-License-Identifier: GPL-3.0-or-later
+const WUI_INPUT_SELECT_CLASS = "wui_input_select";
+const WUI_INPUT_SELECT_CLASS_HINT = "wui_input_select_hint";
+const WUI_INPUT_SELECT_CLASS_HINT_TOGGLER = "wui_input_select_hint_toggler";
+const WUI_INPUT_SELECT_CLASS_INPUT = "wui_input_select_input";
+const WUI_INPUT_SELECT_CLASS_LABEL = "wui_input_select_label";
+// WuiInputSelect create an HTML input for selecting one more item.
+//
+// Format of generated HTML output,
+//
+// <div [id=${id}] class="${WUI_INPUT_SELECT_CLASS}">
+// <div>
+// <label class="${WUI_INPUT_SELECT_CLASS_LABEL} [${class_label}]">
+// ${label} | HTMLElement
+// </label>
+// <select
+// name=${name}
+// class="${WUI_INPUT_SELECT_CLASS_INPUT} [${class_input}]"
+// [disabled=${is_disabled}]
+// >
+// <option value="${options[key].value}">${key in options}</option>
+// </select>
+// [<span class="${WUI_INPUT_SELECT_CLASS_HINT_TOGGLER}">i </span>]
+// </div>
+// [<div class="${WUI_INPUT_SELECT_CLASS_HINT}">${hint}</div>]
+// </div>
+//
+// The "hint" option is optional, if it set the input will have a hint toggler
+// to display or hide the input information.
+//
+// User can set onChangeHandler to receive new value when the input value
+// changes.
+export class WuiInputSelect {
+ constructor(opts) {
+ this.opts = opts;
+ this.value_key = {}; // The reverse of options.options
+ this.value = "";
+ this.el = document.createElement("div");
+ if (opts.id) {
+ this.el.id = opts.id;
+ }
+ this.el.classList.add(WUI_INPUT_SELECT_CLASS);
+ this.el.style.padding = "2px";
+ const wrapper = document.createElement("div");
+ this.generateLabel(wrapper);
+ this.generateInput(wrapper);
+ if (opts.hint) {
+ this.generateHintToggler(wrapper);
+ }
+ this.el.appendChild(wrapper);
+ if (opts.hint) {
+ this.generateHint();
+ }
+ }
+ generateLabel(wrapper) {
+ this.el_label = document.createElement("label");
+ this.el_label.classList.add(WUI_INPUT_SELECT_CLASS_LABEL);
+ if (this.opts.class_label) {
+ this.el_label.classList.add(this.opts.class_label);
+ }
+ if (typeof this.opts.label === "string") {
+ this.el_label.innerHTML = `${this.opts.label} `;
+ }
+ else {
+ this.el_label.appendChild(this.opts.label);
+ }
+ wrapper.appendChild(this.el_label);
+ }
+ generateInput(wrapper) {
+ this.el_input = document.createElement("select");
+ this.el_input.name = this.opts.name;
+ this.el_input.classList.add(WUI_INPUT_SELECT_CLASS_INPUT);
+ if (this.opts.class_input) {
+ this.el_input.classList.add(this.opts.class_input);
+ }
+ Object.entries(this.opts.options).forEach(([key, option]) => {
+ const elOption = document.createElement("option");
+ elOption.value = option.value;
+ elOption.innerHTML = key;
+ if (option.selected) {
+ elOption.selected = true;
+ }
+ this.el_input.appendChild(elOption);
+ this.value_key[option.value] = key;
+ });
+ if (this.opts.is_disabled) {
+ this.el_input.disabled = true;
+ }
+ if (this.opts.onChangeHandler) {
+ this.el_input.onclick = (ev) => {
+ ev.preventDefault();
+ ev.stopPropagation();
+ this.onClickInput();
+ };
+ }
+ wrapper.appendChild(this.el_input);
+ }
+ generateHintToggler(wrapper) {
+ this.el_hint_toggler = document.createElement("span");
+ this.el_hint_toggler.classList.add(WUI_INPUT_SELECT_CLASS_HINT_TOGGLER);
+ this.el_hint_toggler.innerHTML = " &#x2139;";
+ this.el_hint_toggler.onmouseover = () => {
+ this.el_hint_toggler.style.cursor = "pointer";
+ };
+ this.el_hint_toggler.onclick = () => {
+ this.onClickHintToggler();
+ };
+ wrapper.appendChild(this.el_hint_toggler);
+ }
+ generateHint() {
+ this.el_hint = document.createElement("div");
+ this.el_hint.classList.add(WUI_INPUT_SELECT_CLASS_HINT);
+ this.el_hint.innerHTML = this.opts.hint || "";
+ if (this.opts.is_hint_toggled) {
+ this.el_hint.style.display = "block";
+ }
+ else {
+ this.el_hint.style.display = "none";
+ }
+ this.el_hint.style.borderRadius = "2px";
+ this.el_hint.style.padding = "4px";
+ this.el_hint.style.marginTop = "2px";
+ this.el.appendChild(this.el_hint);
+ }
+ onClickHintToggler() {
+ if (this.el_hint.style.display === "none") {
+ this.el_hint.style.display = "block";
+ }
+ else {
+ this.el_hint.style.display = "none";
+ }
+ }
+ onClickInput() {
+ if (!this.opts.onChangeHandler) {
+ return false;
+ }
+ const value = this.el_input.value;
+ if (this.value !== value) {
+ const key = this.value_key[value];
+ if (key) {
+ this.opts.onChangeHandler(key, value);
+ this.value = value;
+ }
+ }
+ return true;
+ }
+ // set the input value.
+ set(v) {
+ this.el_input.value = v;
+ }
+}