##// END OF EJS Templates
hgweb: change text of followlines links to "older / newer"...
Denis Laxalde -
r32071:1cf0b651 stable
parent child Browse files
Show More
@@ -1,234 +1,234 b''
1 1 // followlines.js - JavaScript utilities for followlines UI
2 2 //
3 3 // Copyright 2017 Logilab SA <contact@logilab.fr>
4 4 //
5 5 // This software may be used and distributed according to the terms of the
6 6 // GNU General Public License version 2 or any later version.
7 7
8 8 //** Install event listeners for line block selection and followlines action */
9 9 document.addEventListener('DOMContentLoaded', function() {
10 10 var sourcelines = document.getElementsByClassName('sourcelines')[0];
11 11 if (typeof sourcelines === 'undefined') {
12 12 return;
13 13 }
14 14 // URL to complement with "linerange" query parameter
15 15 var targetUri = sourcelines.dataset.logurl;
16 16 if (typeof targetUri === 'undefined')Β {
17 17 return;
18 18 }
19 19
20 20 var isHead = parseInt(sourcelines.dataset.ishead || "0");
21 21
22 22 // tooltip to invite on lines selection
23 23 var tooltip = document.createElement('div');
24 24 tooltip.id = 'followlines-tooltip';
25 25 tooltip.classList.add('hidden');
26 26 var initTooltipText = 'click to start following lines history from here';
27 27 tooltip.textContent = initTooltipText;
28 28 sourcelines.appendChild(tooltip);
29 29
30 30 //* position "element" on top-right of cursor */
31 31 function positionTopRight(element, event) {
32 32 var x = (event.clientX + 10) + 'px',
33 33 y = (event.clientY - 20) + 'px';
34 34 element.style.top = y;
35 35 element.style.left = x;
36 36 }
37 37
38 38 var tooltipTimeoutID;
39 39 //* move the "tooltip" with cursor (top-right) and show it after 1s */
40 40 function moveAndShowTooltip(e) {
41 41 if (typeof tooltipTimeoutID !== 'undefined') {
42 42 // avoid accumulation of timeout callbacks (blinking)
43 43 window.clearTimeout(tooltipTimeoutID);
44 44 }
45 45 tooltip.classList.add('hidden');
46 46 positionTopRight(tooltip, e);
47 47 tooltipTimeoutID = window.setTimeout(function() {
48 48 tooltip.classList.remove('hidden');
49 49 }, 1000);
50 50 }
51 51
52 52 // on mousemove, show tooltip close to cursor position
53 53 sourcelines.addEventListener('mousemove', moveAndShowTooltip);
54 54
55 55 // retrieve all direct <span> children of <pre class="sourcelines">
56 56 var spans = Array.prototype.filter.call(
57 57 sourcelines.children,
58 58 function(x) { return x.tagName === 'SPAN' });
59 59
60 60 // add a "followlines-select" class to change cursor type in CSS
61 61 for (var i = 0; i < spans.length; i++) {
62 62 spans[i].classList.add('followlines-select');
63 63 }
64 64
65 65 var lineSelectedCSSClass = 'followlines-selected';
66 66
67 67 //** add CSS class on <span> element in `from`-`to` line range */
68 68 function addSelectedCSSClass(from, to) {
69 69 for (var i = from; i <= to; i++) {
70 70 spans[i].classList.add(lineSelectedCSSClass);
71 71 }
72 72 }
73 73
74 74 //** remove CSS class from previously selected lines */
75 75 function removeSelectedCSSClass() {
76 76 var elements = sourcelines.getElementsByClassName(
77 77 lineSelectedCSSClass);
78 78 while (elements.length) {
79 79 elements[0].classList.remove(lineSelectedCSSClass);
80 80 }
81 81 }
82 82
83 83 // ** return the <span> element parent of `element` */
84 84 function findParentSpan(element) {
85 85 var parent = element.parentElement;
86 86 if (parent === null) {
87 87 return null;
88 88 }
89 89 if (element.tagName == 'SPAN' && parent.isSameNode(sourcelines)) {
90 90 return element;
91 91 }
92 92 return findParentSpan(parent);
93 93 }
94 94
95 95 //** event handler for "click" on the first line of a block */
96 96 function lineSelectStart(e) {
97 97 var startElement = findParentSpan(e.target);
98 98 if (startElement === null) {
99 99 // not a <span> (maybe <a>): abort, keeping event listener
100 100 // registered for other click with <span> target
101 101 return;
102 102 }
103 103
104 104 // update tooltip text
105 105 tooltip.textContent = 'click again to terminate line block selection here';
106 106
107 107 var startId = parseInt(startElement.id.slice(1));
108 108 startElement.classList.add(lineSelectedCSSClass); // CSS
109 109
110 110 // remove this event listener
111 111 sourcelines.removeEventListener('click', lineSelectStart);
112 112
113 113 //** event handler for "click" on the last line of the block */
114 114 function lineSelectEnd(e) {
115 115 var endElement = findParentSpan(e.target);
116 116 if (endElement === null) {
117 117 // not a <span> (maybe <a>): abort, keeping event listener
118 118 // registered for other click with <span> target
119 119 return;
120 120 }
121 121
122 122 // remove this event listener
123 123 sourcelines.removeEventListener('click', lineSelectEnd);
124 124
125 125 // hide tooltip and disable motion tracking
126 126 tooltip.classList.add('hidden');
127 127 sourcelines.removeEventListener('mousemove', moveAndShowTooltip);
128 128 window.clearTimeout(tooltipTimeoutID);
129 129
130 130 //* restore initial "tooltip" state */
131 131 function restoreTooltip() {
132 132 tooltip.textContent = initTooltipText;
133 133 sourcelines.addEventListener('mousemove', moveAndShowTooltip);
134 134 }
135 135
136 136 // compute line range (startId, endId)
137 137 var endId = parseInt(endElement.id.slice(1));
138 138 if (endId == startId) {
139 139 // clicked twice the same line, cancel and reset initial state
140 140 // (CSS, event listener for selection start, tooltip)
141 141 removeSelectedCSSClass();
142 142 sourcelines.addEventListener('click', lineSelectStart);
143 143 restoreTooltip();
144 144 return;
145 145 }
146 146 var inviteElement = endElement;
147 147 if (endId < startId) {
148 148 var tmp = endId;
149 149 endId = startId;
150 150 startId = tmp;
151 151 inviteElement = startElement;
152 152 }
153 153
154 154 addSelectedCSSClass(startId - 1, endId -1); // CSS
155 155
156 156 // append the <div id="followlines"> element to last line of the
157 157 // selection block
158 158 var divAndButton = followlinesBox(targetUri, startId, endId, isHead);
159 159 var div = divAndButton[0],
160 160 button = divAndButton[1];
161 161 inviteElement.appendChild(div);
162 162 // set position close to cursor (top-right)
163 163 positionTopRight(div, e);
164 164
165 165 //** event handler for cancelling selection */
166 166 function cancel() {
167 167 // remove invite box
168 168 div.parentNode.removeChild(div);
169 169 // restore initial event listeners
170 170 sourcelines.addEventListener('click', lineSelectStart);
171 171 sourcelines.removeEventListener('click', cancel);
172 172 // remove styles on selected lines
173 173 removeSelectedCSSClass();
174 174 // restore tooltip element
175 175 restoreTooltip();
176 176 }
177 177
178 178 // bind cancel event to click on <button>
179 179 button.addEventListener('click', cancel);
180 180 // as well as on an click on any source line
181 181 sourcelines.addEventListener('click', cancel);
182 182 }
183 183
184 184 sourcelines.addEventListener('click', lineSelectEnd);
185 185
186 186 }
187 187
188 188 sourcelines.addEventListener('click', lineSelectStart);
189 189
190 190 //** return a <div id="followlines"> and inner cancel <button> elements */
191 191 function followlinesBox(targetUri, fromline, toline, isHead) {
192 192 // <div id="followlines">
193 193 var div = document.createElement('div');
194 194 div.id = 'followlines';
195 195
196 196 // <div class="followlines-cancel">
197 197 var buttonDiv = document.createElement('div');
198 198 buttonDiv.classList.add('followlines-cancel');
199 199
200 200 // <button>x</button>
201 201 var button = document.createElement('button');
202 202 button.textContent = 'x';
203 203 buttonDiv.appendChild(button);
204 204 div.appendChild(buttonDiv);
205 205
206 206 // <div class="followlines-link">
207 207 var aDiv = document.createElement('div');
208 208 aDiv.classList.add('followlines-link');
209 209 aDiv.textContent = 'follow history of lines ' + fromline + ':' + toline + ':';
210 210 var linesep = document.createElement('br');
211 211 aDiv.appendChild(linesep);
212 212 // link to "ascending" followlines
213 213 var aAsc = document.createElement('a');
214 214 var url = targetUri + '?patch=&linerange=' + fromline + ':' + toline;
215 215 aAsc.setAttribute('href', url);
216 aAsc.textContent = 'ascending';
216 aAsc.textContent = 'older';
217 217 aDiv.appendChild(aAsc);
218 218
219 219 if (!isHead) {
220 220 var sep = document.createTextNode(' / ');
221 221 aDiv.appendChild(sep);
222 222 // link to "descending" followlines
223 223 var aDesc = document.createElement('a');
224 224 aDesc.setAttribute('href', url + '&descend=');
225 aDesc.textContent = 'descending';
225 aDesc.textContent = 'newer';
226 226 aDiv.appendChild(aDesc);
227 227 }
228 228
229 229 div.appendChild(aDiv);
230 230
231 231 return [div, button];
232 232 }
233 233
234 234 }, false);
General Comments 0
You need to be logged in to leave comments. Login now