From f395e8ec0723e4fe6b7cbc169cc4bdae287fce1a Mon Sep 17 00:00:00 2001 From: 4aiman Date: Wed, 27 May 2026 22:55:43 +0300 Subject: [PATCH] Fix sub-modal (ingredient) closing parent modal (recipe editor) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: ingredient modal's closeModal called history.back(), which triggered recipe editor's popHandler → closed recipe editor too. Fix: modal suspend/resume system. - When sub-modal opens, parent modal's popHandler is suspended - When sub-modal closes, parent is resumed - Parent popHandler ignores popstate events while suspended - closeModal resumes parent before calling history.back() Also: closeModal now pops exactly 1 history entry (not _historyDepth). The _historyDepth counter tracks fullscreen entries within the modal, which are handled by popHandler's decrements. closeModal only needs to pop the modal's own base entry. --- frontend/js/main.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/frontend/js/main.js b/frontend/js/main.js index ef29427..1be53df 100644 --- a/frontend/js/main.js +++ b/frontend/js/main.js @@ -806,15 +806,21 @@ function showModal(html, onSubmit) { `; + // Suspend parent modal if sub-modal opening on top + const parentOverlay = document.querySelector(".modal-overlay"); + if (parentOverlay && parentOverlay._suspend) parentOverlay._suspend(); + document.body.appendChild(overlay); // Simple history stack: each open = pushState, each back = popState pops it. // Modal = 1 entry. Fullscreen map/chart inside modal = 1 more entry each. // Back always pops the top entry. No re-pushing, no flags. let _historyDepth = 1; // how many entries this modal owns + let _suspended = false; // true when sub-modal is open on top history.pushState({ modal: true }, ""); const popHandler = () => { + if (_suspended) return; // sub-modal handles this popstate _historyDepth--; // Check what's on top and collapse it @@ -855,13 +861,19 @@ function showModal(html, onSubmit) { history.pushState({ modalFs: true }, ""); }; + // Suspend/resume this modal's popHandler when a sub-modal opens on top + overlay._suspend = function() { _suspended = true; }; + overlay._resume = function() { _suspended = false; }; + function closeModal() { window.removeEventListener("popstate", popHandler); overlay.remove(); - // Pop all entries this modal owns - if (_historyDepth > 0) { - for (let i = 0; i < _historyDepth; i++) history.back(); - } + // Resume parent modal if this was a sub-modal + const parent = document.querySelector(".modal-overlay"); + if (parent && parent._resume) parent._resume(); + // Pop this modal's history entry + _modalPopHandled = true; + history.back(); } overlay.querySelector("#modal-back").onclick = () => closeModal();