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/utils.js src/hg/js/utils.js index 1b57db8..8998d26 100644 --- src/hg/js/utils.js +++ src/hg/js/utils.js @@ -457,30 +457,77 @@ // json help routines function tdbGetJsonRecord(trackName) { return hgTracks.trackDb[trackName]; } // NOTE: These must jive with tdbKindOfParent() and tdbKindOfChild() in trackDb.h function tdbIsFolder(tdb) { return (tdb.kindOfParent === 1); } function tdbIsComposite(tdb) { return (tdb.kindOfParent === 2); } function tdbIsMultiTrack(tdb) { return (tdb.kindOfParent === 3); } function tdbIsView(tdb) { return (tdb.kindOfParent === 4); } // Don't expect to use function tdbIsContainer(tdb) { return (tdb.kindOfParent === 2 || tdb.kindOfParent === 3); } function tdbIsLeaf(tdb) { return (tdb.kindOfParent === 0); } function tdbIsFolderContent(tdb) { return (tdb.kindOfChild === 1); } function tdbIsCompositeSubtrack(tdb) { return (tdb.kindOfChild === 2); } function tdbIsMultiTrackSubtrack(tdb) { return (tdb.kindOfChild === 3); } function tdbIsSubtrack(tdb) { return (tdb.kindOfChild === 2 || tdb.kindOfChild === 3); } function tdbHasParent(tdb) { return (tdb.kindOfChild !== 0 && tdb.parentTrack); } +function tdbFindChildless(trackDb, delTracks) { + /* Find parents that have no children left anymore in hgTracks.trackDb if you remove delTracks. + * return obj with o.loneParents as array of [parent, array of children] , and o.others as an array of all other tracks*/ + others = []; + + var familySize = {}; + var families = {}; + // sort trackDb into object topParent -> count of children + for (var trackName of Object.keys(hgTracks.trackDb)) { + var rec = hgTracks.trackDb[trackName]; + if (rec.topParent===undefined) { + //others.push(trackName); + continue; // ignore top-level tracks + } + + var topParent = rec.topParent; + if (!familySize.hasOwnProperty(topParent)) { + familySize[topParent] = 0; + families[topParent] = []; + } + familySize[topParent]++; + families[topParent].push(trackName); + } + + // decrease the parent's count for each track to delete + for (var delTrack of delTracks) { + var tdbRec = hgTracks.trackDb[delTrack]; + if (tdbRec.topParent) + familySize[tdbRec.topParent]--; + } + + // for the parents with a count of 0, create an array of [parentName, children] + loneParents = []; + for (var parentName of Object.keys(familySize)) { + if (familySize[parentName]===0) + loneParents.push([parentName, families[parentName]]); + else + for (var child of families[parentName]) + others.push(child); + } + + o = {}; + o.loneParents = loneParents; + o.others = others; + return o; +} + function aryFind(ary,val) {// returns the index of a value on the array or -1; for (var ix=0; ix < ary.length; ix++) { if (ary[ix] === val) { return ix; } } return -1; } function aryRemove(ary,vals) { // removes one or more variables that are found in the array for (var vIx=0; vIx < vals.length; vIx++) { var ix = aryFind(ary,vals[vIx]); if (ix !== -1)