1ff9db2c7a16fbc5f3ef80468cea9c0d93469b22
hiram
  Thu Feb 24 14:05:28 2022 -0800
add a column 1 tool tip to indicate request or browser refs #28930

diff --git src/hg/js/gar.js src/hg/js/gar.js
index 104fb1d..e9c7c11 100644
--- src/hg/js/gar.js
+++ src/hg/js/gar.js
@@ -188,44 +188,47 @@
             gar.countVisHidden(thisClade, categoryVisible, isGCA, isGCF, canBeRequested, ucscDb);
             ++visRows;
           } else {
             gar.countVisHidden(thisClade, categoryHidden, isGCA, isGCF, canBeRequested, ucscDb);
           }
         }
       }
       var notVis = totalRows - visRows;
       /* fixup the hideAll checkbox status, if there are any rows visible,
        * those hideAll checkboxes should indicate off so they are
        * thereby ready to do the function of 'hideAll'.  Or if all rows
        * are not visible, they should be on to indicate 'hideAll' is in effect
        */
       /* reset the checked status on all the other show/hide check boxes */
       gar.checkBoxNames.forEach(function(checkBox, name) {
+         // add the counts (visible/hidden) to the checkBox label text
+         var visibleCount = 0;
          if (categoryVisible.get(name)) {
            checkBox.checked = true;
+           visibleCount = categoryVisible.get(name);
          } else {
            checkBox.checked = false;
          }
-         // add the counts (visible/hidden) to the checkBox label text
-         var visibleCount = 0;
          var hiddenCount = 0;
-         if ( categoryVisible.get(name) ) {
-           visibleCount = categoryVisible.get(name);
-         }
          if ( categoryHidden.get(name) ) {
            hiddenCount = categoryHidden.get(name);
          }
+         if (hiddenCount > 0 && visibleCount > 0) {
+           checkBox.indeterminate = true;
+         } else {
+           checkBox.indeterminate = false;
+         }
          var labelId = name + "Label";
          var labelEl = document.getElementById(labelId);
          var labelText = gar.checkBoxLabels.get(name);
          if (labelEl) {
             labelEl.innerText = labelText + " (" + visibleCount.toLocaleString() + "/" + hiddenCount.toLocaleString() + ")";
          } else {
 alert("no element for label '" + labelId + "'");
          }
       });
       var hideAllList = document.getElementsByClassName('hideAll');
 //      var thisEt = gar.millis() - t0;
       var thisEt = et;
       if (visRows > 0) {
 //        var pageEt = gar.garEndTime.getTime() - window.garStartTime.getTime();
 //        perfDisplay.innerHTML = "countRows  " + gar.garEndTime.getTime() + " - " + window.garStartTime.getTime() + " = page load time " + pageEt + " millis : DOMContentLoaded: " + gar.onLoadTime.getTime();
@@ -266,31 +269,30 @@
           var c = gar.cladeTableList[i].rows[j].cells[n];
           if (c) {
             gar.setCellVis(c, tf);
           }
         }
       }
     },
 
     // the 'e' is the event object from the checkbox
     // the 'e.value' is the column name.
     // can find the column number from columnNames Map object
     resetColumnVis: function(e) {
       var t0 = gar.millis();
       var n = gar.columnNames.get(e.value);
       var tf = e.checked;       // true - turn column on, false - turn off
-// alert("column '" + e.value + "' n '" + n + " : checked: '" + tf + "'");
       gar.setColumnNvis(n, tf);
       var et = gar.millis() - t0;
       gar.countVisibleRows(et);
     },
 
     hideTable: function(tableName) {
       tId = document.getElementById(tableName);
       var buttonName = tableName + "HideShow";
       bId = document.getElementById(buttonName);
       if ( tId.style.display === "none") {
         tId.style.display = "block";
         bId.innerHTML = "[hide]";
       } else {
         tId.style.display = "none";
         bId.innerHTML = "[show]";
@@ -440,30 +442,61 @@
     return undefined;
     },
 
 // obtain table name from
 // https://stackoverflow.com/questions/9066792/get-table-parent-of-an-element
     parentTable: function (e) {
     while (e) {
       e = e.parentNode;
       if (e.tagName.toLowerCase() === 'table') {
           return e;
       }
     }
     return undefined;
     },
 
+    // turn off the column 1 tool tip on mouse exit the table cell
+    col1TipOff: function(evt) {
+        $('#col1ToolTip').css('display','none');
+    },
+
+    // tooltip display for column one to indicate browser available or
+    //  request can be done
+    col1Tip: function(evt) {
+      if (evt.currentTarget) {
+        var cellRect = evt.currentTarget.getBoundingClientRect();
+        var cellLeft = Math.floor(cellRect.left);
+        var cellTop = Math.floor(cellRect.top);
+        var cellWidth = Math.floor(cellRect.width);
+        var cellHeight = Math.floor(cellRect.height);
+        var yOffset = Math.floor(window.pageYOffset);
+        var tipTop = Math.floor(yOffset + cellTop + (cellHeight/3));
+        var tipLeft = Math.floor(cellLeft+(cellWidth*0.8));
+        // class 'gar' means it can be requested
+        // NOT 'gar' means it exists (there are 'gak' and 'ucscDb' browsers)
+        var browserExists = ! evt.currentTarget.parentNode.classList.contains('gar');
+        if (browserExists) {
+          $('#col1ToolTip').html("browser");
+        } else {
+          $('#col1ToolTip').html("request");
+        }
+        $('#col1ToolTip').css('top',tipTop + "px");
+        $('#col1ToolTip').css('left',tipLeft + "px");
+        $('#col1ToolTip').css('display','block');
+      }
+    },
+
   // Original JavaScript code by Chirp Internet: chirpinternet.eu
   // Please acknowledge use of this code by including this header.
 //      const form = document.getElementById("modalFeedback");
 
     openModal: function(e) {
      if (e.name && e.name !== "specific") {
        var pTable = gar.parentTable(e);
        var thisRow = gar.whichRow(e);
 //       var thisCell = pTable.closest('td').cellIndex;
        var comName = pTable.rows[thisRow].cells[0].innerText;
        var sciName = pTable.rows[thisRow].cells[1].innerText;
        gar.commonName.textContent = comName;
        gar.betterCommonName.value = comName;
        gar.sciName.textContent = sciName;
        gar.asmIdText.textContent = e.name;