comparison mercurial/templates/static/followlines.js @ 31848:7160bdd56b84

hgweb: add a floating tooltip to invite on followlines action In followlines.js, we create a <div id="followlines-tooltip"> element to draw attention of users on "followlines" feature. The element shows up on hover of source lines after one second and follows the cursor. After first click (start line selection), the text changes and indicates that next click will terminate selection.
author Denis Laxalde <denis.laxalde@logilab.fr>
date Thu, 06 Apr 2017 19:15:09 +0200
parents d15c9feb4399
children 5c1abb4bd3ee
comparison
equal deleted inserted replaced
31847:39d36c2db68e 31848:7160bdd56b84
14 // URL to complement with "linerange" query parameter 14 // URL to complement with "linerange" query parameter
15 var targetUri = sourcelines.dataset.logurl; 15 var targetUri = sourcelines.dataset.logurl;
16 if (typeof targetUri === 'undefined') { 16 if (typeof targetUri === 'undefined') {
17 return; 17 return;
18 } 18 }
19
20 // tooltip to invite on lines selection
21 var tooltip = document.createElement('div');
22 tooltip.id = 'followlines-tooltip';
23 tooltip.classList.add('hidden');
24 var initTooltipText = 'click to start following lines history from here';
25 tooltip.textContent = initTooltipText;
26 sourcelines.appendChild(tooltip);
27
28 var tooltipTimeoutID;
29 //* move the "tooltip" with cursor (top-right) and show it after 1s */
30 function moveAndShowTooltip(e) {
31 if (typeof tooltipTimeoutID !== 'undefined') {
32 // avoid accumulation of timeout callbacks (blinking)
33 window.clearTimeout(tooltipTimeoutID);
34 }
35 tooltip.classList.add('hidden');
36 var x = (e.clientX + 10) + 'px',
37 y = (e.clientY - 20) + 'px';
38 tooltip.style.top = y;
39 tooltip.style.left = x;
40 tooltipTimeoutID = window.setTimeout(function() {
41 tooltip.classList.remove('hidden');
42 }, 1000);
43 }
44
45 // on mousemove, show tooltip close to cursor position
46 sourcelines.addEventListener('mousemove', moveAndShowTooltip);
19 47
20 // retrieve all direct <span> children of <pre class="sourcelines"> 48 // retrieve all direct <span> children of <pre class="sourcelines">
21 var spans = Array.prototype.filter.call( 49 var spans = Array.prototype.filter.call(
22 sourcelines.children, 50 sourcelines.children,
23 function(x) { return x.tagName === 'SPAN' }); 51 function(x) { return x.tagName === 'SPAN' });
63 if (startElement === null) { 91 if (startElement === null) {
64 // not a <span> (maybe <a>): abort, keeping event listener 92 // not a <span> (maybe <a>): abort, keeping event listener
65 // registered for other click with <span> target 93 // registered for other click with <span> target
66 return; 94 return;
67 } 95 }
96
97 // update tooltip text
98 tooltip.textContent = 'click again to terminate line block selection here';
99
68 var startId = parseInt(startElement.id.slice(1)); 100 var startId = parseInt(startElement.id.slice(1));
69 startElement.classList.add(lineSelectedCSSClass); // CSS 101 startElement.classList.add(lineSelectedCSSClass); // CSS
70 102
71 // remove this event listener 103 // remove this event listener
72 sourcelines.removeEventListener('click', lineSelectStart); 104 sourcelines.removeEventListener('click', lineSelectStart);
81 } 113 }
82 114
83 // remove this event listener 115 // remove this event listener
84 sourcelines.removeEventListener('click', lineSelectEnd); 116 sourcelines.removeEventListener('click', lineSelectEnd);
85 117
118 // hide tooltip and disable motion tracking
119 tooltip.classList.add('hidden');
120 sourcelines.removeEventListener('mousemove', moveAndShowTooltip);
121 window.clearTimeout(tooltipTimeoutID);
122
123 //* restore initial "tooltip" state */
124 function restoreTooltip() {
125 tooltip.textContent = initTooltipText;
126 sourcelines.addEventListener('mousemove', moveAndShowTooltip);
127 }
128
86 // compute line range (startId, endId) 129 // compute line range (startId, endId)
87 var endId = parseInt(endElement.id.slice(1)); 130 var endId = parseInt(endElement.id.slice(1));
88 if (endId == startId) { 131 if (endId == startId) {
89 // clicked twice the same line, cancel and reset initial state 132 // clicked twice the same line, cancel and reset initial state
90 // (CSS and event listener for selection start) 133 // (CSS, event listener for selection start, tooltip)
91 removeSelectedCSSClass(); 134 removeSelectedCSSClass();
92 sourcelines.addEventListener('click', lineSelectStart); 135 sourcelines.addEventListener('click', lineSelectStart);
136 restoreTooltip();
93 return; 137 return;
94 } 138 }
95 var inviteElement = endElement; 139 var inviteElement = endElement;
96 if (endId < startId) { 140 if (endId < startId) {
97 var tmp = endId; 141 var tmp = endId;
116 // restore initial event listeners 160 // restore initial event listeners
117 sourcelines.addEventListener('click', lineSelectStart); 161 sourcelines.addEventListener('click', lineSelectStart);
118 sourcelines.removeEventListener('click', cancel); 162 sourcelines.removeEventListener('click', cancel);
119 // remove styles on selected lines 163 // remove styles on selected lines
120 removeSelectedCSSClass(); 164 removeSelectedCSSClass();
165 // restore tooltip element
166 restoreTooltip();
121 } 167 }
122 168
123 // bind cancel event to click on <button> 169 // bind cancel event to click on <button>
124 button.addEventListener('click', cancel); 170 button.addEventListener('click', cancel);
125 // as well as on an click on any source line 171 // as well as on an click on any source line