c3e7b398ffd33e71d9810e6f8906e3caf57290a3
hiram
  Mon Oct 26 15:54:45 2020 -0700
correctly following window scrolling refs #21980

diff --git src/hg/js/mouseOver.js src/hg/js/mouseOver.js
index 0db0224..cca9571 100644
--- src/hg/js/mouseOver.js
+++ src/hg/js/mouseOver.js
@@ -34,62 +34,59 @@
      }
   }
   return answer;
 }
 
 function mouseLeftTrackImage(evt) {
   if (mapData.visible) {
     var mouseOver = document.querySelector(".wigMouseOver");
     mouseOver.classList.toggle("showMouseOver");
     mapData.visible = false;
   }
 }
 
 function mouseInTrackImage(evt) {
   var trackName = evt.target.id.replace("img_data_", "");
-  var firstRect = "";
-  if (mapData.spans[trackName]) {
-    var lastRect = mapData.spans[trackName].length - 1;
-    firstRect = mapData.spans[trackName][lastRect].x1 + ".." + mapData.spans[trackName][lastRect].x2;
-  }
   var evX = evt.x;
   var evY = evt.y;
-  var oLeft = $(this).offset().left;
-  var oTop = $(this).offset().top;
   var offLeft = Math.max(0, Math.floor(evt.x - $(this).offset().left));
   var windowUp = false;     // see if window is supposed to become visible
   var foundIdx = -1;
   var valP = "noX";
   if (mapData.spans[trackName]) {
      foundIdx = findRange(offLeft, mapData.spans[trackName]);
   }
   if (foundIdx > -1) {
+    var tdName = "td_data_" + trackName;
+    var elId  = document.getElementById(tdName);
+    var rectBounds = elId.getBoundingClientRect();
+    var rectTop = Math.floor(rectBounds.top);	// follows window scrolling
+    var rectLeft = Math.floor(rectBounds.left);
     valP = mapData.spans[trackName][foundIdx].v;
     // value to display
     var msg = " " + mapData.spans[trackName][foundIdx].v + " ";
     $('#mouseOverText').html(msg);
     var msgWidth = Math.ceil($('#mouseOverText').width());
     var msgHeight = Math.ceil($('#mouseOverText').height());
-    var posLeft = (evt.x - msgWidth) + "px";
-//    var posTop = (oTop + rect.y1) + "px";
-    var posTop = oTop + "px";
+    var posLeft = offLeft + (rectLeft - msgWidth) + "px";
+    var posTop = rectTop + "px";
     $('#mouseOverContainer').css('left',posLeft);
     $('#mouseOverContainer').css('top',posTop);
     windowUp = true;      // yes, window is to become visible
   }
   var offTop = Math.max(0, Math.floor(evt.y - $(this).offset().top));
-  var msg = "<p>. . . mouse in target.id: " + evt.target.id + "(" + trackName + ")[" + foundIdx + "]='" + valP + "' ["  + firstRect + "] at " + offLeft + "," + offTop + ", evX,Y: " + evX + "," + evY + ", offL,T: " + oLeft + "," + oTop + "</p>";
+  var msg = "<p>. . . mouse in target.id: " + evt.target.id + "(" + trackName + ")[" + foundIdx + "]='" + valP + "' at " + offLeft + "," + offTop + ", evX,Y: " + evX + "," + evY + "</p>";
   $('#eventRects').html(msg);
   if (windowUp) {     // the window should become visible
     if (! mapData.visible) {        // should *NOT* have to keep track !*!
       var contain = document.getElementById('mouseOverContainer');
       var mouseOver = document.querySelector(".wigMouseOver");
       mouseOver.classList.toggle("showMouseOver");
       mapData.visible = true;
     }
   } else {    // the window should disappear
     if (mapData.visible) {
       var mouseOver = document.querySelector(".wigMouseOver");
       mouseOver.classList.toggle("showMouseOver");
       mapData.visible = false;
     }
   } //      window visible/not visible
@@ -109,55 +106,56 @@
 //        where n is an integer in the range: 0..width,
 //        and s is the value string to display
 //     Will need to get them sorted on x1 for efficient searching as
 //     they accumulate in the local data structure here.
 // =========================================================================
 function receiveData(arr) {
   if (typeof mapData.spans === 'undefined') {
     mapData.spans = {};         // get this object started first time
     mapData.tracks = [];
     mapData.boxCount = [];
   }
   mapData.visible = false;
   for (var trackName in arr) {
     mapData.tracks.push(trackName);
     mapData.spans[trackName] = [];      // start array
-    // add a 'mousemove' event listener to each track display object
+    // add a 'mousemove' and 'mouseout' event listener to each track
+    //     display object
     var objectName = "td_data_" + trackName;
     var objectId  = document.getElementById(objectName);
     objectId.addEventListener('mousemove', mouseInTrackImage);
     objectId.addEventListener('mouseout', mouseLeftTrackImage);
     var itemCount = 0;	// just for monitoring purposes
     // save incoming x1,x2,v data into the mapData.spans[trackName][] array
     arr[trackName].forEach(function(box) {
       mapData.spans[trackName].push(box); ++itemCount});
     mapData.boxCount.push(itemCount);	// merely for debugging watch
   }
-  var msg = "<ul>";
-  for (var idx in mapData.tracks) {
-      var trackName = mapData.tracks[idx];
-      var imgData = "td_data_" + trackName;
-      var imgMap  = document.getElementById(imgData);
-      var imageRect = imgMap.getBoundingClientRect();
-      var top = Math.floor(imageRect.top);
-      var left = Math.floor(imageRect.left);
-      var width = Math.floor(imageRect.width);
-      var height = Math.floor(imageRect.height);
-     msg += "<li>" + trackName + " at left,top (x,y)(w,h):" + left + "," + top + "(" + width + "," + height + ") has: " + mapData.boxCount[idx] + " mapBoxes</li>";
-  }
-  msg += "</ul>";
-  $('#debugMsg').html(msg);
+//  var msg = "<ul>";
+//  for (var idx in mapData.tracks) {
+//      var trackName = mapData.tracks[idx];
+//      var imgData = "td_data_" + trackName;
+//      var imgMap  = document.getElementById(imgData);
+//      var imageRect = imgMap.getBoundingClientRect();
+//      var top = Math.floor(imageRect.top);
+//      var left = Math.floor(imageRect.left);
+//      var width = Math.floor(imageRect.width);
+//      var height = Math.floor(imageRect.height);
+//     msg += "<li>" + trackName + " at left,top (x,y)(w,h):" + left + "," + top + "(" + width + "," + height + ") has: " + mapData.boxCount[idx] + " mapBoxes</li>";
+//  }
+//  msg += "</ul>";
+//  $('#debugMsg').html(msg);
 }
 
 // =========================================================================
 // fetchMapData() sends JSON request, callback to receiveData() upon return
 // =========================================================================
 function fetchMapData(url) {
   var xmlhttp = new XMLHttpRequest();
   xmlhttp.onreadystatechange = function() {
     if (4 === this.readyState && 200 === this.status) {
       var mapData = JSON.parse(this.responseText);
       receiveData(mapData);
     }
   };
   xmlhttp.open("GET", url, true);
   xmlhttp.send();  // sends request and exits this function