c11fa0744b12d0a369c0b73722afff9ced9764c5 chmalee Thu Nov 30 13:53:31 2023 -0800 Fix over correction of timer controlling whether a second tooltip should show up. Make code for determining y position of tooltip aware of which direction the mouse enters from so as not to obscure the element to be moused over, refs Max email diff --git src/hg/js/utils.js src/hg/js/utils.js index 4b07a5e..1c3500b 100644 --- src/hg/js/utils.js +++ src/hg/js/utils.js @@ -3863,37 +3863,41 @@ /* The actual mouseover positioning function. * refEl is an already existing element with coords that we use to position popUpEl. * popUpEl will try to be as close to the right/above the refEl, except when: * it would extend past the screen in which case it would go left/below appropriately. * the refEl takes up the whole screen, in which case we can cover the refEl * with no consequence */ rect = boundingRect(refEl); refX = rect.x; refY = rect.y; refWidth = rect.width; refHeight = rect.height; refRight = rect.right; refLeft = rect.left; refTop = rect.top; refBottom = rect.bottom; let windowWidth = window.innerWidth; let windowHeight = window.innerHeight; // figure out how large the mouseover will be - // use firstChild because popUpEl should be a div with a sole child in it - let popUpRect = popUpEl.firstChild.getBoundingClientRect(); + let popUpRect = popUpEl.getBoundingClientRect(); // position the popUp to the right and above the cursor by default + // tricky: when the mouse enters the element from the top, we want the tooltip + // relatively close to the element itself, because the mouse will already be + // on top of it, leaving it clickable or interactable. But if we are entering + // the element from the bottom, if we position the tooltip close to the mouse, + // we obscure the element itself, so we need to leave a bit of extra room let topOffset; - if (refEl.coords !== undefined && refEl.coords.length > 0 && refEl.coords.split(",").length == 4) { - // boundingRect has determined exactly as close as we can get to the item without covering - topOffset = refTop - popUpRect.height; + if (Math.abs(mouseY - refBottom) < Math.abs(mouseY - refTop)) { + // just use the mouseY position for placement, the -15 accounts for enough room + topOffset = mouseY - window.scrollY - popUpRect.height - 15; } else { // just use the mouseY position for placement, the -5 accounts for cursor size topOffset = mouseY - window.scrollY - popUpRect.height - 5; } let leftOffset = mouseX + 15; // add 15 for large cursor sizes // first case, refEl takes the whole width of the image, so not a big deal to cover some of it // this is most common for the track labels if (mouseX + popUpRect.width >= (windowWidth - 25)) { // move to the left leftOffset = mouseX - popUpRect.width; } // or the mouse is on the right third of the screen if (mouseX > (windowWidth* 0.66)) { // move to the left @@ -3963,31 +3967,31 @@ } function mousemoveTimerHelper(e) { /* user has moved the mouse and then stopped moving for long enough. */ clearTimeout(mousemoveTimer); canShowNewMouseover = true; mousemoveTimer = undefined; } function mousemoveHelper(e) { /* Helper function for deciding whether to keep a tooltip visible upon a mousemove event */ if (mousemoveTimer === undefined) { // if we are over another mouseable element we want to show that one instead // use this timer to do so let callback = mousemoveTimerHelper.bind(mouseoverContainer); - mousemoveTimer = setTimeout(callback, 150, e); + mousemoveTimer = setTimeout(callback, 300, e); } if (mousedNewItem && canShowNewMouseover && !mouseIsOverPopup(e, this, 0)) { // the !mouseIsOverPopup() check catches the corner case where the mouse // was moved slowly enough to the popup to set off the mousemoveTimer, but // is now over the pop up itself hideMouseoverText(this); mousemoveController.abort(); } else { if (mouseIsOverPopup(e, this) || mouseIsOverItem(e, this)) { // the mouse is in the general area of the popup/item // the mouse needs to stop moving and then the flag will // get set by the mousemoveTimer canShowNewMouseover = false; return;