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 {
334 evt.preventDefault();334 evt.preventDefault();
335 evt.stopPropagation();335 evt.stopPropagation();
336 await this.complete(POPUP_RESULT.CANCELLED);336 await this.complete(POPUP_RESULT.CANCELLED);
337 window.removeEventListener('cancel', cancelListenerBound);
338 };337 };
339 const cancelListenerBound = cancelListener.bind(this);338 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
342 const keyListener = async (evt) => {353 const keyListener = async (evt) => {
343 switch (evt.key) {354 switch (evt.key) {
@@ -366,16 +377,16 @@ export class Popup {
366 evt.preventDefault();377 evt.preventDefault();
367 evt.stopPropagation();378 evt.stopPropagation();
368 const result = Number(document.activeElement.getAttribute('data-result') ?? this.defaultResult);379 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.
369 await this.complete(result);382 await this.complete(result);
370 window.removeEventListener('keydown', keyListenerBound);
371383
372 break;384 break;
373 }385 }
374 }386 }
375387
376 };388 };
377 const keyListenerBound = keyListener.bind(this);389 this.dlg.addEventListener('keydown', keyListener.bind(this));
378 this.dlg.addEventListener('keydown', keyListenerBound);
379 }390 }
380391
381 /**392 /**
@@ -445,9 +456,11 @@ export class Popup {
445 * - popup with `POPUP_TYPE.INPUT` will return the input value - or `false` on negative and `null` on cancelled456 * - popup with `POPUP_TYPE.INPUT` will return the input value - or `false` on negative and `null` on cancelled
446 * - All other will return the result value as provided as `POPUP_RESULT` or a custom number value457 * - All other will return the result value as provided as `POPUP_RESULT` or a custom number value
447 *458 *
459 * <b>IMPORTANT:</b> If the popup closing was cancelled via the `onClosing` handler, the return value will be `Promise<undefined>`.
460 *
448 * @param {POPUP_RESULT|number} result - The result of the popup (either an existing `POPUP_RESULT` or a custom result value)461 * @param {POPUP_RESULT|number} result - The result of the popup (either an existing `POPUP_RESULT` or a custom result value)
449 *462 *
450 * @returns {Promise<string|number|boolean?>} A promise that resolves with the value of the popup when it is completed.463 * @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>
451 */464 */
452 async complete(result) {465 async complete(result) {
453 // In all cases besides INPUT the popup value should be the result466 // In all cases besides INPUT the popup value should be the result
@@ -481,7 +494,13 @@ export class Popup {
481494
482 if (this.onClosing) {495 if (this.onClosing) {
483 const shouldClose = this.onClosing(this);496 const shouldClose = this.onClosing(this);
484 if (!shouldClose) return;497 if (!shouldClose) {
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 }
485 }504 }
486505
487 Popup.util.lastResult = { value, result, inputResults: this.inputResults };506 Popup.util.lastResult = { value, result, inputResults: this.inputResults };