48a9ad0dffa17597791e51ac5dbaf38eee270864 hiram Wed Nov 4 11:18:44 2020 -0800 clean up mouseOver.css and fix off positions in hgTracks refs #21980 diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js index 938879f..20e5da7 100644 --- src/hg/js/hgTracks.js +++ src/hg/js/hgTracks.js @@ -4550,64 +4550,91 @@ // the center label also events here, can't use that // plus there is a one pixel line under the center label that has no // id name at all, so verify we are getting the event from the correct // element. if (! evt.currentTarget.id.includes("td_data_")) { return; } var trackName = evt.currentTarget.id.replace("td_data_", ""); if (trackName.length < 1) { return; } // verify valid trackName // find location of this slice in the image, this is the track // image in the graphic, including left margin and center label // This location follows the window scrolling, could go negative var tdId = document.getElementById(evt.currentTarget.id); var tdRect = tdId.getBoundingClientRect(); var tdLeft = Math.floor(tdRect.left); var tdTop = Math.floor(tdRect.top); var tdHeight = Math.floor(tdRect.height); + // find the location of the image itself, this could be the single complete // graphic image of all the tracks, or possibly the single image of the // track itself. This location also follows the window scrolling and can // even go negative when the web browser scrolls a window that is larger // than the width of the web browser. - var imageName = "img_data_" + trackName; - var imageId = document.getElementById(imageName); - var imageRect = imageId.getBoundingClientRect(); - var imageLeft = Math.floor(imageRect.left); - var imageTop = Math.floor(imageRect.top); - var evtX = evt.pageX; // location of mouse on the web browser screen - var evtY = evt.pageY; - var offLeft = Math.max(0, Math.floor(evtX - tdLeft)); + var imgName = "img_data_" + trackName; + var imgId = document.getElementById(imgName); + var imgRect = imgId.getBoundingClientRect(); + var imgLeft = Math.floor(imgRect.left); + var imgTop = Math.floor(imgRect.top); + var imgWidth = Math.floor(imgRect.width); + var imgHeight = Math.floor(imgRect.height); + var imgRectX = Math.floor(imgRect.x); + var evtX = Math.floor(evt.pageX); // location of mouse relative to the whole page + var evtY = Math.floor(evt.pageY); // even when the top of page has scolled off + var offX = Math.floor(evt.offsetX); + // This is very strange how this offLeft worked out, but it does work. + // What offLeft measures is how far into the graph is the cursor from + // the left side of the graph. This is needed as an index to find + // the data values that belong to the graph which are in mouseOver.spans + // It is always a positive number from 0 to (N-1) where N is the + // number of pixels in the graph. + // The jQuery pageX,pageY are a bit odd, they are always positive as + // measured from the top left corner of the page. The 'page' is + // the whole document even when it scrolls off screen to the top. + // jQuery documentation says the evt.offsetX is not always supported + // by all browsers. Will see about that. + // I don't see a way to simplify this offLeft. What I'm seeing is that + // evtX-offsetX is always 3, which I believe is the margin on the left + // side of the page between the page edge and where the image begins. + // Then, tdLeft is the offset from the left edge of the image to where + // the graph begins. This tdLeft changes as the window scrolls left + // and right, including going negative when it scrolls off screen left. + // + var offLeft = Math.max(0, Math.floor(2*offX - tdLeft + imgRectX - evtX)); var windowUp = false; // see if window is supposed to become visible var foundIdx = -1; if (mouseOver.spans[trackName]) { foundIdx = mouseOver.findRange(offLeft, mouseOver.spans[trackName]); } - // TBD: will want to indicate 'no data' when not found + // can show 'no data' when not found if (foundIdx > -1) { // value to display - var mouseOverValue = " " + mouseOver.spans[trackName][foundIdx].v + " "; + mouseOverValue = " " + mouseOver.spans[trackName][foundIdx].v + " "; + $('#mouseOverText').html(mouseOverValue); + } else { + var mouseOverValue = "no data"; $('#mouseOverText').html(mouseOverValue); + } var msgWidth = Math.ceil($('#mouseOverText').width()); var msgHeight = Math.ceil($('#mouseOverText').height()); - var posLeft = evtX - msgWidth + "px"; + var posLeft = imgLeft + offX - msgWidth + "px"; var posTop = tdTop + "px"; $('#mouseOverText').css('left',posLeft); $('#mouseOverText').css('top',posTop); - $('#mouseOverVerticalLine').css('left',evtX + "px"); + $('#mouseOverVerticalLine').css('left',imgLeft + offX + "px"); $('#mouseOverVerticalLine').css('top',posTop); $('#mouseOverVerticalLine').css('height',tdHeight + "px"); windowUp = true; // yes, window is to become visible - } + if (windowUp) { // the window should become visible mouseOver.popUpVisible(); } else { // the window should disappear mouseOver.popUpDisappear(); } // window visible/not visible }, // mouseInTrackImage function (evt) // timeout calls here upon completion delayCompleted: function() { mouseOver.delayDone = true; // mouse could just be sitting there with no events, if there // have been events during the timer, the evt has been recorded // so the popUp appears where the mouse is while it moved during the // time delay since mostRecentMouseEvt is up to date to now