Fossil

Check-in [ae932acdd2]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Coding style fixes and comment updates.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | timeline-keyboard-navigation
Files: files | file ages | folders
SHA3-256: ae932acdd23980124ca6d892cd126d7c6dde7febd664b5d13904bdfaa09844bc
User & Date: florian 2022-08-07 08:12:00.000
Context
2022-08-11
05:48
Refactorings to cookie handling. ... (check-in: cf38f5abb8 user: florian tags: timeline-keyboard-navigation)
2022-08-07
08:12
Coding style fixes and comment updates. ... (check-in: ae932acdd2 user: florian tags: timeline-keyboard-navigation)
08:09
Shortcut SHIFT+H to scroll to the focused entry without moving focus. This may be handy in conjunction with scrolling by arrow keys or PgUp/Dn. ... (check-in: 8d1edb8206 user: florian tags: timeline-keyboard-navigation)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/graph.js.
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
    TimelineGraph(tx);
  }
}());

/*
** Timeline keyboard navigation shortcuts:
**
** ### NOTE: The keyboard shortcuts are listed in /timeline help text. ###
**
** 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 ESC)
** 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







|










|







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
    TimelineGraph(tx);
  }
}());

/*
** Timeline keyboard navigation shortcuts:
**
** ### NOTE: The keyboard shortcuts are listed in the /timeline help screen. ###
**
** 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 ESC)
** 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 ESC 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
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
**
**  o kTMLN: ensure the correct page is opened when used from /finfo (it seems
**    the tooltip also gets this "wrong", but maybe that's acceptable, because
**    in order to be able to construct /file URLs, the information provided by
**    the timeline-data-N blocks would have to be extended).
**  o kFRST, kLAST: check if the previous/next page should be opened if focus is
**    already at the top/bottom.
**  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:not(.timelineSecondary) .tl-nodemark')
                || document.querySelector('.timelineSelected .tl-nodemark')







<
<
<







836
837
838
839
840
841
842



843
844
845
846
847
848
849
**
**  o kTMLN: ensure the correct page is opened when used from /finfo (it seems
**    the tooltip also gets this "wrong", but maybe that's acceptable, because
**    in order to be able to construct /file URLs, the information provided by
**    the timeline-data-N blocks would have to be extended).
**  o kFRST, kLAST: check if the previous/next page should be opened if focus is
**    already at the top/bottom.



*/
(function(){
  window.addEventListener('load',function(){
    function focusDefaultId(){
      var tn = document.querySelector(
                '.timelineSelected:not(.timelineSecondary) .tl-nodemark')
                || document.querySelector('.timelineSelected .tl-nodemark')
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
    }
    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,
            'filediff': ti.fileDiff,
            'hashdigits': ti.hashDigits,
            'hash': ti.rowinfo[k].h,
            'branch': ti.rowinfo[k].br
          };
        }
      }
      return null;
    }
    function focusScrollToIntoViewTheFossilWay(e){
      var y = 0;
      do{
        y += e.offsetTop;
      }while( e = e.offsetParent );
      window.scrollTo(0,y-window.innerHeight/2);
    }
    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 ){
            focusScrollToIntoViewTheFossilWay(td);
            //if( td.scrollIntoViewIfNeeded ) td.scrollIntoViewIfNeeded();
            //else td.scrollIntoView(false);
          }
          return true;
        }
      }
      return false;
    }
    function focusCacheInit(){
      var e = document.getElementById('timeline-kbfocus');







|








|















|
<
<
<
<







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
    }
    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,
            'filehash': ti.fileDiff,
            'hashdigits': ti.hashDigits,
            'hash': ti.rowinfo[k].h,
            'branch': ti.rowinfo[k].br
          };
        }
      }
      return null;
    }
    function fossilScrollIntoView(e){
      var y = 0;
      do{
        y += e.offsetTop;
      }while( e = e.offsetParent );
      window.scrollTo(0,y-window.innerHeight/2);
    }
    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 ) fossilScrollIntoView(td);




          return true;
        }
      }
      return false;
    }
    function focusCacheInit(){
      var e = document.getElementById('timeline-kbfocus');
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
        case kTMLB:
        case kVIEW:
        case kDONE: break;
        default: return;
      }
      if( key==kSCRL ){
        var td = document.querySelector('.timelineFocused');
        if( td ) focusScrollToIntoViewTheFossilWay(td);
        return;
      }
      else if( key==kUNTK ){
        var tid = focusTickedId();
        if( tid ){
          var gn = document.getElementById('tln'+tid.slice(1));
          if( gn ) gn.click();







|







978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
        case kTMLB:
        case kVIEW:
        case kDONE: break;
        default: return;
      }
      if( key==kSCRL ){
        var td = document.querySelector('.timelineFocused');
        if( td ) fossilScrollIntoView(td);
        return;
      }
      else if( key==kUNTK ){
        var tid = focusTickedId();
        if( tid ){
          var gn = document.getElementById('tln'+tid.slice(1));
          if( gn ) gn.click();
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
          var ri = timelineGetRowInfo(id);
          if( ri ){
            var hh = encodeURIComponent(ri.hash.slice(0,ri.hashdigits));
            var br = encodeURIComponent(ri.branch);
            var page;
            switch( key ){
              case kTMLN:
                page = '/timeline' + ( ri.filediff ? '?m&cf=' : '?m&c=' ) + hh;
                break;
              case kTMLB:
                page = '/timeline?r=' + br +
                  ( ri.filediff ? '&m&cf=' : '&m&c=' ) + hh;
                break;
              case kVIEW:
                page = '/info/' + hh;
                break;
            }
            var href = ri.baseurl + page;
            if( href!=location.href.slice(-href.length) ){







|



|







1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
          var ri = timelineGetRowInfo(id);
          if( ri ){
            var hh = encodeURIComponent(ri.hash.slice(0,ri.hashdigits));
            var br = encodeURIComponent(ri.branch);
            var page;
            switch( key ){
              case kTMLN:
                page = '/timeline' + ( ri.filehash ? '?m&cf=' : '?m&c=' ) + hh;
                break;
              case kTMLB:
                page = '/timeline?r=' + br +
                  ( ri.filehash ? '&m&cf=' : '&m&c=' ) + hh;
                break;
              case kVIEW:
                page = '/info/' + hh;
                break;
            }
            var href = ri.baseurl + page;
            if( href!=location.href.slice(-href.length) ){