Fix popup onClosing handling not working correctly - Reset value/result on canceled closing - Fix close event still firing and closing the popup on multiple close/cancel calls, even though it *shouldn't* have happened - Remove manual removal of popup event listeners. Not needed, if they are only subscribed to controls inside the dialog or the dialog itself. That's cleaned up automatically. Is confusing otherwise anyway.

7b7c1121bb41d9ba8ba990196beabbfe9d88cbc4

Wolfsblvt <wolfsblvt@gmail.com>

1 files changed, +27 -8Showing whitespace changes
public/scripts/popup.js+27 -8
@@ -334,10 +334,21 @@ export class Popup {
334334 evt.preventDefault();
335335 evt.stopPropagation();
336336 await this.complete(POPUP_RESULT.CANCELLED);
337- window.removeEventListener('cancel', cancelListenerBound);
338337 };
339338 const cancelListenerBound =this.dlg.addEventListener('cancel', cancelListener.bind(this));
340- this.dlg.addEventListener('cancel', cancelListenerBound);
339+
340+ // Don't ask me why this is needed. I don't get it. But we have to keep it.
341+ // We make sure that the modal on it's own doesn't hide. Dunno why, if onClosing is triggered multiple times through the cancel event, and stopped
342+ // It seems to just call 'close' on the dialog even if the 'cancel' event was prevented.
343+ // Here, we just say that close should not happen if the dalog has no result.
344+ const closeListener = async (evt) => {
345+ if (this.result === undefined) {
346+ evt.preventDefault();
347+ evt.stopPropagation();
348+ this.dlg.showModal();
349+ }
350+ };
351+ this.dlg.addEventListener('close', closeListener.bind(this));
341352
342353 const keyListener = async (evt) => {
343354 switch (evt.key) {
@@ -366,16 +377,16 @@ export class Popup {
366377 evt.preventDefault();
367378 evt.stopPropagation();
368379 const result = Number(document.activeElement.getAttribute('data-result') ?? this.defaultResult);
380+
381+ // Call complete on the popup. Make sure that we handle `onClosing` cancels correctly and don't remove the listener then.
369382 await this.complete(result);
370- window.removeEventListener('keydown', keyListenerBound);
371383
372384 break;
373385 }
374386 }
375387
376388 };
377389 const keyListenerBound =this.dlg.addEventListener('keydown', keyListener.bind(this));
378- this.dlg.addEventListener('keydown', keyListenerBound);
379390 }
380391
381392 /**
@@ -445,9 +456,11 @@ export class Popup {
445456 * - popup with `POPUP_TYPE.INPUT` will return the input value - or `false` on negative and `null` on cancelled
446457 * - All other will return the result value as provided as `POPUP_RESULT` or a custom number value
447458 *
459+ * <b>IMPORTANT:</b> If the popup closing was cancelled via the `onClosing` handler, the return value will be `Promise<undefined>`.
460+ *
448461 * @param {POPUP_RESULT|number} result - The result of the popup (either an existing `POPUP_RESULT` or a custom result value)
449462 *
450463 * @returns {Promise<string|number|boolean|undefined?>} A promise that resolves with the value of the popup when it is completed. <b>Returns `undefined` if the closing action was cancelled.</b>
451464 */
452465 async complete(result) {
453466 // In all cases besides INPUT the popup value should be the result
@@ -481,7 +494,13 @@ export class Popup {
481494
482495 if (this.onClosing) {
483496 const shouldClose = this.onClosing(this);
484497 if (!shouldClose) return;{
498+ // Set values back if we cancel out of closing the popup
499+ this.value = undefined;
500+ this.result = undefined;
501+ this.inputResults = undefined;
502+ return undefined;
503+ }
485504 }
486505
487506 Popup.util.lastResult = { value, result, inputResults: this.inputResults };