Fossil SCM
Experimental change to have the tooltip appear automatically after a "dwell timeout", in addition to mouse clicks. See the wiki page linked to this branch for more information.
Commit
bba5337010c0e5e3b12d83e244dddda79931d070116206f885c1ae4380c038fa
Parent
cdb85ba9c96ab6c…
1 file changed
+47
-2
+47
-2
| --- src/graph.js | ||
| +++ src/graph.js | ||
| @@ -76,10 +76,18 @@ | ||
| 76 | 76 | } |
| 77 | 77 | var tooltipObj = document.createElement("span"); |
| 78 | 78 | tooltipObj.className = "tl-tooltip"; |
| 79 | 79 | tooltipObj.style.visibility = "hidden"; |
| 80 | 80 | document.getElementsByClassName("content")[0].appendChild(tooltipObj); |
| 81 | +/* This object must be in the global scope, so that (non-shadowed) access is | |
| 82 | +** possible from within a setTimeout() closure. */ | |
| 83 | +window.tooltipInfo = { | |
| 84 | + dwellTimeout: 250, /* The tooltip dwell timeout. */ | |
| 85 | + idTimer: 0, /* The tooltip dwell timer. */ | |
| 86 | + ixElement: -1, /* The id of the last hovered element. */ | |
| 87 | + posX: 0, posY: 0 /* The last mouse position. */ | |
| 88 | +}; | |
| 81 | 89 | |
| 82 | 90 | /* Construct that graph corresponding to the timeline-data-N object */ |
| 83 | 91 | function TimelineGraph(tx){ |
| 84 | 92 | var topObj = document.getElementById("timelineTable"+tx.iTableId); |
| 85 | 93 | amendCss(tx.circleNodes, tx.showArrowheads); |
| @@ -87,18 +95,52 @@ | ||
| 87 | 95 | topObj.ondblclick = dblclickOnGraph |
| 88 | 96 | topObj.onmousemove = function(e) { |
| 89 | 97 | var ix = findTxIndex(e); |
| 90 | 98 | var cursor = (ix<0) ? "" : "pointer"; /* Or: cursor = "help"? */ |
| 91 | 99 | document.getElementsByTagName('body')[0].style.cursor = cursor; |
| 100 | + /* Keep the already visible tooltip at a constant position, as long as the | |
| 101 | + ** mouse is over the same element. */ | |
| 102 | + if (tooltipObj.style.display != "none" && ix == tooltipInfo.ixElement) | |
| 103 | + return; | |
| 104 | + /* The tooltip is either not visible, or the mouse is over a different | |
| 105 | + ** element, so clear the dwell timer, and record the new element id and | |
| 106 | + ** mouse position. */ | |
| 107 | + if (tooltipInfo.idTimer != 0) { | |
| 108 | + clearTimeout(tooltipInfo.idTimer); | |
| 109 | + tooltipInfo.idTimer = 0; | |
| 110 | + } | |
| 111 | + if (ix >= 0) { | |
| 112 | + /* Close the tooltip only if the mouse is over another element, and init | |
| 113 | + ** the dwell timer again. */ | |
| 114 | + tooltipObj.style.display = "none"; | |
| 115 | + tooltipInfo.ixElement = ix; | |
| 116 | + tooltipInfo.posX = e.x; | |
| 117 | + tooltipInfo.posY = e.y; | |
| 118 | + tooltipInfo.idTimer = setTimeout(function() { | |
| 119 | + this.tooltipInfo.idTimer = 0; | |
| 120 | + showGraphTooltip( | |
| 121 | + this.tooltipInfo.ixElement, | |
| 122 | + this.tooltipInfo.posX, | |
| 123 | + this.tooltipInfo.posY); | |
| 124 | + }.bind(window),tooltipInfo.dwellTimeout); | |
| 125 | + } | |
| 126 | + else | |
| 127 | + tooltipInfo.ix = -1; | |
| 92 | 128 | }; |
| 93 | 129 | topObj.onmouseleave = function(e) { |
| 94 | 130 | /* Hide the tooltip if the mouse is outside the "timelineTableN" element, |
| 95 | 131 | ** and outside the tooltip. */ |
| 96 | 132 | if (tooltipObj.style.display != "none" && |
| 97 | 133 | e.relatedTarget && |
| 98 | 134 | e.relatedTarget != tooltipObj) { |
| 99 | 135 | tooltipObj.style.display = "none"; |
| 136 | + /* Clear the dwell timer. */ | |
| 137 | + if (tooltipInfo.idTimer != 0) { | |
| 138 | + clearTimeout(tooltipInfo.idTimer); | |
| 139 | + tooltipInfo.idTimer = 0; | |
| 140 | + } | |
| 141 | + tooltipInfo.ix = -1; | |
| 100 | 142 | } |
| 101 | 143 | }; |
| 102 | 144 | var canvasDiv; |
| 103 | 145 | var railPitch; |
| 104 | 146 | var mergeOffset; |
| @@ -480,10 +522,13 @@ | ||
| 480 | 522 | dest += encodeURIComponent(tx.rowinfo[ix].h) |
| 481 | 523 | return dest |
| 482 | 524 | } |
| 483 | 525 | function clickOnGraph(e){ |
| 484 | 526 | var ix = findTxIndex(e); |
| 527 | + showGraphTooltip(ix,e.x,e.y); | |
| 528 | + } | |
| 529 | + function showGraphTooltip(ix,posX,posY){ | |
| 485 | 530 | if( ix<0 ){ |
| 486 | 531 | tooltipObj.style.display = "none" |
| 487 | 532 | }else{ |
| 488 | 533 | var br = tx.rowinfo[ix].br |
| 489 | 534 | var dest = branchHyperlink(ix) |
| @@ -493,13 +538,13 @@ | ||
| 493 | 538 | .replace(/"/g, """) |
| 494 | 539 | .replace(/'/g, "'"); |
| 495 | 540 | tooltipObj.innerHTML = "<a href=\""+dest+"\">"+hbr+"</a>" |
| 496 | 541 | tooltipObj.style.display = "inline" |
| 497 | 542 | tooltipObj.style.position = "absolute" |
| 498 | - var x = e.x + 4 + window.pageXOffset | |
| 543 | + var x = posX + 4 + window.pageXOffset | |
| 499 | 544 | tooltipObj.style.left = x+"px" |
| 500 | - var y = e.y + window.pageYOffset - tooltipObj.clientHeight - 4 | |
| 545 | + var y = posY + window.pageYOffset - tooltipObj.clientHeight - 4 | |
| 501 | 546 | tooltipObj.style.top = y+"px" |
| 502 | 547 | tooltipObj.style.visibility = "visible" |
| 503 | 548 | } |
| 504 | 549 | } |
| 505 | 550 | function dblclickOnGraph(e){ |
| 506 | 551 |
| --- src/graph.js | |
| +++ src/graph.js | |
| @@ -76,10 +76,18 @@ | |
| 76 | } |
| 77 | var tooltipObj = document.createElement("span"); |
| 78 | tooltipObj.className = "tl-tooltip"; |
| 79 | tooltipObj.style.visibility = "hidden"; |
| 80 | document.getElementsByClassName("content")[0].appendChild(tooltipObj); |
| 81 | |
| 82 | /* Construct that graph corresponding to the timeline-data-N object */ |
| 83 | function TimelineGraph(tx){ |
| 84 | var topObj = document.getElementById("timelineTable"+tx.iTableId); |
| 85 | amendCss(tx.circleNodes, tx.showArrowheads); |
| @@ -87,18 +95,52 @@ | |
| 87 | topObj.ondblclick = dblclickOnGraph |
| 88 | topObj.onmousemove = function(e) { |
| 89 | var ix = findTxIndex(e); |
| 90 | var cursor = (ix<0) ? "" : "pointer"; /* Or: cursor = "help"? */ |
| 91 | document.getElementsByTagName('body')[0].style.cursor = cursor; |
| 92 | }; |
| 93 | topObj.onmouseleave = function(e) { |
| 94 | /* Hide the tooltip if the mouse is outside the "timelineTableN" element, |
| 95 | ** and outside the tooltip. */ |
| 96 | if (tooltipObj.style.display != "none" && |
| 97 | e.relatedTarget && |
| 98 | e.relatedTarget != tooltipObj) { |
| 99 | tooltipObj.style.display = "none"; |
| 100 | } |
| 101 | }; |
| 102 | var canvasDiv; |
| 103 | var railPitch; |
| 104 | var mergeOffset; |
| @@ -480,10 +522,13 @@ | |
| 480 | dest += encodeURIComponent(tx.rowinfo[ix].h) |
| 481 | return dest |
| 482 | } |
| 483 | function clickOnGraph(e){ |
| 484 | var ix = findTxIndex(e); |
| 485 | if( ix<0 ){ |
| 486 | tooltipObj.style.display = "none" |
| 487 | }else{ |
| 488 | var br = tx.rowinfo[ix].br |
| 489 | var dest = branchHyperlink(ix) |
| @@ -493,13 +538,13 @@ | |
| 493 | .replace(/"/g, """) |
| 494 | .replace(/'/g, "'"); |
| 495 | tooltipObj.innerHTML = "<a href=\""+dest+"\">"+hbr+"</a>" |
| 496 | tooltipObj.style.display = "inline" |
| 497 | tooltipObj.style.position = "absolute" |
| 498 | var x = e.x + 4 + window.pageXOffset |
| 499 | tooltipObj.style.left = x+"px" |
| 500 | var y = e.y + window.pageYOffset - tooltipObj.clientHeight - 4 |
| 501 | tooltipObj.style.top = y+"px" |
| 502 | tooltipObj.style.visibility = "visible" |
| 503 | } |
| 504 | } |
| 505 | function dblclickOnGraph(e){ |
| 506 |
| --- src/graph.js | |
| +++ src/graph.js | |
| @@ -76,10 +76,18 @@ | |
| 76 | } |
| 77 | var tooltipObj = document.createElement("span"); |
| 78 | tooltipObj.className = "tl-tooltip"; |
| 79 | tooltipObj.style.visibility = "hidden"; |
| 80 | document.getElementsByClassName("content")[0].appendChild(tooltipObj); |
| 81 | /* This object must be in the global scope, so that (non-shadowed) access is |
| 82 | ** possible from within a setTimeout() closure. */ |
| 83 | window.tooltipInfo = { |
| 84 | dwellTimeout: 250, /* The tooltip dwell timeout. */ |
| 85 | idTimer: 0, /* The tooltip dwell timer. */ |
| 86 | ixElement: -1, /* The id of the last hovered element. */ |
| 87 | posX: 0, posY: 0 /* The last mouse position. */ |
| 88 | }; |
| 89 | |
| 90 | /* Construct that graph corresponding to the timeline-data-N object */ |
| 91 | function TimelineGraph(tx){ |
| 92 | var topObj = document.getElementById("timelineTable"+tx.iTableId); |
| 93 | amendCss(tx.circleNodes, tx.showArrowheads); |
| @@ -87,18 +95,52 @@ | |
| 95 | topObj.ondblclick = dblclickOnGraph |
| 96 | topObj.onmousemove = function(e) { |
| 97 | var ix = findTxIndex(e); |
| 98 | var cursor = (ix<0) ? "" : "pointer"; /* Or: cursor = "help"? */ |
| 99 | document.getElementsByTagName('body')[0].style.cursor = cursor; |
| 100 | /* Keep the already visible tooltip at a constant position, as long as the |
| 101 | ** mouse is over the same element. */ |
| 102 | if (tooltipObj.style.display != "none" && ix == tooltipInfo.ixElement) |
| 103 | return; |
| 104 | /* The tooltip is either not visible, or the mouse is over a different |
| 105 | ** element, so clear the dwell timer, and record the new element id and |
| 106 | ** mouse position. */ |
| 107 | if (tooltipInfo.idTimer != 0) { |
| 108 | clearTimeout(tooltipInfo.idTimer); |
| 109 | tooltipInfo.idTimer = 0; |
| 110 | } |
| 111 | if (ix >= 0) { |
| 112 | /* Close the tooltip only if the mouse is over another element, and init |
| 113 | ** the dwell timer again. */ |
| 114 | tooltipObj.style.display = "none"; |
| 115 | tooltipInfo.ixElement = ix; |
| 116 | tooltipInfo.posX = e.x; |
| 117 | tooltipInfo.posY = e.y; |
| 118 | tooltipInfo.idTimer = setTimeout(function() { |
| 119 | this.tooltipInfo.idTimer = 0; |
| 120 | showGraphTooltip( |
| 121 | this.tooltipInfo.ixElement, |
| 122 | this.tooltipInfo.posX, |
| 123 | this.tooltipInfo.posY); |
| 124 | }.bind(window),tooltipInfo.dwellTimeout); |
| 125 | } |
| 126 | else |
| 127 | tooltipInfo.ix = -1; |
| 128 | }; |
| 129 | topObj.onmouseleave = function(e) { |
| 130 | /* Hide the tooltip if the mouse is outside the "timelineTableN" element, |
| 131 | ** and outside the tooltip. */ |
| 132 | if (tooltipObj.style.display != "none" && |
| 133 | e.relatedTarget && |
| 134 | e.relatedTarget != tooltipObj) { |
| 135 | tooltipObj.style.display = "none"; |
| 136 | /* Clear the dwell timer. */ |
| 137 | if (tooltipInfo.idTimer != 0) { |
| 138 | clearTimeout(tooltipInfo.idTimer); |
| 139 | tooltipInfo.idTimer = 0; |
| 140 | } |
| 141 | tooltipInfo.ix = -1; |
| 142 | } |
| 143 | }; |
| 144 | var canvasDiv; |
| 145 | var railPitch; |
| 146 | var mergeOffset; |
| @@ -480,10 +522,13 @@ | |
| 522 | dest += encodeURIComponent(tx.rowinfo[ix].h) |
| 523 | return dest |
| 524 | } |
| 525 | function clickOnGraph(e){ |
| 526 | var ix = findTxIndex(e); |
| 527 | showGraphTooltip(ix,e.x,e.y); |
| 528 | } |
| 529 | function showGraphTooltip(ix,posX,posY){ |
| 530 | if( ix<0 ){ |
| 531 | tooltipObj.style.display = "none" |
| 532 | }else{ |
| 533 | var br = tx.rowinfo[ix].br |
| 534 | var dest = branchHyperlink(ix) |
| @@ -493,13 +538,13 @@ | |
| 538 | .replace(/"/g, """) |
| 539 | .replace(/'/g, "'"); |
| 540 | tooltipObj.innerHTML = "<a href=\""+dest+"\">"+hbr+"</a>" |
| 541 | tooltipObj.style.display = "inline" |
| 542 | tooltipObj.style.position = "absolute" |
| 543 | var x = posX + 4 + window.pageXOffset |
| 544 | tooltipObj.style.left = x+"px" |
| 545 | var y = posY + window.pageYOffset - tooltipObj.clientHeight - 4 |
| 546 | tooltipObj.style.top = y+"px" |
| 547 | tooltipObj.style.visibility = "visible" |
| 548 | } |
| 549 | } |
| 550 | function dblclickOnGraph(e){ |
| 551 |