diff --git a/datasette/static/datasette-modal.js b/datasette/static/datasette-modal.js
index 78012894..08a09e62 100644
--- a/datasette/static/datasette-modal.js
+++ b/datasette/static/datasette-modal.js
@@ -11,6 +11,8 @@
* - The standard Datasette modal frame: sizing, rounded corners,
* backdrop, animations, and optional .modal-header scaffolding
* - Close-on-backdrop-click and Escape key handling
+ * - Declarative cancel buttons: clicking any element inside the modal
+ * with a `data-modal-cancel` attribute calls requestClose("cancel")
* - A `busy` property that blocks user-initiated dismissal while an
* operation is in flight
* - A `closeGuard` hook for "discard unsaved changes?" style prompts
@@ -526,6 +528,14 @@ datasette-modal .btn:disabled {
dialog.addEventListener("click", (ev) => {
if (ev.target === dialog) {
this.requestClose("backdrop");
+ return;
+ }
+ // Declarative cancel buttons: any element inside the modal
+ // with a data-modal-cancel attribute requests a close
+ var cancelTrigger =
+ ev.target.closest && ev.target.closest("[data-modal-cancel]");
+ if (cancelTrigger && dialog.contains(cancelTrigger)) {
+ this.requestClose("cancel");
}
});
diff --git a/datasette/static/edit-tools.js b/datasette/static/edit-tools.js
index b656c7f5..b83d6fef 100644
--- a/datasette/static/edit-tools.js
+++ b/datasette/static/edit-tools.js
@@ -1559,7 +1559,7 @@ function ensureTableCreateDialog(manager) {
@@ -1601,10 +1601,6 @@ function ensureTableCreateDialog(manager) {
row.querySelector(".table-create-column-name").focus();
});
- tableCreateDialogState.cancelButton.addEventListener("click", function () {
- closeTableCreateDialogIfConfirmed(tableCreateDialogState);
- });
-
tableCreateDialogState.tableName.addEventListener("input", function () {
clearTableCreateDialogError(tableCreateDialogState);
});
@@ -3640,7 +3636,7 @@ function ensureRowDeleteDialog(manager) {
Delete row ?
`,
@@ -3663,10 +3659,6 @@ function ensureRowDeleteDialog(manager) {
isBusy: false,
};
- rowDeleteDialogState.cancelButton.addEventListener("click", function () {
- modal.requestClose("cancel");
- });
-
dialog.addEventListener("keydown", function (ev) {
if (
ev.key === "Enter" &&
diff --git a/datasette/static/table.js b/datasette/static/table.js
index 8f3804b7..b588fe03 100644
--- a/datasette/static/table.js
+++ b/datasette/static/table.js
@@ -202,7 +202,7 @@ function ensureSetColumnTypeDialog() {
`,
@@ -223,10 +223,6 @@ function ensureSetColumnTypeDialog() {
isBusy: false,
};
- setColumnTypeDialogState.cancelButton.addEventListener("click", function () {
- modal.requestClose("cancel");
- });
-
modal.addEventListener("datasette-modal-close", function () {
clearSetColumnTypeDialogError(setColumnTypeDialogState);
setSetColumnTypeDialogBusy(setColumnTypeDialogState, false);
diff --git a/docs/generate-datasette-modal-example.sh b/docs/generate-datasette-modal-example.sh
index 4fedf8b3..f774c679 100755
--- a/docs/generate-datasette-modal-example.sh
+++ b/docs/generate-datasette-modal-example.sh
@@ -73,7 +73,7 @@ document.addEventListener("datasette_init", function (event) {
Hello from a plugin!
`,
@@ -81,9 +81,6 @@ document.addEventListener("datasette_init", function (event) {
if (!modal) {
return; // Browser does not support