7d7ba731c432325f1b3c235402a5af54b23e1ec7 chmalee Fri Nov 3 14:59:07 2023 -0700 Make user clicks into an input or select or contextmenu make tooltips go away. Also decrease fudgeFactor on mousemove so tooltips are a little more senstitive and turn off faster, refs Max email diff --git src/hg/js/utils.js src/hg/js/utils.js index 660f173..008cfd6 100644 --- src/hg/js/utils.js +++ src/hg/js/utils.js @@ -3920,69 +3920,69 @@ // signal handler for when mousemove has gone far enough away from the pop up // we can't use removeEventListener because the function call is hard to keep // track of because of a bounded this keyword let mousemoveController; // The div that moves around the users screen with the visible mouseover text var mouseoverContainer; function hideMouseoverText(ele) { /* Actually hides the tooltip text */ let tooltipTarget = ele; tooltipTarget.classList.remove("isShown"); tooltipTarget.style.opacity = "0"; tooltipTarget.style.visibility = "hidden"; } -function mouseIsOverPopup(ev, ele, fudgeFactor=45) { +function mouseIsOverPopup(ev, ele, fudgeFactor=25) { /* Is the mouse positioned over the popup? */ let targetBox = ele.getBoundingClientRect(); let mouseX = ev.clientX; let mouseY = ev.clientY; if ( (mouseX >= (targetBox.left - fudgeFactor) && mouseX <= (targetBox.right + fudgeFactor) && mouseY >= (targetBox.top - fudgeFactor) && mouseY <= (targetBox.bottom + fudgeFactor)) ) { return true; } return false; } -function mouseIsOverItem(ev, ele, fudgeFactor=45) { +function mouseIsOverItem(ev, ele, fudgeFactor=25) { /* Is the mouse positioned over the item that triggered the popup? */ let origName = ele.getAttribute("origItemMouseoverId"); let origTargetBox = boundingRect($("[mouseoverid='"+origName+"']")[0]); let mouseX = ev.clientX; let mouseY = ev.clientY; if ( (mouseX >= (origTargetBox.left - fudgeFactor) && mouseX <= (origTargetBox.right + fudgeFactor) && mouseY >= (origTargetBox.top - fudgeFactor) && mouseY <= (origTargetBox.bottom + fudgeFactor)) ) { return true; } return false; } 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, 250, e); + mousemoveTimer = setTimeout(callback, 500, 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; @@ -4102,30 +4102,83 @@ } function titleTagToMouseover(mapEl) { /* for a given area tag, extract the title text into a div that can be positioned * like a standard tooltip mouseover next to the item */ addMouseover(mapEl, mapEl.title); } function convertTitleTagsToMouseovers() { /* make all the title tags in the ideogram or main image have mouseovers */ $("[name=ideoMap]>[title],#imgTbl [title]").each(function(i, a) { if (a.title !== undefined && a.title.length > 0) { titleTagToMouseover(a); } }); + const inps = document.getElementsByTagName("input"); + const sels = document.getElementsByTagName("select"); + for (let inp of inps) { + if (!(inp.type == "hidden" || inp.type == "HIDDEN")) { + inp.addEventListener("focus", (ev) => { + hideMouseoverText(mouseoverContainer); + mousemoveController.abort(); + canShowNewMouseover = false; + }); + inp.addEventListener("blur", (evt) => { + canShowNewMouseover = true; + }); + } + } + for (let sel of sels) { + sel.addEventListener("focus", (ev) => { + hideMouseoverText(mouseoverContainer); + mousemoveController.abort(); + canShowNewMouseover = false; + }); + sel.addEventListener("blur", (evt) => { + canShowNewMouseover = true; + }); + } + let imgTbl = document.getElementById("imgTbl"); + if (imgTbl) { + imgTbl.addEventListener("contextmenu", function(e) { + hideMouseoverText(mouseoverContainer); + mousemoveController.abort(); + canShowNewMouseover = false; + // right-click menu doesn't capture focus so manually catch it + document.addEventListener("click", function(ev) { + // there is a race condition where the close happens after an inputs + // focus happens, which means mouseovers get re-enabled when the focus + // on the input should prevent them, catch that here: + if (!(document.activeElement.tagName === "INPUT" || + document.activeElement === "SELECT")) { + canShowNewMouseover = true; + } + }, {once: true}); + document.addEventListener("keyup", function(ev) { + if (ev.keyCode == 27) { + // there is a race condition where the close happens after an inputs + // focus happens, which means mouseovers get re-enabled when the focus + // on the input should prevent them, catch that here: + if (!(document.activeElement.tagName === "INPUT" || + document.activeElement === "SELECT")) { + canShowNewMouseover = true; + } + } + }, {once: true}); + }); + } } function tooltipNodesToMouseover() { /* For server side printed tooltip texts, make them work as pop ups. * Note this assumes two siblings nodes placed next to each other: * <nodeName class="Tooltip">the text or element that is hoverable</nodename> * <nodeName class="Tooltiptext'>the text/html of the popup itself * Please note that the Tooltiptext node can have any arbitrary html in it, like * line breaks or links*/ $(".Tooltip").each(function(i, n) { tooltiptext = n.getAttribute("mouseoverText"); if (tooltiptext !== null) { addMouseover(n, tooltiptext); } });