diff options
| -rw-r--r-- | input/example.ts | 16 | ||||
| -rw-r--r-- | input/file.ts | 134 |
2 files changed, 150 insertions, 0 deletions
diff --git a/input/example.ts b/input/example.ts index 2fbd5ad..473c4a1 100644 --- a/input/example.ts +++ b/input/example.ts @@ -1,11 +1,26 @@ // SPDX-FileCopyrightText: 2021 M. Shulhan <ms@kilabit.info> // SPDX-License-Identifier: GPL-3.0-or-later +import { WuiInputFile } from "./file.js"; import { WuiInputString, WuiInputStringOpts } from "./string.js"; import { WuiInputNumber, WuiInputNumberOpts } from "./number.js"; import { WuiInputSelect, WuiInputSelectOpts } from "./select.js"; import { WuiInputCheckboxes, WuiInputCheckboxesOpts } from "./checkboxes.js"; +function exampleInputFile() { + const inputFile = new WuiInputFile(); + + inputFile.label = "Input file"; + inputFile.hint = "Select file to be uploaded."; + inputFile.accept = "image/*"; + inputFile.onChange = (file: File) => { + console.log( + `Uploading ${file.name} with size ${file.size}, type ${file.type}, and last modified at ${file.lastModified}.`, + ); + }; + document.body.appendChild(inputFile.element()); +} + function exampleInputString() { const elExample = document.createElement("div"); @@ -236,6 +251,7 @@ function exampleInputCheckboxes() { elExample.appendChild(elLog); } +exampleInputFile(); exampleInputString(); exampleInputNumber(); exampleInputSelect(); diff --git a/input/file.ts b/input/file.ts new file mode 100644 index 0000000..fd42f6d --- /dev/null +++ b/input/file.ts @@ -0,0 +1,134 @@ +// SPDX-FileCopyrightText: 2024 M. Shulhan <ms@kilabit.info> +// SPDX-License-Identifier: GPL-3.0-or-later + +export class WuiInputFile { + id: string = ""; + class: string = ""; + + // Filter for files. For example "image/*" to allow selecting image files. + accept: string = ""; + label: string = ""; + hint: string = ""; + + classInput: string = ""; // Custom CSS class for input element. + classLabel: string = ""; // Custom CSS class for label. + classHint: string = ""; // Custom CSS class for hint text. + classHintToggle: string = ""; // Custom CSS class for hint toggler. + + isDisabled: boolean = false; + isHintShowed: boolean = false; + + onChange?: (file: File) => void; + + private elHint: HTMLElement = document.createElement("div"); + + constructor() {} + + element(): HTMLElement { + const el = document.createElement("div"); + + if (this.id) { + el.id = this.id; + } + + el.classList.add("wui_input_file"); + if (this.class) { + el.classList.add(this.class); + } + + const wrapper = document.createElement("div"); + this.generateLabel(wrapper); + this.generateInput(wrapper); + this.generateHintToggler(wrapper); + el.appendChild(wrapper); + this.generateHint(el); + + return el; + } + + private generateLabel(wrapper: HTMLElement) { + const elLabel = document.createElement("label"); + + elLabel.classList.add("wui_input_file_label"); + if (this.classLabel) { + elLabel.classList.add(this.classLabel); + } + + elLabel.innerHTML = `${this.label} `; + + wrapper.appendChild(elLabel); + } + + private generateInput(wrapper: HTMLElement) { + const elInput = document.createElement("input") as HTMLInputElement; + + elInput.type = "file"; + + elInput.classList.add("wui_input_file_input"); + if (this.classInput) { + elInput.classList.add(this.classInput); + } + + if (this.accept) { + elInput.accept = this.accept; + } + + if (this.isDisabled) { + elInput.disabled = true; + } + + elInput.onchange = (event) => { + const file = (event.target as HTMLInputElement).files![0]; + if (file && this.onChange) { + this.onChange(file); + } + }; + + wrapper.appendChild(elInput); + } + + private generateHintToggler(wrapper: HTMLElement) { + const elHintToggler = document.createElement("span"); + + elHintToggler.classList.add("wui_input_file_hint_toggler"); + if (this.classHintToggle) { + elHintToggler.classList.add(this.classHintToggle); + } + + elHintToggler.innerHTML = " ℹ"; + + elHintToggler.onmouseover = () => { + elHintToggler.style.cursor = "pointer"; + }; + elHintToggler.onclick = () => { + if (this.elHint.style.display === "none") { + this.elHint.style.display = "block"; + } else { + this.elHint.style.display = "none"; + } + }; + wrapper.appendChild(elHintToggler); + } + + private generateHint(parent: HTMLElement) { + this.elHint = document.createElement("div"); + + this.elHint.classList.add("wui_input_file_hint"); + if (this.classHint) { + this.elHint.classList.add(this.classHint); + } + + this.elHint.innerHTML = this.hint; + this.elHint.style.borderRadius = "2px"; + this.elHint.style.padding = "4px"; + this.elHint.style.marginTop = "2px"; + + if (this.isHintShowed) { + this.elHint.style.display = "block"; + } else { + this.elHint.style.display = "none"; + } + + parent.appendChild(this.elHint); + } +} |
