c35f61249daf6b5f463754b180c3fe74ef42d39d
max
  Tue Oct 15 06:13:50 2024 -0700
when hiding tracks on right-click, hide parents if possible, rather than their children, refs #27890

diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js
index 8c6f319..18da867 100644
--- src/hg/js/hgTracks.js
+++ src/hg/js/hgTracks.js
@@ -2130,76 +2130,96 @@
         /* move a track to either "top" or "bottom" position */
         let newPos = "0.5";
         if (hgTracks.trackDb[0]!=="ruler")
             newPos = 0;
 
         if (topOrBottom==="bottom") {
             newPos = String(parseInt($(".imgOrd").last().attr("abbr"))+1);
         }
 
         let trEl = $(document.getElementById('tr_' + id));
         trEl.attr('abbr', newPos);
 
         dragReorder.sort($("#imgTbl"));
         dragReorder.setOrder($("#imgTbl"));
     },
-    hideTracks: function (ids, hideParent) 
+    hideTracks: function (ids)
     {
         var cartVars = [];
         var cartVals = [];
 
-        for (var i = 0; i<ids.length; i++) {
-            var id = ids[i];
-            var rec = hgTracks.trackDb[id];
-            if (hideParent) {
-                // only hide the parent, not children
-                $(document.getElementById('tr_' + id)).remove();
-                if (tdbHasParent(rec) && tdbIsLeaf(rec)) {
-                    id = rec.parentTrack;
+        // find parent tracks that are losing all their children (lone parents)
+        var familyAnalysis = tdbFindChildless(hgTracks.trackDb, ids);
+
+        // lone parents get special treatment
+        for (var delFam of familyAnalysis.loneParents) {
+            var loneParent = delFam[0];
+            var loneParentChildren = delFam[1];
+
+            // remove all the lone parent children now from the track image
+            for (var childName of loneParentChildren) {
+                $(document.getElementById('tr_' + childName)).remove();
             }
-                cartVars.push(id);
-                cartVals.push('hide');
+
+            // and set the lone parent to hide in the cart and also in the track list below
+            cartVars.push(loneParent);
+            cartVals.push('[]');
+            vis.update(loneParent, 'hide');
         }
-            else { 
+
+        // 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];
+            var rec = hgTracks.trackDb[id];
             if (tdbIsSubtrack(rec)) {
-                    // Remove subtrack level vis and explicitly uncheck.
-                    //cart.setVars( [ id, id+"_sel" ], [ '[]', 0 ] ); 
                 cartVars.push(id);
                 cartVals.push('[]');
 
                 cartVars.push(id+"_sel");
                 cartVals.push(0);
             } else if (tdbIsFolderContent(rec)) {
                 // supertrack children need to have _sel set to trigger superttrack reshaping
-                    //cart.setVars( [ id, id+"_sel" ], [ 'hide', 0 ] ); 
                 cartVars.push(id);
                 cartVals.push('hide');
 
                 cartVars.push(id+"_sel");
                 cartVals.push(0);
             } else {
-                    //cart.setVars([id], ['hide']);  // Others, just set vis hide.
+                // normal, top-level track
                 cartVars.push(id);
                 cartVals.push('hide');
             }
             $(document.getElementById('tr_' + id)).remove();
         }
-        }
         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;
+
+            hideList.push(otherId);
+        }
+        rightClick.hideTracks(hideList);
+    },
     makeMapItem: function (id)
     {   // Create a dummy mapItem on the fly
         // (for objects that don't have corresponding entry in the map).
         if (id && id.length > 0 && hgTracks.trackDb) {
             var title;
             var rec = hgTracks.trackDb[id];
             if (rec) {
                 title = rec.shortLabel;
             } else {
                 title = id;
             }
             return {id: id, title: "configure " + title};
         } else {
             return null;
         }
@@ -2482,36 +2502,31 @@
                 }
             }
 
             $.ajax({
                 type: "PUT",
                 async: false,
                 url: "../cgi-bin/hgCollection",
                 data: "cmd=addTrack&track=" + id + "&collection=" + collectionName + "&hgsid=" + getHgsid(),
                 trueSuccess: mySuccess,
                 success: catchErrorOrDispatch,
                 error: errorHandler,
             });
 
             imageV2.fullReload();
         } else if (cmd === "hideOthers") {
-            var hideIds = [];
-            for (var otherId in hgTracks.trackDb) {
-                if (otherId!==id && otherId!=="ruler") 
-                    hideIds.push(otherId);
-            }
-            rightClick.hideTracks(hideIds, true);
+            rightClick.hideOthers(id);
         } else if (cmd === "moveTop") {
             rightClick.moveTo(id, "top");
         } else if (cmd === "moveBottom") {
             rightClick.moveTo(id, "bottom");
         } else if ((cmd === 'sortExp') || (cmd === 'sortSim')) {
             url = "hgTracks?hgsid=" + getHgsid() + "&" + cmd + "=";
             rec = hgTracks.trackDb[id];
             if (tdbHasParent(rec) && tdbIsLeaf(rec))
                 url += rec.parentTrack;
             else {
                 // The button already has the ref
                 var link2 = normed($( 'td#td_btn_'+ rightClick.selectedMenuItem.id ).children('a')); 
                 if (link2)
                     url = $(link2).attr('href');
                 else
@@ -2659,31 +2674,31 @@
                 updateObj[key] = 1;
                 cart.setVarsObj(updateObj,null,false);
                 imageV2.requestImgUpdate(id, id + ".doMergeItems=1");
             }
         } else {   // if ( cmd in 'hide','dense','squish','pack','full','show' )
             // Change visibility settings:
             //
             // First change the select on our form:
             rec = hgTracks.trackDb[id];
             selectUpdated = vis.update(id, cmd);
 
             // Now change the track image
             if (imageV2.enabled && cmd === 'hide') {
                 // Hide local display of this track and update server side cart.
                 // Subtracks controlled by 2 settings so del vis and set sel=0.
-                rightClick.hideTracks([id], false);
+                rightClick.hideTracks([id]);
             } else if (!imageV2.mapIsUpdateable) {
                 jQuery('body').css('cursor', 'wait');
                 if (selectUpdated) {
                     // assert(document.TrackForm);
                     document.TrackForm.submit();
                 } else {
                         // Add vis update to queue then submit
                         cart.setVars([id], [cmd], null, false); // synchronous
                         document.TrackHeaderForm.submit();
                 }
             } else {
                 imageV2.requestImgUpdate(id, id + "=" + cmd, "", cmd);
             }
         }
     },