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) 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; }