Fossil SCM

Implement Javascript-based keyboard navigation for web UI diffs. Shortcuts SHIFT+I or I show or hide all diffs, and P or O show the next or previous diff. See [forum:a78f44576c| Forum Post a78f44576c] for more information.

florian 2022-09-28 14:24 trunk
Commit b7e089e0f3ef8109b45febcd11a2b03af952d58db6c69e3eb5c60c7b4e8f63a1
1 file changed +94
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -18,10 +18,104 @@
1818
}, false);
1919
};
2020
document.querySelectorAll('table.diff').forEach(addToggle);
2121
});
2222
23
+/*
24
+** Diff keyboard navigation shortcuts:
25
+**
26
+** SHIFT+I - Show all diffs.
27
+** I - Hide all diffs.
28
+** P - Show only next diff, hide all others.
29
+** O - Show only previous diff, hide all others.
30
+**
31
+** Ideas and TODOs:
32
+**
33
+** o Documentation.
34
+** o Restore shown/hidden state on back/forward navigation (or simply reset
35
+** shown/hidden state to show all).
36
+*/
37
+(function(){
38
+ window.addEventListener('load',function(){
39
+ function btnScrollIntoView(e){
40
+ e = e.parentElement;
41
+ var rc = e.getBoundingClientRect();
42
+ var y = 0;
43
+ do{
44
+ y += e.offsetTop;
45
+ }while( e = e.offsetParent );
46
+ window.scrollTo(0,y-6*rc.height);
47
+ }
48
+ document.addEventListener('keydown',function(evt){
49
+ //if( evt.target.tagName=='INPUT' || evt.target.tagName=='SELECT' ) return;
50
+ var
51
+ mSHIFT = 1<<13,
52
+ kSHOW = mSHIFT | 73 /* SHIFT+I */,
53
+ kHIDE = 73 /* I */,
54
+ kNEXT = 80 /* P */,
55
+ kPREV = 79 /* O */,
56
+ mod = evt.altKey<<15 | evt.ctrlKey<<14 | evt.shiftKey<<13,
57
+ key = ( evt.which || evt.keyCode ) | mod;
58
+ switch( key ){
59
+ case kSHOW:
60
+ case kHIDE:
61
+ case kNEXT:
62
+ case kPREV: break;
63
+ default: return;
64
+ }
65
+ evt.preventDefault();
66
+ evt.stopPropagation();
67
+ if( key==kSHOW || key==kHIDE ){
68
+ var btn = document.getElementsByClassName('diff-toggle');
69
+ if( btn.length>0 ){
70
+ var chg = 0;
71
+ for( var i=0; i<btn.length; i++ ){
72
+ if( btn[i].checked && key==kHIDE ){
73
+ btn[i].click();
74
+ chg++;
75
+ }
76
+ else if( !btn[i].checked && key==kSHOW ){
77
+ btn[i].click();
78
+ chg++;
79
+ }
80
+ }
81
+ if( chg>0 ) btnScrollIntoView(btn[0]);
82
+ }
83
+ }
84
+ else if( key==kNEXT || key==kPREV ){
85
+ var btn = document.getElementsByClassName('diff-toggle');
86
+ if( btn.length>1 ){
87
+ var nFolded = 0, n = -2;
88
+ for( var i=0; i<btn.length; i++ ){
89
+ if( !btn[i].checked ) nFolded++;
90
+ }
91
+ if( nFolded==0 ){
92
+ n = ( key==kNEXT ? 0 : btn.length-1 );
93
+ for( var i=0; i<btn.length; i++ ){
94
+ if( n!=i ) btn[i].click();
95
+ }
96
+ }
97
+ else{
98
+ for( var i=0; i<btn.length; i++ ){
99
+ if( btn[i].checked ){
100
+ if( n==-2 ) n = ( key==kNEXT ? i+1 : i-1 );
101
+ if( n!=i ) btn[i].click();
102
+ }
103
+ }
104
+ }
105
+ if( n==-2 ) n = ( key==kNEXT ? 0 : btn.length-1 );
106
+ if( n in btn ){
107
+ if( !btn[n].checked ) btn[n].click();
108
+ btnScrollIntoView(btn[n]);
109
+ }
110
+ }
111
+ else btn[0].click();
112
+ }
113
+ }/*,true*/);
114
+ },false);
115
+}());
116
+
23117
window.fossil.onPageLoad(function(){
24118
const F = window.fossil, D = F.dom;
25119
const Diff = F.diff = {
26120
e:{/*certain cached DOM elements*/},
27121
config: {
28122
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -18,10 +18,104 @@
18 }, false);
19 };
20 document.querySelectorAll('table.diff').forEach(addToggle);
21 });
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23 window.fossil.onPageLoad(function(){
24 const F = window.fossil, D = F.dom;
25 const Diff = F.diff = {
26 e:{/*certain cached DOM elements*/},
27 config: {
28
--- src/fossil.diff.js
+++ src/fossil.diff.js
@@ -18,10 +18,104 @@
18 }, false);
19 };
20 document.querySelectorAll('table.diff').forEach(addToggle);
21 });
22
23 /*
24 ** Diff keyboard navigation shortcuts:
25 **
26 ** SHIFT+I - Show all diffs.
27 ** I - Hide all diffs.
28 ** P - Show only next diff, hide all others.
29 ** O - Show only previous diff, hide all others.
30 **
31 ** Ideas and TODOs:
32 **
33 ** o Documentation.
34 ** o Restore shown/hidden state on back/forward navigation (or simply reset
35 ** shown/hidden state to show all).
36 */
37 (function(){
38 window.addEventListener('load',function(){
39 function btnScrollIntoView(e){
40 e = e.parentElement;
41 var rc = e.getBoundingClientRect();
42 var y = 0;
43 do{
44 y += e.offsetTop;
45 }while( e = e.offsetParent );
46 window.scrollTo(0,y-6*rc.height);
47 }
48 document.addEventListener('keydown',function(evt){
49 //if( evt.target.tagName=='INPUT' || evt.target.tagName=='SELECT' ) return;
50 var
51 mSHIFT = 1<<13,
52 kSHOW = mSHIFT | 73 /* SHIFT+I */,
53 kHIDE = 73 /* I */,
54 kNEXT = 80 /* P */,
55 kPREV = 79 /* O */,
56 mod = evt.altKey<<15 | evt.ctrlKey<<14 | evt.shiftKey<<13,
57 key = ( evt.which || evt.keyCode ) | mod;
58 switch( key ){
59 case kSHOW:
60 case kHIDE:
61 case kNEXT:
62 case kPREV: break;
63 default: return;
64 }
65 evt.preventDefault();
66 evt.stopPropagation();
67 if( key==kSHOW || key==kHIDE ){
68 var btn = document.getElementsByClassName('diff-toggle');
69 if( btn.length>0 ){
70 var chg = 0;
71 for( var i=0; i<btn.length; i++ ){
72 if( btn[i].checked && key==kHIDE ){
73 btn[i].click();
74 chg++;
75 }
76 else if( !btn[i].checked && key==kSHOW ){
77 btn[i].click();
78 chg++;
79 }
80 }
81 if( chg>0 ) btnScrollIntoView(btn[0]);
82 }
83 }
84 else if( key==kNEXT || key==kPREV ){
85 var btn = document.getElementsByClassName('diff-toggle');
86 if( btn.length>1 ){
87 var nFolded = 0, n = -2;
88 for( var i=0; i<btn.length; i++ ){
89 if( !btn[i].checked ) nFolded++;
90 }
91 if( nFolded==0 ){
92 n = ( key==kNEXT ? 0 : btn.length-1 );
93 for( var i=0; i<btn.length; i++ ){
94 if( n!=i ) btn[i].click();
95 }
96 }
97 else{
98 for( var i=0; i<btn.length; i++ ){
99 if( btn[i].checked ){
100 if( n==-2 ) n = ( key==kNEXT ? i+1 : i-1 );
101 if( n!=i ) btn[i].click();
102 }
103 }
104 }
105 if( n==-2 ) n = ( key==kNEXT ? 0 : btn.length-1 );
106 if( n in btn ){
107 if( !btn[n].checked ) btn[n].click();
108 btnScrollIntoView(btn[n]);
109 }
110 }
111 else btn[0].click();
112 }
113 }/*,true*/);
114 },false);
115 }());
116
117 window.fossil.onPageLoad(function(){
118 const F = window.fossil, D = F.dom;
119 const Diff = F.diff = {
120 e:{/*certain cached DOM elements*/},
121 config: {
122

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button