e5cddda75c01e4bc890d381eb4b95713c96cea1c
chmalee
  Tue Aug 25 10:08:37 2026 -0700
Remove track from visible tracks group on hiding the track, refs #38035

diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js
index 86ee723677b..a45463f4d1d 100644
--- src/hg/js/hgTracks.js
+++ src/hg/js/hgTracks.js
@@ -2049,32 +2049,34 @@
     },
     
     initForAjax: function()
     {   // To better support the back-button, it is good to eliminate extraneous form puts
         // Towards that end, we support visBoxes making ajax calls to update cart.
         var sels = $('select.normalText,select.hiddenText');
         $(sels).on("change", function() {
             var track = $(this).attr('name');
             let newVis = $(this).val();
             if (newVis === 'hide') {
                 var rec = hgTracks.trackDb[track];
                 if (rec)
                     rec.visibility = 0;
                 // else Would be nice to hide subtracks as well but that may be overkill
                 $(document.getElementById('tr_' + track)).remove();
+                // also remove this from the Visible Tracks group
+                removeTrackFromVisibleGroup(track);
                 cart.updateSessionPanel();
-                imageV2.drawHighlights();
+                imageV2.afterImgChange(true);
                 $(this).attr('class', 'hiddenText');
             } else
                 $(this).attr('class', 'normalText');
             document.querySelectorAll('[name="'+track+'"]').forEach( (sel) => {
                 sel.value = newVis;
             });
             
             cart.setVars([track], [$(this).val()]);
             imageV2.markAsDirtyPage();
             return false;
         });
         // Now we can rid the submt of the burden of all those vis boxes
         var form = $('form#TrackForm');
         $(form).on("submit", function () {
             $('select.normalText,select.hiddenText').prop('disabled',true);
@@ -3280,30 +3282,38 @@
                 var hiDefinedWidth = $(highlightArea).data('widthPixels');
                 hiOffset.left = Math.max(hiDefinedLeft + relativeX,
                                          portalAbsoluteX);
                 var right     = Math.min(hiDefinedLeft + hiDefinedWidth + relativeX,
                                          portalAbsoluteX + portalWidth);
                 var newWidth = Math.max(right - hiOffset.left,0);
                 if (hiDefinedWidth !== newWidth)
                     $(highlightArea).width(newWidth);
                 $(highlightArea).offset(hiOffset);
             }
         }
     }
 
 };
 
+function removeTrackFromVisibleGroup(track) {
+/* When a track has been hidden by the user, remove its select and label from
+ * the visible tracks group */
+    let rec = document.querySelector("[id^='visible-'] [data-track=\"" + track + "\"]");
+    if (rec)
+        rec.parentElement.remove();
+}
+
   ///////////////////////////////////////
  //// rightClick (aka context menu) ////
 ///////////////////////////////////////
 var rightClick = {
 
     menu: null,
     selectedMenuItem: null,   // currently choosen context menu item (via context menu).
     floatingMenuItem: null,
     currentMapItem:   null,
     supportZoomCodon: true,  // add zoom to exon and zoom to codon to right click menu
     clickedHighlightIdx : null,  // the index (0,1,...) of the highlight item that overlaps the last right-click
 
     moveTo : function(id, topOrBottom) {
         /* move a track to either "top" or "bottom" position */
         let newPos = "0.5";
@@ -3363,39 +3373,41 @@
                 // The problem is that it's not easy to find out if there is an easier way to hide them, the code
                 // would have to go over all possible parents, not just topParents. Maybe one day.
                 //if (tdbIsSubtrack(rec)) {
                  //  cartVars.push(childName+"_sel");
                  //   cartVals.push('0');
                 //}
             }
 
             // and set the lone parent to hide in the cart
             cartVars.push(loneParent);
             cartVals.push('hide');  // need to explicitely set to "hide", not "[]", to hide the default tracks
              
             // update the track list below the image
             vis.update(loneParent, 'hide');
             rightClick.hideLegends();
+            removeTrackFromVisibleGroup(loneParent);
             delete hgTracks.trackDb[loneParent]; // for the next right-click
         }
 
         // handle all other tracks, they are either not parents or parents with at least one child left
         var delIds = familyAnalysis.others;
         for (var i = 0; i<delIds.length; i++) {
             var id = delIds[i];
             cartHideAnyTrack(id, cartVars, cartVals);
             $(document.getElementById('tr_' + id)).remove();
+            removeTrackFromVisibleGroup(id);
             delete hgTracks.trackDb[id]; // for the next right-click
         }
         imageV2.afterImgChange(true);
         cart.setVars( cartVars, cartVals );
     },
 
     hideOthers: function (id) {
         /* hide all tracks but 'id'. Hide parents of composites/folders, rather than their children */
         var myParent = hgTracks.trackDb[id].parentTrack;
 
         var hideList = [];
         for (var otherId in hgTracks.trackDb) {
             if (otherId===id || otherId==="ruler")
                 continue;