fa4c30bd748a9c94307d007cba26dd1505995e82 hiram Fri Oct 30 16:38:22 2020 -0700 add error handline on failed json read and vertical hightline line to indicate where on graph value is and turn off popUp when window scrolls refs #21980 diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js index 9602be2..2e634c7 100644 --- src/hg/js/hgTracks.js +++ src/hg/js/hgTracks.js @@ -4478,123 +4478,134 @@ // 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 tdName = "td_data_" + trackName; - var tdElement = document.getElementById(tdName); + var tdData = "td_data_" + trackName; + var tdElement = document.getElementById(tdData); var id = tdElement.id; tdElement.addEventListener('mousemove', mouseOver.mouseInTrackImage); tdElement.addEventListener('mouseout', mouseOver.popUpDisappear); - var imgName = "img_data_" + trackName; - var imgElement = document.getElementById(imgName); - mouseOver.fetchMapData(mouseOver.jsonFileName(imgElement, trackName)); + 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"); mouseOver.visible = false; +// $('#mouseOverContainer').css('display','none'); // does not work + $('#mouseOverLine').css('display','none'); } }, 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"); mouseOver.visible = true; +// $('#mouseOverContainer').css('display','block'); // does not work + $('#mouseOverLine').css('display','block'); } }, //the evt.target.id is the img_data_<trackName> element of the track graphic mouseInTrackImage: function (evt) { // 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 (trackName.length < 1) { return; } // verify valid trackName // find location of this <td> 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 tdRect = tdId.getBoundingClientRect(); var tdLeft = Math.floor(tdRect.left); var tdTop = Math.floor(tdRect.top); // 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 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 windowUp = false; // see if window is supposed to become visible var foundIdx = -1; if (mouseOver.spans[trackName]) { foundIdx = mouseOver.findRange(offLeft, mouseOver.spans[trackName]); } // 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 posTop = tdTop + "px"; $('#mouseOverContainer').css('left',posLeft); $('#mouseOverContainer').css('top',posTop); + $('#mouseOverLine').css('left',evt.x + "px"); + $('#mouseOverLine').css('top',posTop); + // Setting the height of this line to the full image height eliminates + // the mouse event area +// $('#mouseOverLine').css('height',imageHeight + "px"); +// $('#mouseOverLine').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) // ======================================================================= // receiveData() callback for successful JSON request, receives incoming // JSON data and gets it into global variables for use here. // The incoming 'arr' is a a set of objects where the object key name is // the track name, used here as an array reference: arr[trackName] // (currently only one object per json file, one file for each track, @@ -4603,91 +4614,107 @@ // is an array of span definitions, where each element in the array is a // mapBox definition object: // {x1:n, x2:n, value:s} // 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 objectName = "td_data_" + trackName; - var objectId = document.getElementById(objectName); - if (! objectId) { return; } // not sure why objects are not found + var tdData = "td_data_" + trackName; + var tdDataId = document.getElementById(tdData); + if (! tdDataId) { return; } // not sure why objects are not always found // there should be a more simple jQuery function to bind these events - objectId.addEventListener('mousemove', mouseOver.mouseInTrackImage); - objectId.addEventListener('mouseout', mouseOver.popUpDisappear); - // would be nice to know when the window is scrolling in the browser so - // the text box could disappear. These do not appear to work. - // Beware, onscroll event is continuous while scrolling. -// objectId.addEventListener('onscroll', popUpDisappear); -// window.addEventListener('onscroll', popUpDisappear); + tdDataId.addEventListener('mousemove', mouseOver.mouseInTrackImage); + tdDataId.addEventListener('mouseout', mouseOver.popUpDisappear); 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) + { + if (mouseOver.tracks[trackName]) { +// alert("failed request trackName: '"+ trackName + "'"); + delete mouseOver.tracks[trackName]; + } + }, + // ========================================================================= // fetchMapData() sends JSON request, callback to receiveData() upon return // ========================================================================= - fetchMapData: function (url) + fetchMapData: function (url, trackName) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (4 === this.readyState && 200 === this.status) { var mapData = JSON.parse(this.responseText); mouseOver.receiveData(mapData); + } else { + if (4 === this.readyState && 404 === this.status) { + failedRequest(trackName); + } } }; xmlhttp.open("GET", url, true); xmlhttp.send(); // sends request and exits this function // the onreadystatechange callback above will trigger // when the data has safely arrived }, - getMouseOverData: function () + getData: function () { // verify hgTracks and hgTracks.trackDb exist before running wild if (typeof(hgTracks) !== "undefined") { if (typeof (hgTracks.trackDb) !== "undefined") { for (var trackName in hgTracks.trackDb) { - var isWiggle = false; var rec = hgTracks.trackDb[trackName]; + if (rec.visibility !== 2) { continue; } + var isWiggle = false; if (rec.type.includes("wig")) { isWiggle = true; } if (rec.type.includes("bigWig")) { isWiggle = true; } if (! isWiggle) { continue; } - var imgName = "img_data_" + trackName; - var imgElement = document.getElementById(imgName); + var imgData = "img_data_" + trackName; + var imgElement = document.getElementById(imgData); if (imgElement) { - mouseOver.fetchMapData(mouseOver.jsonFileName(imgElement, trackName)); + mouseOver.fetchMapData(mouseOver.jsonFileName(imgElement, trackName), trackName); } } } } }, + // any scrolling turns the popUp message off + scroll: function() + { + if (mouseOver.visible) { mouseOver.popUpDisappear(); } + }, + addListener: function () { - window.addEventListener('load', mouseOver.getMouseOverData, false); + mouseOver.visible = false; + window.addEventListener('scroll', mouseOver.scroll, false); + window.addEventListener('load', mouseOver.getData, false); } }; // var mouseOver ////////////////////// //// track search //// ////////////////////// var trackSearch = { searchKeydown: function (event) { if (event.which === 13) { // Required to fix problem on IE and Safari where value of hgt_tSearch is "-" // (i.e. not "Search"). // NOTE: must match TRACK_SEARCH_PAGER in hg/inc/searchTracks.h $("input[name=hgt_tsPage]").val(0);