689349fca5a4865a1891db8cd39d392657b2b09b jcasper Wed Apr 22 02:54:09 2026 -0700 Replacing the subtrackUrl setting for faceted composites with subtrackUrls, which supports outlinks in multiple fields. refs #36320 diff --git src/hg/hgTrackUi/hgTrackUi.c src/hg/hgTrackUi/hgTrackUi.c index d4d3ac60db7..5839d4bd2a6 100644 --- src/hg/hgTrackUi/hgTrackUi.c +++ src/hg/hgTrackUi/hgTrackUi.c @@ -3048,31 +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"); +const char *subtrackUrls = trackDbSetting(tdb, "subtrackUrls"); // --- 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; @@ -3223,32 +3223,46 @@ 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(subtrackUrls)) + { + struct slPair *pairs = slPairListFromString((char *)subtrackUrls, TRUE); + if (pairs) + { + jsonWriteObjectStart(jw, "subtrackUrls"); + for (struct slPair *p = pairs; p != NULL; p = p->next) + { + char *encoded = htmlEncode((char *)p->val); + jsonWriteString(jw, p->name, encoded); + freeMem(encoded); + } + jsonWriteObjectEnd(jw); + } + slPairFreeValsAndList(&pairs); + } 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");