b91db8547a0bb5431b4246b5faaf5696f73b2115
chmalee
  Thu Jul 16 11:25:35 2026 -0700
hubSpace: add Hub Upload menu link, selection banner, and shareable hub links, refs #37705

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

diff --git src/hg/js/hgHubConnect.js src/hg/js/hgHubConnect.js
index 67d0182602f..e5ed93ecf7a 100644
--- src/hg/js/hgHubConnect.js
+++ src/hg/js/hgHubConnect.js
@@ -57,46 +57,61 @@
 // hover effect to highlight table rows
 $(function() {
     $(".hubList tr").hover(
 
     function() {
         $(this).addClass("hoverRow");
     }, function() {
         $(this).removeClass("hoverRow");
     });
 });
 
 
 // initializes the tabs - with cookie option
 // cookie option requires jquery.cookie.js
 $(function() {
+  // maps a URL hash to the index of the matching tab, or -1 if none matches
+  function tabIndexForHash(hash) {
+      if (hash === "#conn") { hash = "#unlistedHubs"; }
+      if (hash === "#dev")  { hash = "#hubDeveloper"; }
+      return $("#tabs > ul > li > a[href='" + hash + "']").parent().index();
+  }
+
   $("#tabs").tabs({
       active: localStorage.getItem("hubTab") !== null ? localStorage.getItem("hubTab") : 0,
       activate: function(event, ui) {
           localStorage.setItem("hubTab", ui.newTab.index());
       },
   });
-  // activate tabs if the current URL ends with the appropriate tab name
-  var tabName = window.location.hash;
-  if (tabName==="#publicHubs")
-      $("#tabs").tabs("option", "active", 0);
-  if (tabName==="#conn" || tabName === "#unlistedHubs")
-      $("#tabs").tabs("option", "active", 1);
-  if (tabName==="#dev" || tabName === "#hubDeveloper")
-      $("#tabs").tabs("option", "active", 2);
-  if (tabName==="#hubUpload")
-      $("#tabs").tabs("option", "active", 3);
+  // activate the tab named by the current URL hash
+  var initialIndex = tabIndexForHash(window.location.hash);
+  if (initialIndex >= 0)
+      $("#tabs").tabs("option", "active", initialIndex);
+
+  // menubar links point to hgHubConnect#<tab>. When already on this page a same-page
+  // hash link only scrolls; intercept and switch tabs instead.
+  $(document).on("click", "a[href*='hgHubConnect'][href*='#']", function(ev) {
+      var index = tabIndexForHash(this.hash);
+      if (index >= 0) {
+          ev.preventDefault();
+          $("#tabs").tabs("option", "active", index);
+          // we didn't navigate, so close the hover menu holding this link
+          var $menuParent = $(this).closest("li.menuparent");
+          $menuParent.hideSuperfishUl();
+          $menuParent.find("> button, > a").attr("aria-expanded", "false");
+      }
+  });
 
   $("#tabs").tabs().on("tabsactivate", function(event, ui) {
     const  newHash = ui.newTab.find("a").attr("href");
     if (newHash) {
       history.replaceState(null, null, newHash);
     }
     if (newHash === "#hubUpload") {
         hubCreate.init();
     }
   });
 });
 
 // creates keyup event; listening for return key press
 $(document).ready(function() {
     $('#loadSampleHub').bind('click', function(e) {