Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch timeline-keyboard-navigation Through [fff09df34f] Excluding Merge-Ins
This is equivalent to a diff from ab553393a1 to fff09df34f
|
2022-08-05
| ||
| 06:22 | Shortcut SHIFT+J to view the timeline of the focused entry filtered by branch. Add the 'm' query parameter to /timeline links. check-in: 7bbd1b9918 user: florian tags: timeline-keyboard-navigation | |
|
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 | |
| 12:02 | The smart "scroll to" routine also needs to scroll upwards when used for their new purpose. check-in: fff09df34f user: florian tags: timeline-keyboard-navigation | |
| 11:46 | Docs v0.1, with upper-/lower-case letter notation, instead of SHIFT+LETTER (which may be somewhat confusing for the "," and ";" case). check-in: b02508d358 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 skins/ardoise/css.txt.
| ︙ | ︙ | |||
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 |
.timelineCurrent > .timelineVerboseCell {
vertical-align: top;
text-align: left;
padding: .75em;
border-radius: 5px;
border: dashed #ff8000
}
.timelineModernCell[id], .timelineColumnarCell[id], .timelineDetailCell[id] {
background-color: #000
}
.tl-canvas {
margin: 0 6px 0 10px
}
.tl-rail {
| > > > > > > > > > | 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 |
.timelineCurrent > .timelineVerboseCell {
vertical-align: top;
text-align: left;
padding: .75em;
border-radius: 5px;
border: dashed #ff8000
}
.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:white;opacity:0.2' d='M0,0h1v1h-1z'/%3E%3C/svg%3E") !important;
/*Note: IE requires explicit declarations for the next three properties.*/
background-position: top left;
background-repeat: repeat repeat;
background-size: 64px 64px;
}
.timelineModernCell[id], .timelineColumnarCell[id], .timelineDetailCell[id] {
background-color: #000
}
.tl-canvas {
margin: 0 6px 0 10px
}
.tl-rail {
|
| ︙ | ︙ |
Changes to skins/darkmode/css.txt.
| ︙ | ︙ | |||
351 352 353 354 355 356 357 358 359 360 361 362 363 364 |
.timelineCurrent > .timelineVerboseCell {
/*vertical-align: top;
text-align: left;*/
padding: .75em;
border-radius: 5px;
border: dashed #ff8000
}
.timelineModernCell[id], .timelineColumnarCell[id], .timelineDetailCell[id] {
background-color: inherit;/*#000*/
}
.tl-canvas {
margin: 0 6px 0 10px
}
.tl-rail {
| > > > > > > > > > | 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 |
.timelineCurrent > .timelineVerboseCell {
/*vertical-align: top;
text-align: left;*/
padding: .75em;
border-radius: 5px;
border: dashed #ff8000
}
.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:white;opacity:0.2' d='M0,0h1v1h-1z'/%3E%3C/svg%3E") !important;
/*Note: IE requires explicit declarations for the next three properties.*/
background-position: top left;
background-repeat: repeat repeat;
background-size: 64px 64px;
}
.timelineModernCell[id], .timelineColumnarCell[id], .timelineDetailCell[id] {
background-color: inherit;/*#000*/
}
.tl-canvas {
margin: 0 6px 0 10px
}
.tl-rail {
|
| ︙ | ︙ |
Changes to skins/eagle/css.txt.
| ︙ | ︙ | |||
187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
.timelineSelected {
background-color: #7EA2D9;
}
.timelineSecondary {
background-color: #7EA27E;
}
/* commit node */
.tl-node {
width: 10px;
height: 10px;
border: 1px solid #fff;
background: #485D7B;
| > > > > > > > > > | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
.timelineSelected {
background-color: #7EA2D9;
}
.timelineSecondary {
background-color: #7EA27E;
}
.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:white;opacity:0.2' 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;
}
/* commit node */
.tl-node {
width: 10px;
height: 10px;
border: 1px solid #fff;
background: #485D7B;
|
| ︙ | ︙ |
Changes to skins/xekri/css.txt.
| ︙ | ︙ | |||
840 841 842 843 844 845 846 847 848 849 850 851 852 853 |
span.timelineSelected {
padding: 0 1em 0 1em;
border-radius: 1rem;
background: #333;
box-shadow: 2px 2px 1px #000;
}
.timelineTable .timelineModernCell .timelineModernComment ,
.timelineTable .timelineModernCell .timelineModernDetail ,
.timelineTable .timelineCompactCell .timelineCompactComment ,
.timelineTable .timelineCompactCell .timelineCompactDetail ,
.timelineTable .timelineVerboseCell .timelineVerboseComment ,
.timelineTable .timelineVerboseCell .timelineVerboseDetail {
| > > > > > > > > > > | 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 |
span.timelineSelected {
padding: 0 1em 0 1em;
border-radius: 1rem;
background: #333;
box-shadow: 2px 2px 1px #000;
}
.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:white;opacity:0.2' d='M0,0h1v1h-1z'/%3E%3C/svg%3E") !important;
/*Note: IE requires explicit declarations for the next three properties.*/
background-position: top left;
background-repeat: repeat repeat;
background-size: 64px 64px;
}
.timelineTable .timelineModernCell .timelineModernComment ,
.timelineTable .timelineModernCell .timelineModernDetail ,
.timelineTable .timelineCompactCell .timelineCompactComment ,
.timelineTable .timelineCompactCell .timelineCompactDetail ,
.timelineTable .timelineVerboseCell .timelineVerboseComment ,
.timelineTable .timelineVerboseCell .timelineVerboseDetail {
|
| ︙ | ︙ |
Changes to src/default.css.
| ︙ | ︙ | |||
49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
border-radius: 0;
border-width: 0;
}
tr.timelineCurrent td {
border-radius: 0;
border-width: 0;
}
span.timelineLeaf {
font-weight: bold;
}
span.timelineHistDsp {
font-weight: bold;
}
td.timelineTime {
| > > > > > > > > > | 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:black;opacity:0.1' 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 |
function hideGraphTooltip(){ /* Hide the tooltip */
document.removeEventListener('keydown',onKeyDown,/* useCapture == */true);
stopCloseTimer();
tooltipObj.style.display = "none";
tooltipInfo.ixActive = -1;
tooltipInfo.idNodeActive = 0;
}
| | | 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;
}
window.onpageshow = window.onpagehide = hideGraphTooltip;
function stopDwellTimer(){
if(tooltipInfo.idTimer!=0){
clearTimeout(tooltipInfo.idTimer);
tooltipInfo.idTimer = 0;
}
}
function resumeCloseTimer(){
|
| ︙ | ︙ | |||
796 797 798 799 800 801 802 |
var dataObj = document.getElementById("timeline-data-"+i);
if(!dataObj) break;
var txJson = dataObj.textContent || dataObj.innerText;
var tx = JSON.parse(txJson);
TimelineGraph(tx);
}
}());
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 |
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.
** ESC - 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 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
** 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 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 Tweak the focus indicator background color and opacity to be suitable for
** the light-background skins, and override it for the dark-background skins
** (Ardoise, Dark Mode, Eagle, Xekri).
** 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')
|| document.querySelector('.timelineCurrent .tl-nodemark');
return tn ? tn.id : 'm1';
}
function focusSelectedId(){
var tn = document.querySelector(
'.timelineSelected:not(.timelineSecondary) .tl-nodemark');
return tn ? tn.id : null;
}
function focus2ndSelectedId(){
var tn = document.querySelector('.timelineSecondary .tl-nodemark');
return tn ? tn.id : null;
}
function focusCurrentId(){
var tn = document.querySelector('.timelineCurrent .tl-nodemark');
return tn ? tn.id : null;
}
function focusTickedId(){
var nd = document.querySelector('.tl-node.sel');
return nd ? 'm' + nd.id.slice(3) : null;
}
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,
'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');
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 */,
kCYCL = 72 /* H */,
kTICK = 188 /* , */,
kUNTK = mSHIFT | 188 /* , */,
kCPYH = 66 /* B */,
kCPYB = mSHIFT | 66 /* SHIFT+B */,
kTMLN = 74 /* J */,
kVIEW = 75 /* K */,
kDONE = 27 /* ESC */,
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 kCYCL: break;
case kTICK: break;
case kUNTK: break;
case kCPYH: break;
case kCPYB: break;
case kTMLN: break;
case kVIEW: break;
case kDONE: break;
default: return;
}
if( key==kUNTK ){
var tid = focusTickedId();
if( tid ){
var gn = document.getElementById('tln'+tid.slice(1));
if( gn ) gn.click();
}
return;
}
else if( key==kCPYH || key==kCPYB ){
var fid = focusCacheGet();
if( fid ){
var ri = timelineGetRowInfo(fid);
if( ri ){
copyTextToClipboard(
key==kCPYH ? ri.hash.slice(0,ri.hashdigits) : ri.branch);
}
}
return;
}
else 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==kCYCL ){
var sel = focusSelectedId();
var sl2 = focus2ndSelectedId();
var cur = focusCurrentId();
var tik = focusTickedId();
if( id==sel ) id = sl2 || cur || tik || sel;
else if( id==sl2 ) id = cur || tik || sel || sl2;
else if( id==cur ) id = tik || sel || sl2 || cur;
else if( id==tik ) id = sel || sl2 || cur || tik;
else id = sel || sl2 || cur || tik || id;
}
else 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.
| ︙ | ︙ | |||
1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 |
**
** When multiple time-related filters are used, e.g. ym, yw, and ymd,
** which one(s) is/are applied is unspecified and may change between
** fossil versions.
**
** CHECKIN or TIMEORTAG can be a check-in hash prefix, or a tag, or the
** name of a branch.
*/
void page_timeline(void){
Stmt q; /* Query used to generate the timeline */
Blob sql; /* text of SQL used to generate timeline */
Blob desc; /* Description of the timeline */
int nEntry; /* Max number of entries on timeline */
int p_rid; /* artifact p and its parents */
| > > > > > > > > > > > > > > > | 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 |
**
** When multiple time-related filters are used, e.g. ym, yw, and ymd,
** which one(s) is/are applied is unspecified and may change between
** fossil versions.
**
** CHECKIN or TIMEORTAG can be a check-in hash prefix, or a tag, or the
** name of a branch.
**
** Keyboard navigation shortcuts:
**
** N Focus first (newest) entry.
** n Focus next (newer) entry, or open next page.
** m Focus previous (older) entry, or open previous page.
** M Focus last (oldest) entry.
** h Move focus between selected, current (check-out) and ticked entries.
** , Tick/untick the node of the focused entry.
** ; Untick the nodes of all entries.
** b Copy the commit hash of the focused entry to clipboard.
** B Copy the branch name of the focused entry to clipboard.
** j View timeline of focused entry.
** k View details of focused entry.
** ESC Disable keyboard navigation mode.
*/
void page_timeline(void){
Stmt q; /* Query used to generate the timeline */
Blob sql; /* text of SQL used to generate timeline */
Blob desc; /* Description of the timeline */
int nEntry; /* Max number of entries on timeline */
int p_rid; /* artifact p and its parents */
|
| ︙ | ︙ | |||
2727 2728 2729 2730 2731 2732 2733 |
/* Report any errors. */
if( zError ){
@ <p class="generalError">%h(zError)</p>
}
if( zNewerButton ){
| | | | 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 |
/* Report any errors. */
if( zError ){
@ <p class="generalError">%h(zError)</p>
}
if( zNewerButton ){
@ %z(chref("button tl-button-next","%s",zNewerButton))%h(zNewerButtonLabel)\
@ ↑</a>
}
www_print_timeline(&q, tmFlags, zThisUser, zThisTag, zBrName,
selectedRid, secondaryRid, 0);
db_finalize(&q);
if( zOlderButton ){
@ %z(chref("button tl-button-prev","%s",zOlderButton))%h(zOlderButtonLabel)\
@ ↓</a>
}
document_emit_js(/*handles pikchrs rendered above*/);
style_finish_page();
}
/*
|
| ︙ | ︙ |