Skip to content

Commit

Permalink
[GLT-4292] fixed date input premature submission (#234)
Browse files Browse the repository at this point in the history
  • Loading branch information
djcooke authored Oct 31, 2024
1 parent ef151a1 commit 0a0ef3d
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 22 deletions.
2 changes: 2 additions & 0 deletions changes/fix_date_input.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Date inputs submitting before entry is completed. Now requires pressing enter or clicking the submit
(checkmark) button to submit, similar to text inputs
69 changes: 47 additions & 22 deletions ts/component/date-input.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,76 @@
import { makeClickout, makeIcon } from "../util/html-utils";

export class DateInput {
private container: HTMLElement;
private dateInput: HTMLInputElement;
private keydownListener: (event: KeyboardEvent) => void;
private mousedownListener: (event: MouseEvent) => void;

constructor(labelText: string, onChange: (value: string) => void) {
this.container = document.createElement("div");
this.container.className =
"font-inter font-medium text-12 text-black bg-grey-100 px-2 py-1 rounded-md hover:ring-2 ring-green-200 ring-offset-1 inline-flex";
"inline-block flex-auto rounded-md ring-red ring-2 ring-offset-1";

// remove date input on click outside of element
const clickout = makeClickout();
clickout.classList.remove("hidden");
clickout.onclick = () => {
this.destroy();
};

this.dateInput = document.createElement("input");
this.dateInput.type = "date";
this.dateInput.className = "ring-0 border-0 outline-0 rounded-sm px-1";
this.dateInput.onchange = () => {
this.styleValidity();
};

const submit = () => {
if (this.dateInput.value) {
onChange(this.dateInput.value);
this.destroy(); // destroy the date input after selection
this.destroy();
}
};

const label = document.createElement("span");
label.textContent = `${labelText}: `;

this.container.appendChild(label);
this.container.appendChild(this.dateInput);

// remove date input on 'Esc' key press
this.keydownListener = (event: KeyboardEvent) => {
if (event.key === "Esc" || event.key === "Escape") {
if (event.key === "Enter") {
// submit on Enter (ignored if invalid)
submit();
} else if (event.key === "Esc" || event.key === "Escape") {
// remove date input on 'Esc' key press
this.destroy();
}
};
// remove date input when mousedown outside of the date input
this.mousedownListener = (event: MouseEvent) => {
if (event.target !== this.dateInput) {
setTimeout(() => {
this.destroy();
}, 0);
}
};
document.addEventListener("keydown", this.keydownListener);
document.addEventListener("mousedown", this.mousedownListener);

const label = document.createElement("span");
label.textContent = `${labelText}: `;

const submitIcon = makeIcon("check");
submitIcon.onclick = submit;
submitIcon.classList.add("text-black", "hover:text-green");

var innerContainer = document.createElement("div");
innerContainer.className =
"font-inter font-medium text-12 text-black px-2 py-1 inline-block space-x-2 relative z-40";
innerContainer.append(label, this.dateInput, submitIcon);

this.container.append(innerContainer, clickout);

// wait for browser to render element before setting focus
window.setTimeout(() => this.dateInput.focus(), 0);
}

private styleValidity() {
if (this.dateInput.value) {
this.container.classList.replace("ring-red", "ring-green-200");
} else {
this.container.classList.replace("ring-green-200", "ring-red");
}
}

destroy() {
private destroy() {
this.container.remove();
document.removeEventListener("keydown", this.keydownListener);
document.removeEventListener("mousedown", this.mousedownListener);
}

public getElement() {
Expand Down

0 comments on commit 0a0ef3d

Please sign in to comment.