Fix Escape key navigation and dynamic parent targeting in stacked modals

This commit is contained in:
2026-04-19 09:09:31 +08:00
parent c10bf81d24
commit 84bd01087c
9 changed files with 50 additions and 11 deletions
@@ -150,13 +150,20 @@ class DescriptionEditor extends BaseTablist {
this.tabs = [this.#tabsByID.general, this.#tabsByID.travel, this.#tabsByID.bus, this.#tabsByID.recurring, this.#tabsByID.annotation];
this.currentTab = this.tabs[0];
this.#descriptionInput.onchange = () => this.#onDescriptionChange();
this.#offsetButton.onclick = () => this.lineItemEditor.originalLineItemSelector.onOpen();
this.#offsetButton.onclick = () => this.lineItemEditor.originalLineItemSelector.onOpen(this.#modal.id);
this.#form.onsubmit = () => {
if (this.currentTab.validate()) {
this.#submit();
}
return false;
};
const closeButton = document.getElementById(`${prefix}-close`);
this.#modal.onkeydown = (event) => {
if (event.key === "Escape") {
closeButton.click();
}
};
}
/**
@@ -97,6 +97,14 @@ class JournalEntryAccountSelector extends BaseCombobox {
this.#clearButton = document.getElementById(`${prefix}-btn-clear`);
this.#clearButton.onclick = () => this.#lineItemEditor.clearAccount();
const modal = document.getElementById(`${prefix}-modal`);
const closeButton = document.getElementById(`${prefix}-close`);
modal.onkeydown = (event) => {
if (event.key === "Escape") {
closeButton.click();
}
};
}
/**
@@ -228,7 +228,7 @@ class JournalEntryLineItemEditor {
this.#accountSelectors = JournalEntryAccountSelector.getInstances(this);
this.originalLineItemSelector = new OriginalLineItemSelector(this);
this.#originalLineItemControl.onclick = () => this.originalLineItemSelector.onOpen()
this.#originalLineItemControl.onclick = () => this.originalLineItemSelector.onOpen(this.modal.id)
this.#originalLineItemDelete.onclick = () => this.clearOriginalLineItem();
this.#descriptionControl.onclick = () => this.#descriptionEditors[this.debitCredit].onOpen();
this.#accountControl.onclick = () => this.#accountSelectors[this.debitCredit].onOpen();
+8
View File
@@ -895,6 +895,14 @@ class RecurringAccountSelector extends BaseCombobox {
this.#clearButton = document.getElementById(`${prefix}-clear`);
this.#clearButton.onclick = () => this.#editor.clearAccount();
const modal = document.getElementById(`${prefix}-modal`);
const closeButton = document.getElementById(`${prefix}-close`);
modal.onkeydown = (event) => {
if (event.key === "Escape") {
closeButton.click();
}
};
}
/**
@@ -65,6 +65,12 @@ class OriginalLineItemSelector extends BaseCombobox {
*/
#debitCredit;
/**
* The close button.
* @type {HTMLButtonElement}
*/
#closeButton;
/**
* Constructs an original line item selector.
*
@@ -82,6 +88,14 @@ class OriginalLineItemSelector extends BaseCombobox {
for (const option of this.options) {
this.#optionById[option.id] = option;
}
this.#closeButton = document.getElementById(`${prefix}-close`);
const modal = document.getElementById(`${prefix}-modal`);
modal.onkeydown = (event) => {
if (event.key === "Escape") {
this.#closeButton.click();
}
};
}
/**
@@ -162,8 +176,10 @@ class OriginalLineItemSelector extends BaseCombobox {
/**
* The callback when the original line item selector is shown.
*
* @param parentID {string} the ID of the parent element
*/
onOpen() {
onOpen(parentID) {
this.#closeButton.dataset.bsTarget = `#${parentID}`;
this.#currencyCode = this.#lineItemEditor.currencyCode;
this.#debitCredit = this.#lineItemEditor.debitCredit;
this.query.value = "";
@@ -19,12 +19,12 @@ account-selector-modal.html: The modal for the account selector
Author: imacat@mail.imacat.idv.tw (imacat)
First written: 2023/2/25
#}
<div id="accounting-account-selector-{{ debit_credit }}-modal" class="modal fade accounting-account-selector" data-debit-credit="{{ debit_credit }}" tabindex="-1" aria-labelledby="accounting-account-selector-{{ debit_credit }}-modal-label" aria-hidden="true">
<div id="accounting-account-selector-{{ debit_credit }}-modal" class="modal fade accounting-account-selector" data-debit-credit="{{ debit_credit }}" tabindex="-1" aria-labelledby="accounting-account-selector-{{ debit_credit }}-modal-label" aria-hidden="true" data-bs-keyboard="false">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="accounting-account-selector-{{ debit_credit }}-modal-label">{{ A_("Select Account") }}</h1>
<button type="button" class="btn-close" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal" aria-label="{{ A_("Close") }}"></button>
<button id="accounting-account-selector-{{ debit_credit }}-close" type="button" class="btn-close" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal" aria-label="{{ A_("Close") }}"></button>
</div>
<div class="modal-body">
<div class="input-group mb-2">
@@ -21,14 +21,14 @@ First written: 2023/2/28
#}
<form id="accounting-description-editor-{{ description_editor.debit_credit }}" class="accounting-description-editor" data-debit-credit="{{ description_editor.debit_credit }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div id="accounting-description-editor-{{ description_editor.debit_credit }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-description-editor-{{ description_editor.debit_credit }}-modal-label" aria-hidden="true">
<div id="accounting-description-editor-{{ description_editor.debit_credit }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-description-editor-{{ description_editor.debit_credit }}-modal-label" aria-hidden="true" data-bs-keyboard="false">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="accounting-description-editor-{{ description_editor.debit_credit }}-modal-label">
<label for="accounting-description-editor-{{ description_editor.debit_credit }}-description">{{ A_("Description") }}</label>
</h1>
<button class="btn-close" type="button" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal" aria-label="{{ A_("Close") }}"></button>
<button id="accounting-description-editor-{{ description_editor.debit_credit }}-close" class="btn-close" type="button" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal" aria-label="{{ A_("Close") }}"></button>
</div>
<div class="modal-body">
<div class="d-flex justify-content-between mb-3">
@@ -19,12 +19,12 @@ original-line-item-selector-modal.html: The modal of the original line item sele
Author: imacat@mail.imacat.idv.tw (imacat)
First written: 2023/2/25
#}
<div id="accounting-original-line-item-selector-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-original-line-item-selector-modal-label" aria-hidden="true">
<div id="accounting-original-line-item-selector-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-original-line-item-selector-modal-label" aria-hidden="true" data-bs-keyboard="false">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="accounting-original-line-item-selector-modal-label">{{ A_("Select Original Line Item") }}</h1>
<button type="button" class="btn-close" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal" aria-label="{{ A_("Close") }}"></button>
<button id="accounting-original-line-item-selector-close" type="button" class="btn-close" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal" aria-label="{{ A_("Close") }}"></button>
</div>
<div class="modal-body">
<div class="input-group mb-2">
@@ -19,12 +19,12 @@ recurring-account-selector-modal.html: The modal of the account selector for the
Author: imacat@mail.imacat.idv.tw (imacat)
First written: 2023/3/22
#}
<div id="accounting-recurring-accounting-selector-{{ expense_income }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-recurring-accounting-selector-{{ expense_income }}-modal-label" aria-hidden="true">
<div id="accounting-recurring-accounting-selector-{{ expense_income }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-recurring-accounting-selector-{{ expense_income }}-modal-label" aria-hidden="true" data-bs-keyboard="false">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="accounting-recurring-accounting-selector-{{ expense_income }}-modal-label">{{ A_("Select Account") }}</h1>
<button type="button" class="btn-close" data-bs-toggle="modal" data-bs-target="#accounting-recurring-item-editor-{{ expense_income }}-modal" aria-label="{{ A_("Close") }}"></button>
<button id="accounting-recurring-accounting-selector-{{ expense_income }}-close" type="button" class="btn-close" data-bs-toggle="modal" data-bs-target="#accounting-recurring-item-editor-{{ expense_income }}-modal" aria-label="{{ A_("Close") }}"></button>
</div>
<div class="modal-body">
<div class="input-group mb-2">