--- master.js 2026-11-09 14:51:03.930696542 +0000 +++ patched.js 2026-11-09 14:51:04.010697259 +0000 @@ -37,7 +37,7 @@ this.$blocker = null; if (this.options.closeExisting) while ($.modal.isActive()) - $.modal.close(); // Close any open modals. + getCurrent().close(true); // Close any open modals, ignoring cancellations. modals.push(this); if (el.is('a')) { target = el.attr('href'); @@ -104,7 +104,14 @@ }); }, - close: function() { + close: function(force) { + // Give listeners a chance to cancel the close before anything is torn + // down. A handler can return false or call event.preventDefault(). + if (!force) { + var ev = $.Event($.modal.BEFORE_CLOSE); + this.$elm.trigger(ev, [this._ctx()]); + if (ev.isDefaultPrevented()) return false; + } modals.pop(); this.unblock(); this.hide(); @@ -152,7 +159,6 @@ }, hide: function() { - this.$elm.trigger($.modal.BEFORE_CLOSE, [this._ctx()]); if (this.closeButton) this.closeButton.remove(); var _this = this; if(this.options.doFade) { @@ -165,6 +171,7 @@ }); } this.$elm.trigger($.modal.CLOSE, [this._ctx()]); + return true; }, showSpinner: function() { @@ -189,7 +196,8 @@ if (!$.modal.isActive()) return; if (event) event.preventDefault(); var current = getCurrent(); - current.close(); + // A cancelled close returns null; the modal is still open and current. + if (current.close() === false) return null; return current.$elm; };