77a4340b7205e040f0ae5298abc1271ce2f7ca33
jcasper
  Wed Apr 15 10:21:50 2026 -0700
Adding 'subtrackUrl' trackDb option for faceted composites to specify a
linkout url, refs #36320

diff --git src/hg/hgTrackUi/hgTrackUi.c src/hg/hgTrackUi/hgTrackUi.c
index ab13cb88f3e..9fabeab5f47 100644
--- src/hg/hgTrackUi/hgTrackUi.c
+++ src/hg/hgTrackUi/hgTrackUi.c
@@ -3048,30 +3048,31 @@
     "<style>body.cgi { background: #F0F0F0; }"
     "table.hgInside { background: #FFFFFF; }</style>";
 const char placeholderDiv[] = "<div id='metadata-placeholder'></div>\n";
 
 // --- Get data from 'settings' field in 'trackDb' entry ---
 // required
 const char *metaDataUrl = trackDbSetting(tdb, "metaDataUrl");
 const char *primaryKey = trackDbSetting(tdb, "primaryKey");
 
 struct slPair *dataTypes = parseDataTypes(tdb);
 boolean hasDataTypes = (dataTypes != NULL);
 
 // optional
 const char *colorSettingsUrl = (const char *)hashFindVal(tdb->settingsHash, "colorSettingsUrl");
 const char *maxCheckboxes = (const char *)hashFindVal(tdb->settingsHash, "maxCheckboxes");
+const char *subtrackUrl = trackDbSetting(tdb, "subtrackUrl");
 // --- done parsing values from trackDb.settings ---
 
 const char *metaDataId = tdb->track;
 const int metaDataIdLen = strlen(metaDataId);
 
 printf(pageStyle);       // css
 printf(placeholderDiv);  // placholder
 
 // start by figuring out what's on by default and hasn't been overridden
 struct hash *defaultOn = hashNew(0);
 for (struct trackDb *st = tdb->subtracks; st != NULL; st = st->next)
     {
     char *setting = NULL;
     char *words[2];
     boolean enabled = TRUE;
@@ -3222,30 +3223,32 @@
     hashElFreeList(&elList);
     }
 jsonWriteListEnd(jw);
 
 jsonWriteString(jw, "mdid", (char *)metaDataId);
 jsonWriteString(jw, "primaryKey", (char *)primaryKey);  // must exist
 if (maxCheckboxes) // only if present in trackDb.settings entry
     jsonWriteString(jw, "maxCheckboxes", (char *)maxCheckboxes);
 if (colorSettingsUrl) // only if present in trackDb.settings entry
     jsonWriteString(jw, "colorSettingsUrl", cgiEncode((char *)colorSettingsUrl));
 jsonWriteString(jw, "metadataUrl", cgiEncode((char *)metaDataUrl));
 jsonWriteString(jw, "track", tdb->track);
 char *defaultSortField = trackDbSetting(tdb, "defaultSortField");
 if (isNotEmpty(defaultSortField))
     jsonWriteString(jw, "defaultSortField", defaultSortField);
+if (subtrackUrl)
+    jsonWriteString(jw, "subtrackUrl", (char *)subtrackUrl);
 if (isNotEmpty(cartOptionalString(cart, "udcTimeout")))
     jsonWriteBoolean(jw, "udcTimeout", TRUE);
 
 jsonWriteObjectEnd(jw);
 printf("<script id=\"app-data\" type=\"application/json\">%s</script>\n", jw->dy->string);
 jsonWriteFree(&jw);
 /* --- END embedded JSON data --- */
 
 jsIncludeFile("dataTables-2.2.2.min.js", NULL);
 jsIncludeFile("dataTables.select-3.0.0.min.js", NULL);
 jsIncludeFile("facetedComposite.js", NULL);
 
 webIncludeResourceFile("dataTables-2.2.2.min.css");
 webIncludeResourceFile("dataTables.select-3.0.0.min.css");
 webIncludeResourceFile("facetedComposite.css");