@@ -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