Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch timeline-keyboard-navigation Through [15f943f0c2] Excluding Merge-Ins
This is equivalent to a diff from ab553393a1 to 15f943f0c2
|
2022-08-04
| ||
| 12:19 | Remove the accordion from the "Changes" division of the /vinfo page (at least temporarily) because it is cutting off the bottom of the diff. check-in: 69a6f45387 user: drh tags: trunk | |
| 03:51 | Shortcuts B and SHIFT+B top copy the hash or branch name of the focused entry to clipboard. check-in: f23a6d13a2 user: florian tags: timeline-keyboard-navigation | |
| 03:45 | Shortcut "," (comma) to tick/untick the node of the currently focused entry. This has the same effect as mouse clicks, i.e. as soon as two nodes are ticked, the corresponding diff page is opened. check-in: 15f943f0c2 user: florian tags: timeline-keyboard-navigation | |
| 03:41 | Shortcuts SHIFT+N and SHIFT+M to put focus the first (topmost) or last (bottommost) entry. check-in: 145df5a3e1 user: florian tags: timeline-keyboard-navigation | |
| 03:34 | Merge with trunk to get the latest web UI updates. check-in: 0f9981971e user: florian tags: timeline-keyboard-navigation | |
|
2022-08-02
| ||
| 20:55 | Put all sections of the /vinfo page (or the /info page for a check-in) inside an accordion widget. check-in: ab553393a1 user: drh tags: trunk | |
| 00:45 | Corrected broken link introduced in the previous commit which works under (fossil ui) but not on the live server (due to the addition of another URI path element). check-in: bf0efda706 user: stephan tags: trunk | |
Changes to src/default.css.
| ︙ | |||
49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | + + + + + + + + + |
border-radius: 0;
border-width: 0;
}
tr.timelineCurrent td {
border-radius: 0;
border-width: 0;
}
.timelineFocused {
background-image: url("data:image/svg+xml,%3Csvg \
xmlns='http://www.w3.org/2000/svg' viewBox='0,0,1,1'%3E%3Cpath \
style='fill:orange;opacity:0.5' d='M0,0h1v1h-1z'/%3E%3C/svg%3E");
/*Note: IE requires explicit declarations for the next three properties.*/
background-position: top left;
background-repeat: repeat repeat;
background-size: 64px 64px;
}
span.timelineLeaf {
font-weight: bold;
}
span.timelineHistDsp {
font-weight: bold;
}
td.timelineTime {
|
| ︙ |
Changes to src/graph.js.
| ︙ | |||
132 133 134 135 136 137 138 | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | - + |
function hideGraphTooltip(){ /* Hide the tooltip */
document.removeEventListener('keydown',onKeyDown,/* useCapture == */true);
stopCloseTimer();
tooltipObj.style.display = "none";
tooltipInfo.ixActive = -1;
tooltipInfo.idNodeActive = 0;
}
|
| ︙ | |||
796 797 798 799 800 801 802 | 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + |
var dataObj = document.getElementById("timeline-data-"+i);
if(!dataObj) break;
var txJson = dataObj.textContent || dataObj.innerText;
var tx = JSON.parse(txJson);
TimelineGraph(tx);
}
}());
/*
** Timeline keyboard navigation shortcuts:
**
** N - Select next (newer) entry.
** M - Select previous (older) entry.
** J - View timeline of selected entry.
** K - View details of selected entry.
** L - Disable keyboard navigation mode.
**
** When navigating to a page with a timeline display, such as /timeline, /info,
** or /finfo, keyboard navigation mode needs to be "activated" first, i.e. if no
** timeline entry is focused yet, pressing any of the listed keys (except L)
** sets the visual focus indicator to the highlighted or current (check-out)
** entry if available, or to the topmost entry otherwise. A session cookie[0] is
** used to direct pages loaded in the future to enable keyboard navigation mode
** and automatically set the focus indicator to the highlighted, current, or
** topmost entry. Pressing N and M on the /timeline page while the topmost or
** bottommost entry is focused loads the next or previous page if available,
** similar to the [↑ More] and [↓ More] links. Pressing L disables keyboard
** navigation, i.e. removes the focus indicator and deletes the session cookie.
** When navigating backwards or forwards in browser history, the focused entry
** is restored using a hidden[1] input field.
**
** [0]: The lifetime and values of cookies can be tracked on the /cookies page.
** A session cookie is preferred over other storage APIs because Fossil already
** requires cookies to be enabled for reasonable functionality, and it's more
** likely that other storage APIs are blocked by users for privacy reasons, for
** example.
** [1]: This feature only works with a normal (text) input field hidden by CSS
** styles, instead of a true hidden (by type) input field, but according to MDN,
** screen readers should ignore it even without an aria-hidden="true" attribute
** (which is even discouraged for hidden by CSS elements). Also, this feature
** breaks if disabled[=true] or tabindex="-1" attributes are added to the input
** field, or (in FF) if page unload handlers are present.
**
** Ideas and TODOs:
**
** o Shortcut to select the topmost or bottommost entry, either by separate
** key, or with modifiers (SHIFT+N, SHIFT+M)?
** o Shortcut to toggle the tick-mark for the focused check-in node.
** o Shortcuts to copy branch name or hash of the focused entry to clipboard.
** o Shortcut to put the focus indicator to the default item(s), in (cyclic)
** order ticked → highlighted → check-out → ticked → ...
** o Improve scrolling the focused element into view for browsers without the
** Element.scrollIntoViewIfNeeded() function, maybe with a Polyfill, or
** something similar to the scrollToSelected() function in this source file.
*/
(function(){
window.addEventListener('load',function(){
function focusDefaultId(){
var tn = document.querySelector('.timelineSelected .tl-nodemark') ||
document.querySelector('.timelineCurrent .tl-nodemark');
return tn ? tn.id : 'm1';
}
function focusFirstId(id){
return 'm1';
}
function focusLastId(id){
var el = document.getElementsByClassName('tl-nodemark');
var tn = el ? el[el.length-1] : null;
return tn ? tn.id : id;
}
function focusNextId(id,dx){
if( dx<-1 ) return focusFirstId(id);
if( dx>+1 ) return focusLastId(id);
var m = /^m(\d+)$/.exec(id);
return m!==null ? 'm' + (parseInt(m[1]) + dx) : null;
}
function timelineGetDataBlock(i){
var tb = document.getElementById('timeline-data-' + i);
return tb ? JSON.parse(tb.textContent || tb.innerText) : null;
}
function timelineGetRowInfo(id){
var ti;
for(var i=0; ti=timelineGetDataBlock(i); i++){
for( var k=0; k<ti.rowinfo.length; k++ ){
if( id=='m' + ti.rowinfo[k].id ) return {
'baseurl': ti.baseUrl, 'hash': ti.rowinfo[k].h };
}
}
return null;
}
function focusVisualize(id,scroll){
var td = document.querySelector('.timelineFocused');
if( td ) td.classList.remove('timelineFocused');
if( !id ) return true;
var tn = document.getElementById(id);
if( tn ){
td = tn.parentElement.nextElementSibling;
if( td ) {
td.classList.add('timelineFocused');
if( scroll ){
if( td.scrollIntoViewIfNeeded ) td.scrollIntoViewIfNeeded();
else td.scrollIntoView(false);
}
return true;
}
}
return false;
}
function focusCacheInit(){
var e = document.getElementById('timeline-kbfocus');
if( !e ){
e = document.createElement('input');
e.type = 'text';
e.style.display = 'none';
e.style.visibility = 'hidden';
e.id = 'timeline-kbfocus';
document.body.appendChild(e);
}
}
function focusCacheGet(){
var e = document.getElementById('timeline-kbfocus');
return e ? e.value : null;
}
function focusCacheSet(v){
var e = document.getElementById('timeline-kbfocus');
if( e ) e.value = v;
}
focusCacheInit();
document.addEventListener('keydown',function(evt){
if( evt.target.tagName=='INPUT' ) return;
var
mSHIFT = 1<<13,
kFRST = mSHIFT | 78 /* SHIFT+N */,
kNEXT = 78 /* N */,
kPREV = 77 /* M */,
kLAST = mSHIFT | 77 /* SHIFT+M */,
kTICK = 188 /* , */,
kTMLN = 74 /* J */,
kVIEW = 75 /* K */,
kDONE = 76 /* L */,
mod = evt.altKey<<15 | evt.ctrlKey<<14 | evt.shiftKey<<13,
key = ( evt.which || evt.keyCode ) | mod;
var dx = 0;
switch( key ){
case kFRST: dx = -2; break;
case kNEXT: dx = -1; break;
case kPREV: dx = +1; break;
case kLAST: dx = +2; break;
case kTICK: break;
case kTMLN: break;
case kVIEW: break;
case kDONE: break;
default: return;
}
if( key==kDONE ){
focusCacheSet(null);
focusVisualize(null,false);
document.cookie =
'fossil_timeline_kbnav=;expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/';
return;
}
document.cookie = 'fossil_timeline_kbnav=1;path=/';
var id = focusCacheGet();
if( id && dx==0 ){
if( key==kTICK ){
var gn = document.getElementById('tln'+id.slice(1));
if( gn ) gn.click();
}
else/* if( key==kTMLN || key==kVIEW )*/{
var ri = timelineGetRowInfo(id);
if( ri ){
var page = key==kVIEW ? '/info/' : '/timeline?c=';
var href = ri.baseurl + page + encodeURIComponent(ri.hash);
if( href!=location.href.slice(-href.length) ){
location.href = href;
return;
}
}
}
}
else if ( id && dx!=0 ){
id = focusNextId(id,dx);
if( id && !document.getElementById(id) ){
var btn =
document.querySelector('.tl-button-' + ( dx>0 ? 'prev' : 'next' ));
if( btn ) btn.click();
return;
}
}
else if ( !id ) id = focusDefaultId();
focusCacheSet(id);
focusVisualize(id,true);
}/*,true*/);
window.addEventListener('pageshow',function(evt){
var id = focusCacheGet();
if( !id || !focusVisualize(id,false) ){
if( document.cookie.match(/fossil_timeline_kbnav=1/) ){
id = focusDefaultId();
focusCacheSet(id);
focusVisualize(id,false);
}
}
},false);
},false);
}());
|
Changes to src/timeline.c.
| ︙ | |||
2727 2728 2729 2730 2731 2732 2733 | 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 | - + - + |
/* Report any errors. */
if( zError ){
@ <p class="generalError">%h(zError)</p>
}
if( zNewerButton ){
|
| ︙ |