| | @@ -116,10 +116,11 @@ |
| 116 | 116 | ** over a graph node. Or -1 when the mouse is not |
| 117 | 117 | ** over anything. */ |
| 118 | 118 | ixActive: -1, /* The item shown in the tooltip is tx.rowinfo[ixActive]. |
| 119 | 119 | ** ixActive is -1 if the tooltip is not visible */ |
| 120 | 120 | nodeHover: null, /* Graph node under mouse when ixHover==-2 */ |
| 121 | + idNodeActive: 0, /* Element ID of the graph node with the tooltip. */ |
| 121 | 122 | posX: 0, posY: 0 /* The last mouse position. */ |
| 122 | 123 | }; |
| 123 | 124 | |
| 124 | 125 | /* Functions used to control the tooltip popup and its timer */ |
| 125 | 126 | function onKeyDown(event){ /* Hide the tooltip when ESC key pressed */ |
| | @@ -132,10 +133,11 @@ |
| 132 | 133 | function hideGraphTooltip(){ /* Hide the tooltip */ |
| 133 | 134 | document.removeEventListener('keydown',onKeyDown,/* useCapture == */true); |
| 134 | 135 | stopCloseTimer(); |
| 135 | 136 | tooltipObj.style.display = "none"; |
| 136 | 137 | tooltipInfo.ixActive = -1; |
| 138 | + tooltipInfo.idNodeActive = 0; |
| 137 | 139 | } |
| 138 | 140 | document.body.onunload = hideGraphTooltip |
| 139 | 141 | function stopDwellTimer(){ |
| 140 | 142 | if(tooltipInfo.idTimer!=0){ |
| 141 | 143 | clearTimeout(tooltipInfo.idTimer); |
| | @@ -169,36 +171,11 @@ |
| 169 | 171 | topObj.onclick = clickOnGraph |
| 170 | 172 | topObj.ondblclick = dblclickOnGraph |
| 171 | 173 | topObj.onmousemove = function(e) { |
| 172 | 174 | var ix = findTxIndex(e); |
| 173 | 175 | topObj.style.cursor = (ix<0) ? "" : "pointer" |
| 174 | | - /* Keep the already visible tooltip at a constant position, as long as the |
| 175 | | - ** mouse is over the same element. */ |
| 176 | | - if(tooltipObj.style.display != "none"){ |
| 177 | | - if(ix == tooltipInfo.ixHover) return; |
| 178 | | - } |
| 179 | | - /* The tooltip is either not visible, or the mouse is over a different |
| 180 | | - ** element, so clear the dwell timer, and record the new element id and |
| 181 | | - ** mouse position. */ |
| 182 | | - stopDwellTimer(); |
| 183 | | - if(ix >= 0){ |
| 184 | | - tooltipInfo.ixHover = ix; |
| 185 | | - tooltipInfo.posX = e.clientX; |
| 186 | | - tooltipInfo.posY = e.clientY; |
| 187 | | - stopCloseTimer(); |
| 188 | | - if(tooltipInfo.dwellTimeout>0){ |
| 189 | | - tooltipInfo.idTimer = setTimeout(function() { |
| 190 | | - tooltipInfo.idTimer = 0; |
| 191 | | - stopCloseTimer(); |
| 192 | | - showGraphTooltip(); |
| 193 | | - },tooltipInfo.dwellTimeout); |
| 194 | | - } |
| 195 | | - }else{ |
| 196 | | - /* The mouse is not over an element with a tooltip */ |
| 197 | | - tooltipInfo.ixHover = -1; |
| 198 | | - resumeCloseTimer(); |
| 199 | | - } |
| 176 | + mouseOverGraph(e,ix,null); |
| 200 | 177 | }; |
| 201 | 178 | topObj.onmouseleave = function(e) { |
| 202 | 179 | /* Hide the tooltip if the mouse is outside the "timelineTableN" element, |
| 203 | 180 | ** and outside the tooltip. */ |
| 204 | 181 | if(e.relatedTarget && e.relatedTarget != tooltipObj){ |
| | @@ -208,18 +185,26 @@ |
| 208 | 185 | stopCloseTimer(); |
| 209 | 186 | } |
| 210 | 187 | }; |
| 211 | 188 | function mouseOverNode(e){ /* Invoked by mousemove events over a graph node */ |
| 212 | 189 | e.stopPropagation() |
| 213 | | - if(tooltipInfo.ixHover==-2) return |
| 214 | | - tooltipInfo.ixHover = -2 |
| 215 | | - tooltipInfo.posX = e.clientX |
| 216 | | - tooltipInfo.posY = e.clientY |
| 217 | | - tooltipInfo.nodeHover = this |
| 218 | | - stopCloseTimer(); |
| 219 | | - if(tooltipInfo.dwellTimeout>0){ |
| 220 | | - tooltipInfo.idTimer = setTimeout(function() { |
| 190 | + mouseOverGraph(e,-2,this) |
| 191 | + } |
| 192 | + /* Combined mousemove handler for graph nodes and rails. */ |
| 193 | + function mouseOverGraph(e,ix,node){ |
| 194 | + stopDwellTimer(); // Mouse movement: reset the dwell timer. |
| 195 | + var ownTooltip = // Check if the hovered element already has the tooltip. |
| 196 | + (ix>=0 && ix==tooltipInfo.ixActive) || |
| 197 | + (ix==-2 && tooltipInfo.idNodeActive==node.id); |
| 198 | + if(ownTooltip) stopCloseTimer(); // ownTooltip: clear the close timer. |
| 199 | + else resumeCloseTimer(); // !ownTooltip: resume the close timer. |
| 200 | + tooltipInfo.ixHover = ix; |
| 201 | + tooltipInfo.nodeHover = node; |
| 202 | + tooltipInfo.posX = e.clientX; |
| 203 | + tooltipInfo.posY = e.clientY; |
| 204 | + if(ix!=-1 && !ownTooltip && tooltipInfo.dwellTimeout>0){ // Go dwell timer. |
| 205 | + tooltipInfo.idTimer = setTimeout(function(){ |
| 221 | 206 | tooltipInfo.idTimer = 0; |
| 222 | 207 | stopCloseTimer(); |
| 223 | 208 | showGraphTooltip(); |
| 224 | 209 | },tooltipInfo.dwellTimeout); |
| 225 | 210 | } |
| | @@ -611,10 +596,12 @@ |
| 611 | 596 | dest += tx.fileDiff ? "&m&cf=" : "&m&c=" |
| 612 | 597 | dest += encodeURIComponent(tx.rowinfo[ix].h) |
| 613 | 598 | return dest |
| 614 | 599 | } |
| 615 | 600 | function clickOnGraph(e){ |
| 601 | + stopCloseTimer(); |
| 602 | + stopDwellTimer(); |
| 616 | 603 | tooltipInfo.ixHover = findTxIndex(e); |
| 617 | 604 | tooltipInfo.posX = e.clientX; |
| 618 | 605 | tooltipInfo.posY = e.clientY; |
| 619 | 606 | showGraphTooltip(); |
| 620 | 607 | } |
| | @@ -630,10 +617,11 @@ |
| 630 | 617 | html = "artifact <a id=\"tooltip-link\" href=\""+dest+"\">"+h+"</a>" |
| 631 | 618 | }else{ |
| 632 | 619 | html = "check-in <a id=\"tooltip-link\" href=\""+dest+"\">"+h+"</a>" |
| 633 | 620 | } |
| 634 | 621 | tooltipInfo.ixActive = -2; |
| 622 | + tooltipInfo.idNodeActive = tooltipInfo.nodeHover.id; |
| 635 | 623 | }else if( tooltipInfo.ixHover>=0 ){ |
| 636 | 624 | ix = tooltipInfo.ixHover |
| 637 | 625 | var br = tx.rowinfo[ix].br |
| 638 | 626 | var dest = branchHyperlink(ix) |
| 639 | 627 | var hbr = br.replace(/&/g, "&") |
| | @@ -641,10 +629,11 @@ |
| 641 | 629 | .replace(/>/g, ">") |
| 642 | 630 | .replace(/"/g, """) |
| 643 | 631 | .replace(/'/g, "'"); |
| 644 | 632 | html = "branch <a id=\"tooltip-link\" href=\""+dest+"\">"+hbr+"</a>" |
| 645 | 633 | tooltipInfo.ixActive = ix; |
| 634 | + tooltipInfo.idNodeActive = 0; |
| 646 | 635 | } |
| 647 | 636 | if( html ){ |
| 648 | 637 | /* Setup while hidden, to ensure proper dimensions. */ |
| 649 | 638 | var s = getComputedStyle(document.body) |
| 650 | 639 | if( tx.rowinfo[ix].bg.length ){ |
| 651 | 640 | |