1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
(function callee(arg){
/* JS counterpart of info.c:output_text_with_line_numbers()
which ties an event handler to the line numbers to allow
selection of individual lines or ranges. */
var tbl = arg || document.querySelectorAll('table.numbered-lines');
if(!tbl) return /* no matching elements */;
else if(!arg){
if(tbl.length>1){ /* multiple query results: recurse */
tbl.forEach( (t)=>callee(t) );
return;
}else{/* single query result */
tbl = tbl[0];
}
}
const tdLn = tbl.querySelector('td'),
urlArgs = (window.location.search||'').replace(/&?\bln=[^&]*/,'');
console.debug("urlArgs =",urlArgs);
tdLn.addEventListener('click', function f(ev){
if(!f.selectedRange){
f.selectedRange = [0,0];
f.mode = 0 /*0=none selected, 1=1 selected, 2=2 selected*/;
}
if('SPAN'===ev.target.tagName){
const rng = f.selectedRange;
const ln = +ev.target.innerText;
if(2===f.mode){/*reset selection*/
f.mode = 0;
//rng[0] = rng[1] = 0;
}
if(0===f.mode){
rng[1] = 0;
rng[0] = ln;
//console.debug("Selected line #"+ln);
history.pushState(undefined,'',urlArgs+'&ln='+ln);
f.mode = 1;
}else if(1===f.mode){
if(ln === rng[0]){/*unselect line*/
//console.debug("Unselected line #"+ln);
history.pushState(undefined,'',urlArgs+'&ln=on');
rng[0] = 0;
f.mode = 0;
}else{
if(ln<rng[0]){
rng[1] = rng[0];
rng[0] = ln;
}else{
rng[1] = ln;
}
//console.debug("Selected range: ",rng);
history.pushState(undefined,'',urlArgs+'&ln='+rng.join('-'));
f.mode = 2;
}
}
}
}, false);
})();
|
>
|
|
|
>
>
>
>
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
>
>
>
|
<
|
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
>
|
<
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
(function callee(arg){
/*
JS counterpart of info.c:output_text_with_line_numbers()
which ties an event handler to the line numbers to allow
selection of individual lines or ranges.
Requires: fossil.bootstrap, fossil.dom, fossil.tooltip
*/
var tbl = arg || document.querySelectorAll('table.numbered-lines');
if(!tbl) return /* no matching elements */;
else if(!arg){
if(tbl.length>1){ /* multiple query results: recurse */
tbl.forEach( (t)=>callee(t) );
return;
}else{/* single query result */
tbl = tbl[0];
}
}
const F = window.fossil, D = F.dom;
const tdLn = tbl.querySelector('td.line-numbers');
const lineState = {
urlArgs: (window.location.search||'').replace(/&?\bln=[^&]*/,''),
start: 0, end: 0
};
const lineTip = new fossil.TooltipWidget({
refresh: function(){
const link = this.state.link;
D.clearElement(link);
if(lineState.start){
const ls = [lineState.start];
if(lineState.end) ls.push(lineState.end);
link.dataset.url = (
window.location.toString().split('?')[0]
+ lineState.urlArgs + '&ln='+ls.join('-')
);
D.append(
D.clearElement(link),
' ',
(ls.length===1 ? 'line ' : 'lines ')+ls.join('-')
);
}else{
D.append(link, "No lines selected.");
}
},
adjustX: function(x){
return x + 20;
},
adjustY: function(y){
return y - this.e.clientHeight/2;
},
init: function(){
const e = this.e;
const btnCopy = D.addClass(D.span(), 'copy-button');
const link = D.attr(D.span(), 'id', 'fossil-ln-link');
this.state = {link};
F.copyButton(btnCopy,{
copyFromElement: link,
extractText: ()=>link.dataset.url
});
D.append(this.e, btnCopy, link)
}
});
tbl.addEventListener('click', function f(ev){
lineTip.show(false);
}, false);
tdLn.addEventListener('click', function f(ev){
if('SPAN'!==ev.target.tagName) return;
else if('number' !== typeof f.mode){
f.mode = 0 /*0=none selected, 1=1 selected, 2=2 selected*/;
}
ev.stopPropagation();
const ln = +ev.target.innerText;
if(2===f.mode){/*reset selection*/
f.mode = 0;
}
if(0===f.mode){
lineState.end = 0;
lineState.start = ln;
f.mode = 1;
}else if(1===f.mode){
if(ln === lineState.start){/*unselect line*/
//console.debug("Unselected line #"+ln);
lineState.start = 0;
f.mode = 0;
}else{
if(ln<lineState.start){
lineState.end = lineState.start;
lineState.start = ln;
}else{
lineState.end = ln;
}
//console.debug("Selected range: ",rng);
f.mode = 2;
}
}
tdLn.querySelectorAll('span.selected-line').forEach(
(e)=>D.removeClass(e, 'selected-line','start','end'));
if(f.mode>0){
lineTip.show(ev.clientX, ev.clientY);
const spans = tdLn.querySelectorAll('span');
if(spans.length>=lineState.start){
let i = lineState.start, end = lineState.end || lineState.start, span = spans[i-1];
for( ; i<=end && span; span = spans[i++] ){
span.classList.add('selected-line');
if(i===lineState.start) span.classList.add('start');
if(i===end) span.classList.add('end');
}
}
lineTip.refresh();
}else{
lineTip.show(false);
}
}, false);
})();
|