Skip to content

Commit b708d2f

Browse files
committed
IMP: methods to allow native close event
1 parent 5a80fab commit b708d2f

File tree

1 file changed

+39
-23
lines changed

1 file changed

+39
-23
lines changed

src/dialog.js

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export default function (Alpine) {
99
const evaluate = expression.length
1010
? evaluateLater(expression)
1111
: () => {};
12+
const canEvaluate = expression.length > 0;
1213
const lockPageScroll = modifiers.includes("noscroll");
1314
const closeBy = el.hasAttribute("closeby")
1415
? el.getAttribute("closeby")
@@ -18,51 +19,61 @@ export default function (Alpine) {
1819
el.style.display = null;
1920
el.style.length === 0 && el.removeAttribute("style");
2021

21-
el.addEventListener("keydown", escapeDialog);
22-
el.addEventListener("click", backdropDialog);
23-
el.addEventListener("submit", methodDialog);
2422
// Open dialog if the initial value is true
2523
if (el._x_isShown) {
2624
open();
2725
}
2826

27+
const closeBySupported = () => {
28+
return "closedBy" in HTMLDialogElement.prototype;
29+
};
30+
2931
function scrollLock(use = true) {
3032
document.body.style.overflow = use ? "hidden" : "";
3133
}
3234

33-
// Also update the AlpineJs logic when the native close is triggered
34-
// by the method=dialog or formmethod=dialog
35-
function methodDialog(event) {
35+
/**
36+
* Prevent submit method=dialog or formmethod=dialog for AlpineJs logic
37+
*/
38+
function dialogSubmit(event) {
3639
if (
37-
event.target.getAttribute("method") === "dialog" ||
38-
(event.submitter &&
39-
event.submitter.getAttribute("formmethod") === "dialog")
40+
(event.target.getAttribute("method") === "dialog" ||
41+
event.submitter?.getAttribute("formmethod") === "dialog") &&
42+
!canEvaluate
4043
) {
41-
evaluate();
44+
event.preventDefault();
4245
}
4346
}
4447

45-
// Prevent native escape for AlpineJs logic
48+
/**
49+
* Prevent native escape for AlpineJs logic
50+
*/
4651
function escapeDialog(event) {
47-
if (event.key !== "Escape") return;
48-
event.preventDefault();
49-
50-
if (closeby !== "any" && closeby !== "closerequest") return;
51-
evaluate();
52+
if (event.key === "Escape" && !canEvaluate) {
53+
event.preventDefault();
54+
}
5255
}
5356

54-
// Mimics the new closeby=any attribute
55-
function backdropDialog(event) {
56-
if (event.target !== el || closeby !== "any") return;
57-
57+
function handleCloseByEvent(event) {
58+
if (event.target !== el) return;
5859
const rect = el.getBoundingClientRect();
5960
const isInDialog =
6061
rect.top <= event.clientY &&
6162
event.clientY <= rect.top + rect.height &&
6263
rect.left <= event.clientX &&
6364
event.clientX <= rect.left + rect.width;
64-
if (isInDialog) return;
6565

66+
if (!isInDialog) {
67+
if (closeBy === "any") {
68+
if (closeBySupported) {
69+
event.preventDefault();
70+
}
71+
evaluate();
72+
}
73+
}
74+
}
75+
76+
function handleCloseEvent() {
6677
evaluate();
6778
}
6879

@@ -80,11 +91,16 @@ export default function (Alpine) {
8091

8192
el._x_doShow = () => open();
8293
el._x_doHide = () => close();
94+
el.addEventListener("keydown", escapeDialog);
95+
el.addEventListener("submit", dialogSubmit);
96+
el.addEventListener("click", handleCloseByEvent);
97+
el.addEventListener("cancel", handleCloseEvent);
8398

8499
cleanup(() => {
85100
el.removeEventListener("keydown", escapeDialog);
86-
el.removeEventListener("click", backdropDialog);
87-
el.removeEventListener("submit", methodDialog);
101+
el.removeEventListener("submit", dialogSubmit);
102+
el.removeEventListener("click", handleCloseByEvent);
103+
el.removeEventListener("cancel", handleCloseEvent);
88104
scrollLock(false);
89105
});
90106
}

0 commit comments

Comments
 (0)