Fossil SCM

Enable customization of the hamburger menu through the default skin header.txt.

florian 2018-10-11 16:36 UTC js-hamburger-menu
Commit 497dbb356fcc0363457e25c077ea3893aae328fd
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -17,11 +17,11 @@
1717
html "<a href='$home$url' class='active $cls'>$name</a>\n"
1818
} else {
1919
html "<a href='$home$url' class='$cls'>$name</a>\n"
2020
}
2121
}
22
-html "<a href='#'>&#9776;</a>"
22
+html "<a id='hbbtn' href='#'>&#9776;</a>"
2323
menulink $index_page Home {}
2424
if {[anycap jor]} {
2525
menulink /timeline Timeline {}
2626
}
2727
if {[hascap oh]} {
2828
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -17,11 +17,11 @@
17 html "<a href='$home$url' class='active $cls'>$name</a>\n"
18 } else {
19 html "<a href='$home$url' class='$cls'>$name</a>\n"
20 }
21 }
22 html "<a href='#'>&#9776;</a>"
23 menulink $index_page Home {}
24 if {[anycap jor]} {
25 menulink /timeline Timeline {}
26 }
27 if {[hascap oh]} {
28
--- skins/default/header.txt
+++ skins/default/header.txt
@@ -17,11 +17,11 @@
17 html "<a href='$home$url' class='active $cls'>$name</a>\n"
18 } else {
19 html "<a href='$home$url' class='$cls'>$name</a>\n"
20 }
21 }
22 html "<a id='hbbtn' href='#'>&#9776;</a>"
23 menulink $index_page Home {}
24 if {[anycap jor]} {
25 menulink /timeline Timeline {}
26 }
27 if {[hascap oh]} {
28
--- skins/default/js.txt
+++ skins/default/js.txt
@@ -16,27 +16,37 @@
1616
** This file contains the JS code specific to the Fossil default skin.
1717
** Currently, the only thing this does is handle clicks on its hamburger
1818
** menu button.
1919
*/
2020
(function() {
21
+ if (!document.getElementById("hbbtn")) return; // no hamburger button
2122
var panel = document.getElementById("hbdrop");
2223
if (!panel) return; // site admin might've nuked it
2324
if (!panel.style) return; // shouldn't happen, but be sure
2425
var panelBorder = panel.style.border;
26
+ var panelInitialized = false; // track first panel display
2527
2628
// Disable animation if this browser doesn't support CSS transitions.
2729
//
2830
// We need this ugly calling form for old browsers that don't allow
2931
// panel.style.hasOwnProperty('transition'); catering to old browsers
3032
// is the whole point here.
3133
var animate = panel.style.transition !== null && (typeof(panel.style.transition) == "string");
32
- var animMS = 400;
34
+
35
+ // The duration of the animation can be overridden from the default skin
36
+ // header.txt by setting the "data-anim-ms" attribute of the panel.
37
+ var animMS = panel.getAttribute("data-anim-ms");
38
+ if (animMS === "0")
39
+ animate = false; // disable animation if "data-anim-ms" === "0"
40
+ else if (!animMS || animMS>>0 !== Number(animMS) || animMS < 0)
41
+ animMS = 400; // set default if missing, empty, non-integer, or negative
42
+
3343
var originalEventHandlers = { }; // original event handlers to be restored
3444
3545
// Calculate panel height despite its being hidden at call time.
3646
// Based on https://stackoverflow.com/a/29047447/142454
37
- var panelHeight; // computed on sitemap load
47
+ var panelHeight; // computed on first panel display
3848
function calculatePanelHeight() {
3949
// Get initial panel styles so we can restore them below.
4050
var es = window.getComputedStyle(panel),
4151
edis = es.display,
4252
epos = es.position,
@@ -64,18 +74,27 @@
6474
// change as a state transition, so it'd skip the CSS transition:
6575
//
6676
// https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions#JavaScript_examples
6777
function showPanel() {
6878
if (animate) {
79
+ if (!panelInitialized) {
80
+ panelInitialized = true;
81
+ // Set up a CSS transition to animate the panel open and
82
+ // closed. Only needs to be done once per page load.
83
+ // Based on https://stackoverflow.com/a/29047447/142454
84
+ calculatePanelHeight();
85
+ panel.style.transition = 'max-height ' + animMS +
86
+ 'ms ease-in-out';
87
+ panel.style.overflowY = 'hidden';
88
+ panel.style.maxHeight = '0';
89
+ }
6990
setTimeout(function() {
7091
panel.style.maxHeight = panelHeight;
7192
panel.style.border = panelBorder;
7293
}, 40); // 25ms is insufficient with Firefox 62
7394
}
74
- else {
75
- panel.style.display = 'block';
76
- }
95
+ panel.style.display = 'block';
7796
originalEventHandlers.onkeydown = document.onkeydown;
7897
document.onkeydown = function(event) {
7998
event = event || window.event;
8099
var key = event.which || event.keyCode;
81100
if (key == 27) {
@@ -99,14 +118,25 @@
99118
}
100119
else {
101120
return panel.style.display == 'block';
102121
}
103122
}
123
+
124
+ // Check if the specified HTML element has any child elements. Note that plain
125
+ // text nodes, comments, and any spaces (presentational or not) are ignored.
126
+ function hasChildren(element) {
127
+ var childElement = element.firstChild;
128
+ while (childElement) {
129
+ if (childElement.nodeType == 1) // Node.ELEMENT_NODE == 1
130
+ return true;
131
+ childElement = childElement.nextSibling;
132
+ }
133
+ return false;
134
+ }
104135
105136
// Click handler for the hamburger button.
106
- var needSitemapHTML = true;
107
- document.querySelector("div.mainmenu > a").onclick = function(event) {
137
+ document.getElementById("hbbtn").onclick = function(event) {
108138
// Break the event handler chain, or the handler for document.onclick
109139
// (about to be installed) may already be triggered by the current event.
110140
if (event.stopPropagation)
111141
event.stopPropagation();
112142
else
@@ -142,44 +172,33 @@
142172
}
143173
else {
144174
panel.style.display = 'none';
145175
}
146176
}
147
- else if (needSitemapHTML) {
148
- // Only get it once per page load: it isn't likely to
149
- // change on us.
150
- var xhr = new XMLHttpRequest();
151
- xhr.onload = function() {
152
- var doc = xhr.responseXML;
153
- if (doc) {
154
- var sm = doc.querySelector("ul#sitemap");
155
- if (sm && xhr.status == 200) {
156
- // Got sitemap. Insert it into the drop-down panel.
157
- needSitemapHTML = false;
158
- panel.innerHTML = sm.outerHTML;
159
-
160
- // Display the panel
161
- if (animate) {
162
- // Set up a CSS transition to animate the panel open and
163
- // closed. Only needs to be done once per page load.
164
- // Based on https://stackoverflow.com/a/29047447/142454
165
- calculatePanelHeight();
166
- panel.style.transition = 'max-height ' + animMS +
167
- 'ms ease-in-out';
168
- panel.style.overflowY = 'hidden';
169
- panel.style.maxHeight = '0';
177
+ else {
178
+ if (!hasChildren(panel)) {
179
+ // Only get the sitemap once per page load: it isn't likely to
180
+ // change on us.
181
+ var xhr = new XMLHttpRequest();
182
+ xhr.onload = function() {
183
+ var doc = xhr.responseXML;
184
+ if (doc) {
185
+ var sm = doc.querySelector("ul#sitemap");
186
+ if (sm && xhr.status == 200) {
187
+ // Got sitemap. Insert it into the drop-down panel.
188
+ panel.innerHTML = sm.outerHTML;
189
+ // Display the panel
170190
showPanel();
171191
}
172
- panel.style.display = 'block';
173
- }
174
- }
175
- // else, can't parse response as HTML or XML
176
- }
177
- xhr.open("GET", "$home/sitemap?popup"); // note the TH1 substitution!
178
- xhr.responseType = "document";
179
- xhr.send();
180
- }
181
- else {
182
- showPanel(); // just show what we built above
192
+ }
193
+ // else, can't parse response as HTML or XML
194
+ }
195
+ xhr.open("GET", "$home/sitemap?popup"); // note the TH1 substitution!
196
+ xhr.responseType = "document";
197
+ xhr.send();
198
+ }
199
+ else {
200
+ showPanel(); // just show what we built above
201
+ }
183202
}
184203
}
185204
})();
186205
--- skins/default/js.txt
+++ skins/default/js.txt
@@ -16,27 +16,37 @@
16 ** This file contains the JS code specific to the Fossil default skin.
17 ** Currently, the only thing this does is handle clicks on its hamburger
18 ** menu button.
19 */
20 (function() {
 
21 var panel = document.getElementById("hbdrop");
22 if (!panel) return; // site admin might've nuked it
23 if (!panel.style) return; // shouldn't happen, but be sure
24 var panelBorder = panel.style.border;
 
25
26 // Disable animation if this browser doesn't support CSS transitions.
27 //
28 // We need this ugly calling form for old browsers that don't allow
29 // panel.style.hasOwnProperty('transition'); catering to old browsers
30 // is the whole point here.
31 var animate = panel.style.transition !== null && (typeof(panel.style.transition) == "string");
32 var animMS = 400;
 
 
 
 
 
 
 
 
33 var originalEventHandlers = { }; // original event handlers to be restored
34
35 // Calculate panel height despite its being hidden at call time.
36 // Based on https://stackoverflow.com/a/29047447/142454
37 var panelHeight; // computed on sitemap load
38 function calculatePanelHeight() {
39 // Get initial panel styles so we can restore them below.
40 var es = window.getComputedStyle(panel),
41 edis = es.display,
42 epos = es.position,
@@ -64,18 +74,27 @@
64 // change as a state transition, so it'd skip the CSS transition:
65 //
66 // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions#JavaScript_examples
67 function showPanel() {
68 if (animate) {
 
 
 
 
 
 
 
 
 
 
 
69 setTimeout(function() {
70 panel.style.maxHeight = panelHeight;
71 panel.style.border = panelBorder;
72 }, 40); // 25ms is insufficient with Firefox 62
73 }
74 else {
75 panel.style.display = 'block';
76 }
77 originalEventHandlers.onkeydown = document.onkeydown;
78 document.onkeydown = function(event) {
79 event = event || window.event;
80 var key = event.which || event.keyCode;
81 if (key == 27) {
@@ -99,14 +118,25 @@
99 }
100 else {
101 return panel.style.display == 'block';
102 }
103 }
 
 
 
 
 
 
 
 
 
 
 
 
104
105 // Click handler for the hamburger button.
106 var needSitemapHTML = true;
107 document.querySelector("div.mainmenu > a").onclick = function(event) {
108 // Break the event handler chain, or the handler for document.onclick
109 // (about to be installed) may already be triggered by the current event.
110 if (event.stopPropagation)
111 event.stopPropagation();
112 else
@@ -142,44 +172,33 @@
142 }
143 else {
144 panel.style.display = 'none';
145 }
146 }
147 else if (needSitemapHTML) {
148 // Only get it once per page load: it isn't likely to
149 // change on us.
150 var xhr = new XMLHttpRequest();
151 xhr.onload = function() {
152 var doc = xhr.responseXML;
153 if (doc) {
154 var sm = doc.querySelector("ul#sitemap");
155 if (sm && xhr.status == 200) {
156 // Got sitemap. Insert it into the drop-down panel.
157 needSitemapHTML = false;
158 panel.innerHTML = sm.outerHTML;
159
160 // Display the panel
161 if (animate) {
162 // Set up a CSS transition to animate the panel open and
163 // closed. Only needs to be done once per page load.
164 // Based on https://stackoverflow.com/a/29047447/142454
165 calculatePanelHeight();
166 panel.style.transition = 'max-height ' + animMS +
167 'ms ease-in-out';
168 panel.style.overflowY = 'hidden';
169 panel.style.maxHeight = '0';
170 showPanel();
171 }
172 panel.style.display = 'block';
173 }
174 }
175 // else, can't parse response as HTML or XML
176 }
177 xhr.open("GET", "$home/sitemap?popup"); // note the TH1 substitution!
178 xhr.responseType = "document";
179 xhr.send();
180 }
181 else {
182 showPanel(); // just show what we built above
183 }
184 }
185 })();
186
--- skins/default/js.txt
+++ skins/default/js.txt
@@ -16,27 +16,37 @@
16 ** This file contains the JS code specific to the Fossil default skin.
17 ** Currently, the only thing this does is handle clicks on its hamburger
18 ** menu button.
19 */
20 (function() {
21 if (!document.getElementById("hbbtn")) return; // no hamburger button
22 var panel = document.getElementById("hbdrop");
23 if (!panel) return; // site admin might've nuked it
24 if (!panel.style) return; // shouldn't happen, but be sure
25 var panelBorder = panel.style.border;
26 var panelInitialized = false; // track first panel display
27
28 // Disable animation if this browser doesn't support CSS transitions.
29 //
30 // We need this ugly calling form for old browsers that don't allow
31 // panel.style.hasOwnProperty('transition'); catering to old browsers
32 // is the whole point here.
33 var animate = panel.style.transition !== null && (typeof(panel.style.transition) == "string");
34
35 // The duration of the animation can be overridden from the default skin
36 // header.txt by setting the "data-anim-ms" attribute of the panel.
37 var animMS = panel.getAttribute("data-anim-ms");
38 if (animMS === "0")
39 animate = false; // disable animation if "data-anim-ms" === "0"
40 else if (!animMS || animMS>>0 !== Number(animMS) || animMS < 0)
41 animMS = 400; // set default if missing, empty, non-integer, or negative
42
43 var originalEventHandlers = { }; // original event handlers to be restored
44
45 // Calculate panel height despite its being hidden at call time.
46 // Based on https://stackoverflow.com/a/29047447/142454
47 var panelHeight; // computed on first panel display
48 function calculatePanelHeight() {
49 // Get initial panel styles so we can restore them below.
50 var es = window.getComputedStyle(panel),
51 edis = es.display,
52 epos = es.position,
@@ -64,18 +74,27 @@
74 // change as a state transition, so it'd skip the CSS transition:
75 //
76 // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions#JavaScript_examples
77 function showPanel() {
78 if (animate) {
79 if (!panelInitialized) {
80 panelInitialized = true;
81 // Set up a CSS transition to animate the panel open and
82 // closed. Only needs to be done once per page load.
83 // Based on https://stackoverflow.com/a/29047447/142454
84 calculatePanelHeight();
85 panel.style.transition = 'max-height ' + animMS +
86 'ms ease-in-out';
87 panel.style.overflowY = 'hidden';
88 panel.style.maxHeight = '0';
89 }
90 setTimeout(function() {
91 panel.style.maxHeight = panelHeight;
92 panel.style.border = panelBorder;
93 }, 40); // 25ms is insufficient with Firefox 62
94 }
95 panel.style.display = 'block';
 
 
96 originalEventHandlers.onkeydown = document.onkeydown;
97 document.onkeydown = function(event) {
98 event = event || window.event;
99 var key = event.which || event.keyCode;
100 if (key == 27) {
@@ -99,14 +118,25 @@
118 }
119 else {
120 return panel.style.display == 'block';
121 }
122 }
123
124 // Check if the specified HTML element has any child elements. Note that plain
125 // text nodes, comments, and any spaces (presentational or not) are ignored.
126 function hasChildren(element) {
127 var childElement = element.firstChild;
128 while (childElement) {
129 if (childElement.nodeType == 1) // Node.ELEMENT_NODE == 1
130 return true;
131 childElement = childElement.nextSibling;
132 }
133 return false;
134 }
135
136 // Click handler for the hamburger button.
137 document.getElementById("hbbtn").onclick = function(event) {
 
138 // Break the event handler chain, or the handler for document.onclick
139 // (about to be installed) may already be triggered by the current event.
140 if (event.stopPropagation)
141 event.stopPropagation();
142 else
@@ -142,44 +172,33 @@
172 }
173 else {
174 panel.style.display = 'none';
175 }
176 }
177 else {
178 if (!hasChildren(panel)) {
179 // Only get the sitemap once per page load: it isn't likely to
180 // change on us.
181 var xhr = new XMLHttpRequest();
182 xhr.onload = function() {
183 var doc = xhr.responseXML;
184 if (doc) {
185 var sm = doc.querySelector("ul#sitemap");
186 if (sm && xhr.status == 200) {
187 // Got sitemap. Insert it into the drop-down panel.
188 panel.innerHTML = sm.outerHTML;
189 // Display the panel
 
 
 
 
 
 
 
 
 
 
190 showPanel();
191 }
192 }
193 // else, can't parse response as HTML or XML
194 }
195 xhr.open("GET", "$home/sitemap?popup"); // note the TH1 substitution!
196 xhr.responseType = "document";
197 xhr.send();
198 }
199 else {
200 showPanel(); // just show what we built above
201 }
 
202 }
203 }
204 })();
205
--- www/customskin.md
+++ www/customskin.md
@@ -1,16 +1,16 @@
11
Theming
22
=======
33
44
Every HTML page generated by Fossil has the following basic structure:
55
6
-
76
<blockquote><table border=1 cellpadding=10><tbody>
87
<tr><td style='background-color:lightblue;text-align:center;'>Header</td></tr>
98
<tr><td style='background-color:lightgreen;text-align:center;'>
109
Fossil-Generated Content</td></tr>
1110
<tr><td style='background-color:lightblue;text-align:center;'>Footer</td></tr>
11
+<tr><td style='background-color:lightyellow;text-align:center;'>Javascript (optional)</td></tr>
1212
</tbody></table></blockquote>
1313
1414
The header and footer control the "look" of Fossil pages. Those
1515
two sections can be customized separately for each repository to
1616
develop a new theme.
@@ -134,10 +134,69 @@
134134
135135
The same TH1 interpreter is used for both the header and the footer
136136
and for all scripts contained within them both. Hence, any global
137137
TH1 variables that are set by the header are available to the footer.
138138
139
+Customizing the ≡ Hamburger Menu
140
+--------------------------------
141
+
142
+The menu bar of the default skin has an entry to open a drop-down menu with
143
+additional navigation links, represented by the ≡ button (hence the name
144
+"hamburger menu"). The Javascript logic to open and close the hamburger menu
145
+when the button is clicked is contained in the optional Javascript part (js.txt)
146
+of the default skin. Out of the box, the drop-down menu shows the [Site
147
+Map](../../../sitemap), loaded by an AJAX request prior to the first display.
148
+
149
+The ≡ button for the hamburger menu is added to the menu bar by the following
150
+TH1 command in the default skin header.txt, right before the menu bar links:
151
+
152
+ html "<a id='hbbtn' href='#'>&#9776;</a>"
153
+
154
+The hamburger button can be repositioned between the other menu links (but the
155
+drop-down menu is always left-aligned with the menu bar), or it can be removed
156
+by deleting the above statement (the Javascript logic detects this case and
157
+remains idle, so it's not necessary to modify the default skin js.txt).
158
+
159
+The following empty element at the bottom of the default skin header.txt serves
160
+as the panel to hold the drop-down menu elements:
161
+
162
+ <div id='hbdrop'></div>
163
+
164
+Out of the box, the contents of the panel is populated with the [Site
165
+Map](../../../sitemap), but only if the panel does not already contain any HTML
166
+elements (that is, not just comments, plain text or non-presentational white
167
+space). So the hamburger menu can be customized by replacing the empty `<div
168
+id='hbdrop'></div>` element with a menu structure knitted according to the
169
+following template:
170
+
171
+ <div id="hbdrop" data-anim-ms="400">
172
+ <ul class="columns" style="column-width: 20em; column-count: auto">
173
+ <!-- NEW GROUP WITH HEADING LINK -->
174
+ <li>
175
+ <a href="$home$index_page">Link: Home</a>
176
+ <ul>
177
+ <li><a href="$home/timeline">Link: Timeline</a></li>
178
+ <li><a href="$home/dir?ci=tip">Link: File List</a></li>
179
+ </ul>
180
+ </li>
181
+ <!-- NEW GROUP WITH HEADING TEXT -->
182
+ <li>
183
+ Heading Text
184
+ <ul>
185
+ <li><a href="$home/doc/trunk/www/customskin.md">Link: Theming</a></li>
186
+ <li><a href="$home/doc/trunk/www/th1.md">Link: TH1 Scripts</a></li>
187
+ </ul>
188
+ </li>
189
+ <!-- NEXT GROUP GOES HERE -->
190
+ </ul>
191
+ </div>
192
+
193
+The custom `data-anim-ms` attribute can be added to the panel element to direct
194
+the Javascript logic to override the default menu animation duration of 400 ms.
195
+A faster animation duration of 80-200 ms may be preferred for smaller menus. The
196
+animation is disabled by setting the attribute to `"0"`.
197
+
139198
TH1 Variables
140199
-------------
141200
142201
Before expanding the TH1 within the header and footer, Fossil first
143202
initializes a number of TH1 variables to values that depend on
144203
--- www/customskin.md
+++ www/customskin.md
@@ -1,16 +1,16 @@
1 Theming
2 =======
3
4 Every HTML page generated by Fossil has the following basic structure:
5
6
7 <blockquote><table border=1 cellpadding=10><tbody>
8 <tr><td style='background-color:lightblue;text-align:center;'>Header</td></tr>
9 <tr><td style='background-color:lightgreen;text-align:center;'>
10 Fossil-Generated Content</td></tr>
11 <tr><td style='background-color:lightblue;text-align:center;'>Footer</td></tr>
 
12 </tbody></table></blockquote>
13
14 The header and footer control the "look" of Fossil pages. Those
15 two sections can be customized separately for each repository to
16 develop a new theme.
@@ -134,10 +134,69 @@
134
135 The same TH1 interpreter is used for both the header and the footer
136 and for all scripts contained within them both. Hence, any global
137 TH1 variables that are set by the header are available to the footer.
138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139 TH1 Variables
140 -------------
141
142 Before expanding the TH1 within the header and footer, Fossil first
143 initializes a number of TH1 variables to values that depend on
144
--- www/customskin.md
+++ www/customskin.md
@@ -1,16 +1,16 @@
1 Theming
2 =======
3
4 Every HTML page generated by Fossil has the following basic structure:
5
 
6 <blockquote><table border=1 cellpadding=10><tbody>
7 <tr><td style='background-color:lightblue;text-align:center;'>Header</td></tr>
8 <tr><td style='background-color:lightgreen;text-align:center;'>
9 Fossil-Generated Content</td></tr>
10 <tr><td style='background-color:lightblue;text-align:center;'>Footer</td></tr>
11 <tr><td style='background-color:lightyellow;text-align:center;'>Javascript (optional)</td></tr>
12 </tbody></table></blockquote>
13
14 The header and footer control the "look" of Fossil pages. Those
15 two sections can be customized separately for each repository to
16 develop a new theme.
@@ -134,10 +134,69 @@
134
135 The same TH1 interpreter is used for both the header and the footer
136 and for all scripts contained within them both. Hence, any global
137 TH1 variables that are set by the header are available to the footer.
138
139 Customizing the ≡ Hamburger Menu
140 --------------------------------
141
142 The menu bar of the default skin has an entry to open a drop-down menu with
143 additional navigation links, represented by the ≡ button (hence the name
144 "hamburger menu"). The Javascript logic to open and close the hamburger menu
145 when the button is clicked is contained in the optional Javascript part (js.txt)
146 of the default skin. Out of the box, the drop-down menu shows the [Site
147 Map](../../../sitemap), loaded by an AJAX request prior to the first display.
148
149 The ≡ button for the hamburger menu is added to the menu bar by the following
150 TH1 command in the default skin header.txt, right before the menu bar links:
151
152 html "<a id='hbbtn' href='#'>&#9776;</a>"
153
154 The hamburger button can be repositioned between the other menu links (but the
155 drop-down menu is always left-aligned with the menu bar), or it can be removed
156 by deleting the above statement (the Javascript logic detects this case and
157 remains idle, so it's not necessary to modify the default skin js.txt).
158
159 The following empty element at the bottom of the default skin header.txt serves
160 as the panel to hold the drop-down menu elements:
161
162 <div id='hbdrop'></div>
163
164 Out of the box, the contents of the panel is populated with the [Site
165 Map](../../../sitemap), but only if the panel does not already contain any HTML
166 elements (that is, not just comments, plain text or non-presentational white
167 space). So the hamburger menu can be customized by replacing the empty `<div
168 id='hbdrop'></div>` element with a menu structure knitted according to the
169 following template:
170
171 <div id="hbdrop" data-anim-ms="400">
172 <ul class="columns" style="column-width: 20em; column-count: auto">
173 <!-- NEW GROUP WITH HEADING LINK -->
174 <li>
175 <a href="$home$index_page">Link: Home</a>
176 <ul>
177 <li><a href="$home/timeline">Link: Timeline</a></li>
178 <li><a href="$home/dir?ci=tip">Link: File List</a></li>
179 </ul>
180 </li>
181 <!-- NEW GROUP WITH HEADING TEXT -->
182 <li>
183 Heading Text
184 <ul>
185 <li><a href="$home/doc/trunk/www/customskin.md">Link: Theming</a></li>
186 <li><a href="$home/doc/trunk/www/th1.md">Link: TH1 Scripts</a></li>
187 </ul>
188 </li>
189 <!-- NEXT GROUP GOES HERE -->
190 </ul>
191 </div>
192
193 The custom `data-anim-ms` attribute can be added to the panel element to direct
194 the Javascript logic to override the default menu animation duration of 400 ms.
195 A faster animation duration of 80-200 ms may be preferred for smaller menus. The
196 animation is disabled by setting the attribute to `"0"`.
197
198 TH1 Variables
199 -------------
200
201 Before expanding the TH1 within the header and footer, Fossil first
202 initializes a number of TH1 variables to values that depend on
203

Keyboard Shortcuts

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