1515 @keydown.space.exact =" onKeyDown"
1616 @keydown.left.exact =" onKeyDown"
1717 @keydown.right.exact =" onKeyDown"
18+ @click.capture =" captureDialogClick"
19+ @pointerdown.capture =" captureDialogPointerDown"
20+ @mousedown.stop.prevent
21+ @pointerdown.stop.prevent
1822 >
1923 <div class =" p-lightbox__underlay" ></div >
20- <div
21- ref =" container"
22- class =" p-lightbox__container"
23- @click.capture =" onContainerClick"
24- @pointerdown.capture =" onContainerPointerDown"
25- >
24+ <div ref =" container" class =" p-lightbox__container" >
2625 <div
2726 ref =" content"
2827 tabindex =" 1"
@@ -160,6 +159,7 @@ export default {
160159 trace,
161160 visible: false ,
162161 busy: false ,
162+ closing: false ,
163163 info: localStorage .getItem (" lightbox.info" ) === " true" ,
164164 menuElement: null ,
165165 menuBgColor: " #252525" ,
@@ -286,6 +286,7 @@ export default {
286286 showDialog () {
287287 this .$view .enter (this , this .$refs ? .content );
288288 this .busy = true ;
289+ this .closing = false ;
289290 this .visible = true ;
290291 this .wasFullscreen = $fullscreen .isEnabled ();
291292 this .info = localStorage .getItem (" lightbox.info" ) === " true" ;
@@ -307,6 +308,7 @@ export default {
307308 }
308309
309310 this .busy = false ;
311+ this .closing = false ;
310312
311313 // Publish event to be consumed by other components.
312314 this .$event .publish (" lightbox.closed" );
@@ -328,7 +330,7 @@ export default {
328330 // Traps the focus inside the lightbox dialog.
329331 onFocusOut (ev ) {
330332 if (this .debug ) {
331- this .log (` dialog.${ ev .type } ` , ev );
333+ this .log (` dialog.${ ev .type } ` , { ev } );
332334 }
333335
334336 if (! this .$view .isActive (this )) {
@@ -451,7 +453,8 @@ export default {
451453 this .busy = false ;
452454 })
453455 .catch (() => {
454- this .hideDialog ();
456+ this .busy = false ;
457+ this .close ();
455458 });
456459 });
457460
@@ -1041,7 +1044,7 @@ export default {
10411044 // action when events are triggered on an HTMLMediaElement.
10421045 this .lightbox .on (" pointerUp" , this .lightboxPointerListener );
10431046 this .lightbox .on (" pointerDown" , this .lightboxPointerListener );
1044- this .lightbox .on (" pointerMove" , this .lightboxPointerListener );
1047+ // this.lightbox.on("pointerMove", this.lightboxPointerListener);
10451048
10461049 // Add PhotoSwipe lightbox controls,
10471050 // see https://photoswipe.com/adding-ui-elements/.
@@ -1150,6 +1153,7 @@ export default {
11501153
11511154 // Show first image.
11521155 this .lightbox .loadAndOpen (this .index );
1156+ this .busy = false ;
11531157
11541158 return Promise .resolve ();
11551159 },
@@ -1179,9 +1183,11 @@ export default {
11791183 },
11801184 onClick : (ev ) =>
11811185 this .onControlClick (ev, () => {
1182- if (lightbox && lightbox . pswp ) {
1183- lightbox .pswp . close ( );
1186+ if (this . debug ) {
1187+ this . log ( " lightbox.close.click " , ev );
11841188 }
1189+
1190+ this .close ();
11851191 }),
11861192 });
11871193
@@ -1410,22 +1416,28 @@ export default {
14101416 onHideMenu () {
14111417 this .menuVisible = false ;
14121418 },
1413- closeLightbox () {
1414- if (this .isBusy (" close lightbox" )) {
1415- return Promise .reject ();
1419+ close () {
1420+ if (this .closing ) {
1421+ return new Promise ((resolve ) => {
1422+ this .$event .subscribeOnce (" lightbox.leave" , resolve);
1423+ });
14161424 }
14171425
1418- const pswp = this . pswp () ;
1426+ this . closing = true ;
14191427
1420- if (pswp) {
1421- this .busy = true ;
1428+ if (this .lightbox ) {
14221429 return new Promise ((resolve ) => {
14231430 this .$event .subscribeOnce (" lightbox.leave" , resolve);
1424- this .destroyLightbox ();
1431+ setTimeout (() => {
1432+ this .destroyLightbox ();
1433+ }, 150 );
14251434 });
14261435 }
14271436
1428- return this .hideDialog ();
1437+ return new Promise ((resolve ) => {
1438+ this .$event .subscribeOnce (" lightbox.leave" , resolve);
1439+ this .hideDialog ();
1440+ });
14291441 },
14301442 onLightboxOpened () {
14311443 this .addEventListeners ();
@@ -1437,20 +1449,23 @@ export default {
14371449 },
14381450 // Destroys the PhotoSwipe lightbox instance after use, see onClose().
14391451 destroyLightbox () {
1440- if ( this .lightbox ) {
1441- this .lightbox . destroy ();
1442- this .$event . publish ( " lightbox.destroy" );
1443- return ;
1444- }
1452+ this .$nextTick (() => {
1453+ if ( this .lightbox ) {
1454+ this .lightbox .destroy ( );
1455+ return ;
1456+ }
14451457
1446- this .hideDialog ();
1458+ this .hideDialog ();
1459+ });
14471460 },
14481461 onLightboxDestroyed () {
14491462 // Remove lightbox reference.
14501463 this .lightbox = null ;
14511464
14521465 // Hide lightbox and sidebar.
1453- this .hideDialog ();
1466+ this .$nextTick (() => {
1467+ this .hideDialog ();
1468+ });
14541469 },
14551470 // Returns the picture (model) caption as sanitized HTML, if any.
14561471 formatCaption (model ) {
@@ -1499,6 +1514,7 @@ export default {
14991514
15001515 this .clearTimeouts ();
15011516 this .removeEventListeners ();
1517+ this .closing = true ;
15021518 },
15031519 // Resets the component state after closing the lightbox.
15041520 onReset () {
@@ -1562,19 +1578,98 @@ export default {
15621578 return ;
15631579 }
15641580
1581+ if (this .debug ) {
1582+ this .log (` background.event.${ ev? .type }` , { ev });
1583+ }
1584+
15651585 if (this.controlsVisible()) {
1566- this .closeLightbox ();
1586+ this.close ();
15671587 } else {
15681588 this.showControls();
15691589 }
15701590 },
1571- // Called when the lightbox receives a pointer move, down or up event.
1572- onLightboxPointerEvent (ev ) {
1573- if (ev && ev .originalEvent .target .closest (" .pswp__dynamic-caption" )) {
1591+ // Returns the type of control if the event originates
1592+ // from a PhotoSwipe UI control, like the close button.
1593+ pswpControl(ev) {
1594+ if (!ev) {
1595+ return false;
1596+ }
1597+
1598+ let target;
1599+
1600+ if (ev.originalEvent?.target) {
1601+ target = ev.originalEvent.target;
1602+ } else if (ev.target) {
1603+ target = ev.target;
1604+ } else {
1605+ return false;
1606+ }
1607+
1608+ if (typeof target.closest === "function") {
1609+ if (target.closest(".pswp__button--close-button")) {
1610+ if (this.debug) {
1611+ this.log(` pswp .$ {ev? .type } on close` , { ev });
1612+ }
1613+
1614+ return "close";
1615+ }
1616+
1617+ if (target.closest(".pswp__button")) {
1618+ if (this.debug) {
1619+ this.log(` pswp .$ {ev? .type } on button` , { ev });
1620+ }
1621+
1622+ return "button";
1623+ }
1624+
1625+ if (target.closest(".pswp__top-bar")) {
1626+ if (this.debug) {
1627+ this.log(` pswp .$ {ev? .type } on top- bar` , { ev });
1628+ }
1629+
1630+ return "top-bar";
1631+ }
1632+ }
1633+
1634+ return false;
1635+ },
1636+ // Called when the lightbox receives a pointer down or up event.
1637+ // Move events are ignored for now.
1638+ onLightboxPointerEvent(ev, action) {
1639+ if (!ev || !ev.originalEvent?.target) {
1640+ return;
1641+ }
1642+
1643+ const target = ev.originalEvent.target;
1644+
1645+ if (this.debug) {
1646+ this.log(` lightbox .event .$ {ev .type }` , { ev, target, action });
1647+ }
1648+
1649+ // Close the lightbox when the user clicks the close button if it is visible.
1650+ const pswpControl = this.pswpControl(ev);
1651+ if (pswpControl === "close") {
1652+ if (this.controlsVisible()) {
1653+ ev.preventDefault();
1654+ this.close();
1655+ }
1656+ return;
1657+ }
1658+
1659+ if (target.closest(".pswp__dynamic-caption")) {
15741660 ev.preventDefault();
15751661 }
15761662 },
1663+ // Handle user clicks on a control. Does not reliably work for the close button.
15771664 onControlClick(ev, action) {
1665+ if (!ev) {
1666+ return;
1667+ }
1668+
1669+ if (this.debug) {
1670+ this.log(` control .event .$ {ev .type }` , { ev, action });
1671+ }
1672+
15781673 if (ev && ev.cancelable) {
15791674 ev.stopPropagation();
15801675 ev.preventDefault();
@@ -1593,11 +1688,16 @@ export default {
15931688
15941689 return false;
15951690 },
1596- onContainerClick (ev ) {
1691+ // Capture click events on the dialog component.
1692+ captureDialogClick(ev) {
15971693 if (!ev) {
15981694 return;
15991695 }
16001696
1697+ if (this.debug) {
1698+ this.log(` dialog .capture .$ {ev .type }` , { ev, target: ev.target });
1699+ }
1700+
16011701 // Reveal the controls when the user clicks or touches the top of the screen,
16021702 // where they are located when visible.
16031703 if (ev.y <= 128) {
@@ -1612,12 +1712,16 @@ export default {
16121712 ev.preventDefault();
16131713 }
16141714 },
1615- // Called when a pointer down (click, touch) event is captured by the lightbox container .
1616- onContainerPointerDown (ev ) {
1715+ // Capture pointer down events on the dialog component .
1716+ captureDialogPointerDown (ev) {
16171717 if (!ev) {
16181718 return;
16191719 }
16201720
1721+ if (this.debug) {
1722+ this.log(` dialog .capture .$ {ev .type }` , { ev, target: ev.target });
1723+ }
1724+
16211725 // Handle the click and touch events on custom content.
16221726 if (
16231727 ev.target instanceof HTMLMediaElement ||
@@ -1652,12 +1756,16 @@ export default {
16521756 this.toggleVideo();
16531757 }
16541758 },
1655- // Called when the user clicks on an image slide in the lightbox.
1759+ // Handle user clicks on an image slide in the lightbox.
16561760 onContentClick(ev) {
16571761 if (!ev) {
16581762 return;
16591763 }
16601764
1765+ if (this.debug) {
1766+ this.log(` content .event .$ {ev .type }` , { ev, target: ev.target, originalTarget: ev.originalEvent?.target });
1767+ }
1768+
16611769 if (this.slideshow.active) {
16621770 this.pauseSlideshow();
16631771 }
@@ -1670,12 +1778,16 @@ export default {
16701778 pswp.currSlide.toggleZoom();
16711779 }
16721780 },
1673- // Called when the user taps on an image slide in the lightbox.
1781+ // Handle user taps on an image slide in the lightbox.
16741782 onContentTap(ev) {
16751783 if (!ev) {
16761784 return;
16771785 }
16781786
1787+ if (this.debug) {
1788+ this.log(` content .event .$ {ev .type }` , { ev, target: ev.target, originalTarget: ev.originalEvent?.target });
1789+ }
1790+
16791791 if (ev.target instanceof HTMLMediaElement) {
16801792 // Do nothing.
16811793 } else {
@@ -1806,7 +1918,7 @@ export default {
18061918
18071919 switch (ev.code) {
18081920 case "Escape":
1809- this .closeLightbox ();
1921+ this.close ();
18101922 return true;
18111923 case "Period":
18121924 this.onShowMenu();
@@ -2224,7 +2336,7 @@ export default {
22242336 let album = null;
22252337
22262338 // Close lightbox and open edit dialog when closed.
2227- this .closeLightbox ().then (() => {
2339+ this.close ().then(() => {
22282340 this.$event.publish("dialog.edit", { selection, album, index });
22292341 });
22302342 },
@@ -2530,7 +2642,7 @@ export default {
25302642 data.loading = false;
25312643
25322644 if (this.trace) {
2533- this .log (` image.${ ev .type } ` , [ ev, ev .target ] );
2645+ this.log(` image .event . $ {ev .type }` , { ev, target: ev.target } );
25342646 }
25352647
25362648 // Abort if image URL is empty or the current slide is undefined.
@@ -2569,7 +2681,7 @@ export default {
25692681 // Set thumbnail src to load the new image.
25702682 image.src = thumb.src;
25712683 } catch (err) {
2572- this .log (` failed to load image size ${ thumb .size } ` , err);
2684+ this.log(` failed to load image size ${thumb .size }` , { err } );
25732685 data.loading = false;
25742686 }
25752687 },
0 commit comments