##// END OF EJS Templates
hgweb: rely on a specific class to change cursor type in followlines UI...
Denis Laxalde -
r31784:02eb52e9 default
parent child Browse files
Show More
@@ -1,161 +1,166
1 1 // linerangelog.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 // retrieve all direct <span> children of <pre class="sourcelines">
21 21 var spans = Array.prototype.filter.call(
22 22 sourcelines.children,
23 23 function(x) { return x.tagName === 'SPAN' });
24 24
25 // add a "followlines-select" class to change cursor type in CSS
26 for (var i = 0; i < spans.length; i++) {
27 spans[i].classList.add('followlines-select');
28 }
29
25 30 var lineSelectedCSSClass = 'followlines-selected';
26 31
27 32 //** add CSS class on <span> element in `from`-`to` line range */
28 33 function addSelectedCSSClass(from, to) {
29 34 for (var i = from; i <= to; i++) {
30 35 spans[i].classList.add(lineSelectedCSSClass);
31 36 }
32 37 }
33 38
34 39 //** remove CSS class from previously selected lines */
35 40 function removeSelectedCSSClass() {
36 41 var elements = sourcelines.getElementsByClassName(
37 42 lineSelectedCSSClass);
38 43 while (elements.length) {
39 44 elements[0].classList.remove(lineSelectedCSSClass);
40 45 }
41 46 }
42 47
43 48 // ** return the <span> element parent of `element` */
44 49 function findParentSpan(element) {
45 50 var parent = element.parentElement;
46 51 if (parent === null) {
47 52 return null;
48 53 }
49 54 if (element.tagName == 'SPAN' && parent.isSameNode(sourcelines)) {
50 55 return element;
51 56 }
52 57 return findParentSpan(parent);
53 58 }
54 59
55 60 //** event handler for "click" on the first line of a block */
56 61 function lineSelectStart(e) {
57 62 var startElement = findParentSpan(e.target);
58 63 if (startElement === null) {
59 64 // not a <span> (maybe <a>): abort, keeping event listener
60 65 // registered for other click with <span> target
61 66 return;
62 67 }
63 68 var startId = parseInt(startElement.id.slice(1));
64 69 startElement.classList.add(lineSelectedCSSClass); // CSS
65 70
66 71 // remove this event listener
67 72 sourcelines.removeEventListener('click', lineSelectStart);
68 73
69 74 //** event handler for "click" on the last line of the block */
70 75 function lineSelectEnd(e) {
71 76 var endElement = findParentSpan(e.target);
72 77 if (endElement === null) {
73 78 // not a <span> (maybe <a>): abort, keeping event listener
74 79 // registered for other click with <span> target
75 80 return;
76 81 }
77 82
78 83 // remove this event listener
79 84 sourcelines.removeEventListener('click', lineSelectEnd);
80 85
81 86 // compute line range (startId, endId)
82 87 var endId = parseInt(endElement.id.slice(1));
83 88 if (endId == startId) {
84 89 // clicked twice the same line, cancel and reset initial state
85 90 // (CSS and event listener for selection start)
86 91 removeSelectedCSSClass();
87 92 sourcelines.addEventListener('click', lineSelectStart);
88 93 return;
89 94 }
90 95 var inviteElement = endElement;
91 96 if (endId < startId) {
92 97 var tmp = endId;
93 98 endId = startId;
94 99 startId = tmp;
95 100 inviteElement = startElement;
96 101 }
97 102
98 103 addSelectedCSSClass(startId - 1, endId -1); // CSS
99 104
100 105 // append the <div id="followlines"> element to last line of the
101 106 // selection block
102 107 var divAndButton = followlinesBox(targetUri, startId, endId);
103 108 var div = divAndButton[0],
104 109 button = divAndButton[1];
105 110 inviteElement.appendChild(div);
106 111
107 112 //** event handler for cancelling selection */
108 113 function cancel() {
109 114 // remove invite box
110 115 div.parentNode.removeChild(div);
111 116 // restore initial event listeners
112 117 sourcelines.addEventListener('click', lineSelectStart);
113 118 sourcelines.removeEventListener('click', cancel);
114 119 // remove styles on selected lines
115 120 removeSelectedCSSClass();
116 121 }
117 122
118 123 // bind cancel event to click on <button>
119 124 button.addEventListener('click', cancel);
120 125 // as well as on an click on any source line
121 126 sourcelines.addEventListener('click', cancel);
122 127 }
123 128
124 129 sourcelines.addEventListener('click', lineSelectEnd);
125 130
126 131 }
127 132
128 133 sourcelines.addEventListener('click', lineSelectStart);
129 134
130 135 //** return a <div id="followlines"> and inner cancel <button> elements */
131 136 function followlinesBox(targetUri, fromline, toline) {
132 137 // <div id="followlines">
133 138 var div = document.createElement('div');
134 139 div.id = 'followlines';
135 140
136 141 // <div class="followlines-cancel">
137 142 var buttonDiv = document.createElement('div');
138 143 buttonDiv.classList.add('followlines-cancel');
139 144
140 145 // <button>x</button>
141 146 var button = document.createElement('button');
142 147 button.textContent = 'x';
143 148 buttonDiv.appendChild(button);
144 149 div.appendChild(buttonDiv);
145 150
146 151 // <div class="followlines-link">
147 152 var aDiv = document.createElement('div');
148 153 aDiv.classList.add('followlines-link');
149 154
150 155 // <a href="/log/<rev>/<file>?patch=&linerange=...">
151 156 var a = document.createElement('a');
152 157 var url = targetUri + '?patch=&linerange=' + fromline + ':' + toline;
153 158 a.setAttribute('href', url);
154 159 a.textContent = 'follow lines ' + fromline + ':' + toline;
155 160 aDiv.appendChild(a);
156 161 div.appendChild(aDiv);
157 162
158 163 return [div, button];
159 164 }
160 165
161 166 }, false);
@@ -1,471 +1,471
1 1 body {
2 2 margin: 0;
3 3 padding: 0;
4 4 background: white;
5 5 color: black;
6 6 font-family: sans-serif;
7 7 }
8 8
9 9 .container {
10 10 padding-left: 115px;
11 11 }
12 12
13 13 .main {
14 14 position: relative;
15 15 background: white;
16 16 padding: 2em 2em 2em 0;
17 17 }
18 18
19 19 #.main {
20 20 width: 98%;
21 21 }
22 22
23 23 .overflow {
24 24 width: 100%;
25 25 overflow: auto;
26 26 }
27 27
28 28 .menu {
29 29 width: 90px;
30 30 margin: 0;
31 31 font-size: 80%;
32 32 text-align: left;
33 33 position: absolute;
34 34 top: 20px;
35 35 left: 20px;
36 36 right: auto;
37 37 }
38 38
39 39 .menu ul {
40 40 list-style: none;
41 41 padding: 0;
42 42 margin: 10px 0 0 0;
43 43 border-left: 2px solid #999;
44 44 }
45 45
46 46 .menu li {
47 47 margin-bottom: 3px;
48 48 padding: 2px 4px;
49 49 background: white;
50 50 color: black;
51 51 font-weight: normal;
52 52 }
53 53
54 54 .menu li.active {
55 55 font-weight: bold;
56 56 }
57 57
58 58 .menu img {
59 59 width: 75px;
60 60 height: 90px;
61 61 border: 0;
62 62 }
63 63
64 64 div.atom-logo {
65 65 margin-top: 10px;
66 66 }
67 67
68 68 .atom-logo img{
69 69 width: 14px;
70 70 height: 14px;
71 71 border: 0;
72 72 }
73 73
74 74 .menu a { color: black; display: block; }
75 75
76 76 .search {
77 77 position: absolute;
78 78 top: .7em;
79 79 right: 2em;
80 80 }
81 81
82 82 form.search div#hint {
83 83 display: none;
84 84 position: absolute;
85 85 top: 40px;
86 86 right: 0px;
87 87 width: 190px;
88 88 padding: 5px;
89 89 background: #ffc;
90 90 font-size: 70%;
91 91 border: 1px solid yellow;
92 92 border-radius: 5px;
93 93 }
94 94
95 95 form.search:hover div#hint { display: block; }
96 96
97 97 a { text-decoration:none; }
98 98 .age { white-space:nowrap; }
99 99 .date { white-space:nowrap; }
100 100 .indexlinks { white-space:nowrap; }
101 101 .parity0,
102 102 .stripes4 > :nth-child(4n+1),
103 103 .stripes2 > :nth-child(2n+1) { background-color: #f0f0f0; }
104 104 .parity1,
105 105 .stripes4 > :nth-child(4n+3),
106 106 .stripes2 > :nth-child(2n+2) { background-color: white; }
107 107 .plusline { color: green; }
108 108 .minusline { color: #dc143c; } /* crimson */
109 109 .atline { color: purple; }
110 110
111 111 .diffstat-table {
112 112 margin-top: 1em;
113 113 }
114 114 .diffstat-file {
115 115 white-space: nowrap;
116 116 font-size: 90%;
117 117 }
118 118 .diffstat-total {
119 119 white-space: nowrap;
120 120 font-size: 90%;
121 121 }
122 122 .diffstat-graph {
123 123 width: 100%;
124 124 }
125 125 .diffstat-add {
126 126 background-color: green;
127 127 float: left;
128 128 }
129 129 .diffstat-remove {
130 130 background-color: red;
131 131 float: left;
132 132 }
133 133
134 134 .navigate {
135 135 text-align: right;
136 136 font-size: 60%;
137 137 margin: 1em 0;
138 138 }
139 139
140 140 .tag {
141 141 color: #999;
142 142 font-size: 70%;
143 143 font-weight: normal;
144 144 margin-left: .5em;
145 145 vertical-align: baseline;
146 146 }
147 147
148 148 .branchhead {
149 149 color: #000;
150 150 font-size: 80%;
151 151 font-weight: normal;
152 152 margin-left: .5em;
153 153 vertical-align: baseline;
154 154 }
155 155
156 156 ul#graphnodes .branchhead {
157 157 font-size: 75%;
158 158 }
159 159
160 160 .branchname {
161 161 color: #000;
162 162 font-size: 60%;
163 163 font-weight: normal;
164 164 margin-left: .5em;
165 165 vertical-align: baseline;
166 166 }
167 167
168 168 h3 .branchname {
169 169 font-size: 80%;
170 170 }
171 171
172 172 /* Common */
173 173 pre { margin: 0; }
174 174
175 175 h2 { font-size: 120%; border-bottom: 1px solid #999; }
176 176 h2 a { color: #000; }
177 177 h3 {
178 178 margin-top: +.7em;
179 179 font-size: 100%;
180 180 }
181 181
182 182 /* log and tags tables */
183 183 .bigtable {
184 184 border-bottom: 1px solid #999;
185 185 border-collapse: collapse;
186 186 font-size: 90%;
187 187 width: 100%;
188 188 font-weight: normal;
189 189 text-align: left;
190 190 }
191 191
192 192 .bigtable td {
193 193 vertical-align: top;
194 194 }
195 195
196 196 .bigtable th {
197 197 padding: 1px 4px;
198 198 border-bottom: 1px solid #999;
199 199 }
200 200 .bigtable tr { border: none; }
201 201 .bigtable .age { width: 7em; }
202 202 .bigtable .author { width: 15em; }
203 203 .bigtable .description { }
204 204 .bigtable .description .base { font-size: 70%; float: right; line-height: 1.66; }
205 205 .bigtable .node { width: 5em; font-family: monospace;}
206 206 .bigtable .permissions { width: 8em; text-align: left;}
207 207 .bigtable .size { width: 5em; text-align: right; }
208 208 .bigtable .annotate { text-align: right; }
209 209 .bigtable td.annotate { font-size: smaller; }
210 210 .bigtable td.source { font-size: inherit; }
211 211 tr.thisrev a { color:#999999; text-decoration: none; }
212 212 tr.thisrev td.source { color:#009900; }
213 213 td.annotate {
214 214 white-space: nowrap;
215 215 }
216 216 div.annotate-info {
217 217 display: none;
218 218 position: absolute;
219 219 background-color: #FFFFFF;
220 220 border: 1px solid #999;
221 221 text-align: left;
222 222 color: #000000;
223 223 padding: 5px;
224 224 }
225 225 div.annotate-info a { color: #0000FF; }
226 226 td.annotate:hover div.annotate-info { display: inline; }
227 227
228 228 .source, .sourcefirst {
229 229 font-family: monospace;
230 230 white-space: pre;
231 231 padding: 1px 4px;
232 232 font-size: 90%;
233 233 }
234 234 .sourcefirst { border-bottom: 1px solid #999; font-weight: bold; }
235 235 .source a { color: #999; font-size: smaller; font-family: monospace;}
236 236 .bottomline { border-bottom: 1px solid #999; }
237 237
238 238 .sourcelines {
239 239 font-size: 90%;
240 240 position: relative;
241 241 counter-reset: lineno;
242 242 }
243 243
244 244 .wrap > span {
245 245 white-space: pre-wrap;
246 246 }
247 247
248 248 .linewraptoggle {
249 249 float: right;
250 250 }
251 251
252 252 .diffblocks { counter-reset: lineno; }
253 253 .diffblocks > div { counter-increment: lineno; }
254 254
255 255 .sourcelines > span {
256 256 display: inline-block;
257 257 box-sizing: border-box;
258 258 width: 100%;
259 259 padding: 1px 0px 1px 5em;
260 260 counter-increment: lineno;
261 261 }
262 262
263 263 .sourcelines > span:before {
264 264 -moz-user-select: -moz-none;
265 265 -khtml-user-select: none;
266 266 -webkit-user-select: none;
267 267 -ms-user-select: none;
268 268 user-select: none;
269 269 display: inline-block;
270 270 margin-left: -5em;
271 271 width: 4em;
272 272 font-size: smaller;
273 273 color: #999;
274 274 text-align: right;
275 275 content: counters(lineno, ".");
276 276 float: left;
277 277 }
278 278
279 279 .sourcelines > span:target, tr:target td {
280 280 background-color: #bfdfff;
281 281 }
282 282
283 div.overflow pre.sourcelines > span:hover {
283 div.overflow pre.sourcelines > span.followlines-select:hover {
284 284 cursor: cell;
285 285 }
286 286
287 287 pre.sourcelines > span.followlines-selected {
288 288 background-color: #99C7E9;
289 289 }
290 290
291 291 div#followlines {
292 292 background-color: #B7B7B7;
293 293 border: 1px solid #CCC;
294 294 border-radius: 5px;
295 295 padding: 4px;
296 296 position: absolute;
297 297 }
298 298
299 299 div.followlines-cancel {
300 300 text-align: right;
301 301 }
302 302
303 303 div.followlines-cancel > button {
304 304 line-height: 80%;
305 305 padding: 0;
306 306 border: 0;
307 307 border-radius: 2px;
308 308 background-color: inherit;
309 309 font-weight: bold;
310 310 }
311 311
312 312 div.followlines-cancel > button:hover {
313 313 color: #FFFFFF;
314 314 background-color: #CF1F1F;
315 315 }
316 316
317 317 div.followlines-link {
318 318 margin: 2px;
319 319 margin-top: 4px;
320 320 font-family: sans-serif;
321 321 }
322 322
323 323 .sourcelines > a {
324 324 display: inline-block;
325 325 position: absolute;
326 326 left: 0px;
327 327 width: 4em;
328 328 height: 1em;
329 329 }
330 330
331 331 .fileline { font-family: monospace; }
332 332 .fileline img { border: 0; }
333 333
334 334 .tagEntry .closed { color: #99f; }
335 335
336 336 /* Changeset entry */
337 337 #changesetEntry {
338 338 border-collapse: collapse;
339 339 font-size: 90%;
340 340 width: 100%;
341 341 margin-bottom: 1em;
342 342 }
343 343
344 344 #changesetEntry th {
345 345 padding: 1px 4px;
346 346 width: 4em;
347 347 text-align: right;
348 348 font-weight: normal;
349 349 color: #999;
350 350 margin-right: .5em;
351 351 vertical-align: top;
352 352 }
353 353
354 354 div.description {
355 355 border-left: 2px solid #999;
356 356 margin: 1em 0 1em 0;
357 357 padding: .3em;
358 358 white-space: pre;
359 359 font-family: monospace;
360 360 }
361 361
362 362 /* Graph */
363 363 div#wrapper {
364 364 position: relative;
365 365 border-top: 1px solid black;
366 366 border-bottom: 1px solid black;
367 367 margin: 0;
368 368 padding: 0;
369 369 }
370 370
371 371 canvas {
372 372 position: absolute;
373 373 z-index: 5;
374 374 top: -0.7em;
375 375 margin: 0;
376 376 }
377 377
378 378 ul#graphnodes {
379 379 position: absolute;
380 380 z-index: 10;
381 381 top: -1.0em;
382 382 list-style: none inside none;
383 383 padding: 0;
384 384 }
385 385
386 386 ul#nodebgs {
387 387 list-style: none inside none;
388 388 padding: 0;
389 389 margin: 0;
390 390 top: -0.7em;
391 391 }
392 392
393 393 ul#graphnodes li, ul#nodebgs li {
394 394 height: 39px;
395 395 }
396 396
397 397 ul#graphnodes li .info {
398 398 display: block;
399 399 font-size: 70%;
400 400 position: relative;
401 401 top: -3px;
402 402 }
403 403
404 404 /* Comparison */
405 405 .legend {
406 406 padding: 1.5% 0 1.5% 0;
407 407 }
408 408
409 409 .legendinfo {
410 410 border: 1px solid #999;
411 411 font-size: 80%;
412 412 text-align: center;
413 413 padding: 0.5%;
414 414 }
415 415
416 416 .equal {
417 417 background-color: #ffffff;
418 418 }
419 419
420 420 .delete {
421 421 background-color: #faa;
422 422 color: #333;
423 423 }
424 424
425 425 .insert {
426 426 background-color: #ffa;
427 427 }
428 428
429 429 .replace {
430 430 background-color: #e8e8e8;
431 431 }
432 432
433 433 .header {
434 434 text-align: center;
435 435 }
436 436
437 437 .block {
438 438 border-top: 1px solid #999;
439 439 }
440 440
441 441 .breadcrumb {
442 442 color: gray;
443 443 }
444 444
445 445 .breadcrumb a {
446 446 color: blue;
447 447 }
448 448
449 449 .scroll-loading {
450 450 -webkit-animation: change_color 1s linear 0s infinite alternate;
451 451 -moz-animation: change_color 1s linear 0s infinite alternate;
452 452 -o-animation: change_color 1s linear 0s infinite alternate;
453 453 animation: change_color 1s linear 0s infinite alternate;
454 454 }
455 455
456 456 @-webkit-keyframes change_color {
457 457 from { background-color: #A0CEFF; } to { }
458 458 }
459 459 @-moz-keyframes change_color {
460 460 from { background-color: #A0CEFF; } to { }
461 461 }
462 462 @-o-keyframes change_color {
463 463 from { background-color: #A0CEFF; } to { }
464 464 }
465 465 @keyframes change_color {
466 466 from { background-color: #A0CEFF; } to { }
467 467 }
468 468
469 469 .scroll-loading-error {
470 470 background-color: #FFCCCC !important;
471 471 }
General Comments 0
You need to be logged in to leave comments. Login now