Fossil SCM

The javascript Advanced/Basic toggles on the timelines is working well enough now to merge to trunk.

drh 2017-11-26 01:37 trunk merge
Commit e91d26720582817b4574b1a6d06e8739516dd8fae0c554fa0f2768584775160a
--- skins/black_and_white/header.txt
+++ skins/black_and_white/header.txt
@@ -14,11 +14,11 @@
1414
</div>
1515
<div class="mainmenu">
1616
<th1>
1717
html "<a href='$home$index_page'>Home</a>\n"
1818
if {[anycap jor]} {
19
- html "<a href='$home/timeline?basic'>Timeline</a>\n"
19
+ html "<a href='$home/timeline'>Timeline</a>\n"
2020
}
2121
if {[anoncap oh]} {
2222
html "<a href='$home/tree?ci=tip'>Files</a>\n"
2323
}
2424
if {[anoncap o]} {
2525
--- skins/black_and_white/header.txt
+++ skins/black_and_white/header.txt
@@ -14,11 +14,11 @@
14 </div>
15 <div class="mainmenu">
16 <th1>
17 html "<a href='$home$index_page'>Home</a>\n"
18 if {[anycap jor]} {
19 html "<a href='$home/timeline?basic'>Timeline</a>\n"
20 }
21 if {[anoncap oh]} {
22 html "<a href='$home/tree?ci=tip'>Files</a>\n"
23 }
24 if {[anoncap o]} {
25
--- skins/black_and_white/header.txt
+++ skins/black_and_white/header.txt
@@ -14,11 +14,11 @@
14 </div>
15 <div class="mainmenu">
16 <th1>
17 html "<a href='$home$index_page'>Home</a>\n"
18 if {[anycap jor]} {
19 html "<a href='$home/timeline'>Timeline</a>\n"
20 }
21 if {[anoncap oh]} {
22 html "<a href='$home/tree?ci=tip'>Files</a>\n"
23 }
24 if {[anoncap o]} {
25
--- skins/blitz/header.txt
+++ skins/blitz/header.txt
@@ -37,11 +37,11 @@
3737
}
3838
html "<a href='$home$url'>$name</a></li>\n"
3939
}
4040
menulink $index_page Home
4141
if {[anycap jor]} {
42
- menulink /timeline?basic Timeline
42
+ menulink /timeline Timeline
4343
}
4444
if {[hascap oh]} {
4545
menulink /dir?ci=tip Files
4646
}
4747
if {[hascap o]} {
4848
--- skins/blitz/header.txt
+++ skins/blitz/header.txt
@@ -37,11 +37,11 @@
37 }
38 html "<a href='$home$url'>$name</a></li>\n"
39 }
40 menulink $index_page Home
41 if {[anycap jor]} {
42 menulink /timeline?basic Timeline
43 }
44 if {[hascap oh]} {
45 menulink /dir?ci=tip Files
46 }
47 if {[hascap o]} {
48
--- skins/blitz/header.txt
+++ skins/blitz/header.txt
@@ -37,11 +37,11 @@
37 }
38 html "<a href='$home$url'>$name</a></li>\n"
39 }
40 menulink $index_page Home
41 if {[anycap jor]} {
42 menulink /timeline Timeline
43 }
44 if {[hascap oh]} {
45 menulink /dir?ci=tip Files
46 }
47 if {[hascap o]} {
48
--- skins/blitz_no_logo/header.txt
+++ skins/blitz_no_logo/header.txt
@@ -34,11 +34,11 @@
3434
}
3535
html "<a href='$home$url'>$name</a></li>\n"
3636
}
3737
menulink $index_page Home
3838
if {[anycap jor]} {
39
- menulink /timeline?basic Timeline
39
+ menulink /timeline Timeline
4040
}
4141
if {[hascap oh]} {
4242
menulink /dir?ci=tip Files
4343
}
4444
if {[hascap o]} {
4545
--- skins/blitz_no_logo/header.txt
+++ skins/blitz_no_logo/header.txt
@@ -34,11 +34,11 @@
34 }
35 html "<a href='$home$url'>$name</a></li>\n"
36 }
37 menulink $index_page Home
38 if {[anycap jor]} {
39 menulink /timeline?basic Timeline
40 }
41 if {[hascap oh]} {
42 menulink /dir?ci=tip Files
43 }
44 if {[hascap o]} {
45
--- skins/blitz_no_logo/header.txt
+++ skins/blitz_no_logo/header.txt
@@ -34,11 +34,11 @@
34 }
35 html "<a href='$home$url'>$name</a></li>\n"
36 }
37 menulink $index_page Home
38 if {[anycap jor]} {
39 menulink /timeline Timeline
40 }
41 if {[hascap oh]} {
42 menulink /dir?ci=tip Files
43 }
44 if {[hascap o]} {
45
--- skins/bootstrap/header.txt
+++ skins/bootstrap/header.txt
@@ -54,13 +54,13 @@
5454
html "<li><a href='$home/wiki'>Wiki</a></li>\n"
5555
}
5656
}
5757
if {[anycap jor]} {
5858
if {[string compare $current_page "timeline"] == 0} {
59
- html "<li class='active'><a href='$home/timeline?basic'>Timeline</a></li>\n"
59
+ html "<li class='active'><a href='$home/timeline'>Timeline</a></li>\n"
6060
} else {
61
- html "<li><a href='$home/timeline?basic'>Timeline</a></li>\n"
61
+ html "<li><a href='$home/timeline'>Timeline</a></li>\n"
6262
}
6363
}
6464
if {[hascap oh]} {
6565
if {[string compare [string range $current_page 0 2] "dir"] == 0} {
6666
html "<li class='active'><a href='$home/dir?ci=tip'>Files</a></li>\n"
6767
--- skins/bootstrap/header.txt
+++ skins/bootstrap/header.txt
@@ -54,13 +54,13 @@
54 html "<li><a href='$home/wiki'>Wiki</a></li>\n"
55 }
56 }
57 if {[anycap jor]} {
58 if {[string compare $current_page "timeline"] == 0} {
59 html "<li class='active'><a href='$home/timeline?basic'>Timeline</a></li>\n"
60 } else {
61 html "<li><a href='$home/timeline?basic'>Timeline</a></li>\n"
62 }
63 }
64 if {[hascap oh]} {
65 if {[string compare [string range $current_page 0 2] "dir"] == 0} {
66 html "<li class='active'><a href='$home/dir?ci=tip'>Files</a></li>\n"
67
--- skins/bootstrap/header.txt
+++ skins/bootstrap/header.txt
@@ -54,13 +54,13 @@
54 html "<li><a href='$home/wiki'>Wiki</a></li>\n"
55 }
56 }
57 if {[anycap jor]} {
58 if {[string compare $current_page "timeline"] == 0} {
59 html "<li class='active'><a href='$home/timeline'>Timeline</a></li>\n"
60 } else {
61 html "<li><a href='$home/timeline'>Timeline</a></li>\n"
62 }
63 }
64 if {[hascap oh]} {
65 if {[string compare [string range $current_page 0 2] "dir"] == 0} {
66 html "<li class='active'><a href='$home/dir?ci=tip'>Files</a></li>\n"
67
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -19,11 +19,11 @@
1919
html "<a href='$home$url'>$name</a>\n"
2020
}
2121
}
2222
menulink $index_page Home
2323
if {[anycap jor]} {
24
- menulink /timeline?basic Timeline
24
+ menulink /timeline Timeline
2525
}
2626
if {[hascap oh]} {
2727
menulink /dir?ci=tip Files
2828
}
2929
if {[hascap o]} {
3030
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -19,11 +19,11 @@
19 html "<a href='$home$url'>$name</a>\n"
20 }
21 }
22 menulink $index_page Home
23 if {[anycap jor]} {
24 menulink /timeline?basic Timeline
25 }
26 if {[hascap oh]} {
27 menulink /dir?ci=tip Files
28 }
29 if {[hascap o]} {
30
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -19,11 +19,11 @@
19 html "<a href='$home$url'>$name</a>\n"
20 }
21 }
22 menulink $index_page Home
23 if {[anycap jor]} {
24 menulink /timeline Timeline
25 }
26 if {[hascap oh]} {
27 menulink /dir?ci=tip Files
28 }
29 if {[hascap o]} {
30
--- skins/eagle/header.txt
+++ skins/eagle/header.txt
@@ -98,11 +98,11 @@
9898
html "<a href='$home$url'>$name</a>\n"
9999
}
100100
menulink $index_page Home
101101
menulink /help Help
102102
if {[anycap jor]} {
103
- menulink /timeline?basic Timeline
103
+ menulink /timeline Timeline
104104
}
105105
if {[anoncap oh]} {
106106
menulink /dir?ci=tip Files
107107
}
108108
if {[anoncap o]} {
109109
--- skins/eagle/header.txt
+++ skins/eagle/header.txt
@@ -98,11 +98,11 @@
98 html "<a href='$home$url'>$name</a>\n"
99 }
100 menulink $index_page Home
101 menulink /help Help
102 if {[anycap jor]} {
103 menulink /timeline?basic Timeline
104 }
105 if {[anoncap oh]} {
106 menulink /dir?ci=tip Files
107 }
108 if {[anoncap o]} {
109
--- skins/eagle/header.txt
+++ skins/eagle/header.txt
@@ -98,11 +98,11 @@
98 html "<a href='$home$url'>$name</a>\n"
99 }
100 menulink $index_page Home
101 menulink /help Help
102 if {[anycap jor]} {
103 menulink /timeline Timeline
104 }
105 if {[anoncap oh]} {
106 menulink /dir?ci=tip Files
107 }
108 if {[anoncap o]} {
109
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -98,11 +98,11 @@
9898
html "<a href='$home$url'>$name</a>\n"
9999
}
100100
menulink $index_page Home
101101
menulink /help Help
102102
if {[anycap jor]} {
103
- menulink /timeline?basic Timeline
103
+ menulink /timeline Timeline
104104
}
105105
if {[anoncap oh]} {
106106
menulink /dir?ci=tip Files
107107
}
108108
if {[anoncap o]} {
109109
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -98,11 +98,11 @@
98 html "<a href='$home$url'>$name</a>\n"
99 }
100 menulink $index_page Home
101 menulink /help Help
102 if {[anycap jor]} {
103 menulink /timeline?basic Timeline
104 }
105 if {[anoncap oh]} {
106 menulink /dir?ci=tip Files
107 }
108 if {[anoncap o]} {
109
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -98,11 +98,11 @@
98 html "<a href='$home$url'>$name</a>\n"
99 }
100 menulink $index_page Home
101 menulink /help Help
102 if {[anycap jor]} {
103 menulink /timeline Timeline
104 }
105 if {[anoncap oh]} {
106 menulink /dir?ci=tip Files
107 }
108 if {[anoncap o]} {
109
--- skins/khaki/header.txt
+++ skins/khaki/header.txt
@@ -12,11 +12,11 @@
1212
</div>
1313
<div class="mainmenu">
1414
<th1>
1515
html "<a href='$home$index_page'>Home</a>\n"
1616
if {[anycap jor]} {
17
- html "<a href='$home/timeline?basic'>Timeline</a>\n"
17
+ html "<a href='$home/timeline'>Timeline</a>\n"
1818
}
1919
if {[anoncap oh]} {
2020
html "<a href='$home/tree?ci=tip'>Files</a>\n"
2121
}
2222
if {[anoncap o]} {
2323
--- skins/khaki/header.txt
+++ skins/khaki/header.txt
@@ -12,11 +12,11 @@
12 </div>
13 <div class="mainmenu">
14 <th1>
15 html "<a href='$home$index_page'>Home</a>\n"
16 if {[anycap jor]} {
17 html "<a href='$home/timeline?basic'>Timeline</a>\n"
18 }
19 if {[anoncap oh]} {
20 html "<a href='$home/tree?ci=tip'>Files</a>\n"
21 }
22 if {[anoncap o]} {
23
--- skins/khaki/header.txt
+++ skins/khaki/header.txt
@@ -12,11 +12,11 @@
12 </div>
13 <div class="mainmenu">
14 <th1>
15 html "<a href='$home$index_page'>Home</a>\n"
16 if {[anycap jor]} {
17 html "<a href='$home/timeline'>Timeline</a>\n"
18 }
19 if {[anoncap oh]} {
20 html "<a href='$home/tree?ci=tip'>Files</a>\n"
21 }
22 if {[anoncap o]} {
23
--- skins/original/header.txt
+++ skins/original/header.txt
@@ -13,11 +13,11 @@
1313
</div>
1414
<div class="mainmenu">
1515
<th1>
1616
html "<a href='$home$index_page'>Home</a>\n"
1717
if {[anycap jor]} {
18
- html "<a href='$home/timeline?basic'>Timeline</a>\n"
18
+ html "<a href='$home/timeline'>Timeline</a>\n"
1919
}
2020
if {[anoncap oh]} {
2121
html "<a href='$home/tree?ci=tip'>Files</a>\n"
2222
}
2323
if {[anoncap o]} {
2424
--- skins/original/header.txt
+++ skins/original/header.txt
@@ -13,11 +13,11 @@
13 </div>
14 <div class="mainmenu">
15 <th1>
16 html "<a href='$home$index_page'>Home</a>\n"
17 if {[anycap jor]} {
18 html "<a href='$home/timeline?basic'>Timeline</a>\n"
19 }
20 if {[anoncap oh]} {
21 html "<a href='$home/tree?ci=tip'>Files</a>\n"
22 }
23 if {[anoncap o]} {
24
--- skins/original/header.txt
+++ skins/original/header.txt
@@ -13,11 +13,11 @@
13 </div>
14 <div class="mainmenu">
15 <th1>
16 html "<a href='$home$index_page'>Home</a>\n"
17 if {[anycap jor]} {
18 html "<a href='$home/timeline'>Timeline</a>\n"
19 }
20 if {[anoncap oh]} {
21 html "<a href='$home/tree?ci=tip'>Files</a>\n"
22 }
23 if {[anoncap o]} {
24
--- skins/plain_gray/header.txt
+++ skins/plain_gray/header.txt
@@ -10,11 +10,11 @@
1010
</div>
1111
<div class="mainmenu">
1212
<th1>
1313
html "<a href='$home$index_page'>Home</a>\n"
1414
if {[anycap jor]} {
15
- html "<a href='$home/timeline?basic'>Timeline</a>\n"
15
+ html "<a href='$home/timeline'>Timeline</a>\n"
1616
}
1717
if {[anoncap oh]} {
1818
html "<a href='$home/tree?ci=tip'>Files</a>\n"
1919
}
2020
if {[anoncap o]} {
2121
--- skins/plain_gray/header.txt
+++ skins/plain_gray/header.txt
@@ -10,11 +10,11 @@
10 </div>
11 <div class="mainmenu">
12 <th1>
13 html "<a href='$home$index_page'>Home</a>\n"
14 if {[anycap jor]} {
15 html "<a href='$home/timeline?basic'>Timeline</a>\n"
16 }
17 if {[anoncap oh]} {
18 html "<a href='$home/tree?ci=tip'>Files</a>\n"
19 }
20 if {[anoncap o]} {
21
--- skins/plain_gray/header.txt
+++ skins/plain_gray/header.txt
@@ -10,11 +10,11 @@
10 </div>
11 <div class="mainmenu">
12 <th1>
13 html "<a href='$home$index_page'>Home</a>\n"
14 if {[anycap jor]} {
15 html "<a href='$home/timeline'>Timeline</a>\n"
16 }
17 if {[anoncap oh]} {
18 html "<a href='$home/tree?ci=tip'>Files</a>\n"
19 }
20 if {[anoncap o]} {
21
--- skins/rounded1/header.txt
+++ skins/rounded1/header.txt
@@ -14,11 +14,11 @@
1414
</div>
1515
<div class="mainmenu">
1616
<th1>
1717
html "<a href='$home$index_page'>Home</a>\n"
1818
if {[anycap jor]} {
19
- html "<a href='$home/timeline?basic'>Timeline</a>\n"
19
+ html "<a href='$home/timeline'>Timeline</a>\n"
2020
}
2121
if {[anoncap oh]} {
2222
html "<a href='$home/tree?ci=tip'>Files</a>\n"
2323
}
2424
if {[anoncap o]} {
2525
--- skins/rounded1/header.txt
+++ skins/rounded1/header.txt
@@ -14,11 +14,11 @@
14 </div>
15 <div class="mainmenu">
16 <th1>
17 html "<a href='$home$index_page'>Home</a>\n"
18 if {[anycap jor]} {
19 html "<a href='$home/timeline?basic'>Timeline</a>\n"
20 }
21 if {[anoncap oh]} {
22 html "<a href='$home/tree?ci=tip'>Files</a>\n"
23 }
24 if {[anoncap o]} {
25
--- skins/rounded1/header.txt
+++ skins/rounded1/header.txt
@@ -14,11 +14,11 @@
14 </div>
15 <div class="mainmenu">
16 <th1>
17 html "<a href='$home$index_page'>Home</a>\n"
18 if {[anycap jor]} {
19 html "<a href='$home/timeline'>Timeline</a>\n"
20 }
21 if {[anoncap oh]} {
22 html "<a href='$home/tree?ci=tip'>Files</a>\n"
23 }
24 if {[anoncap o]} {
25
--- skins/xekri/header.txt
+++ skins/xekri/header.txt
@@ -102,11 +102,11 @@
102102
html "<a href='$home$url'>$name</a>\n"
103103
}
104104
}
105105
menulink $index_page Home
106106
if {[anycap jor]} {
107
- menulink /timeline?basic Timeline
107
+ menulink /timeline Timeline
108108
}
109109
if {[anoncap oh]} {
110110
menulink /dir?ci=tip Files
111111
}
112112
if {[anoncap o]} {
113113
--- skins/xekri/header.txt
+++ skins/xekri/header.txt
@@ -102,11 +102,11 @@
102 html "<a href='$home$url'>$name</a>\n"
103 }
104 }
105 menulink $index_page Home
106 if {[anycap jor]} {
107 menulink /timeline?basic Timeline
108 }
109 if {[anoncap oh]} {
110 menulink /dir?ci=tip Files
111 }
112 if {[anoncap o]} {
113
--- skins/xekri/header.txt
+++ skins/xekri/header.txt
@@ -102,11 +102,11 @@
102 html "<a href='$home$url'>$name</a>\n"
103 }
104 }
105 menulink $index_page Home
106 if {[anycap jor]} {
107 menulink /timeline Timeline
108 }
109 if {[anoncap oh]} {
110 menulink /dir?ci=tip Files
111 }
112 if {[anoncap o]} {
113
+14 -16
--- src/finfo.c
+++ src/finfo.c
@@ -287,11 +287,10 @@
287287
** ubg Background color by user name
288288
** ci=UUID Ancestors of a particular check-in
289289
** orig=UUID If both ci and orig are supplied, only show those
290290
** changes on a direct path from orig to ci.
291291
** showid Show RID values for debugging
292
-** basic Minimize clutter and complication
293292
**
294293
** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
295294
** year-month-day form, it may be truncated, and it may also name a
296295
** timezone offset from UTC as "-HH:MM" (westward) or "+HH:MM"
297296
** (eastward). Either no timezone suffix or "Z" means UTC.
@@ -314,11 +313,10 @@
314313
int uBg = P("ubg")!=0;
315314
int fDebug = atoi(PD("debug","0"));
316315
int fShowId = P("showid")!=0;
317316
Stmt qparent;
318317
int iTableId = timeline_tableid();
319
- int bBasic = PB("basic");
320318
int bHashBeforeComment = 0; /* Show hash before the comment */
321319
int bHashAfterComment = 0; /* Show hash after the comment */
322320
int bHashInDetail = 0; /* Show the hash inside the detail section */
323321
int bShowDetail; /* Show the detail section */
324322
int bSeparateDetail; /* Detail section in a separate column */
@@ -332,11 +330,11 @@
332330
if( brBg ) url_add_parameter(&url, "brbg", 0);
333331
if( uBg ) url_add_parameter(&url, "ubg", 0);
334332
baseCheckin = name_to_rid_www("ci");
335333
zPrevDate[0] = 0;
336334
zFilename = PD("name","");
337
- eCommentFormat = bBasic ? 5 : db_get_int("timeline-comment-format", 0);
335
+ eCommentFormat = db_get_int("timeline-comment-format", 0);
338336
bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
339337
bSeparateDetail = (eCommentFormat & 8)!=0;
340338
switch( (eCommentFormat>>1)&3 ){
341339
case 1: bHashAfterComment = 1; break;
342340
case 2: bHashInDetail = 1; break;
@@ -346,11 +344,11 @@
346344
if( fnid==0 ){
347345
@ No such file: %h(zFilename)
348346
style_footer();
349347
return;
350348
}
351
- if( g.perm.Admin && !bBasic ){
349
+ if( g.perm.Admin ){
352350
style_submenu_element("MLink Table", "%R/mlink?name=%t", zFilename);
353351
}
354352
if( baseCheckin ){
355353
if( P("orig")!=0 ){
356354
origCheckin = name_to_typed_rid(P("orig"),"ci");
@@ -447,17 +445,12 @@
447445
}else{
448446
blob_appendf(&title, "History of ");
449447
hyperlinked_path(zFilename, &title, 0, "tree", "");
450448
if( fShowId ) blob_appendf(&title, " (%d)", fnid);
451449
}
452
- if( bBasic ){
453
- style_submenu_element("Details", "%s",
454
- url_render(&url, "basic", 0, 0, 0));
455
- }else{
456
- style_submenu_element("Declutter", "%s",
457
- url_render(&url, "basic", "1", 0, 0));
458
- }
450
+ style_submenu_jsbutton("Advanced", STYLE_BASIC, "reclutter()");
451
+ style_submenu_jsbutton("Basic", STYLE_CLUTTER, "declutter()");
459452
@ <h2>%b(&title)</h2>
460453
blob_reset(&title);
461454
pGraph = graph_init();
462455
@ <table id="timelineTable%d(iTableId)" class="timelineTable">
463456
if( baseCheckin ){
@@ -528,23 +521,28 @@
528521
@ <td class="timelineTableCell">
529522
}
530523
if( bHashBeforeComment && zUuid ){
531524
hyperlink_to_uuid(zUuid);
532525
}
533
- @ <span class="timelineComment timelineCheckinComment">%W(zCom)</span>
526
+ @ <span class="timelineComment timelineCheckinComment" \
527
+ @ onclick='toggleEllipsis(%d(frid))'>
528
+ @ %W(zCom)</span>
534529
if( bHashAfterComment && zUuid ){
535530
hyperlink_to_uuid(zUuid);
536531
}
537532
if( bShowDetail ){
533
+ @ <span class='timelineEllipsis anticlutter' id='ellipsis-%d(frid)' \
534
+ @ onclick='expandEllipsis(%d(frid))'>&#x22ef;</span>
538535
if( bSeparateDetail ){
539536
if( zBgClr && zBgClr[0] ){
540537
@ <td class="timelineTableCell timelineDetailCell"
541538
@ style="background-color: %h(zBgClr);">
542539
}else{
543540
@ <td class="timelineTableCell timelineDetailCell">
544541
}
545542
}
543
+ cgi_printf("<span class='clutter' id='detail-%d'>", frid);
546544
cgi_printf("<span class='timelineDetail timelineCheckinDetail'>(");
547545
if( zUuid && bHashInDetail ){
548546
@ file: %z(href("%R/artifact/%!S",zUuid))[%S(zUuid)]</a>
549547
if( fShowId ){
550548
int srcId = delta_source_rid(frid);
@@ -589,22 +587,22 @@
589587
}else{
590588
@ <b>Deleted</b>
591589
}
592590
}
593591
}
594
- if( g.perm.Hyperlink && zUuid && !bBasic ){
592
+ if( g.perm.Hyperlink && zUuid ){
595593
const char *z = zFilename;
596
- @ <span class='timelineExtraLinks'>
594
+ @ <span id='links-%d(frid)'><span class='timelineExtraLinks'>
597595
@ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
598596
@ [annotate]</a>
599597
@ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
600598
@ [blame]</a>
601599
@ %z(href("%R/timeline?n=all&uf=%!S",zUuid))[check-ins&nbsp;using]</a>
602600
if( fpid>0 ){
603601
@ %z(href("%R/fdiff?sbs=1&v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a>
604602
}
605
- @ </span>
603
+ @ </span></span>
606604
}
607605
if( fDebug & FINFO_DEBUG_MLINK ){
608606
int ii;
609607
char *zAncLink;
610608
@ <br />fid=%d(frid) pid=%d(fpid) mid=%d(fmid)
@@ -617,11 +615,11 @@
617615
zAncLink = href("%R/finfo?name=%T&ci=%!S&debug=1",zFilename,zCkin);
618616
@ %z(zAncLink)[ancestry]</a>
619617
}
620618
tag_private_status(frid);
621619
if( bShowDetail ){
622
- @ </span>
620
+ @ </span></span>
623621
}
624622
@ </td></tr>
625623
}
626624
db_finalize(&q);
627625
db_finalize(&qparent);
628626
--- src/finfo.c
+++ src/finfo.c
@@ -287,11 +287,10 @@
287 ** ubg Background color by user name
288 ** ci=UUID Ancestors of a particular check-in
289 ** orig=UUID If both ci and orig are supplied, only show those
290 ** changes on a direct path from orig to ci.
291 ** showid Show RID values for debugging
292 ** basic Minimize clutter and complication
293 **
294 ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
295 ** year-month-day form, it may be truncated, and it may also name a
296 ** timezone offset from UTC as "-HH:MM" (westward) or "+HH:MM"
297 ** (eastward). Either no timezone suffix or "Z" means UTC.
@@ -314,11 +313,10 @@
314 int uBg = P("ubg")!=0;
315 int fDebug = atoi(PD("debug","0"));
316 int fShowId = P("showid")!=0;
317 Stmt qparent;
318 int iTableId = timeline_tableid();
319 int bBasic = PB("basic");
320 int bHashBeforeComment = 0; /* Show hash before the comment */
321 int bHashAfterComment = 0; /* Show hash after the comment */
322 int bHashInDetail = 0; /* Show the hash inside the detail section */
323 int bShowDetail; /* Show the detail section */
324 int bSeparateDetail; /* Detail section in a separate column */
@@ -332,11 +330,11 @@
332 if( brBg ) url_add_parameter(&url, "brbg", 0);
333 if( uBg ) url_add_parameter(&url, "ubg", 0);
334 baseCheckin = name_to_rid_www("ci");
335 zPrevDate[0] = 0;
336 zFilename = PD("name","");
337 eCommentFormat = bBasic ? 5 : db_get_int("timeline-comment-format", 0);
338 bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
339 bSeparateDetail = (eCommentFormat & 8)!=0;
340 switch( (eCommentFormat>>1)&3 ){
341 case 1: bHashAfterComment = 1; break;
342 case 2: bHashInDetail = 1; break;
@@ -346,11 +344,11 @@
346 if( fnid==0 ){
347 @ No such file: %h(zFilename)
348 style_footer();
349 return;
350 }
351 if( g.perm.Admin && !bBasic ){
352 style_submenu_element("MLink Table", "%R/mlink?name=%t", zFilename);
353 }
354 if( baseCheckin ){
355 if( P("orig")!=0 ){
356 origCheckin = name_to_typed_rid(P("orig"),"ci");
@@ -447,17 +445,12 @@
447 }else{
448 blob_appendf(&title, "History of ");
449 hyperlinked_path(zFilename, &title, 0, "tree", "");
450 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
451 }
452 if( bBasic ){
453 style_submenu_element("Details", "%s",
454 url_render(&url, "basic", 0, 0, 0));
455 }else{
456 style_submenu_element("Declutter", "%s",
457 url_render(&url, "basic", "1", 0, 0));
458 }
459 @ <h2>%b(&title)</h2>
460 blob_reset(&title);
461 pGraph = graph_init();
462 @ <table id="timelineTable%d(iTableId)" class="timelineTable">
463 if( baseCheckin ){
@@ -528,23 +521,28 @@
528 @ <td class="timelineTableCell">
529 }
530 if( bHashBeforeComment && zUuid ){
531 hyperlink_to_uuid(zUuid);
532 }
533 @ <span class="timelineComment timelineCheckinComment">%W(zCom)</span>
 
 
534 if( bHashAfterComment && zUuid ){
535 hyperlink_to_uuid(zUuid);
536 }
537 if( bShowDetail ){
 
 
538 if( bSeparateDetail ){
539 if( zBgClr && zBgClr[0] ){
540 @ <td class="timelineTableCell timelineDetailCell"
541 @ style="background-color: %h(zBgClr);">
542 }else{
543 @ <td class="timelineTableCell timelineDetailCell">
544 }
545 }
 
546 cgi_printf("<span class='timelineDetail timelineCheckinDetail'>(");
547 if( zUuid && bHashInDetail ){
548 @ file: %z(href("%R/artifact/%!S",zUuid))[%S(zUuid)]</a>
549 if( fShowId ){
550 int srcId = delta_source_rid(frid);
@@ -589,22 +587,22 @@
589 }else{
590 @ <b>Deleted</b>
591 }
592 }
593 }
594 if( g.perm.Hyperlink && zUuid && !bBasic ){
595 const char *z = zFilename;
596 @ <span class='timelineExtraLinks'>
597 @ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
598 @ [annotate]</a>
599 @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
600 @ [blame]</a>
601 @ %z(href("%R/timeline?n=all&uf=%!S",zUuid))[check-ins&nbsp;using]</a>
602 if( fpid>0 ){
603 @ %z(href("%R/fdiff?sbs=1&v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a>
604 }
605 @ </span>
606 }
607 if( fDebug & FINFO_DEBUG_MLINK ){
608 int ii;
609 char *zAncLink;
610 @ <br />fid=%d(frid) pid=%d(fpid) mid=%d(fmid)
@@ -617,11 +615,11 @@
617 zAncLink = href("%R/finfo?name=%T&ci=%!S&debug=1",zFilename,zCkin);
618 @ %z(zAncLink)[ancestry]</a>
619 }
620 tag_private_status(frid);
621 if( bShowDetail ){
622 @ </span>
623 }
624 @ </td></tr>
625 }
626 db_finalize(&q);
627 db_finalize(&qparent);
628
--- src/finfo.c
+++ src/finfo.c
@@ -287,11 +287,10 @@
287 ** ubg Background color by user name
288 ** ci=UUID Ancestors of a particular check-in
289 ** orig=UUID If both ci and orig are supplied, only show those
290 ** changes on a direct path from orig to ci.
291 ** showid Show RID values for debugging
 
292 **
293 ** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
294 ** year-month-day form, it may be truncated, and it may also name a
295 ** timezone offset from UTC as "-HH:MM" (westward) or "+HH:MM"
296 ** (eastward). Either no timezone suffix or "Z" means UTC.
@@ -314,11 +313,10 @@
313 int uBg = P("ubg")!=0;
314 int fDebug = atoi(PD("debug","0"));
315 int fShowId = P("showid")!=0;
316 Stmt qparent;
317 int iTableId = timeline_tableid();
 
318 int bHashBeforeComment = 0; /* Show hash before the comment */
319 int bHashAfterComment = 0; /* Show hash after the comment */
320 int bHashInDetail = 0; /* Show the hash inside the detail section */
321 int bShowDetail; /* Show the detail section */
322 int bSeparateDetail; /* Detail section in a separate column */
@@ -332,11 +330,11 @@
330 if( brBg ) url_add_parameter(&url, "brbg", 0);
331 if( uBg ) url_add_parameter(&url, "ubg", 0);
332 baseCheckin = name_to_rid_www("ci");
333 zPrevDate[0] = 0;
334 zFilename = PD("name","");
335 eCommentFormat = db_get_int("timeline-comment-format", 0);
336 bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
337 bSeparateDetail = (eCommentFormat & 8)!=0;
338 switch( (eCommentFormat>>1)&3 ){
339 case 1: bHashAfterComment = 1; break;
340 case 2: bHashInDetail = 1; break;
@@ -346,11 +344,11 @@
344 if( fnid==0 ){
345 @ No such file: %h(zFilename)
346 style_footer();
347 return;
348 }
349 if( g.perm.Admin ){
350 style_submenu_element("MLink Table", "%R/mlink?name=%t", zFilename);
351 }
352 if( baseCheckin ){
353 if( P("orig")!=0 ){
354 origCheckin = name_to_typed_rid(P("orig"),"ci");
@@ -447,17 +445,12 @@
445 }else{
446 blob_appendf(&title, "History of ");
447 hyperlinked_path(zFilename, &title, 0, "tree", "");
448 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
449 }
450 style_submenu_jsbutton("Advanced", STYLE_BASIC, "reclutter()");
451 style_submenu_jsbutton("Basic", STYLE_CLUTTER, "declutter()");
 
 
 
 
 
452 @ <h2>%b(&title)</h2>
453 blob_reset(&title);
454 pGraph = graph_init();
455 @ <table id="timelineTable%d(iTableId)" class="timelineTable">
456 if( baseCheckin ){
@@ -528,23 +521,28 @@
521 @ <td class="timelineTableCell">
522 }
523 if( bHashBeforeComment && zUuid ){
524 hyperlink_to_uuid(zUuid);
525 }
526 @ <span class="timelineComment timelineCheckinComment" \
527 @ onclick='toggleEllipsis(%d(frid))'>
528 @ %W(zCom)</span>
529 if( bHashAfterComment && zUuid ){
530 hyperlink_to_uuid(zUuid);
531 }
532 if( bShowDetail ){
533 @ <span class='timelineEllipsis anticlutter' id='ellipsis-%d(frid)' \
534 @ onclick='expandEllipsis(%d(frid))'>&#x22ef;</span>
535 if( bSeparateDetail ){
536 if( zBgClr && zBgClr[0] ){
537 @ <td class="timelineTableCell timelineDetailCell"
538 @ style="background-color: %h(zBgClr);">
539 }else{
540 @ <td class="timelineTableCell timelineDetailCell">
541 }
542 }
543 cgi_printf("<span class='clutter' id='detail-%d'>", frid);
544 cgi_printf("<span class='timelineDetail timelineCheckinDetail'>(");
545 if( zUuid && bHashInDetail ){
546 @ file: %z(href("%R/artifact/%!S",zUuid))[%S(zUuid)]</a>
547 if( fShowId ){
548 int srcId = delta_source_rid(frid);
@@ -589,22 +587,22 @@
587 }else{
588 @ <b>Deleted</b>
589 }
590 }
591 }
592 if( g.perm.Hyperlink && zUuid ){
593 const char *z = zFilename;
594 @ <span id='links-%d(frid)'><span class='timelineExtraLinks'>
595 @ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
596 @ [annotate]</a>
597 @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
598 @ [blame]</a>
599 @ %z(href("%R/timeline?n=all&uf=%!S",zUuid))[check-ins&nbsp;using]</a>
600 if( fpid>0 ){
601 @ %z(href("%R/fdiff?sbs=1&v1=%!S&v2=%!S",zPUuid,zUuid))[diff]</a>
602 }
603 @ </span></span>
604 }
605 if( fDebug & FINFO_DEBUG_MLINK ){
606 int ii;
607 char *zAncLink;
608 @ <br />fid=%d(frid) pid=%d(fpid) mid=%d(fmid)
@@ -617,11 +615,11 @@
615 zAncLink = href("%R/finfo?name=%T&ci=%!S&debug=1",zFilename,zCkin);
616 @ %z(zAncLink)[ancestry]</a>
617 }
618 tag_private_status(frid);
619 if( bShowDetail ){
620 @ </span></span>
621 }
622 @ </td></tr>
623 }
624 db_finalize(&q);
625 db_finalize(&qparent);
626
+67 -23
--- src/style.c
+++ src/style.c
@@ -47,21 +47,29 @@
4747
static int nSubmenu = 0; /* Number of buttons */
4848
static struct SubmenuCtrl {
4949
const char *zName; /* Form query parameter */
5050
const char *zLabel; /* Label. Might be NULL for FF_MULTI */
5151
unsigned char eType; /* FF_ENTRY, FF_MULTI, FF_BINARY */
52
- unsigned char isDisabled; /* True if this control is grayed out */
52
+ unsigned char eVisible; /* STYLE_NORMAL, STYLE_VISIBLE, .... */
5353
short int iSize; /* Width for FF_ENTRY. Count for FF_MULTI */
5454
const char *const *azChoice; /* value/display pairs for FF_MULTI */
5555
const char *zFalse; /* FF_BINARY label when false */
5656
const char *zJS; /* Javascript to run on toggle */
5757
} aSubmenuCtrl[20];
5858
static int nSubmenuCtrl = 0;
59
-#define FF_ENTRY 1
60
-#define FF_MULTI 2
61
-#define FF_BINARY 3
62
-#define FF_CHECKBOX 4
59
+#define FF_ENTRY 1 /* Text entry box */
60
+#define FF_MULTI 2 /* Combobox. Multiple choices. */
61
+#define FF_BINARY 3 /* Control binary query parameter */
62
+#define FF_CHECKBOX 4 /* Check-box with JS */
63
+#define FF_JSBUTTON 5 /* Run JS when clicked */
64
+
65
+#if INTERFACE
66
+#define STYLE_NORMAL 0 /* Normal display of control */
67
+#define STYLE_DISABLED 1 /* Control is disabled */
68
+#define STYLE_CLUTTER 2 /* Only visible in "Advanced" display */
69
+#define STYLE_BASIC 4 /* Only visible in "Basic" display */
70
+#endif /* INTERFACE */
6371
6472
/*
6573
** Remember that the header has been generated. The footer is omitted
6674
** if an error occurs before the header.
6775
*/
@@ -248,59 +256,71 @@
248256
}
249257
void style_submenu_entry(
250258
const char *zName, /* Query parameter name */
251259
const char *zLabel, /* Label before the entry box */
252260
int iSize, /* Size of the entry box */
253
- int isDisabled /* True if disabled */
261
+ int eVisible /* Visible or disabled */
254262
){
255263
assert( nSubmenuCtrl < count(aSubmenuCtrl) );
256264
aSubmenuCtrl[nSubmenuCtrl].zName = zName;
257265
aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
258266
aSubmenuCtrl[nSubmenuCtrl].iSize = iSize;
259
- aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
267
+ aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
260268
aSubmenuCtrl[nSubmenuCtrl].eType = FF_ENTRY;
261269
nSubmenuCtrl++;
262270
}
263271
void style_submenu_checkbox(
264272
const char *zName, /* Query parameter name */
265273
const char *zLabel, /* Label to display after the checkbox */
266
- int isDisabled, /* True if disabled */
274
+ int eVisible, /* Visible or disabled */
267275
const char *zJS /* Optional javascript to run on toggle */
268276
){
269277
assert( nSubmenuCtrl < count(aSubmenuCtrl) );
270278
aSubmenuCtrl[nSubmenuCtrl].zName = zName;
271279
aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
272
- aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
280
+ aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
273281
aSubmenuCtrl[nSubmenuCtrl].zJS = zJS;
274282
aSubmenuCtrl[nSubmenuCtrl].eType = FF_CHECKBOX;
275283
nSubmenuCtrl++;
284
+}
285
+void style_submenu_jsbutton(
286
+ const char *zLabel, /* Label to display on the submenu */
287
+ int eVisible, /* Visible or disabled */
288
+ const char *zJS /* Javascript to run when clicked */
289
+){
290
+ assert( nSubmenuCtrl < count(aSubmenuCtrl) );
291
+ aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
292
+ aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
293
+ aSubmenuCtrl[nSubmenuCtrl].zJS = zJS;
294
+ aSubmenuCtrl[nSubmenuCtrl].eType = FF_JSBUTTON;
295
+ nSubmenuCtrl++;
276296
}
277297
void style_submenu_binary(
278298
const char *zName, /* Query parameter name */
279299
const char *zTrue, /* Label to show when parameter is true */
280300
const char *zFalse, /* Label to show when the parameter is false */
281
- int isDisabled /* True if this control is disabled */
301
+ int eVisible /* Visible or disabled */
282302
){
283303
assert( nSubmenuCtrl < count(aSubmenuCtrl) );
284304
aSubmenuCtrl[nSubmenuCtrl].zName = zName;
285305
aSubmenuCtrl[nSubmenuCtrl].zLabel = zTrue;
286306
aSubmenuCtrl[nSubmenuCtrl].zFalse = zFalse;
287
- aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
307
+ aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
288308
aSubmenuCtrl[nSubmenuCtrl].eType = FF_BINARY;
289309
nSubmenuCtrl++;
290310
}
291311
void style_submenu_multichoice(
292
- const char *zName, /* Query parameter name */
293
- int nChoice, /* Number of options */
294
- const char *const *azChoice,/* value/display pairs. 2*nChoice entries */
295
- int isDisabled /* True if this control is disabled */
312
+ const char *zName, /* Query parameter name */
313
+ int nChoice, /* Number of options */
314
+ const char *const *azChoice, /* value/display pairs. 2*nChoice entries */
315
+ int eVisible /* Visible or disabled */
296316
){
297317
assert( nSubmenuCtrl < count(aSubmenuCtrl) );
298318
aSubmenuCtrl[nSubmenuCtrl].zName = zName;
299319
aSubmenuCtrl[nSubmenuCtrl].iSize = nChoice;
300320
aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice;
301
- aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
321
+ aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
302322
aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
303323
nSubmenuCtrl++;
304324
}
305325
void style_submenu_sql(
306326
const char *zName, /* Query parameter name */
@@ -329,11 +349,11 @@
329349
if( n>0 ){
330350
aSubmenuCtrl[nSubmenuCtrl].zName = zName;
331351
aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
332352
aSubmenuCtrl[nSubmenuCtrl].iSize = n/2;
333353
aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char *const *)az;
334
- aSubmenuCtrl[nSubmenuCtrl].isDisabled = 0;
354
+ aSubmenuCtrl[nSubmenuCtrl].eVisible = STYLE_NORMAL;
335355
aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
336356
nSubmenuCtrl++;
337357
}
338358
}
339359
@@ -563,18 +583,26 @@
563583
}
564584
}
565585
}
566586
for(i=0; i<nSubmenuCtrl; i++){
567587
const char *zQPN = aSubmenuCtrl[i].zName;
568
- const char *zDisabled = " disabled";
569
- if( !aSubmenuCtrl[i].isDisabled ){
570
- zDisabled = "";
588
+ const char *zDisabled = "";
589
+ const char *zXtraClass = "";
590
+ if( aSubmenuCtrl[i].eVisible & STYLE_DISABLED ){
591
+ zDisabled = " disabled";
592
+ }else if( zQPN ){
571593
cgi_tag_query_parameter(zQPN);
594
+ }
595
+ if( aSubmenuCtrl[i].eVisible & STYLE_CLUTTER ){
596
+ zXtraClass = " clutter";
597
+ }
598
+ if( aSubmenuCtrl[i].eVisible & STYLE_BASIC ){
599
+ zXtraClass = " anticlutter";
572600
}
573601
switch( aSubmenuCtrl[i].eType ){
574602
case FF_ENTRY:
575
- @ <span class='submenuctrl'>\
603
+ @ <span class='submenuctrl%s(zXtraClass)'>\
576604
@ &nbsp;%h(aSubmenuCtrl[i].zLabel)\
577605
@ <input type='text' name='%s(zQPN)' value='%h(PD(zQPN, ""))' \
578606
if( aSubmenuCtrl[i].iSize<0 ){
579607
@ size='%d(-aSubmenuCtrl[i].iSize)' \
580608
}else if( aSubmenuCtrl[i].iSize>0 ){
@@ -584,10 +612,13 @@
584612
@ onchange='gebi("f01").submit();'%s(zDisabled)></span>
585613
break;
586614
case FF_MULTI: {
587615
int j;
588616
const char *zVal = P(zQPN);
617
+ if( zXtraClass[0] ){
618
+ @ <span class='%s(zXtraClass+1)'>
619
+ }
589620
if( aSubmenuCtrl[i].zLabel ){
590621
@ &nbsp;%h(aSubmenuCtrl[i].zLabel)\
591622
}
592623
@ <select class='submenuctrl' size='1' name='%s(zQPN)' \
593624
@ onchange='gebi("f01").submit();'%s(zDisabled)>
@@ -598,15 +629,18 @@
598629
@ selected\
599630
}
600631
@ >%h(aSubmenuCtrl[i].azChoice[j+1])</option>
601632
}
602633
@ </select>
634
+ if( zXtraClass[0] ){
635
+ @ </span>
636
+ }
603637
break;
604638
}
605639
case FF_BINARY: {
606640
int isTrue = PB(zQPN);
607
- @ <select class='submenuctrl' size='1' name='%s(zQPN)' \
641
+ @ <select class='submenuctrl%s(zXtraClass)' size='1' name='%s(zQPN)' \
608642
@ onchange='gebi("f01").submit();'%s(zDisabled)>
609643
@ <option value='1'\
610644
if( isTrue ){
611645
@ selected\
612646
}
@@ -618,11 +652,11 @@
618652
@ >%h(aSubmenuCtrl[i].zFalse)</option>
619653
@ </select>
620654
break;
621655
}
622656
case FF_CHECKBOX: {
623
- @ <label class='submenuctrl submenuckbox'>\
657
+ @ <label class='submenuctrl submenuckbox%s(zXtraClass)'>\
624658
@ <input type='checkbox' name='%s(zQPN)' \
625659
if( PB(zQPN) ){
626660
@ checked \
627661
}
628662
if( aSubmenuCtrl[i].zJS ){
@@ -630,10 +664,16 @@
630664
}else{
631665
@ onchange='gebi("f01").submit();'%s(zDisabled)>\
632666
}
633667
@ %h(aSubmenuCtrl[i].zLabel)</label>
634668
break;
669
+ }
670
+ case FF_JSBUTTON: {
671
+ @ <a class="label%s(zXtraClass)" \
672
+ @ onclick='%s(aSubmenuCtrl[i].zJS)'%s(zDisabled)>\
673
+ @ %s(aSubmenuCtrl[i].zLabel)</a>
674
+ break;
635675
}
636676
}
637677
}
638678
@ </div>
639679
if( nSubmenuCtrl ){
@@ -1492,10 +1532,14 @@
14921532
},
14931533
{ "p.searchEmpty",
14941534
"Message explaining that there are no search results",
14951535
@ font-style: italic;
14961536
},
1537
+ { ".clutter",
1538
+ "Detail screen objects",
1539
+ @ display: none;
1540
+ },
14971541
{ 0,
14981542
0,
14991543
0
15001544
}
15011545
};
15021546
--- src/style.c
+++ src/style.c
@@ -47,21 +47,29 @@
47 static int nSubmenu = 0; /* Number of buttons */
48 static struct SubmenuCtrl {
49 const char *zName; /* Form query parameter */
50 const char *zLabel; /* Label. Might be NULL for FF_MULTI */
51 unsigned char eType; /* FF_ENTRY, FF_MULTI, FF_BINARY */
52 unsigned char isDisabled; /* True if this control is grayed out */
53 short int iSize; /* Width for FF_ENTRY. Count for FF_MULTI */
54 const char *const *azChoice; /* value/display pairs for FF_MULTI */
55 const char *zFalse; /* FF_BINARY label when false */
56 const char *zJS; /* Javascript to run on toggle */
57 } aSubmenuCtrl[20];
58 static int nSubmenuCtrl = 0;
59 #define FF_ENTRY 1
60 #define FF_MULTI 2
61 #define FF_BINARY 3
62 #define FF_CHECKBOX 4
 
 
 
 
 
 
 
 
63
64 /*
65 ** Remember that the header has been generated. The footer is omitted
66 ** if an error occurs before the header.
67 */
@@ -248,59 +256,71 @@
248 }
249 void style_submenu_entry(
250 const char *zName, /* Query parameter name */
251 const char *zLabel, /* Label before the entry box */
252 int iSize, /* Size of the entry box */
253 int isDisabled /* True if disabled */
254 ){
255 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
256 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
257 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
258 aSubmenuCtrl[nSubmenuCtrl].iSize = iSize;
259 aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
260 aSubmenuCtrl[nSubmenuCtrl].eType = FF_ENTRY;
261 nSubmenuCtrl++;
262 }
263 void style_submenu_checkbox(
264 const char *zName, /* Query parameter name */
265 const char *zLabel, /* Label to display after the checkbox */
266 int isDisabled, /* True if disabled */
267 const char *zJS /* Optional javascript to run on toggle */
268 ){
269 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
270 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
271 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
272 aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
273 aSubmenuCtrl[nSubmenuCtrl].zJS = zJS;
274 aSubmenuCtrl[nSubmenuCtrl].eType = FF_CHECKBOX;
275 nSubmenuCtrl++;
 
 
 
 
 
 
 
 
 
 
 
 
276 }
277 void style_submenu_binary(
278 const char *zName, /* Query parameter name */
279 const char *zTrue, /* Label to show when parameter is true */
280 const char *zFalse, /* Label to show when the parameter is false */
281 int isDisabled /* True if this control is disabled */
282 ){
283 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
284 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
285 aSubmenuCtrl[nSubmenuCtrl].zLabel = zTrue;
286 aSubmenuCtrl[nSubmenuCtrl].zFalse = zFalse;
287 aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
288 aSubmenuCtrl[nSubmenuCtrl].eType = FF_BINARY;
289 nSubmenuCtrl++;
290 }
291 void style_submenu_multichoice(
292 const char *zName, /* Query parameter name */
293 int nChoice, /* Number of options */
294 const char *const *azChoice,/* value/display pairs. 2*nChoice entries */
295 int isDisabled /* True if this control is disabled */
296 ){
297 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
298 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
299 aSubmenuCtrl[nSubmenuCtrl].iSize = nChoice;
300 aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice;
301 aSubmenuCtrl[nSubmenuCtrl].isDisabled = isDisabled;
302 aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
303 nSubmenuCtrl++;
304 }
305 void style_submenu_sql(
306 const char *zName, /* Query parameter name */
@@ -329,11 +349,11 @@
329 if( n>0 ){
330 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
331 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
332 aSubmenuCtrl[nSubmenuCtrl].iSize = n/2;
333 aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char *const *)az;
334 aSubmenuCtrl[nSubmenuCtrl].isDisabled = 0;
335 aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
336 nSubmenuCtrl++;
337 }
338 }
339
@@ -563,18 +583,26 @@
563 }
564 }
565 }
566 for(i=0; i<nSubmenuCtrl; i++){
567 const char *zQPN = aSubmenuCtrl[i].zName;
568 const char *zDisabled = " disabled";
569 if( !aSubmenuCtrl[i].isDisabled ){
570 zDisabled = "";
 
 
571 cgi_tag_query_parameter(zQPN);
 
 
 
 
 
 
572 }
573 switch( aSubmenuCtrl[i].eType ){
574 case FF_ENTRY:
575 @ <span class='submenuctrl'>\
576 @ &nbsp;%h(aSubmenuCtrl[i].zLabel)\
577 @ <input type='text' name='%s(zQPN)' value='%h(PD(zQPN, ""))' \
578 if( aSubmenuCtrl[i].iSize<0 ){
579 @ size='%d(-aSubmenuCtrl[i].iSize)' \
580 }else if( aSubmenuCtrl[i].iSize>0 ){
@@ -584,10 +612,13 @@
584 @ onchange='gebi("f01").submit();'%s(zDisabled)></span>
585 break;
586 case FF_MULTI: {
587 int j;
588 const char *zVal = P(zQPN);
 
 
 
589 if( aSubmenuCtrl[i].zLabel ){
590 @ &nbsp;%h(aSubmenuCtrl[i].zLabel)\
591 }
592 @ <select class='submenuctrl' size='1' name='%s(zQPN)' \
593 @ onchange='gebi("f01").submit();'%s(zDisabled)>
@@ -598,15 +629,18 @@
598 @ selected\
599 }
600 @ >%h(aSubmenuCtrl[i].azChoice[j+1])</option>
601 }
602 @ </select>
 
 
 
603 break;
604 }
605 case FF_BINARY: {
606 int isTrue = PB(zQPN);
607 @ <select class='submenuctrl' size='1' name='%s(zQPN)' \
608 @ onchange='gebi("f01").submit();'%s(zDisabled)>
609 @ <option value='1'\
610 if( isTrue ){
611 @ selected\
612 }
@@ -618,11 +652,11 @@
618 @ >%h(aSubmenuCtrl[i].zFalse)</option>
619 @ </select>
620 break;
621 }
622 case FF_CHECKBOX: {
623 @ <label class='submenuctrl submenuckbox'>\
624 @ <input type='checkbox' name='%s(zQPN)' \
625 if( PB(zQPN) ){
626 @ checked \
627 }
628 if( aSubmenuCtrl[i].zJS ){
@@ -630,10 +664,16 @@
630 }else{
631 @ onchange='gebi("f01").submit();'%s(zDisabled)>\
632 }
633 @ %h(aSubmenuCtrl[i].zLabel)</label>
634 break;
 
 
 
 
 
 
635 }
636 }
637 }
638 @ </div>
639 if( nSubmenuCtrl ){
@@ -1492,10 +1532,14 @@
1492 },
1493 { "p.searchEmpty",
1494 "Message explaining that there are no search results",
1495 @ font-style: italic;
1496 },
 
 
 
 
1497 { 0,
1498 0,
1499 0
1500 }
1501 };
1502
--- src/style.c
+++ src/style.c
@@ -47,21 +47,29 @@
47 static int nSubmenu = 0; /* Number of buttons */
48 static struct SubmenuCtrl {
49 const char *zName; /* Form query parameter */
50 const char *zLabel; /* Label. Might be NULL for FF_MULTI */
51 unsigned char eType; /* FF_ENTRY, FF_MULTI, FF_BINARY */
52 unsigned char eVisible; /* STYLE_NORMAL, STYLE_VISIBLE, .... */
53 short int iSize; /* Width for FF_ENTRY. Count for FF_MULTI */
54 const char *const *azChoice; /* value/display pairs for FF_MULTI */
55 const char *zFalse; /* FF_BINARY label when false */
56 const char *zJS; /* Javascript to run on toggle */
57 } aSubmenuCtrl[20];
58 static int nSubmenuCtrl = 0;
59 #define FF_ENTRY 1 /* Text entry box */
60 #define FF_MULTI 2 /* Combobox. Multiple choices. */
61 #define FF_BINARY 3 /* Control binary query parameter */
62 #define FF_CHECKBOX 4 /* Check-box with JS */
63 #define FF_JSBUTTON 5 /* Run JS when clicked */
64
65 #if INTERFACE
66 #define STYLE_NORMAL 0 /* Normal display of control */
67 #define STYLE_DISABLED 1 /* Control is disabled */
68 #define STYLE_CLUTTER 2 /* Only visible in "Advanced" display */
69 #define STYLE_BASIC 4 /* Only visible in "Basic" display */
70 #endif /* INTERFACE */
71
72 /*
73 ** Remember that the header has been generated. The footer is omitted
74 ** if an error occurs before the header.
75 */
@@ -248,59 +256,71 @@
256 }
257 void style_submenu_entry(
258 const char *zName, /* Query parameter name */
259 const char *zLabel, /* Label before the entry box */
260 int iSize, /* Size of the entry box */
261 int eVisible /* Visible or disabled */
262 ){
263 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
264 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
265 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
266 aSubmenuCtrl[nSubmenuCtrl].iSize = iSize;
267 aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
268 aSubmenuCtrl[nSubmenuCtrl].eType = FF_ENTRY;
269 nSubmenuCtrl++;
270 }
271 void style_submenu_checkbox(
272 const char *zName, /* Query parameter name */
273 const char *zLabel, /* Label to display after the checkbox */
274 int eVisible, /* Visible or disabled */
275 const char *zJS /* Optional javascript to run on toggle */
276 ){
277 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
278 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
279 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
280 aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
281 aSubmenuCtrl[nSubmenuCtrl].zJS = zJS;
282 aSubmenuCtrl[nSubmenuCtrl].eType = FF_CHECKBOX;
283 nSubmenuCtrl++;
284 }
285 void style_submenu_jsbutton(
286 const char *zLabel, /* Label to display on the submenu */
287 int eVisible, /* Visible or disabled */
288 const char *zJS /* Javascript to run when clicked */
289 ){
290 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
291 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
292 aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
293 aSubmenuCtrl[nSubmenuCtrl].zJS = zJS;
294 aSubmenuCtrl[nSubmenuCtrl].eType = FF_JSBUTTON;
295 nSubmenuCtrl++;
296 }
297 void style_submenu_binary(
298 const char *zName, /* Query parameter name */
299 const char *zTrue, /* Label to show when parameter is true */
300 const char *zFalse, /* Label to show when the parameter is false */
301 int eVisible /* Visible or disabled */
302 ){
303 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
304 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
305 aSubmenuCtrl[nSubmenuCtrl].zLabel = zTrue;
306 aSubmenuCtrl[nSubmenuCtrl].zFalse = zFalse;
307 aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
308 aSubmenuCtrl[nSubmenuCtrl].eType = FF_BINARY;
309 nSubmenuCtrl++;
310 }
311 void style_submenu_multichoice(
312 const char *zName, /* Query parameter name */
313 int nChoice, /* Number of options */
314 const char *const *azChoice, /* value/display pairs. 2*nChoice entries */
315 int eVisible /* Visible or disabled */
316 ){
317 assert( nSubmenuCtrl < count(aSubmenuCtrl) );
318 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
319 aSubmenuCtrl[nSubmenuCtrl].iSize = nChoice;
320 aSubmenuCtrl[nSubmenuCtrl].azChoice = azChoice;
321 aSubmenuCtrl[nSubmenuCtrl].eVisible = eVisible;
322 aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
323 nSubmenuCtrl++;
324 }
325 void style_submenu_sql(
326 const char *zName, /* Query parameter name */
@@ -329,11 +349,11 @@
349 if( n>0 ){
350 aSubmenuCtrl[nSubmenuCtrl].zName = zName;
351 aSubmenuCtrl[nSubmenuCtrl].zLabel = zLabel;
352 aSubmenuCtrl[nSubmenuCtrl].iSize = n/2;
353 aSubmenuCtrl[nSubmenuCtrl].azChoice = (const char *const *)az;
354 aSubmenuCtrl[nSubmenuCtrl].eVisible = STYLE_NORMAL;
355 aSubmenuCtrl[nSubmenuCtrl].eType = FF_MULTI;
356 nSubmenuCtrl++;
357 }
358 }
359
@@ -563,18 +583,26 @@
583 }
584 }
585 }
586 for(i=0; i<nSubmenuCtrl; i++){
587 const char *zQPN = aSubmenuCtrl[i].zName;
588 const char *zDisabled = "";
589 const char *zXtraClass = "";
590 if( aSubmenuCtrl[i].eVisible & STYLE_DISABLED ){
591 zDisabled = " disabled";
592 }else if( zQPN ){
593 cgi_tag_query_parameter(zQPN);
594 }
595 if( aSubmenuCtrl[i].eVisible & STYLE_CLUTTER ){
596 zXtraClass = " clutter";
597 }
598 if( aSubmenuCtrl[i].eVisible & STYLE_BASIC ){
599 zXtraClass = " anticlutter";
600 }
601 switch( aSubmenuCtrl[i].eType ){
602 case FF_ENTRY:
603 @ <span class='submenuctrl%s(zXtraClass)'>\
604 @ &nbsp;%h(aSubmenuCtrl[i].zLabel)\
605 @ <input type='text' name='%s(zQPN)' value='%h(PD(zQPN, ""))' \
606 if( aSubmenuCtrl[i].iSize<0 ){
607 @ size='%d(-aSubmenuCtrl[i].iSize)' \
608 }else if( aSubmenuCtrl[i].iSize>0 ){
@@ -584,10 +612,13 @@
612 @ onchange='gebi("f01").submit();'%s(zDisabled)></span>
613 break;
614 case FF_MULTI: {
615 int j;
616 const char *zVal = P(zQPN);
617 if( zXtraClass[0] ){
618 @ <span class='%s(zXtraClass+1)'>
619 }
620 if( aSubmenuCtrl[i].zLabel ){
621 @ &nbsp;%h(aSubmenuCtrl[i].zLabel)\
622 }
623 @ <select class='submenuctrl' size='1' name='%s(zQPN)' \
624 @ onchange='gebi("f01").submit();'%s(zDisabled)>
@@ -598,15 +629,18 @@
629 @ selected\
630 }
631 @ >%h(aSubmenuCtrl[i].azChoice[j+1])</option>
632 }
633 @ </select>
634 if( zXtraClass[0] ){
635 @ </span>
636 }
637 break;
638 }
639 case FF_BINARY: {
640 int isTrue = PB(zQPN);
641 @ <select class='submenuctrl%s(zXtraClass)' size='1' name='%s(zQPN)' \
642 @ onchange='gebi("f01").submit();'%s(zDisabled)>
643 @ <option value='1'\
644 if( isTrue ){
645 @ selected\
646 }
@@ -618,11 +652,11 @@
652 @ >%h(aSubmenuCtrl[i].zFalse)</option>
653 @ </select>
654 break;
655 }
656 case FF_CHECKBOX: {
657 @ <label class='submenuctrl submenuckbox%s(zXtraClass)'>\
658 @ <input type='checkbox' name='%s(zQPN)' \
659 if( PB(zQPN) ){
660 @ checked \
661 }
662 if( aSubmenuCtrl[i].zJS ){
@@ -630,10 +664,16 @@
664 }else{
665 @ onchange='gebi("f01").submit();'%s(zDisabled)>\
666 }
667 @ %h(aSubmenuCtrl[i].zLabel)</label>
668 break;
669 }
670 case FF_JSBUTTON: {
671 @ <a class="label%s(zXtraClass)" \
672 @ onclick='%s(aSubmenuCtrl[i].zJS)'%s(zDisabled)>\
673 @ %s(aSubmenuCtrl[i].zLabel)</a>
674 break;
675 }
676 }
677 }
678 @ </div>
679 if( nSubmenuCtrl ){
@@ -1492,10 +1532,14 @@
1532 },
1533 { "p.searchEmpty",
1534 "Message explaining that there are no search results",
1535 @ font-style: italic;
1536 },
1537 { ".clutter",
1538 "Detail screen objects",
1539 @ display: none;
1540 },
1541 { 0,
1542 0,
1543 0
1544 }
1545 };
1546
+64 -47
--- src/timeline.c
+++ src/timeline.c
@@ -103,11 +103,10 @@
103103
#define TIMELINE_UCOLOR 0x0080 /* Background color by user */
104104
#define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */
105105
#define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */
106106
#define TIMELINE_SHOWRID 0x0400 /* Show RID values in addition to UUIDs */
107107
#define TIMELINE_BISECT 0x0800 /* Show supplimental bisect information */
108
-#define TIMELINE_BASIC 0x1000 /* Minimize clutter and distraction */
109108
#endif
110109
111110
/*
112111
** Hash a string and use the hash to determine a background color.
113112
*/
@@ -265,19 +264,17 @@
265264
}
266265
zPrevDate[0] = 0;
267266
mxWikiLen = db_get_int("timeline-max-comment", 0);
268267
dateFormat = db_get_int("timeline-date-format", 0);
269268
bCommentGitStyle = db_get_int("timeline-truncate-at-blank", 0);
270
- if( tmFlags & TIMELINE_BASIC ){
271
- eCommentFormat = 5; /* Comment only */
272
- }else{
269
+ {
273270
/* Undocumented query parameter commentformat=N takes a numeric parameter to
274271
** adjust the comment-format for testing purposes. */
275272
const char *z = P("commentformat");
276273
eCommentFormat = z ? atoi(z) : db_get_int("timeline-comment-format", 0);
277274
}
278
- bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
275
+ bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
279276
bSeparateDetail = (eCommentFormat & 8)!=0; /* Bit 3 turns on the detail column */
280277
switch( (eCommentFormat>>1)&3 ){
281278
case 1: bHashAfterComment = 1; break;
282279
case 2: bHashInDetail = 1; break;
283280
default: bHashBeforeComment = 1; break;
@@ -493,15 +490,16 @@
493490
}
494491
db_column_blob(pQuery, commentColumn, &comment);
495492
if( zType[0]!='c' ){
496493
/* Comments for anything other than a check-in are generated by
497494
** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
498
- @ <span class='timelineComment'>
495
+ @ <span class='timelineComment' onclick='toggleEllipsis(%d(rid))'>
499496
wiki_convert(&comment, 0, WIKI_INLINE);
500497
@ </span>
501498
}else{
502
- @ <span class='timelineComment timelineCheckinComment'>
499
+ @ <span class='timelineComment timelineCheckinComment' \
500
+ @ onclick='toggleEllipsis(%d(rid))'>
503501
if( bCommentGitStyle ){
504502
/* Truncate comment at first blank line */
505503
int ii, jj;
506504
int n = blob_size(&comment);
507505
char *z = blob_str(&comment);
@@ -510,20 +508,20 @@
510508
for(jj=ii+1; jj<n && z[jj]!='\n' && fossil_isspace(z[jj]); jj++){}
511509
if( z[jj]=='\n' ) break;
512510
}
513511
}
514512
z[ii] = 0;
515
- @ %W(z)
513
+ cgi_printf("%W",z);
516514
}else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
517515
Blob truncated;
518516
blob_zero(&truncated);
519517
blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
520518
blob_append(&truncated, "...", 3);
521519
@ %W(blob_str(&truncated))
522520
blob_reset(&truncated);
523521
}else{
524
- @ %W(blob_str(&comment))
522
+ cgi_printf("%W",blob_str(&comment));
525523
}
526524
@ </span>
527525
}
528526
blob_reset(&comment);
529527
@@ -557,18 +555,21 @@
557555
558556
/* Generate extra information and hyperlinks to follow the comment.
559557
** Example: "(check-in: [abcdefg], user: drh, tags: trunk)"
560558
*/
561559
if( bShowDetail ){
560
+ @ <span class='timelineEllipsis anticlutter' id='ellipsis-%d(rid)' \
561
+ @ onclick='expandEllipsis(%d(rid))'>&#x22ef;</span>
562562
if( bSeparateDetail ){
563563
if( zBgClr && zBgClr[0] && rid!=selectedRid ){
564564
@ <td class="timelineTableCell timelineDetailCell"
565565
@ style="background-color: %h(zBgClr);">
566566
}else{
567567
@ <td class="timelineTableCell timelineDetailCell">
568568
}
569569
}
570
+ cgi_printf("<span class='clutter' id='detail-%d'>", rid);
570571
if( zType[0]=='c' ){
571572
cgi_printf("<span class='timelineDetail timelineCheckinDetail'>(");
572573
}else{
573574
cgi_printf("<span class='timelineDetail'>(");
574575
}
@@ -638,11 +639,11 @@
638639
cgi_printf(" id: %d&larr;%d", rid, srcId);
639640
}else{
640641
cgi_printf(" id: %d", rid);
641642
}
642643
}
643
- cgi_printf(")</span>\n"); /* End of the details section */
644
+ cgi_printf(")</span></span>\n"); /* End of the details section */
644645
}
645646
646647
tag_private_status(rid);
647648
648649
/* Generate extra hyperlinks at the end of the comment */
@@ -814,11 +815,11 @@
814815
iRailPitch = atoi(PD("railpitch","0"));
815816
showArrowheads = skin_detail_boolean("timeline-arrowheads");
816817
circleNodes = skin_detail_boolean("timeline-circle-nodes");
817818
colorGraph = skin_detail_boolean("timeline-color-graph-lines");
818819
819
- @ <script>(function(){
820
+ @ <script>
820821
@ "use strict";
821822
@ var css = "";
822823
if( circleNodes ){
823824
@ css += ".tl-node, .tl-node:after { border-radius: 50%%; }";
824825
}
@@ -1141,10 +1142,40 @@
11411142
}else{
11421143
@ location.href="%R/vdiff?from="+selRow.h+"&to="+p.h+"&sbs=1";
11431144
}
11441145
}
11451146
@ }
1147
+ @ }
1148
+ @ function changeDisplay(selector,value){
1149
+ @ var x = document.getElementsByClassName(selector);
1150
+ @ var n = x.length;
1151
+ @ for(var i=0; i<n; i++) {x[i].style.display = value;}
1152
+ @ }
1153
+ @ function declutter(){
1154
+ @ changeDisplay('clutter','none');
1155
+ @ changeDisplay('anticlutter','inline');
1156
+ @ checkHeight();
1157
+ @ }
1158
+ @ function reclutter(){
1159
+ @ changeDisplay('clutter','inline');
1160
+ @ changeDisplay('anticlutter','none');
1161
+ @ checkHeight();
1162
+ @ }
1163
+ @ function toggleEllipsis(id){
1164
+ @ var x = gebi("ellipsis-"+id);
1165
+ @ if( x.style.display=='none' ){
1166
+ @ x.style.display='inline';
1167
+ @ gebi("detail-"+id).style.display='none';
1168
+ @ x = document.getElementById("links-"+id);
1169
+ @ if(x) x.style.display='none';
1170
+ @ }else{
1171
+ @ x.style.display='none';
1172
+ @ gebi("detail-"+id).style.display='inline';
1173
+ @ x = document.getElementById("links-"+id);
1174
+ @ if(x) x.style.display='inline';
1175
+ @ }
1176
+ @ checkHeight();
11461177
@ }
11471178
@ var lastRow = gebi("m"+rowinfo[rowinfo.length-1].id);
11481179
@ var lastY = 0;
11491180
@ function checkHeight(){
11501181
@ var h = absoluteY(lastRow);
@@ -1154,11 +1185,11 @@
11541185
@ }
11551186
@ setTimeout(checkHeight, 1000);
11561187
@ }
11571188
@ initGraph();
11581189
@ checkHeight();
1159
- @ }())</script>
1190
+ @ </script>
11601191
}
11611192
}
11621193
11631194
/*
11641195
** Create a temporary table suitable for storing timeline data.
@@ -1324,11 +1355,11 @@
13241355
az[i++] = "Wiki";
13251356
}
13261357
assert( i<=count(az) );
13271358
}
13281359
if( i>2 ){
1329
- style_submenu_multichoice("y", i/2, az, isDisabled);
1360
+ style_submenu_multichoice("y", i/2, az, isDisabled|STYLE_CLUTTER);
13301361
}
13311362
}
13321363
13331364
/*
13341365
** If the zChng string is not NULL, then it should be a comma-separated
@@ -1574,11 +1605,10 @@
15741605
/*
15751606
** WEBPAGE: timeline
15761607
**
15771608
** Query parameters:
15781609
**
1579
-** basic Minimum clutter and distraction
15801610
** a=TIMEORTAG After this event
15811611
** b=TIMEORTAG Before this event
15821612
** c=TIMEORTAG "Circa" this event
15831613
** m=TIMEORTAG Mark this event
15841614
** n=COUNT Suggested number of events in output
@@ -1626,12 +1656,11 @@
16261656
int nEntry; /* Max number of entries on timeline */
16271657
int p_rid = name_to_typed_rid(P("p"),"ci"); /* artifact p and its parents */
16281658
int d_rid = name_to_typed_rid(P("d"),"ci"); /* artifact d and descendants */
16291659
int f_rid = name_to_typed_rid(P("f"),"ci"); /* artifact f and close family */
16301660
const char *zUser = P("u"); /* All entries by this user if not NULL */
1631
- int bBasic = PB("basic"); /* Minimize clutter and distraction */
1632
- const char *zType = PD("y",bBasic?"ci":"all"); /* Type of events. All if NULL */
1661
+ const char *zType = PD("y","all"); /* Type of events. All if NULL */
16331662
const char *zAfter = P("a"); /* Events after this time */
16341663
const char *zBefore = P("b"); /* Events before this time */
16351664
const char *zCirca = P("c"); /* Events near this time */
16361665
const char *zMark = P("m"); /* Mark this event or an event this time */
16371666
const char *zTagName = P("t"); /* Show events with this tag */
@@ -1732,11 +1761,11 @@
17321761
/* For exact maching, inhibit links to the selected tag. */
17331762
zThisTag = zTagName;
17341763
}
17351764
17361765
/* Display a checkbox to enable/disable display of related check-ins. */
1737
- if( !bBasic ) style_submenu_checkbox("rel", "Related", 0, 0);
1766
+ style_submenu_checkbox("rel", "Related", STYLE_CLUTTER, 0);
17381767
17391768
/* Construct the tag match expression. */
17401769
zTagSql = tagMatchExpression(matchStyle, zTagName, &zMatchDesc, &zError);
17411770
}
17421771
@@ -1864,13 +1893,11 @@
18641893
blob_append(&sql, ")", -1);
18651894
path_reset();
18661895
addFileGlobExclusion(zChng, &sql);
18671896
tmFlags |= TIMELINE_DISJOINT;
18681897
db_multi_exec("%s", blob_sql_text(&sql));
1869
- if( !bBasic ){
1870
- style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
1871
- }
1898
+ style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER,0);
18721899
blob_appendf(&desc, "%d check-ins going from ",
18731900
db_int(0, "SELECT count(*) FROM timeline"));
18741901
blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h", zFrom), zFrom);
18751902
blob_append(&desc, " to ", -1);
18761903
blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo);
@@ -1916,15 +1943,13 @@
19161943
if( p_rid ){
19171944
/* If both p= and d= are set, we don't have the uuid of d yet. */
19181945
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid);
19191946
}
19201947
}
1921
- if( !bBasic ){
1922
- style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
1923
- style_submenu_entry("n","Max:",4,0);
1924
- timeline_y_submenu(1);
1925
- }
1948
+ style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER, 0);
1949
+ style_submenu_entry("n","Max:",4,STYLE_CLUTTER);
1950
+ timeline_y_submenu(1);
19261951
}else if( f_rid && g.perm.Read ){
19271952
/* If f= is present, ignore all other parameters other than n= */
19281953
char *zUuid;
19291954
db_multi_exec(
19301955
"CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
@@ -1938,14 +1963,12 @@
19381963
if( useDividers ) selectedRid = f_rid;
19391964
blob_appendf(&desc, "Parents and children of check-in ");
19401965
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
19411966
blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid);
19421967
tmFlags |= TIMELINE_DISJOINT;
1943
- if( !bBasic ){
1944
- style_submenu_checkbox("unhide", "Unhide", 0, 0);
1945
- style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
1946
- }
1968
+ style_submenu_checkbox("unhide", "Unhide", STYLE_CLUTTER, 0);
1969
+ style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER, 0);
19471970
}else{
19481971
/* Otherwise, a timeline based on a span of time */
19491972
int n;
19501973
const char *zEType = "timeline item";
19511974
char *zDate;
@@ -2225,34 +2248,29 @@
22252248
/* timeline_submenu(&url, "Newer", "a", zDate, "b"); */
22262249
zNewerButton = fossil_strdup(url_render(&url, "a", zDate, "b", 0));
22272250
}
22282251
free(zDate);
22292252
}
2230
- if( !bBasic ){
2231
- if( zType[0]=='a' || zType[0]=='c' ){
2232
- style_submenu_checkbox("unhide", "Unhide", 0, 0);
2233
- }
2234
- style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
2235
- style_submenu_entry("n","Max:",4,0);
2236
- timeline_y_submenu(disableY);
2237
- style_submenu_entry("t", "Tag Filter:", -8, 0);
2238
- style_submenu_multichoice("ms", count(azMatchStyles)/2, azMatchStyles, 0);
2239
- }
2240
- }
2241
- blob_zero(&cond);
2242
- }
2243
- if( bBasic ){
2244
- timeline_submenu(&url, "Details", "basic", 0, 0);
2245
- }else{
2246
- timeline_submenu(&url, "Declutter", "basic", "1", 0);
2253
+ if( zType[0]=='a' || zType[0]=='c' ){
2254
+ style_submenu_checkbox("unhide", "Unhide", STYLE_CLUTTER, 0);
2255
+ }
2256
+ style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER,0);
2257
+ style_submenu_entry("n","Max:",4,STYLE_CLUTTER);
2258
+ timeline_y_submenu(disableY);
2259
+ style_submenu_entry("t", "Tag Filter:", -8, STYLE_CLUTTER);
2260
+ style_submenu_multichoice("ms", count(azMatchStyles)/2, azMatchStyles, STYLE_CLUTTER);
2261
+ }
2262
+ blob_zero(&cond);
22472263
}
22482264
if( PB("showsql") ){
22492265
@ <pre>%h(blob_sql_text(&sql))</pre>
22502266
}
22512267
if( search_restrict(SRCH_CKIN)!=0 ){
22522268
style_submenu_element("Search", "%R/search?y=c");
22532269
}
2270
+ style_submenu_jsbutton("Advanced", STYLE_BASIC, "reclutter()");
2271
+ style_submenu_jsbutton("Basic", STYLE_CLUTTER, "declutter()");
22542272
if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID;
22552273
if( useDividers && zMark && zMark[0] ){
22562274
double r = symbolic_name_to_mtime(zMark);
22572275
if( r>0.0 ) selectedRid = timeline_add_divider(r);
22582276
}
@@ -2263,11 +2281,10 @@
22632281
22642282
/* Report any errors. */
22652283
if( zError ){
22662284
@ <p class="generalError">%h(zError)</p>
22672285
}
2268
- if( bBasic ) tmFlags |= TIMELINE_BASIC;
22692286
22702287
if( zNewerButton ){
22712288
@ %z(xhref("class='button'","%z",zNewerButton))More&nbsp;&uarr;</a>
22722289
}
22732290
www_print_timeline(&q, tmFlags, zThisUser, zThisTag, selectedRid, 0);
22742291
--- src/timeline.c
+++ src/timeline.c
@@ -103,11 +103,10 @@
103 #define TIMELINE_UCOLOR 0x0080 /* Background color by user */
104 #define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */
105 #define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */
106 #define TIMELINE_SHOWRID 0x0400 /* Show RID values in addition to UUIDs */
107 #define TIMELINE_BISECT 0x0800 /* Show supplimental bisect information */
108 #define TIMELINE_BASIC 0x1000 /* Minimize clutter and distraction */
109 #endif
110
111 /*
112 ** Hash a string and use the hash to determine a background color.
113 */
@@ -265,19 +264,17 @@
265 }
266 zPrevDate[0] = 0;
267 mxWikiLen = db_get_int("timeline-max-comment", 0);
268 dateFormat = db_get_int("timeline-date-format", 0);
269 bCommentGitStyle = db_get_int("timeline-truncate-at-blank", 0);
270 if( tmFlags & TIMELINE_BASIC ){
271 eCommentFormat = 5; /* Comment only */
272 }else{
273 /* Undocumented query parameter commentformat=N takes a numeric parameter to
274 ** adjust the comment-format for testing purposes. */
275 const char *z = P("commentformat");
276 eCommentFormat = z ? atoi(z) : db_get_int("timeline-comment-format", 0);
277 }
278 bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
279 bSeparateDetail = (eCommentFormat & 8)!=0; /* Bit 3 turns on the detail column */
280 switch( (eCommentFormat>>1)&3 ){
281 case 1: bHashAfterComment = 1; break;
282 case 2: bHashInDetail = 1; break;
283 default: bHashBeforeComment = 1; break;
@@ -493,15 +490,16 @@
493 }
494 db_column_blob(pQuery, commentColumn, &comment);
495 if( zType[0]!='c' ){
496 /* Comments for anything other than a check-in are generated by
497 ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
498 @ <span class='timelineComment'>
499 wiki_convert(&comment, 0, WIKI_INLINE);
500 @ </span>
501 }else{
502 @ <span class='timelineComment timelineCheckinComment'>
 
503 if( bCommentGitStyle ){
504 /* Truncate comment at first blank line */
505 int ii, jj;
506 int n = blob_size(&comment);
507 char *z = blob_str(&comment);
@@ -510,20 +508,20 @@
510 for(jj=ii+1; jj<n && z[jj]!='\n' && fossil_isspace(z[jj]); jj++){}
511 if( z[jj]=='\n' ) break;
512 }
513 }
514 z[ii] = 0;
515 @ %W(z)
516 }else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
517 Blob truncated;
518 blob_zero(&truncated);
519 blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
520 blob_append(&truncated, "...", 3);
521 @ %W(blob_str(&truncated))
522 blob_reset(&truncated);
523 }else{
524 @ %W(blob_str(&comment))
525 }
526 @ </span>
527 }
528 blob_reset(&comment);
529
@@ -557,18 +555,21 @@
557
558 /* Generate extra information and hyperlinks to follow the comment.
559 ** Example: "(check-in: [abcdefg], user: drh, tags: trunk)"
560 */
561 if( bShowDetail ){
 
 
562 if( bSeparateDetail ){
563 if( zBgClr && zBgClr[0] && rid!=selectedRid ){
564 @ <td class="timelineTableCell timelineDetailCell"
565 @ style="background-color: %h(zBgClr);">
566 }else{
567 @ <td class="timelineTableCell timelineDetailCell">
568 }
569 }
 
570 if( zType[0]=='c' ){
571 cgi_printf("<span class='timelineDetail timelineCheckinDetail'>(");
572 }else{
573 cgi_printf("<span class='timelineDetail'>(");
574 }
@@ -638,11 +639,11 @@
638 cgi_printf(" id: %d&larr;%d", rid, srcId);
639 }else{
640 cgi_printf(" id: %d", rid);
641 }
642 }
643 cgi_printf(")</span>\n"); /* End of the details section */
644 }
645
646 tag_private_status(rid);
647
648 /* Generate extra hyperlinks at the end of the comment */
@@ -814,11 +815,11 @@
814 iRailPitch = atoi(PD("railpitch","0"));
815 showArrowheads = skin_detail_boolean("timeline-arrowheads");
816 circleNodes = skin_detail_boolean("timeline-circle-nodes");
817 colorGraph = skin_detail_boolean("timeline-color-graph-lines");
818
819 @ <script>(function(){
820 @ "use strict";
821 @ var css = "";
822 if( circleNodes ){
823 @ css += ".tl-node, .tl-node:after { border-radius: 50%%; }";
824 }
@@ -1141,10 +1142,40 @@
1141 }else{
1142 @ location.href="%R/vdiff?from="+selRow.h+"&to="+p.h+"&sbs=1";
1143 }
1144 }
1145 @ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1146 @ }
1147 @ var lastRow = gebi("m"+rowinfo[rowinfo.length-1].id);
1148 @ var lastY = 0;
1149 @ function checkHeight(){
1150 @ var h = absoluteY(lastRow);
@@ -1154,11 +1185,11 @@
1154 @ }
1155 @ setTimeout(checkHeight, 1000);
1156 @ }
1157 @ initGraph();
1158 @ checkHeight();
1159 @ }())</script>
1160 }
1161 }
1162
1163 /*
1164 ** Create a temporary table suitable for storing timeline data.
@@ -1324,11 +1355,11 @@
1324 az[i++] = "Wiki";
1325 }
1326 assert( i<=count(az) );
1327 }
1328 if( i>2 ){
1329 style_submenu_multichoice("y", i/2, az, isDisabled);
1330 }
1331 }
1332
1333 /*
1334 ** If the zChng string is not NULL, then it should be a comma-separated
@@ -1574,11 +1605,10 @@
1574 /*
1575 ** WEBPAGE: timeline
1576 **
1577 ** Query parameters:
1578 **
1579 ** basic Minimum clutter and distraction
1580 ** a=TIMEORTAG After this event
1581 ** b=TIMEORTAG Before this event
1582 ** c=TIMEORTAG "Circa" this event
1583 ** m=TIMEORTAG Mark this event
1584 ** n=COUNT Suggested number of events in output
@@ -1626,12 +1656,11 @@
1626 int nEntry; /* Max number of entries on timeline */
1627 int p_rid = name_to_typed_rid(P("p"),"ci"); /* artifact p and its parents */
1628 int d_rid = name_to_typed_rid(P("d"),"ci"); /* artifact d and descendants */
1629 int f_rid = name_to_typed_rid(P("f"),"ci"); /* artifact f and close family */
1630 const char *zUser = P("u"); /* All entries by this user if not NULL */
1631 int bBasic = PB("basic"); /* Minimize clutter and distraction */
1632 const char *zType = PD("y",bBasic?"ci":"all"); /* Type of events. All if NULL */
1633 const char *zAfter = P("a"); /* Events after this time */
1634 const char *zBefore = P("b"); /* Events before this time */
1635 const char *zCirca = P("c"); /* Events near this time */
1636 const char *zMark = P("m"); /* Mark this event or an event this time */
1637 const char *zTagName = P("t"); /* Show events with this tag */
@@ -1732,11 +1761,11 @@
1732 /* For exact maching, inhibit links to the selected tag. */
1733 zThisTag = zTagName;
1734 }
1735
1736 /* Display a checkbox to enable/disable display of related check-ins. */
1737 if( !bBasic ) style_submenu_checkbox("rel", "Related", 0, 0);
1738
1739 /* Construct the tag match expression. */
1740 zTagSql = tagMatchExpression(matchStyle, zTagName, &zMatchDesc, &zError);
1741 }
1742
@@ -1864,13 +1893,11 @@
1864 blob_append(&sql, ")", -1);
1865 path_reset();
1866 addFileGlobExclusion(zChng, &sql);
1867 tmFlags |= TIMELINE_DISJOINT;
1868 db_multi_exec("%s", blob_sql_text(&sql));
1869 if( !bBasic ){
1870 style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
1871 }
1872 blob_appendf(&desc, "%d check-ins going from ",
1873 db_int(0, "SELECT count(*) FROM timeline"));
1874 blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h", zFrom), zFrom);
1875 blob_append(&desc, " to ", -1);
1876 blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo);
@@ -1916,15 +1943,13 @@
1916 if( p_rid ){
1917 /* If both p= and d= are set, we don't have the uuid of d yet. */
1918 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid);
1919 }
1920 }
1921 if( !bBasic ){
1922 style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
1923 style_submenu_entry("n","Max:",4,0);
1924 timeline_y_submenu(1);
1925 }
1926 }else if( f_rid && g.perm.Read ){
1927 /* If f= is present, ignore all other parameters other than n= */
1928 char *zUuid;
1929 db_multi_exec(
1930 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
@@ -1938,14 +1963,12 @@
1938 if( useDividers ) selectedRid = f_rid;
1939 blob_appendf(&desc, "Parents and children of check-in ");
1940 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
1941 blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid);
1942 tmFlags |= TIMELINE_DISJOINT;
1943 if( !bBasic ){
1944 style_submenu_checkbox("unhide", "Unhide", 0, 0);
1945 style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
1946 }
1947 }else{
1948 /* Otherwise, a timeline based on a span of time */
1949 int n;
1950 const char *zEType = "timeline item";
1951 char *zDate;
@@ -2225,34 +2248,29 @@
2225 /* timeline_submenu(&url, "Newer", "a", zDate, "b"); */
2226 zNewerButton = fossil_strdup(url_render(&url, "a", zDate, "b", 0));
2227 }
2228 free(zDate);
2229 }
2230 if( !bBasic ){
2231 if( zType[0]=='a' || zType[0]=='c' ){
2232 style_submenu_checkbox("unhide", "Unhide", 0, 0);
2233 }
2234 style_submenu_checkbox("v", "Files", zType[0]!='a' && zType[0]!='c', 0);
2235 style_submenu_entry("n","Max:",4,0);
2236 timeline_y_submenu(disableY);
2237 style_submenu_entry("t", "Tag Filter:", -8, 0);
2238 style_submenu_multichoice("ms", count(azMatchStyles)/2, azMatchStyles, 0);
2239 }
2240 }
2241 blob_zero(&cond);
2242 }
2243 if( bBasic ){
2244 timeline_submenu(&url, "Details", "basic", 0, 0);
2245 }else{
2246 timeline_submenu(&url, "Declutter", "basic", "1", 0);
2247 }
2248 if( PB("showsql") ){
2249 @ <pre>%h(blob_sql_text(&sql))</pre>
2250 }
2251 if( search_restrict(SRCH_CKIN)!=0 ){
2252 style_submenu_element("Search", "%R/search?y=c");
2253 }
 
 
2254 if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID;
2255 if( useDividers && zMark && zMark[0] ){
2256 double r = symbolic_name_to_mtime(zMark);
2257 if( r>0.0 ) selectedRid = timeline_add_divider(r);
2258 }
@@ -2263,11 +2281,10 @@
2263
2264 /* Report any errors. */
2265 if( zError ){
2266 @ <p class="generalError">%h(zError)</p>
2267 }
2268 if( bBasic ) tmFlags |= TIMELINE_BASIC;
2269
2270 if( zNewerButton ){
2271 @ %z(xhref("class='button'","%z",zNewerButton))More&nbsp;&uarr;</a>
2272 }
2273 www_print_timeline(&q, tmFlags, zThisUser, zThisTag, selectedRid, 0);
2274
--- src/timeline.c
+++ src/timeline.c
@@ -103,11 +103,10 @@
103 #define TIMELINE_UCOLOR 0x0080 /* Background color by user */
104 #define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */
105 #define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */
106 #define TIMELINE_SHOWRID 0x0400 /* Show RID values in addition to UUIDs */
107 #define TIMELINE_BISECT 0x0800 /* Show supplimental bisect information */
 
108 #endif
109
110 /*
111 ** Hash a string and use the hash to determine a background color.
112 */
@@ -265,19 +264,17 @@
264 }
265 zPrevDate[0] = 0;
266 mxWikiLen = db_get_int("timeline-max-comment", 0);
267 dateFormat = db_get_int("timeline-date-format", 0);
268 bCommentGitStyle = db_get_int("timeline-truncate-at-blank", 0);
269 {
 
 
270 /* Undocumented query parameter commentformat=N takes a numeric parameter to
271 ** adjust the comment-format for testing purposes. */
272 const char *z = P("commentformat");
273 eCommentFormat = z ? atoi(z) : db_get_int("timeline-comment-format", 0);
274 }
275 bShowDetail = (eCommentFormat & 1)==0; /* Bit 0 suppresses the comment */
276 bSeparateDetail = (eCommentFormat & 8)!=0; /* Bit 3 turns on the detail column */
277 switch( (eCommentFormat>>1)&3 ){
278 case 1: bHashAfterComment = 1; break;
279 case 2: bHashInDetail = 1; break;
280 default: bHashBeforeComment = 1; break;
@@ -493,15 +490,16 @@
490 }
491 db_column_blob(pQuery, commentColumn, &comment);
492 if( zType[0]!='c' ){
493 /* Comments for anything other than a check-in are generated by
494 ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */
495 @ <span class='timelineComment' onclick='toggleEllipsis(%d(rid))'>
496 wiki_convert(&comment, 0, WIKI_INLINE);
497 @ </span>
498 }else{
499 @ <span class='timelineComment timelineCheckinComment' \
500 @ onclick='toggleEllipsis(%d(rid))'>
501 if( bCommentGitStyle ){
502 /* Truncate comment at first blank line */
503 int ii, jj;
504 int n = blob_size(&comment);
505 char *z = blob_str(&comment);
@@ -510,20 +508,20 @@
508 for(jj=ii+1; jj<n && z[jj]!='\n' && fossil_isspace(z[jj]); jj++){}
509 if( z[jj]=='\n' ) break;
510 }
511 }
512 z[ii] = 0;
513 cgi_printf("%W",z);
514 }else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
515 Blob truncated;
516 blob_zero(&truncated);
517 blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
518 blob_append(&truncated, "...", 3);
519 @ %W(blob_str(&truncated))
520 blob_reset(&truncated);
521 }else{
522 cgi_printf("%W",blob_str(&comment));
523 }
524 @ </span>
525 }
526 blob_reset(&comment);
527
@@ -557,18 +555,21 @@
555
556 /* Generate extra information and hyperlinks to follow the comment.
557 ** Example: "(check-in: [abcdefg], user: drh, tags: trunk)"
558 */
559 if( bShowDetail ){
560 @ <span class='timelineEllipsis anticlutter' id='ellipsis-%d(rid)' \
561 @ onclick='expandEllipsis(%d(rid))'>&#x22ef;</span>
562 if( bSeparateDetail ){
563 if( zBgClr && zBgClr[0] && rid!=selectedRid ){
564 @ <td class="timelineTableCell timelineDetailCell"
565 @ style="background-color: %h(zBgClr);">
566 }else{
567 @ <td class="timelineTableCell timelineDetailCell">
568 }
569 }
570 cgi_printf("<span class='clutter' id='detail-%d'>", rid);
571 if( zType[0]=='c' ){
572 cgi_printf("<span class='timelineDetail timelineCheckinDetail'>(");
573 }else{
574 cgi_printf("<span class='timelineDetail'>(");
575 }
@@ -638,11 +639,11 @@
639 cgi_printf(" id: %d&larr;%d", rid, srcId);
640 }else{
641 cgi_printf(" id: %d", rid);
642 }
643 }
644 cgi_printf(")</span></span>\n"); /* End of the details section */
645 }
646
647 tag_private_status(rid);
648
649 /* Generate extra hyperlinks at the end of the comment */
@@ -814,11 +815,11 @@
815 iRailPitch = atoi(PD("railpitch","0"));
816 showArrowheads = skin_detail_boolean("timeline-arrowheads");
817 circleNodes = skin_detail_boolean("timeline-circle-nodes");
818 colorGraph = skin_detail_boolean("timeline-color-graph-lines");
819
820 @ <script>
821 @ "use strict";
822 @ var css = "";
823 if( circleNodes ){
824 @ css += ".tl-node, .tl-node:after { border-radius: 50%%; }";
825 }
@@ -1141,10 +1142,40 @@
1142 }else{
1143 @ location.href="%R/vdiff?from="+selRow.h+"&to="+p.h+"&sbs=1";
1144 }
1145 }
1146 @ }
1147 @ }
1148 @ function changeDisplay(selector,value){
1149 @ var x = document.getElementsByClassName(selector);
1150 @ var n = x.length;
1151 @ for(var i=0; i<n; i++) {x[i].style.display = value;}
1152 @ }
1153 @ function declutter(){
1154 @ changeDisplay('clutter','none');
1155 @ changeDisplay('anticlutter','inline');
1156 @ checkHeight();
1157 @ }
1158 @ function reclutter(){
1159 @ changeDisplay('clutter','inline');
1160 @ changeDisplay('anticlutter','none');
1161 @ checkHeight();
1162 @ }
1163 @ function toggleEllipsis(id){
1164 @ var x = gebi("ellipsis-"+id);
1165 @ if( x.style.display=='none' ){
1166 @ x.style.display='inline';
1167 @ gebi("detail-"+id).style.display='none';
1168 @ x = document.getElementById("links-"+id);
1169 @ if(x) x.style.display='none';
1170 @ }else{
1171 @ x.style.display='none';
1172 @ gebi("detail-"+id).style.display='inline';
1173 @ x = document.getElementById("links-"+id);
1174 @ if(x) x.style.display='inline';
1175 @ }
1176 @ checkHeight();
1177 @ }
1178 @ var lastRow = gebi("m"+rowinfo[rowinfo.length-1].id);
1179 @ var lastY = 0;
1180 @ function checkHeight(){
1181 @ var h = absoluteY(lastRow);
@@ -1154,11 +1185,11 @@
1185 @ }
1186 @ setTimeout(checkHeight, 1000);
1187 @ }
1188 @ initGraph();
1189 @ checkHeight();
1190 @ </script>
1191 }
1192 }
1193
1194 /*
1195 ** Create a temporary table suitable for storing timeline data.
@@ -1324,11 +1355,11 @@
1355 az[i++] = "Wiki";
1356 }
1357 assert( i<=count(az) );
1358 }
1359 if( i>2 ){
1360 style_submenu_multichoice("y", i/2, az, isDisabled|STYLE_CLUTTER);
1361 }
1362 }
1363
1364 /*
1365 ** If the zChng string is not NULL, then it should be a comma-separated
@@ -1574,11 +1605,10 @@
1605 /*
1606 ** WEBPAGE: timeline
1607 **
1608 ** Query parameters:
1609 **
 
1610 ** a=TIMEORTAG After this event
1611 ** b=TIMEORTAG Before this event
1612 ** c=TIMEORTAG "Circa" this event
1613 ** m=TIMEORTAG Mark this event
1614 ** n=COUNT Suggested number of events in output
@@ -1626,12 +1656,11 @@
1656 int nEntry; /* Max number of entries on timeline */
1657 int p_rid = name_to_typed_rid(P("p"),"ci"); /* artifact p and its parents */
1658 int d_rid = name_to_typed_rid(P("d"),"ci"); /* artifact d and descendants */
1659 int f_rid = name_to_typed_rid(P("f"),"ci"); /* artifact f and close family */
1660 const char *zUser = P("u"); /* All entries by this user if not NULL */
1661 const char *zType = PD("y","all"); /* Type of events. All if NULL */
 
1662 const char *zAfter = P("a"); /* Events after this time */
1663 const char *zBefore = P("b"); /* Events before this time */
1664 const char *zCirca = P("c"); /* Events near this time */
1665 const char *zMark = P("m"); /* Mark this event or an event this time */
1666 const char *zTagName = P("t"); /* Show events with this tag */
@@ -1732,11 +1761,11 @@
1761 /* For exact maching, inhibit links to the selected tag. */
1762 zThisTag = zTagName;
1763 }
1764
1765 /* Display a checkbox to enable/disable display of related check-ins. */
1766 style_submenu_checkbox("rel", "Related", STYLE_CLUTTER, 0);
1767
1768 /* Construct the tag match expression. */
1769 zTagSql = tagMatchExpression(matchStyle, zTagName, &zMatchDesc, &zError);
1770 }
1771
@@ -1864,13 +1893,11 @@
1893 blob_append(&sql, ")", -1);
1894 path_reset();
1895 addFileGlobExclusion(zChng, &sql);
1896 tmFlags |= TIMELINE_DISJOINT;
1897 db_multi_exec("%s", blob_sql_text(&sql));
1898 style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER,0);
 
 
1899 blob_appendf(&desc, "%d check-ins going from ",
1900 db_int(0, "SELECT count(*) FROM timeline"));
1901 blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h", zFrom), zFrom);
1902 blob_append(&desc, " to ", -1);
1903 blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo);
@@ -1916,15 +1943,13 @@
1943 if( p_rid ){
1944 /* If both p= and d= are set, we don't have the uuid of d yet. */
1945 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", d_rid);
1946 }
1947 }
1948 style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER, 0);
1949 style_submenu_entry("n","Max:",4,STYLE_CLUTTER);
1950 timeline_y_submenu(1);
 
 
1951 }else if( f_rid && g.perm.Read ){
1952 /* If f= is present, ignore all other parameters other than n= */
1953 char *zUuid;
1954 db_multi_exec(
1955 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
@@ -1938,14 +1963,12 @@
1963 if( useDividers ) selectedRid = f_rid;
1964 blob_appendf(&desc, "Parents and children of check-in ");
1965 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
1966 blob_appendf(&desc, "%z[%S]</a>", href("%R/info/%!S", zUuid), zUuid);
1967 tmFlags |= TIMELINE_DISJOINT;
1968 style_submenu_checkbox("unhide", "Unhide", STYLE_CLUTTER, 0);
1969 style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER, 0);
 
 
1970 }else{
1971 /* Otherwise, a timeline based on a span of time */
1972 int n;
1973 const char *zEType = "timeline item";
1974 char *zDate;
@@ -2225,34 +2248,29 @@
2248 /* timeline_submenu(&url, "Newer", "a", zDate, "b"); */
2249 zNewerButton = fossil_strdup(url_render(&url, "a", zDate, "b", 0));
2250 }
2251 free(zDate);
2252 }
2253 if( zType[0]=='a' || zType[0]=='c' ){
2254 style_submenu_checkbox("unhide", "Unhide", STYLE_CLUTTER, 0);
2255 }
2256 style_submenu_checkbox("v", "Files", (zType[0]!='a' && zType[0]!='c')|STYLE_CLUTTER,0);
2257 style_submenu_entry("n","Max:",4,STYLE_CLUTTER);
2258 timeline_y_submenu(disableY);
2259 style_submenu_entry("t", "Tag Filter:", -8, STYLE_CLUTTER);
2260 style_submenu_multichoice("ms", count(azMatchStyles)/2, azMatchStyles, STYLE_CLUTTER);
2261 }
2262 blob_zero(&cond);
 
 
 
 
 
 
 
2263 }
2264 if( PB("showsql") ){
2265 @ <pre>%h(blob_sql_text(&sql))</pre>
2266 }
2267 if( search_restrict(SRCH_CKIN)!=0 ){
2268 style_submenu_element("Search", "%R/search?y=c");
2269 }
2270 style_submenu_jsbutton("Advanced", STYLE_BASIC, "reclutter()");
2271 style_submenu_jsbutton("Basic", STYLE_CLUTTER, "declutter()");
2272 if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID;
2273 if( useDividers && zMark && zMark[0] ){
2274 double r = symbolic_name_to_mtime(zMark);
2275 if( r>0.0 ) selectedRid = timeline_add_divider(r);
2276 }
@@ -2263,11 +2281,10 @@
2281
2282 /* Report any errors. */
2283 if( zError ){
2284 @ <p class="generalError">%h(zError)</p>
2285 }
 
2286
2287 if( zNewerButton ){
2288 @ %z(xhref("class='button'","%z",zNewerButton))More&nbsp;&uarr;</a>
2289 }
2290 www_print_timeline(&q, tmFlags, zThisUser, zThisTag, selectedRid, 0);
2291

Keyboard Shortcuts

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