7ee3f386e0a4d9489d284ded95d19ba951468e7d
hiram
Tue Nov 10 09:18:15 2020 -0800
now using fontSize from browser for message box and number of data values for mouseOver mean detection refs and working in reverse display mode #21980
diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js
index 2f7ec64..ea4734b 100644
--- src/hg/js/hgTracks.js
+++ src/hg/js/hgTracks.js
@@ -4455,43 +4455,50 @@
imageV2.history.pushState({lastDbPos: newDbPos, position: newPos, hgsid: + sid },title,
"hgTracks?db="+getDb()+"&"+newDbPos+"&hgsid="+sid);
}
}
}
};
///////////////////////////////////////
//// mouseOver data display 2020-10 ///
///////////////////////////////////////
var mouseOver = {
spans: {},
visible: false,
tracks: {},
+ maximumWidth: {},
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,
+ browserTextSize: 12,
// spans{} - key name is track name, value is an array of
- // objects: {x1, x2, value}
+ // objects: {x1, x2, v, c}
+ // where [x1..x2) is the array index where the value 'v'
+ // is found, and 'c' is the data value count in this value
+ // i.e. when c > 1 the value is a 'mean' of 'c' data values
// 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)
+ // maximumWidth{} - key is track name, value is length of longest
+ // number string as measured when rendered
// 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)
{
var tdData = "td_data_" + trackName;
var tdDataId = document.getElementById(tdData);
@@ -4518,36 +4525,47 @@
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 ) {
+ var idx = 0;
+ if (hgTracks.revCmplDisp) {
+ var rectsLen = rects.length - 1;
+ for ( idx in rects ) {
+ if ((rects[rectsLen-idx].x1 <= x) && (x < rects[rectsLen-idx].x2)) {
+ answer = rectsLen-idx;
+ break;
+ }
+ }
+ } else {
+ for ( 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 !*!
mouseOver.visible = false;
$('#mouseOverText').css('display','none');
$('#mouseOverVerticalLine').css('display','none');
}
if (mouseOver.popUpTimer) {
clearTimeout(mouseOver.popUpTimer);
mouseOver.popUpTimer = null;
}
mouseOver.delayDone = true;
mouseOver.delayInProgress = false;
@@ -4575,59 +4593,66 @@
// location of mouse relative to the whole page
// even when the top of page has scolled off
var evtX = Math.floor(evt.pageX);
// var evtY = Math.floor(evt.pageY);
// var offX = Math.floor(evt.offsetX); // no need for evtY or offX
// 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);
- // clientX appears to be the X coordinate of the mouse hot spot
+ var tdWidth = Math.floor(tdRect.width);
+ var rightSide = tdLeft + tdWidth;
+ // clientX is the X coordinate of the mouse hot spot
var clientX = Math.floor(evt.clientX);
// the graphOffset is the index (x coordinate) into the 'spans' definitions
// of the data value boxes for the graph. The magic number three
// is used elsewhere in this code, note the comment on the constant
// LEFTADD.
var graphOffset = Math.max(0, clientX - tdLeft - 3);
+ if (hgTracks.revCmplDisp) {
+ graphOffset = Math.max(0, rightSide - clientX);
+ }
var windowUp = false; // see if window is supposed to become visible
var foundIdx = -1;
if (mouseOver.spans[trackName]) {
foundIdx = mouseOver.findRange(graphOffset, mouseOver.spans[trackName]);
}
// can show 'no data' when not found
- var mouseOverValue = "no data";
+ var mouseOverValue = "no data";
if (foundIdx > -1) { // value to display
- if (mouseOver.spans[trackName][foundIdx].m) {
+ if (mouseOver.spans[trackName][foundIdx].c > 1) {
mouseOverValue = " mean: " + mouseOver.spans[trackName][foundIdx].v + " ";
} else {
mouseOverValue = " " + mouseOver.spans[trackName][foundIdx].v + " ";
}
}
$('#mouseOverText').html(mouseOverValue);
- var msgWidth = Math.ceil($('#mouseOverText').width());
+ var msgWidth = mouseOver.maximumWidth[trackName];
+ $('#mouseOverText').width(msgWidth);
var msgHeight = Math.ceil($('#mouseOverText').height());
var lineHeight = Math.max(0, tdHeight - msgHeight);
var lineTop = Math.max(0, tdTop + msgHeight);
var msgLeft = Math.max(0, clientX - (msgWidth/2) - 3); // with magic 3
var lineLeft = Math.max(0, clientX - 3); // with magic 3
+ $('#mouseOverText').css('fontSize',mouseOver.browserTextSize);
$('#mouseOverText').css('left',msgLeft + "px");
$('#mouseOverText').css('top',tdTop + "px");
$('#mouseOverVerticalLine').css('left',lineLeft + "px");
$('#mouseOverVerticalLine').css('top',lineTop + "px");
$('#mouseOverVerticalLine').css('height',lineHeight + "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
@@ -4689,35 +4714,57 @@
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" ).
$( tdDataId ).mousemove(mouseOver.mouseMoveDelay);
$( tdDataId ).mouseout(mouseOver.popUpDisappear);
var itemCount = 0; // just for monitoring purposes
// save incoming x1,x2,v data into the mouseOver.spans[trackName][] array
+ var lengthLongestNumberString = 0;
+ var longestNumber = 0;
+ var hasMean = false;
for (var span in arr[trackName]) {
+ if (arr[trackName][span].c > 1) { hasMean = true; }
+ var lenV = arr[trackName][span].v.toString().length;
+ if (lenV > lengthLongestNumberString) {
+ lengthLongestNumberString = lenV;
+ longestNumber = arr[trackName][span].v;
+ }
mouseOver.spans[trackName].push(arr[trackName][span]);
++itemCount;
}
mouseOver.tracks[trackName] = itemCount; // merely for debugging watch
+ var mouseOverValue = "";
+ if (hasMean) {
+ mouseOverValue = " mean: " + longestNumber + " ";
+ } else {
+ mouseOverValue = " " + longestNumber + " ";
+ }
+ $('#mouseOverText').html(mouseOverValue); // see how big as rendered
+ var maximumWidth = Math.ceil($('#mouseOverText').width());
+ $('#mouseOverText').html("no data"); // might be bigger
+ if (Math.ceil($('#mouseOverText').width() > maximumWidth)) {
+ maximumWidth = Math.ceil($('#mouseOverText').width());
+ }
+ mouseOver.maximumWidth[trackName] = maximumWidth;
}
}, // receiveData: function (arr)
failedRequest: function(trackName)
{ // failed request to get json data, remove it from the track list
if (mouseOver.tracks[trackName]) {
delete mouseOver.tracks[trackName];
}
},
// =========================================================================
// fetchMapData() sends JSON request, callback to receiveData() upon return
// =========================================================================
fetchMapData: function (url, trackName)
{
@@ -4747,30 +4794,33 @@
var jsonData = trackList[i].getAttribute('jsonData');
if (jsonData) {
mouseOver.fetchMapData(jsonData, trackName);
}
}
},
// any scrolling turns the popUp message off
scroll: function()
{
if (mouseOver.visible) { mouseOver.popUpDisappear(); }
},
addListener: function () {
mouseOver.visible = false;
+ if (window.browserTextSize) {
+ mouseOver.browserTextSize = window.browserTextSize;
+ }
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").
|