Fossil SCM

Forum post collapse/expand: 1) Is now full width to balance visibility and mobile accessibility. 2) Use arrows (instead of words) to convey intent. 3) When collapsing, scroll the collapser widget to the top of the viewport so that the next post is in view (avoids manual scrolling back up). 4) double-click on a large post toggles expand/collapse (avoids scrolling when expanded).

stephan 2020-07-10 10:02 trunk
Commit a30a6db480ece85773abf8923db91a5b48e3c5fefe7b479b8ddb7d523c73d4d3
+27 -3
--- src/default.css
+++ src/default.css
@@ -773,13 +773,37 @@
773773
div.forumHier > div > form,
774774
div.forumTime > div > form,
775775
div.forumHierRoot > div > form {
776776
margin: 0.5em 0;
777777
}
778
-button.forum-post-collapser {
779
- align-self: flex-start;
780
- margin-top: 0.1em;
778
+.forum-post-collapser {
779
+ font-size: 0.8em;
780
+ margin-top: 0.2em;
781
+ padding: 0;
782
+ height: 1.75em;
783
+ line-height: 1.75em;
784
+ /* ^^^ Those sizes are finely tuned for the current selection of
785
+ arrow characters. If those change, these should, too. Remember that
786
+ FF/Chrome simply do not agree on alignment with most values :/. */
787
+ border-width: 1px;
788
+ border-style: solid;
789
+ border-radius: 0.25em;
790
+ opacity: 0.8;
791
+ cursor: pointer;
792
+ display: flex;
793
+ flex-direction: row;
794
+ justify-content: space-between;
795
+}
796
+.forum-post-collapser > span {
797
+ margin: 0 1em 0 1em;
798
+ vertical-align: middle;
799
+}
800
+.forum-post-collapser.expanded > span::before {
801
+ content: "⇡⇡⇡" /*reminder: FF/Chrome cannot agree on alignment of ⮝*/;
802
+}
803
+.forum-post-collapser:not(.expanded) > span::before {
804
+ content: "⇣⇣⇣";
781805
}
782806
div.forumPostBody{
783807
max-height: 50em;
784808
overflow: auto;
785809
}
786810
--- src/default.css
+++ src/default.css
@@ -773,13 +773,37 @@
773 div.forumHier > div > form,
774 div.forumTime > div > form,
775 div.forumHierRoot > div > form {
776 margin: 0.5em 0;
777 }
778 button.forum-post-collapser {
779 align-self: flex-start;
780 margin-top: 0.1em;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
781 }
782 div.forumPostBody{
783 max-height: 50em;
784 overflow: auto;
785 }
786
--- src/default.css
+++ src/default.css
@@ -773,13 +773,37 @@
773 div.forumHier > div > form,
774 div.forumTime > div > form,
775 div.forumHierRoot > div > form {
776 margin: 0.5em 0;
777 }
778 .forum-post-collapser {
779 font-size: 0.8em;
780 margin-top: 0.2em;
781 padding: 0;
782 height: 1.75em;
783 line-height: 1.75em;
784 /* ^^^ Those sizes are finely tuned for the current selection of
785 arrow characters. If those change, these should, too. Remember that
786 FF/Chrome simply do not agree on alignment with most values :/. */
787 border-width: 1px;
788 border-style: solid;
789 border-radius: 0.25em;
790 opacity: 0.8;
791 cursor: pointer;
792 display: flex;
793 flex-direction: row;
794 justify-content: space-between;
795 }
796 .forum-post-collapser > span {
797 margin: 0 1em 0 1em;
798 vertical-align: middle;
799 }
800 .forum-post-collapser.expanded > span::before {
801 content: "⇡⇡⇡" /*reminder: FF/Chrome cannot agree on alignment of ⮝*/;
802 }
803 .forum-post-collapser:not(.expanded) > span::before {
804 content: "⇣⇣⇣";
805 }
806 div.forumPostBody{
807 max-height: 50em;
808 overflow: auto;
809 }
810
--- src/fossil.page.forumpost.js
+++ src/fossil.page.forumpost.js
@@ -3,60 +3,49 @@
33
/* JS code for /forumpage and friends. Requires fossil.dom. */
44
const P = fossil.page, D = fossil.dom;
55
66
F.onPageLoad(function(){
77
const scrollbarIsVisible = (e)=>e.scrollHeight > e.clientHeight;
8
- const getButtonHandler = function(btn, contentElem){
8
+ /* Returns an event handler which implements the post expand/collapse toggle
9
+ on contentElem when the given widget is activated. */
10
+ const getWidgetHandler = function(widget, contentElem){
911
return function(ev){
1012
if(ev) ev.preventDefault();
11
- const isExpanded = D.hasClass(contentElem,'expanded');
12
- btn.innerText = isExpanded ? 'Expand...' : 'Collapse';
13
+ const wasExpanded = widget.classList.contains('expanded');
14
+ widget.classList.toggle('expanded');
1315
contentElem.classList.toggle('expanded');
16
+ if(wasExpanded) widget.scrollIntoView();
1417
return false;
1518
};
1619
};
17
- /** Install an event handler on element e which calls the given
18
- callback if the user presses the element for a brief period
19
- (time is defined a few lines down from here). */
20
- const addLongpressHandler = function(e, callback){
21
- const longPressTime = 650 /*ms*/;
22
- var timer;
23
- const clearTimer = function(){
24
- if(timer){
25
- clearTimeout(timer);
26
- timer = undefined;
27
- }
28
- };
29
- e.addEventListener('mousedown', function(ev){
30
- timer = setTimeout(function(){
31
- clearTimer();
32
- callback();
33
- }, longPressTime);
34
- }, false);
35
- e.addEventListener('mouseup', clearTimer, false);
36
- e.addEventListener('mouseout', clearTimer, false);
37
- };
3820
/* Adds an Expand/Collapse toggle to all div.forumPostBody
3921
elements which are deemed "too large" (those for which
4022
scrolling is currently activated because they are taller than
4123
their max-height). */
4224
document.querySelectorAll(
4325
'div.forumHier, div.forumTime, div.forumHierRoot'
4426
).forEach(function(forumPostWrapper){
4527
const content = forumPostWrapper.querySelector('div.forumPostBody');
4628
if(!content || !scrollbarIsVisible(content)) return;
47
- const button = D.button('Expand...'),
48
- btnEventHandler = getButtonHandler(button, content);
49
- button.classList.add('forum-post-collapser');
50
- button.addEventListener('click', btnEventHandler, false);
29
+ const widget = D.div(),
30
+ widgetEventHandler = getWidgetHandler(widget, content);
31
+ widget.classList.add('forum-post-collapser');
32
+ widget.addEventListener('click', widgetEventHandler, false);
33
+ /** Append 3 children, which CSS will evenly space across the
34
+ widget. This improves visibility over having the label
35
+ in only the left, right, or center. */
36
+ var i = 0;
37
+ for( ; i < 3; ++i ) D.append(widget, D.span());
5138
if(content.nextSibling){
52
- forumPostWrapper.insertBefore(button, content.nextSibling);
39
+ forumPostWrapper.insertBefore(widget, content.nextSibling);
5340
}else{
54
- forumPostWrapper.appendChild(button);
41
+ forumPostWrapper.appendChild(widget);
5542
}
56
- // uncomment to enable long-press expand/collapse toggle:
57
- // addLongpressHandler(content, btnEventHandler);
58
- // It may interfere with default actions on mobile platforms, though.
43
+ /** A double-click toggle will select "the current word" on the
44
+ post, which is minorly annoying but otherwise harmless. Such
45
+ a toggle has proven convenient on "excessive" posts,
46
+ though. */
47
+ content.addEventListener('dblclick', widgetEventHandler);
5948
});
6049
})/*onload callback*/;
6150
6251
})(window.fossil);
6352
--- src/fossil.page.forumpost.js
+++ src/fossil.page.forumpost.js
@@ -3,60 +3,49 @@
3 /* JS code for /forumpage and friends. Requires fossil.dom. */
4 const P = fossil.page, D = fossil.dom;
5
6 F.onPageLoad(function(){
7 const scrollbarIsVisible = (e)=>e.scrollHeight > e.clientHeight;
8 const getButtonHandler = function(btn, contentElem){
 
 
9 return function(ev){
10 if(ev) ev.preventDefault();
11 const isExpanded = D.hasClass(contentElem,'expanded');
12 btn.innerText = isExpanded ? 'Expand...' : 'Collapse';
13 contentElem.classList.toggle('expanded');
 
14 return false;
15 };
16 };
17 /** Install an event handler on element e which calls the given
18 callback if the user presses the element for a brief period
19 (time is defined a few lines down from here). */
20 const addLongpressHandler = function(e, callback){
21 const longPressTime = 650 /*ms*/;
22 var timer;
23 const clearTimer = function(){
24 if(timer){
25 clearTimeout(timer);
26 timer = undefined;
27 }
28 };
29 e.addEventListener('mousedown', function(ev){
30 timer = setTimeout(function(){
31 clearTimer();
32 callback();
33 }, longPressTime);
34 }, false);
35 e.addEventListener('mouseup', clearTimer, false);
36 e.addEventListener('mouseout', clearTimer, false);
37 };
38 /* Adds an Expand/Collapse toggle to all div.forumPostBody
39 elements which are deemed "too large" (those for which
40 scrolling is currently activated because they are taller than
41 their max-height). */
42 document.querySelectorAll(
43 'div.forumHier, div.forumTime, div.forumHierRoot'
44 ).forEach(function(forumPostWrapper){
45 const content = forumPostWrapper.querySelector('div.forumPostBody');
46 if(!content || !scrollbarIsVisible(content)) return;
47 const button = D.button('Expand...'),
48 btnEventHandler = getButtonHandler(button, content);
49 button.classList.add('forum-post-collapser');
50 button.addEventListener('click', btnEventHandler, false);
 
 
 
 
 
51 if(content.nextSibling){
52 forumPostWrapper.insertBefore(button, content.nextSibling);
53 }else{
54 forumPostWrapper.appendChild(button);
55 }
56 // uncomment to enable long-press expand/collapse toggle:
57 // addLongpressHandler(content, btnEventHandler);
58 // It may interfere with default actions on mobile platforms, though.
 
 
59 });
60 })/*onload callback*/;
61
62 })(window.fossil);
63
--- src/fossil.page.forumpost.js
+++ src/fossil.page.forumpost.js
@@ -3,60 +3,49 @@
3 /* JS code for /forumpage and friends. Requires fossil.dom. */
4 const P = fossil.page, D = fossil.dom;
5
6 F.onPageLoad(function(){
7 const scrollbarIsVisible = (e)=>e.scrollHeight > e.clientHeight;
8 /* Returns an event handler which implements the post expand/collapse toggle
9 on contentElem when the given widget is activated. */
10 const getWidgetHandler = function(widget, contentElem){
11 return function(ev){
12 if(ev) ev.preventDefault();
13 const wasExpanded = widget.classList.contains('expanded');
14 widget.classList.toggle('expanded');
15 contentElem.classList.toggle('expanded');
16 if(wasExpanded) widget.scrollIntoView();
17 return false;
18 };
19 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20 /* Adds an Expand/Collapse toggle to all div.forumPostBody
21 elements which are deemed "too large" (those for which
22 scrolling is currently activated because they are taller than
23 their max-height). */
24 document.querySelectorAll(
25 'div.forumHier, div.forumTime, div.forumHierRoot'
26 ).forEach(function(forumPostWrapper){
27 const content = forumPostWrapper.querySelector('div.forumPostBody');
28 if(!content || !scrollbarIsVisible(content)) return;
29 const widget = D.div(),
30 widgetEventHandler = getWidgetHandler(widget, content);
31 widget.classList.add('forum-post-collapser');
32 widget.addEventListener('click', widgetEventHandler, false);
33 /** Append 3 children, which CSS will evenly space across the
34 widget. This improves visibility over having the label
35 in only the left, right, or center. */
36 var i = 0;
37 for( ; i < 3; ++i ) D.append(widget, D.span());
38 if(content.nextSibling){
39 forumPostWrapper.insertBefore(widget, content.nextSibling);
40 }else{
41 forumPostWrapper.appendChild(widget);
42 }
43 /** A double-click toggle will select "the current word" on the
44 post, which is minorly annoying but otherwise harmless. Such
45 a toggle has proven convenient on "excessive" posts,
46 though. */
47 content.addEventListener('dblclick', widgetEventHandler);
48 });
49 })/*onload callback*/;
50
51 })(window.fossil);
52

Keyboard Shortcuts

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