bc030946a04b1f5c4c0a1501e0eb385747238b1b
mspeir
  Wed Sep 9 11:43:51 2026 -0700
trackDb docs: send a library cross-link to the current spec when the host page has no such anchor, refs #38062

trackDbLibrary.shtml is shared by trackDbDoc.html and all four trackDbHub
version pages. Its setting blurbs cross-reference other settings with a bare
fragment, but the anchor is written by each host page's own table of contents,
so a blurb that mentions a setting newer than a frozen hub spec has no target
on that page. trackDbHub.v0, v1 and v2 therefore carry dangling links to
filterLabel, detailsDynamicTable, filterBy, faceted_composite, onlyVisibility
and detailsStaticTable, and the library is regenerated while those snapshots
stay put, so the set grows with every new setting.

Rather than edit the frozen snapshots or hard-code a page into the library,
check at the moment a blurb is moved out of the hidden library into the
document and repoint the link to trackDbHub.html, which always serves the
current spec, when the anchor is not on the page. Links whose target is
present are untouched, so this changes nothing on trackDbDoc.html or on the
current spec, and it keeps working as settings are added.

Only the visibility blurb's link to faceted_composite is reachable by a reader
today; the rest sit in blurbs those pages do not display. Verified in a browser
on all five pages.

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

diff --git src/hg/htdocs/goldenPath/help/trackDb/trackDbDoc.js src/hg/htdocs/goldenPath/help/trackDb/trackDbDoc.js
index 1f2bcb5902c..c98ccf5cf2b 100644
--- src/hg/htdocs/goldenPath/help/trackDb/trackDbDoc.js
+++ src/hg/htdocs/goldenPath/help/trackDb/trackDbDoc.js
@@ -328,58 +328,77 @@
     },
 
     polishButton: function (obj,openUp) {
         // Called to polish the toggle buttons after an action
         if (openUp) {
             obj.src='/images/remove_sm.gif';
             obj.alt='-';
             obj.title='hide details';
         } else {
             obj.src='/images/add_sm.gif';
             obj.alt='+';
             obj.title='show details';
         }
     },
 
+    repointStaleLinks: function (scope) {
+        // A library blurb can cross-reference a setting that the host page does not list.
+        // The anchor for a setting is written by that page's own table of contents, so on a
+        // frozen older hub spec (trackDbHub.v0/v1/v2.html) such a link has no target here.
+        // Point those at trackDbHub.html, which always serves the current spec and does
+        // document the setting. Links whose target is on the page are left alone, so this
+        // is a no-op on trackDbDoc.html and on the current spec.
+        $(scope).find("a[href^='#']").each(function () {
+            var name = $(this).attr('href').substring(1);
+            if (name.length === 0)
+                return;
+            if (document.getElementById(name) === null
+            &&  document.getElementsByName(name).length === 0)
+                $(this).attr('href','trackDbHub.html#' + name);
+        });
+    },
+
     loadIntro: function (div) {
         // Called at startup to load each track type intro from the library
         var id = $(div).attr('id');
         var intro = tdbDoc.library.lookup(id,true);
         if (intro.length === 1) {
             $(intro).addClass("intro");
             $(intro).detach();
             $(div).replaceWith(intro);
+            tdbDoc.repointStaleLinks(intro);
         }
     },
 
     findDetails: function (td) {
         // Gets the setting description out of the library and puts it in place
         var id = $(td).attr('class');
         var details = tdbDoc.library.lookup(id,true);
         if (details.length === 1) {
             //var detail =  $(details).clone();
             var detail =  $(details).detach();
             //$(detail).attr('id','');  // keep unique ID
             $(detail).addClass("details");
             var format = $(detail).find("div.format");
             if (format.length === 1) {
                 $(format).detach();
                 $(td).find("div.format").replaceWith(format);
             }
             //$(details).clone().appendTo(td);
             //$(details).detatch();
             $(td).append(detail);
+            tdbDoc.repointStaleLinks(detail);
         }
         return $(td).find('div.details');
     },
 
     toggleDetails: function (obj,openUp) {
         // Called to toggle open or closed a single detail div or a related set
         var td = $(obj).parents('td')[0];
         var details = $(td).find('div.details');
         if (details == undefined || details.length !== 1) {
             details = tdbDoc.findDetails(td);
         }
         if (details == undefined || details.length > 1) {
             warn("Can't find details for id:" + td.id);
             return false;
         }