5fef9ecfe121867dc6bd750a6a01b46150bb868e hiram Tue Nov 3 15:46:21 2020 -0800 dirty checkin for transition to click through to description page working and streamline the popUp text window definition refs #21980 diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js index 9f76930..6da3b50 100644 --- src/hg/js/hgTracks.js +++ src/hg/js/hgTracks.js @@ -4460,192 +4460,221 @@ }; /////////////////////////////////////// //// mouseOver data display 2020-10 /// /////////////////////////////////////// var mouseOver = { spans: {}, visible: false, tracks: {}, popUpDelay: 1000, // one second delay before popUp appears popUpTimer: null,// handle from setTimeout to use in clearTimout(popUpTimer) delayDone: true, // mouse has not left element, still receiving move evts delayInProgress: false, // true if working with delay timer done mostRecentMouseEvt: null, + mouseMoveCount: 0, + mouseDelayCount: 0, + mouseInTrackCount: 0, // spans{} - key name is track name, value is an array of // objects: {x1, x2, value} // visible - keep track of window visible or not, value: true|false // shouldn't need to do this here, the window knows if it // is visible or not, just ask it for status // tracks{} - tracks that were set up initially, key is track name // value is the number of boxes (for debugging) // given hgt_....png file name, change to trackName_....json file name jsonFileName: function(imgElement, trackName) { var jsonFile=imgElement.src.replace("hgt/hgt_", "hgt/" + trackName + "_"); jsonFile = jsonFile.replace(".png", ".json"); return jsonFile; }, // called from: updateImgForId when it has updated a track in place // need to refresh the event handlers and json data updateMouseOver: function (trackName) { if (mouseOver.tracks[trackName]) { // there should be a more simple jQuery function to bind these events var tdData = "td_data_" + trackName; - var tdElement = document.getElementById(tdData); - var id = tdElement.id; - tdElement.addEventListener('mousemove', mouseOver.mouseMoveDelay); - tdElement.addEventListener('mouseout', mouseOver.popUpDisappear); + var tdDataId = document.getElementById(tdData); + $( tdDataId ).mousemove(mouseOver.mouseMoveDelay); + $( tdDataId ).mouseout(mouseOver.popUpDisappear); +// $( tdDataId ).bind('mousemove', mouseOver.mouseMoveDelay); +// $( tdDataId ).bind('mouseout', mouseOver.popUpDisappear); +// tdDataId.addEventListener('mousemove', mouseOver.mouseMoveDelay, true); +// tdDataId.addEventListener('mouseout', mouseOver.popUpDisappear, true); var imgData = "img_data_" + trackName; var imgElement = document.getElementById(imgData); mouseOver.fetchMapData(mouseOver.jsonFileName(imgElement, trackName), trackName); } }, // given an X coordinate: x, find the index idx // in the rects[idx] array where rects[idx].x1 <= x < rects[idx].x2 // returning -1 when not found // if we knew the array was sorted on x1 we could get out early // when x < x1 findRange: function (x, rects) { var answer = -1; // assmume not found for ( var idx in rects ) { if ((rects[idx].x1 <= x) && (x < rects[idx].x2)) { answer = idx; break; } } return answer; }, popUpDisappear: function () { if (mouseOver.visible) { // should *NOT* have to keep track !*! // $('#mouseOverText').hide(); // does not function ? - var msgWindow = document.querySelector(".wigMouseOver"); - msgWindow.classList.toggle("showMouseOver"); +// var msgWindow = document.querySelector(".wigMouseOver"); +// msgWindow.classList.toggle("showMouseOver"); mouseOver.visible = false; +// hPrintf("
\n"); // $('#mouseOverContainer').css('display','none'); // does not work - $('#mouseOverLine').css('display','none'); + $('#mouseOverText').css('display','none'); + $('#mouseOverVerticalLine').css('display','none'); } if (mouseOver.popUpTimer) { clearTimeout(mouseOver.popUpTimer); mouseOver.popUpTimer = null; } mouseOver.delayDone = true; mouseOver.delayInProgress = false; }, popUpVisible: function () { if (! mouseOver.visible) { // should *NOT* have to keep track !*! // $('#mouseOverText').show(); // does not function ? - var msgWindow = document.querySelector(".wigMouseOver"); - msgWindow.classList.toggle("showMouseOver"); +// var msgWindow = document.querySelector(".wigMouseOver"); +// msgWindow.classList.toggle("showMouseOver"); mouseOver.visible = true; // $('#mouseOverContainer').css('display','block'); // does not work - $('#mouseOverLine').css('display','block'); + $('#mouseOverText').css('display','block'); + $('#mouseOverVerticalLine').css('display','block'); } }, +// hPrintf("
\n"); +// hPrintf("
\n"); - //the evt.target.id is the img_data_ element of the track graphic + //the evt.currentTarget.id is the td_data_ element of the track graphic mouseInTrackImage: function (evt) { + ++mouseOver.mouseInTrackCount; + +// var msg = ". . . mouseInTrackImage: evt.currentTarget.id: " + evt.currentTarget.id + ", mouseMoveCount: " + mouseOver.mouseMoveCount + ", mouseDelayCount: " + mouseOver.mouseDelayCount + ", mouseInTrackCount: " + mouseOver.mouseInTrackCount; +// $('#debugMsg').html(msg); + // 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.target.id.includes("img_data_")) { return; } - var trackName = evt.target.id.replace("img_data_", ""); + 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 tdName = "td_data_" + trackName; - var tdId = document.getElementById(tdName); +// var tdName = "td_data_" + trackName; + 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 imageId = document.getElementById(evt.target.id); + 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 imageHeight = Math.floor(imageRect.height); - var srcUrl = evt.target.src; - var evX = evt.x; // location of mouse on the web browser screen - var evY = evt.y; - var offLeft = Math.max(0, Math.floor(evt.x - tdLeft)); + 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 windowUp = false; // see if window is supposed to become visible var foundIdx = -1; if (mouseOver.spans[trackName]) { foundIdx = mouseOver.findRange(offLeft, mouseOver.spans[trackName]); } +// var msg = ". . . tdRect: " + tdLeft + "," + tdTop + ", imgRect: " + imageLeft + "," + imageTop + ", evtXY: " + evtX + "," + evtY + ", offLeft: " + offLeft + ", foundIdx: " + foundIdx; +// $('#debugMsg').html(msg); // might want to indicate 'no data' when not found if (foundIdx > -1) { // value to display var mouseOverValue = " " + mouseOver.spans[trackName][foundIdx].v + " "; $('#mouseOverText').html(mouseOverValue); var msgWidth = Math.ceil($('#mouseOverText').width()); var msgHeight = Math.ceil($('#mouseOverText').height()); - var posLeft = evt.x - msgWidth + "px"; + var posLeft = evtX - msgWidth + "px"; var posTop = tdTop + "px"; - $('#mouseOverContainer').css('left',posLeft); - $('#mouseOverContainer').css('top',posTop); - $('#mouseOverLine').css('left',evt.x + "px"); - $('#mouseOverLine').css('top',posTop); +// var msg = ". . . posLeft,Top: " + posLeft + "," + posTop + ", evXY: " + evtX + "," + evtY + ", imageTop: " + imageTop; +// $('#debugMsg').html(msg); + $('#mouseOverText').css('left',posLeft); + $('#mouseOverText').css('top',posTop); + $('#mouseOverVerticalLine').css('left',evtX + "px"); + $('#mouseOverVerticalLine').css('top',posTop); +// msg = ". . . mouseOverText: " + mouseOverValue + " at: " + posLeft + "," + posTop; +// $('#debugMsg').html(msg); // Setting the height of this line to the full image height eliminates // the mouse event area - $('#mouseOverLine').css('height',tdHeight + "px"); -// $('#mouseOverLine').height(imageHeight + "px"); + $('#mouseOverVerticalLine').css('height',tdHeight + "px"); +// $('#mouseOverVerticalLine').height(imageHeight + "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.mouseDelayCount; 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 // If mouse has moved out of element during timeout, the // delayInProgress will be false and nothing happens. if (mouseOver.delayInProgress) { mouseOver.mouseInTrackImage(mouseOver.mostRecentMouseEvt); } }, // all mouse move events come here even during timeout mouseMoveDelay: function (evt) { + ++mouseOver.mouseMoveCount; + mouseOver.mostRecentMouseEvt = evt; // record evt for delayCompleted + +// var msg = ". . . mouseMoveDelay evt.currentTarget.id: " + evt.currentTarget.id + ", mouseMoveCount: " + mouseOver.mouseMoveCount + ", mouseDelayCount: " + mouseOver.mouseDelayCount + ", mouseInTrackCount: " + mouseOver.mouseInTrackCount; +// $('#debugMsg').html(msg); + if (mouseOver.delayInProgress) { if (mouseOver.delayDone) { mouseOver.mouseInTrackImage(evt); // OK to trigger event now return; } else { return; // wait for delay to be done } } mouseOver.delayDone = false; mouseOver.delayInProgress = true; if (mouseOver.popUpTimer) { clearTimeout(mouseOver.popUpTimer); mouseOver.popUpTimer = null; } mouseOver.popUpTimer = setTimeout(mouseOver.delayCompleted, mouseOver.popUpDelay); @@ -4665,33 +4694,42 @@ // 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. // ======================================================================= receiveData: function (arr) { mouseOver.visible = false; for (var trackName in arr) { mouseOver.spans[trackName] = []; // start array // add a 'mousemove' and 'mouseout' event listener to each track // display object var tdData = "td_data_" + trackName; var tdDataId = document.getElementById(tdData); if (! tdDataId) { return; } // not sure why objects are not always found +// from jQuery doc: +// As the .mousemove() method is just a shorthand +// for .on( "mousemove", handler ), detaching is possible +// using .off( "mousemove" ). // there should be a more simple jQuery function to bind these events - tdDataId.addEventListener('mousemove', mouseOver.mouseMoveDelay); - tdDataId.addEventListener('mouseout', mouseOver.popUpDisappear); +// $(tdData).bind('mousemove', mouseOver.mouseMoveDelay); does not work + $( tdDataId ).mousemove(mouseOver.mouseMoveDelay); + $( tdDataId ).mouseout(mouseOver.popUpDisappear); +// $( tdDataId ).bind('mousemove', mouseOver.mouseMoveDelay); +// $( tdDataId ).bind('mouseout', mouseOver.popUpDisappear); +// tdDataId.addEventListener('mousemove', mouseOver.mouseMoveDelay, true); +// tdDataId.addEventListener('mouseout', mouseOver.popUpDisappear, true); var itemCount = 0; // just for monitoring purposes // save incoming x1,x2,v data into the mouseOver.spans[trackName][] array for (var span in arr[trackName]) { mouseOver.spans[trackName].push(arr[trackName][span]); ++itemCount; } mouseOver.tracks[trackName] = itemCount; // merely for debugging watch } }, // receiveData: function (arr) failedRequest: function(trackName) { // failed request to get json data, remove it from the track list if (mouseOver.tracks[trackName]) { // alert("failed request trackName: '"+ trackName + "'"); delete mouseOver.tracks[trackName];