Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Enter + Esc actions to dialogs #417

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 50 additions & 4 deletions scripts/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,26 @@ export function downloadBlob(content, filename, contentType) {
pom.click();
}

/**
* A listener utility for adding keyboard-only interaction to prompts (i.e: close or confirm dialogs without mouse)
* @param {KeyboardEvent} evt - The `keydown` event from the attached listener
* @param {HTMLButtonElement?} confirmBtn - The 'confirm' button, if one exists
* @param {HTMLButtonElement} closeBtn - The 'close' button
*/
export function dialogListener(evt, confirmBtn, closeBtn) {
if (evt.key === 'Enter') {
// If there's no 'confirm' button, we treat it as a close-only dialog (i.e: informational)
if (confirmBtn) {
confirmBtn.click();
} else {
closeBtn.click();
}
} else if (evt.key === 'Escape') {
// Close the dialog
closeBtn.click();
}
}

/**
* Create a custom GUI Alert popup
*
Expand Down Expand Up @@ -176,14 +196,35 @@ export async function confirmPopup({
if (maxHeight)
doms.domConfirmModalDialog.classList.add(`max-w-${maxHeight}`);

// If there's an input in the prompt, focus the cursor upon it
// If there's an input in the prompt, focus the cursor upon it, and apply confirmation listeners
let isFocused = false;
let domFinalInput = null;
for (const domElement of doms.domConfirmModalContent.children) {
if (domElement.type === 'text' || domElement.type === 'password') {
domElement.focus();
break;
if (domElement.type?.includes('text', 'password')) {
// Focus the cursor/keyboard on the first input
if (!isFocused) {
domElement.focus();
isFocused = true;
}
// Keep track of the inputs until we reach the final one
domFinalInput = domElement;
}
}

// A prompt wrapper for dialogListener so we avoid unremovable anon-func listeners
function promptWrapperListener(evt) {
dialogListener(
evt,
hideConfirm ? null : doms.domConfirmModalConfirmButton,
doms.domConfirmModalCancelButton
);
}

// If a final text input is available, listen for 'Enter' and 'Esc' keys to allow for mouse-less dialog interaction
if (domFinalInput) {
domFinalInput.addEventListener('keydown', promptWrapperListener);
}

// Center the buttons
if (centerButtons) {
doms.domConfirmModalButtons.classList.add('centerFlex');
Expand All @@ -208,6 +249,11 @@ export async function confirmPopup({

// Reset any modal settings
doms.domConfirmModalDialog.classList.remove(`max-w-${maxHeight}`);

// Remove any dialog listeners
if (domFinalInput) {
domFinalInput.removeEventListener('keydown', promptWrapperListener);
}
}
}

Expand Down
Loading