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/js/facetedComposite.js src/hg/js/facetedComposite.js
index 052e352c952..e5fbb8da62a 100644
--- src/hg/js/facetedComposite.js
+++ src/hg/js/facetedComposite.js
@@ -116,34 +116,44 @@
         const selectedDataTypes = new Set(  // get dataTypes selected initially
             Object.entries(embeddedData.dataTypes).filter(([_, val]) => val.active === 1)
                 .map(([key]) => key)
         );
         // initialize data type checkboxes (using class instead of 'name')
         document.querySelectorAll("input.cbgroup")
             .forEach(cb => { cb.checked = selectedDataTypes.has(cb.value); });
 
         // Capture initial data type state
         initialState.dataTypes = new Set(selectedDataTypes);
     }
 
     function initTable(allData) {
         const { metadata, rowToIdx, colNames } = allData;
 
-        const ordinaryColumns = colNames.map(key => ({  // all but checkboxes
+        const ordinaryColumns = colNames.map(key => {
+            const col = {
                 data: key,
                 title: toTitleCase(key.replace(/^_/, "")),
-        }));
+            };
+            if (key === embeddedData.primaryKey && embeddedData.subtrackUrl) {
+                col.render = (data, type) => {
+                    if (type !== "display") return data;
+                    const url = embeddedData.subtrackUrl.replace("$$", encodeURIComponent(data));
+                    return `<a href="${url}" target="_blank">${data}</a>`;
+                };
+            }
+            return col;
+        });
 
         const checkboxColumn = {
             data: null,
             orderable: false,
             defaultContent: "",
             title: `
             <label title="Select all visible rows">
             <input type="checkbox" id="select-all"/></label>`,
             // no render function needed
         };
 
         const hasDataTypes = embeddedData.dataTypes &&
                              Object.keys(embeddedData.dataTypes).length > 0;
         const itemLabel = hasDataTypes ? "samples" : "tracks";
         const singularLabel = itemLabel.slice(0, -1);