f04f1b9af06c823602c5e0ecd3b8c2059d7704d3
jcasper
  Thu Aug 27 14:42:31 2026 -0700
Faceted composites now have a max display mode setting instead of a full override
of child track visibilities, with accompanying support for the onlyVisibility setting.  We also
now include a filter block (applied to appropriate child tracks) when those settings are in place.
refs #37662

diff --git src/hg/js/facetedComposite.js src/hg/js/facetedComposite.js
index f19ff0657bf..7847611df23 100644
--- src/hg/js/facetedComposite.js
+++ src/hg/js/facetedComposite.js
@@ -205,30 +205,35 @@
             }
             submitBtnEvent.target.form.submit();  // release submit event
         });
     }
 
     function initDataTypeSelector() {
         // Skip if no dataTypes defined or empty object
         if (!embeddedData.dataTypes || Object.keys(embeddedData.dataTypes).length === 0) {
             return;
         }
 
         const selector = document.getElementById("dataTypeSelector");
         selector.appendChild(Object.assign(document.createElement("label"), {
             innerHTML: "<b>Subtrack types enabled:</b>",
         }));
+
+        selector.appendChild(createInfoIcon(
+            "Multiple types of data can be displayed for each of the samples listed below. " +
+            "Check the boxes for the types you wish to view."));
+
         Object.keys(embeddedData.dataTypes).forEach(name => {
             const label = document.createElement("label");
             const dataType = embeddedData.dataTypes[name];
             label.innerHTML = `
                 <input type="checkbox" class="cbgroup" value="${name}">${dataType.title}`;
             selector.appendChild(label);
         });
         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); });
 
@@ -438,32 +443,32 @@
             {type: "button", className: "filter-tab"});
         const selectedTab = Object.assign(document.createElement("button"),
             {type: "button", className: "filter-tab"});
         toggleWrapper.appendChild(allTab);
         toggleWrapper.appendChild(selectedTab);
         lengthDiv.appendChild(toggleWrapper);
 
         // Refresh the tab labels and the active-tab highlight. Counts are grand
         // totals (default search:'none'), independent of the facet/search
         // filters, so "Selected" never misleadingly reads 0 when tracks are
         // selected but currently hidden by a facet. How many rows are actually
         // visible is reported by DataTables' bottom info line.
         function updateSelectedText() {
             const selCount = table.rows({selected: true}).count();
             const totalCount = table.rows().count();
-            allTab.textContent = `All (${totalCount})`;
-            selectedTab.textContent = `Active (${selCount})`;
+            allTab.textContent = `All Tracks (${totalCount})`;
+            selectedTab.textContent = `Active Tracks (${selCount})`;
             const showSelected = toggleCheckbox.checked;
             allTab.classList.toggle("active", !showSelected);
             selectedTab.classList.toggle("active", showSelected);
         }
         updateSelectedText();
 
         // Clicking a tab switches the selection filter and redraws. "Selected"
         // is always clickable; with nothing selected it just shows an empty list.
         function setFilterMode(showSelected) {
             toggleCheckbox.checked = showSelected;
             table.draw();
             updateSelectedText();
         }
         allTab.addEventListener("click", () => setFilterMode(false));
         selectedTab.addEventListener("click", () => setFilterMode(true));