7d0ceafa7c0753b9cd7e59b5e29641508e59ec87 max Fri Sep 4 12:18:57 2026 -0700 Close the Account dialog when one of its links is clicked, refs #38257 The dialog relied on navigation to remove it: every link in it leads to another page, and loading that page took the dialog away with it. "My Track Hubs" is the exception. On hgHubConnect it points at the page you are already on, and hgHubConnect.js cancels the click and switches to the Connected Hubs tab instead, so nothing ever removed the dialog. The dialog also swallowed the click on its way up, so hgHubConnect.js never saw it and the tab did not change either. Let clicks on links through, and close the dialog on the next tick, after the click has been fully dispatched. diff --git src/hg/js/topLinks.js src/hg/js/topLinks.js index 0911e2749f1..5176fcb3a4b 100644 --- src/hg/js/topLinks.js +++ src/hg/js/topLinks.js @@ -70,59 +70,71 @@ overlay.appendChild(box); document.body.appendChild(overlay); // Swallow Escape and clicks so they don't also reach an underlying dialog's own // close-on-escape / click-outside handlers (e.g. the hgc item-details popup). function onKey(ev) { if (ev.key === "Escape") { ev.preventDefault(); ev.stopImmediatePropagation(); closeModal(); } } overlay.addEventListener("click", function(ev) { if (ev.target === overlay) closeModal(); + // Clicks on a link are the exception: the page may have a handler that needs to see + // them (hgHubConnect.js watches for its own links and switches tab instead of + // reloading). A link click ends the dialog anyway, so nothing is lost by letting an + // underlying popup notice it too. + if (!ev.target.closest("a")) ev.stopPropagation(); }); document.addEventListener("keydown", onKey, true); // capture: run before other handlers closeCurrent = function() { document.removeEventListener("keydown", onKey, true); if (overlay.parentNode) overlay.parentNode.removeChild(overlay); }; return body; } // ---- Login / account dialog -------------------------------------------------------------- function showLoginDialog(link) { var user = link.getAttribute("data-username"); var logoutUrl = link.getAttribute("data-logouturl"); var changePwUrl = link.getAttribute("data-changepwurl"); var changeEmailUrl = link.getAttribute("data-changeemailurl"); var changeRecovEmailUrl = link.getAttribute("data-changerecovemailurl"); var body = document.createElement("div"); var p = el("p"); p.appendChild(document.createTextNode("Signed in as ")); p.appendChild(el("b", {textContent: user})); // textContent avoids HTML injection p.appendChild(document.createTextNode(".")); body.appendChild(p); // helper: add an <li><a> to a list function addLink(ul, href, text) { var li = el("li", {}, {margin: "6px 0"}); - li.appendChild(el("a", {href: href, textContent: text})); + var a = el("a", {href: href, textContent: text}); + // Most of these links leave the page, which takes the dialog with it. "My Track Hubs" + // does not when we are already on hgHubConnect: there hgHubConnect.js cancels the click + // and just switches a tab, so the dialog would stay up. Close it ourselves, deferred + // to the next tick so the click is fully dispatched first -- detaching the link while + // it is still being handled would rob hgHubConnect.js of the tab switch. + a.addEventListener("click", function() { setTimeout(closeModal, 0); }); + li.appendChild(a); ul.appendChild(li); } // "My Data" navigation: sessions, custom tracks, uploaded track hubs (hubSpace). var hgsid = getHgsidSafe(); var navUl = el("ul", {}, {listStyle: "none", margin: "0 0 10px 0", padding: "0"}); addLink(navUl, "../cgi-bin/hgSession?hgS_doMainPage=1&hgsid=" + hgsid, "My Sessions"); addLink(navUl, "../cgi-bin/hgCustom?hgsid=" + hgsid, "My Custom Tracks"); addLink(navUl, "../cgi-bin/hgHubConnect?hgsid=" + hgsid + "#unlistedHubs", "My Track Hubs"); body.appendChild(navUl); // Account actions. var ul = el("ul", {}, {listStyle: "none", margin: "0", padding: "0", borderTop: "1px solid #ddd", paddingTop: "8px"}); if (changePwUrl)