c5a326f3cc42beca0b59c284a2819763548c166a
max
  Wed Jul 8 05:31:13 2026 -0700
Add top-right "Share a link" and "Login" links to the menu bar, refs #10138

New js/topLinks.js drives two links at the top-right of the menu bar on all pages:

- Login: links to the login page when logged out; when logged in it shows the
username and opens an account dialog (My Sessions / My Custom Tracks /
My Track Hubs, change password, sign out).
- Share a link: on hgTracks, one click saves the current view as a session and
shows a copyable short link, with an optional "Specify name" rename step; works
logged-in or anonymously (reserved user "l"). On hgTrackUi and the hgc/hgGene
item-details popup it instead shares the page URL with the hgsid stripped and
the db argument kept.

hgSession gains two JSON endpoints (hgS_doSaveSessionJson, hgS_doRenameSessionJson)
that reuse saveCartAsSession() and addSessionLink(). The menu bar is patched in
lib/web.c (CGI pages) and hgMenubar.c (static pages) via comment placeholders in
globalNavBar.inc. On narrow/phone screens the links collapse into a menu icon with
a dropdown so they no longer overlap the menu.

diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js
index 515f0ada286..31a8467ac00 100644
--- src/hg/js/hgTracks.js
+++ src/hg/js/hgTracks.js
@@ -4861,31 +4861,42 @@
 
         // make sure all links (e.g. help links) open up in a new window
         //response = response.replace(/<a /ig, "<a target='_blank' ");
 
         var cleanHtml = response;
         cleanHtml = stripJsFiles(cleanHtml,false);   // DEBUG msg with true
         cleanHtml = stripCssFiles(cleanHtml,false);  // DEBUG msg with true
         var nonceJs = {};
         cleanHtml = stripCSPAndNonceJs(cleanHtml, false, nonceJs); // DEBUG msg with true
         cleanHtml = stripMainMenu(cleanHtml, false, nonceJs); // DEBUG msg with true
 
         // this is dumb but all relative links need to be stripped of _target = blank so we
         // can jump down the page rather than out to a new tab
         cleanHtml = cleanHtml.replace(/_target ?= ?["']blank["']/g,"");
 
-        $('#hgcDialog').html("<div id='pop' style='font-size:1.1em;'>"+ cleanHtml +"</div>");
+        // "Share a link" at the top of the popup: shares a link to this details page
+        // (the hgc URL with the hgsid stripped), handled by topLinks.js.
+        var shareBar = "<div id='hgcShareBar' style='margin:0 0 8px 0; text-align:right;'>" +
+            "<a id='hgcShareLink' href='#'>Share a link</a></div>";
+        $('#hgcDialog').html("<div id='pop' style='font-size:1.1em;'>"+ shareBar + cleanHtml +"</div>");
+        $('#hgcShareLink').on("click", function(e) {
+            e.preventDefault();
+            // Share the details-page URL with hgsid stripped; keep (or add) db so it opens
+            // standalone, and note that the link shows the page, not the user's active tracks.
+            if (window.topLinks && window.topLinks.shareUrl)
+                window.topLinks.shareUrl(popUpHgcOrHgGene.href, {ensureDb: getDb(), pageNote: true});
+        });
         appendNonceJsToPage(nonceJs);
         let subtrack = tdbIsSubtrack(hgTracks.trackDb[popUpHgcOrHgGene.table]) ? popUpHgcOrHgGene.table : "";
         popUpHgcOrHgGene.saveAllVars = getAllVars( $('#hgcDialog'), subtrack );
 
 
 
         // Strategy for popups with js:
         // - jsFiles and CSS should not be included in html.  Here they are shluped out.
         // - The resulting files ought to be loadable dynamically (with getScript()),
         //   but this was not working nicely with the modal dialog
         //   Therefore include files must be included with hgc CGI !
         // - embedded js should not be in the popup box.
         // - Somethings should be in a popup.ready() function, and this is emulated below,
         //   as soon as the cleanHtml is added
         //   Since there are many possible popup cfg dialogs, the ready should be all inclusive.