rdoc-babel 1.2.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY.rdoc +15 -0
- data/README.rdoc +17 -16
- data/lib/rdoc/generator/babel.rb +82 -15
- data/lib/rdoc/generator/ruby-lang/class-page.html.erb +15 -9
- data/lib/rdoc/generator/ruby-lang/file-page.html.erb +8 -3
- data/lib/rdoc/generator/ruby-lang/images/close_black_18dp.svg +1 -0
- data/lib/rdoc/generator/ruby-lang/images/menu_black_18dp.svg +1 -0
- data/lib/rdoc/generator/ruby-lang/index.html.erb +2 -7
- data/lib/rdoc/generator/ruby-lang/indexes.html.erb +1 -1
- data/lib/rdoc/generator/ruby-lang/rdoc.css +182 -29
- data/lib/rdoc/generator/ruby-lang/scripts/indexFrame.js +183 -32
- data/lib/rdoc/generator/ruby-lang/scripts/mainFrame.js +202 -33
- data/lib/rdoc/generator/ruby-lang/scripts/quicksearch.js +12 -6
- metadata +6 -4
@@ -1,5 +1,12 @@
|
|
1
|
+
/*
|
2
|
+
Script for the left iframe.
|
3
|
+
*/
|
1
4
|
|
2
|
-
|
5
|
+
// CSS must be loaded before finding the geography of indexes
|
6
|
+
// document.addEventListener('DOMContentLoaded', function () {
|
7
|
+
window.addEventListener('load', function () {
|
8
|
+
|
9
|
+
// --- class for index info
|
3
10
|
|
4
11
|
// the info about an index block
|
5
12
|
// index blocks are like this:
|
@@ -44,6 +51,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
44
51
|
const style = window.getComputedStyle(this.list);
|
45
52
|
const listHeightPadding = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);
|
46
53
|
this.entries = this.list.getElementsByTagName('p');
|
54
|
+
this.links = this.list.getElementsByTagName('a');
|
47
55
|
this.entryCount = this.entries.length;
|
48
56
|
// height of one entry
|
49
57
|
const listRect = this.list.getBoundingClientRect();
|
@@ -58,10 +66,12 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
58
66
|
this.searchBox = null;
|
59
67
|
this.list = null;
|
60
68
|
this.entries = [];
|
69
|
+
this.links = [];
|
61
70
|
this.entryCount = 0;
|
62
71
|
this.entryHeight = 0;
|
63
72
|
this.fixedHeight = 0;
|
64
73
|
}
|
74
|
+
// height of this index before the current resize
|
65
75
|
this.prevHeight = null;
|
66
76
|
}
|
67
77
|
|
@@ -72,14 +82,14 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
72
82
|
return 0;
|
73
83
|
}
|
74
84
|
|
85
|
+
// enough room for 2 entries
|
75
86
|
get minHeight() {
|
76
87
|
return this.fixedHeight + 2 * this.entryHeight;
|
77
88
|
}
|
78
89
|
|
79
90
|
setHeight(height, { resetPrev = false } = {}) {
|
80
91
|
if (!this.div) return;
|
81
|
-
|
82
|
-
const h = (~~((height - this.fixedHeight) * 100)) / 100;
|
92
|
+
const h = height - this.fixedHeight;
|
83
93
|
if (this.prevHeight === null || resetPrev) {
|
84
94
|
// no previous or reset asked: set prev = current
|
85
95
|
this.list.style.height = `${h}px`;
|
@@ -92,58 +102,185 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
92
102
|
}
|
93
103
|
}
|
94
104
|
|
105
|
+
// save the layout of this index, including the search text
|
106
|
+
saveInfo(storage) {
|
107
|
+
if (!this.div) return;
|
108
|
+
storage.setItem(`${this.name}Index.prevHeight`, this.prevHeight);
|
109
|
+
storage.setItem(`${this.name}Index.styleHeight`, this.list.style.height);
|
110
|
+
storage.setItem(`${this.name}Index.scrollTop`, this.list.scrollTop);
|
111
|
+
if (this.searchBox) {
|
112
|
+
storage.setItem(`${this.name}Index.searchWidth`, this.searchBox.style.width);
|
113
|
+
storage.setItem(`${this.name}Index.searchText`, this.searchBox.value || '');
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
// restore a previously saved layout & search text
|
118
|
+
restoreInfo(storage) {
|
119
|
+
if (!this.div) return;
|
120
|
+
this.prevHeight = storage.getItem(`${this.name}Index.prevHeight`);
|
121
|
+
this.list.style.height = storage.getItem(`${this.name}Index.styleHeight`);
|
122
|
+
this.list.scrollTop = storage.getItem(`${this.name}Index.scrollTop`);
|
123
|
+
if (this.searchBox) {
|
124
|
+
this.searchBox.style.width = storage.getItem(`${this.name}Index.searchWidth`);
|
125
|
+
this.searchBox.value = storage.getItem(`${this.name}Index.searchText`);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
// highlight the entry for <a> aNode and make sure it is visible
|
130
|
+
setCurrent(aNode) {
|
131
|
+
for (const a of this.links)
|
132
|
+
if (a === aNode) {
|
133
|
+
a.classList.add('current-main');
|
134
|
+
this.ensureVisible(a);
|
135
|
+
}
|
136
|
+
else
|
137
|
+
a.classList.remove('current-main');
|
138
|
+
}
|
139
|
+
|
140
|
+
ensureVisible(a) {
|
141
|
+
const aTopOffset = a.offsetTop - this.links[0].offsetTop;
|
142
|
+
const aHeight = a.getBoundingClientRect().height;
|
143
|
+
const offScreen =
|
144
|
+
// not (completely) visible because above
|
145
|
+
aTopOffset < this.list.scrollTop ||
|
146
|
+
// not (completely) visible because below
|
147
|
+
aTopOffset + aHeight > this.list.scrollTop + this.list.clientHeight
|
148
|
+
;
|
149
|
+
// position in the middle of the list
|
150
|
+
if (offScreen)
|
151
|
+
this.list.scrollTop = aTopOffset - this.list.clientHeight / 2;
|
152
|
+
}
|
153
|
+
|
95
154
|
}
|
96
155
|
|
156
|
+
// --- global setup
|
157
|
+
|
97
158
|
const fileIndex = new Index('file');
|
98
159
|
const classIndex = new Index('class');
|
99
160
|
const methodIndex = new Index('method');
|
100
161
|
|
101
162
|
setupResizing();
|
102
|
-
|
103
|
-
|
163
|
+
|
164
|
+
// --- setup the vertical resizing of indexes by dragging
|
104
165
|
|
105
166
|
const fileClassResizer = document.getElementById('file-class-resizer'); // may be null
|
106
167
|
const classMethodResizer = document.getElementById('class-method-resizer');
|
107
168
|
|
108
|
-
|
169
|
+
if (!restoreLayoutInfo())
|
170
|
+
frameResized(true);
|
171
|
+
setupSearches();
|
109
172
|
|
110
173
|
if (fileClassResizer)
|
111
174
|
fileClassResizer.addEventListener('mousedown', function(e) {startDrag(e, fileIndex, classIndex)});
|
112
175
|
classMethodResizer.addEventListener('mousedown', function(e) {startDrag(e, classIndex, methodIndex)});
|
113
176
|
|
114
|
-
//
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
177
|
+
// --- highlight of the current file/class/method
|
178
|
+
|
179
|
+
highlightCurrentIndexEntries();
|
180
|
+
|
181
|
+
function highlightCurrentIndexEntries() {
|
182
|
+
|
183
|
+
// /C:/docs/ruby/32/core/files/toc_core_md.html
|
184
|
+
// /C:/docs/ruby/32/core/classes/Process.html
|
185
|
+
const currentPath = window.parent.location.pathname;
|
186
|
+
const index = (currentPath.indexOf('/classes/') < 0) ? fileIndex : classIndex;
|
187
|
+
|
188
|
+
for (const a of index.links) {
|
189
|
+
const href = a.getAttribute('href');
|
190
|
+
if (currentPath.endsWith(href)) {
|
191
|
+
index.setCurrent(a);
|
192
|
+
break;
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
if (index === fileIndex)
|
197
|
+
return;
|
198
|
+
|
199
|
+
setCurrentMethod(currentPath);
|
200
|
+
}
|
201
|
+
|
202
|
+
function setCurrentMethod(currentPath) {
|
203
|
+
const hash = window.parent.location.hash;
|
204
|
+
if (!hash) return;
|
205
|
+
|
206
|
+
const currentMethod = `${currentPath}${hash}`;
|
207
|
+
for (const a of methodIndex.links) {
|
208
|
+
const href = a.getAttribute('href');
|
209
|
+
if (currentMethod.endsWith(href)) {
|
210
|
+
methodIndex.setCurrent(a);
|
211
|
+
break;
|
212
|
+
}
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
// --- when clicking on a link, remember the scroll positions & search state of each index
|
217
|
+
|
218
|
+
for (const a of fileIndex.links)
|
219
|
+
a.addEventListener('click', saveLayoutInfo);
|
220
|
+
for (const a of classIndex.links)
|
221
|
+
a.addEventListener('click', saveLayoutInfo);
|
222
|
+
for (const a of methodIndex.links)
|
223
|
+
a.addEventListener('click', saveLayoutInfo);
|
224
|
+
|
225
|
+
function saveLayoutInfo(e) {
|
226
|
+
const s = window.parent.sessionStorage;
|
227
|
+
s.setItem('infoSaved', 'true');
|
228
|
+
|
229
|
+
// the width of the left frame
|
230
|
+
const width = window.parent.document.getElementById('left-container').style.width;
|
231
|
+
s.setItem('left.frameWidth', width);
|
232
|
+
|
233
|
+
// position of the left frame resizer
|
234
|
+
const left = window.parent.document.getElementById('resizer').style.left;
|
235
|
+
s.setItem('left.resizerLeft', left);
|
236
|
+
|
237
|
+
// the height & position of each index
|
238
|
+
fileIndex.saveInfo(s);
|
239
|
+
classIndex.saveInfo(s);
|
240
|
+
methodIndex.saveInfo(s);
|
241
|
+
}
|
242
|
+
|
243
|
+
// restores the saved layout and returns true, or returns false if no saved layout
|
244
|
+
function restoreLayoutInfo() {
|
245
|
+
// restore previous scroll positions & search states if any
|
246
|
+
const s = window.parent.sessionStorage;
|
247
|
+
const saved = s.getItem(`infoSaved`);
|
248
|
+
if (saved) {
|
249
|
+
window.parent.document.getElementById('left-container').style.width = s.getItem('left.frameWidth');
|
250
|
+
window.parent.document.getElementById('resizer').style.left = s.getItem('left.resizerLeft');
|
251
|
+
fileIndex.restoreInfo(s);
|
252
|
+
classIndex.restoreInfo(s);
|
253
|
+
methodIndex.restoreInfo(s);
|
254
|
+
placeResizers();
|
255
|
+
}
|
256
|
+
return saved === 'true';
|
257
|
+
}
|
258
|
+
|
259
|
+
// --- when navigating inside the same main document, handle current method highlighting
|
260
|
+
|
261
|
+
window.parent.addEventListener('hashchange', mainHashChanged);
|
262
|
+
|
263
|
+
// highlight the new method in the main frame, and in the method index
|
264
|
+
function mainHashChanged(e) {
|
265
|
+
const id = e.newURL.split('#')[1];
|
266
|
+
highlightElement(id);
|
267
|
+
setCurrentMethod(window.parent.location.pathname);
|
129
268
|
}
|
130
269
|
|
131
270
|
// highlight the passed id in the main frame
|
132
271
|
function highlightElement(id) {
|
133
|
-
const doc =
|
272
|
+
const doc = window.parent.document;
|
134
273
|
for (const h of doc.querySelectorAll('.highlighted'))
|
135
274
|
h.classList.remove('highlighted');
|
275
|
+
if (id === 'header')
|
276
|
+
return;
|
136
277
|
const e = doc.getElementById(id);
|
137
278
|
if (e)
|
138
279
|
e.classList.add('highlighted');
|
139
280
|
}
|
140
281
|
|
141
|
-
|
142
|
-
for (const a of methodIndex.list.querySelectorAll('a[href*="#method-"]'))
|
143
|
-
a.addEventListener('click', highlightTarget);
|
144
|
-
}
|
282
|
+
// --- search boxes
|
145
283
|
|
146
|
-
// setup search boxes
|
147
284
|
function setupSearches() {
|
148
285
|
const helpText = 'filter...';
|
149
286
|
setupSearch(classIndex.searchBox, classIndex.entries, helpText);
|
@@ -157,6 +294,13 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
157
294
|
searchBox.setAttribute('placeholder', helpText);
|
158
295
|
}
|
159
296
|
|
297
|
+
// --- vertical manual resizing of the indexes
|
298
|
+
// div#file-index
|
299
|
+
// div#file-class-resizer (absent if the above div is not there)
|
300
|
+
// div#class-index
|
301
|
+
// div#class-method-resizer
|
302
|
+
// div#method-index
|
303
|
+
|
160
304
|
let startY; // where drag begins
|
161
305
|
let startTopIndex; // index object above when drag begins
|
162
306
|
let startBottomIndex; // index object below when drag begins
|
@@ -164,7 +308,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
164
308
|
let startBottomHeight; // height of the index below when drag begins
|
165
309
|
|
166
310
|
function startDrag(e, topIndex, bottomIndex) {
|
167
|
-
startY = e.clientY;
|
311
|
+
startY = e.clientY;
|
168
312
|
startTopIndex = topIndex;
|
169
313
|
startBottomIndex = bottomIndex;
|
170
314
|
startTopHeight = topIndex.currentHeight;
|
@@ -189,6 +333,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
189
333
|
placeResizers();
|
190
334
|
}
|
191
335
|
|
336
|
+
// place the vertical resizers between their indexes
|
192
337
|
function placeResizers() {
|
193
338
|
if (fileClassResizer)
|
194
339
|
fileClassResizer.style.top = `${fileIndex.currentHeight}px`;
|
@@ -196,13 +341,14 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
196
341
|
classMethodResizer.style.top = `${fileIndex.currentHeight + classIndex.currentHeight}px`;
|
197
342
|
}
|
198
343
|
|
199
|
-
//
|
344
|
+
// --- resizing of the window by the user or by the left/main resizer in the main frame
|
345
|
+
|
200
346
|
function setupResizing() {
|
201
|
-
// callback on resize event
|
202
347
|
window.addEventListener('resize', function(e) { frameResized(false) });
|
203
348
|
}
|
204
349
|
|
205
350
|
// resize the left index blocks
|
351
|
+
// if initial is true, this is the first resize, called above when loading
|
206
352
|
function frameResized(initial) {
|
207
353
|
|
208
354
|
resizeSearchField(classIndex);
|
@@ -222,7 +368,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
222
368
|
const box = indexBlock.searchBox;
|
223
369
|
const text = indexBlock.text;
|
224
370
|
|
225
|
-
const frameWidth =
|
371
|
+
const frameWidth = window.visualViewport.width;
|
226
372
|
|
227
373
|
const textRect = text.getBoundingClientRect();
|
228
374
|
const textWidth = textRect.width;
|
@@ -250,6 +396,11 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
250
396
|
}
|
251
397
|
|
252
398
|
// returns the initial heights of index blocks for the current window size
|
399
|
+
// if the combined height of the 3 indexes is more than the window height:
|
400
|
+
// - shrinks the file index to 5 entries if more
|
401
|
+
// - shrinks the method index to 33%, but leaving at least 5 entries visible
|
402
|
+
// - shrinks the class index to the available space, but leaving at least 5 entries visible
|
403
|
+
// so if very little height, the result may not fit
|
253
404
|
function initialHeights() {
|
254
405
|
|
255
406
|
// returned information
|
@@ -316,6 +467,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
316
467
|
}
|
317
468
|
|
318
469
|
// returns the updated heights of index blocks for the current window size
|
470
|
+
// resizes each index proportionally
|
319
471
|
function updatedHeights() {
|
320
472
|
|
321
473
|
let frameHeight = window.visualViewport.height;
|
@@ -354,7 +506,6 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
354
506
|
heights.methods = frameHeight - heights.files - heights.classes;
|
355
507
|
|
356
508
|
return heights;
|
357
|
-
|
358
509
|
}
|
359
510
|
|
360
511
|
});
|
@@ -1,29 +1,188 @@
|
|
1
1
|
/*
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
Script for the main frame.
|
3
|
+
Originally an adaptation of (darkfish.js by Michael Granger)
|
4
|
+
*/
|
5
5
|
|
6
6
|
document.addEventListener('DOMContentLoaded', function () {
|
7
7
|
|
8
|
+
const leftContainer = document.getElementById('left-container');
|
9
|
+
const leftFrame = document.getElementById('left-frame');
|
10
|
+
const resizer = document.getElementById('resizer');
|
11
|
+
|
12
|
+
setupTOC();
|
8
13
|
setupShowSource();
|
9
14
|
setupShowConstantValue();
|
10
15
|
setupShowAllFiles();
|
11
16
|
setupInnerLinksHighlight();
|
12
17
|
highlightUrlHash();
|
13
18
|
|
14
|
-
//
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
//
|
19
|
-
//
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
// --- resizing of the left frame
|
20
|
+
|
21
|
+
resizer.addEventListener('mousedown', startWidthResize);
|
22
|
+
|
23
|
+
let startX; // where drag begins
|
24
|
+
let startWidth; // width of left frame when drag begins
|
25
|
+
function startWidthResize(e) {
|
26
|
+
startX = e.clientX;
|
27
|
+
startWidth = leftContainer.getBoundingClientRect().width;
|
28
|
+
document.documentElement.addEventListener('mousemove', doWidthResize);
|
29
|
+
document.documentElement.addEventListener('mouseup', stopWidthResize);
|
30
|
+
leftFrame.contentDocument.addEventListener('mousemove', doWidthResize);
|
31
|
+
leftFrame.contentDocument.addEventListener('mouseup', stopWidthResize);
|
32
|
+
}
|
33
|
+
|
34
|
+
function stopWidthResize(e) {
|
35
|
+
document.documentElement.removeEventListener('mousemove', doWidthResize);
|
36
|
+
document.documentElement.removeEventListener('mouseup', stopWidthResize);
|
37
|
+
leftFrame.contentDocument.removeEventListener('mousemove', doWidthResize);
|
38
|
+
leftFrame.contentDocument.removeEventListener('mouseup', stopWidthResize);
|
39
|
+
}
|
40
|
+
|
41
|
+
function doWidthResize(e) {
|
42
|
+
const dX = e.clientX - startX;
|
43
|
+
const newWidth = startWidth + dX;
|
44
|
+
if (newWidth > 100)
|
45
|
+
leftContainer.style.width = `${newWidth}px`;
|
46
|
+
}
|
47
|
+
|
48
|
+
// --- TOC button setup
|
49
|
+
|
50
|
+
function setupTOC() {
|
51
|
+
|
52
|
+
const nav = document.createElement('nav');
|
53
|
+
nav.innerHTML = `
|
54
|
+
<button id="menu-button">
|
55
|
+
<img class="icon-hamburger">
|
56
|
+
<img class="icon-cross">
|
57
|
+
</button>
|
58
|
+
<div id="menu-content" class="hidden">
|
59
|
+
<p id="menu-top">
|
60
|
+
<a href="#header">(top)</a>
|
61
|
+
</p>
|
62
|
+
<div id="toc-content">
|
63
|
+
</div>
|
64
|
+
</div>
|
65
|
+
`;
|
66
|
+
const main = document.getElementById('main-container');
|
67
|
+
const doc = document.getElementById('documentation');
|
68
|
+
main.insertBefore(nav, doc);
|
69
|
+
|
70
|
+
const menu_button = document.getElementById('menu-button');
|
71
|
+
const menu_content = document.getElementById('menu-content');
|
72
|
+
const toc_content = document.getElementById('toc-content');
|
73
|
+
|
74
|
+
function createTOC() {
|
75
|
+
const headings = document.body.querySelectorAll('h1, h2, h3, h4, h5, h6');
|
76
|
+
if (headings.length == 0)
|
77
|
+
return false;
|
78
|
+
let generated_id_index = 0;
|
79
|
+
const first_summary_heading = firstSummaryHeading();
|
80
|
+
// console.log(`${headings.length} headings`);
|
81
|
+
for (const h of headings) {
|
82
|
+
// console.log(`name = ${h.tagName} id=${h.id} text = ${h.innerText}`);
|
83
|
+
if (!h.id) {
|
84
|
+
generated_id_index++;
|
85
|
+
h.setAttribute('id', `toc-auto-id-${generated_id_index}`);
|
86
|
+
}
|
87
|
+
if (h === first_summary_heading) {
|
88
|
+
const sp = document.createElement('p');
|
89
|
+
toc_content.appendChild(sp);
|
90
|
+
sp.setAttribute('class', 'h2');
|
91
|
+
sp.textContent = 'Summary';
|
92
|
+
}
|
93
|
+
// <p class="toc2"><a href="#label-News">News</a></p>
|
94
|
+
const p = document.createElement('p');
|
95
|
+
toc_content.appendChild(p);
|
96
|
+
p.setAttribute('class', h.tagName.toLowerCase());
|
97
|
+
const a = document.createElement('a');
|
98
|
+
p.appendChild(a);
|
99
|
+
a.setAttribute('href', `#${h.id}`);
|
100
|
+
a.textContent = h.innerText; // h.textContent;
|
101
|
+
}
|
102
|
+
|
103
|
+
return true;
|
104
|
+
}
|
105
|
+
|
106
|
+
function firstSummaryHeading() {
|
107
|
+
const ids = [
|
108
|
+
'class-aliases',
|
109
|
+
'method-list',
|
110
|
+
'namespace-list',
|
111
|
+
'include-list',
|
112
|
+
'constant-list',
|
113
|
+
'external-aliases',
|
114
|
+
'class-attributes',
|
115
|
+
'instance-attributes',
|
116
|
+
];
|
117
|
+
for (const id of ids) {
|
118
|
+
const h = document.querySelector(`#${id} h3`);
|
119
|
+
if (h) return h;
|
120
|
+
}
|
121
|
+
return null;
|
122
|
+
}
|
123
|
+
|
124
|
+
if (!createTOC())
|
125
|
+
nav.classList.add('hidden');
|
126
|
+
|
127
|
+
// show/hide the menu/toc
|
128
|
+
menu_button.addEventListener('click', function(e) {
|
129
|
+
e.preventDefault();
|
130
|
+
toggleMenu();
|
131
|
+
});
|
132
|
+
|
133
|
+
// hide the menu on Escape
|
134
|
+
document.addEventListener('keydown', function(e) {
|
135
|
+
if (!isMenuVisible()) return;
|
136
|
+
if (e.code == 'Escape' && !e.ctrlKey) {
|
137
|
+
e.preventDefault();
|
138
|
+
hideMenu();
|
139
|
+
}
|
140
|
+
});
|
141
|
+
|
142
|
+
// hide the menu when clicking outside of nav
|
143
|
+
document.addEventListener('click', function (event) {
|
144
|
+
if (!isMenuVisible()) return;
|
145
|
+
if (!nav.contains(event.target))
|
146
|
+
hideMenu();
|
147
|
+
});
|
148
|
+
|
149
|
+
function hideMenu() {
|
150
|
+
menu_content.classList.add('hidden');
|
151
|
+
menu_button.classList.remove('show-close');
|
152
|
+
}
|
153
|
+
|
154
|
+
function showMenu() {
|
155
|
+
menu_content.classList.remove('hidden');
|
156
|
+
menu_button.classList.add('show-close');
|
157
|
+
}
|
158
|
+
|
159
|
+
function isMenuVisible() {
|
160
|
+
return !menu_content.classList.contains('hidden');
|
161
|
+
}
|
162
|
+
|
163
|
+
function toggleMenu() {
|
164
|
+
if (isMenuVisible())
|
165
|
+
hideMenu();
|
166
|
+
else
|
167
|
+
showMenu();
|
168
|
+
}
|
169
|
+
|
170
|
+
}
|
171
|
+
|
172
|
+
// --- toggle method source display
|
23
173
|
|
24
174
|
function setupShowSource() {
|
25
175
|
for (const node of document.querySelectorAll('.method-heading'))
|
26
176
|
node.addEventListener('click', toggleSource);
|
177
|
+
// <div id="method-c-_httpdate" class="method-detail">
|
178
|
+
// <div class="method-heading">
|
179
|
+
// ...
|
180
|
+
// </div>
|
181
|
+
// <div class="method-description">
|
182
|
+
// ...
|
183
|
+
// <pre class="method-source-code">
|
184
|
+
// (code)
|
185
|
+
// </pre>
|
27
186
|
}
|
28
187
|
|
29
188
|
function toggleSource(e) {
|
@@ -33,22 +192,23 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
33
192
|
slideToggle(source);
|
34
193
|
}
|
35
194
|
|
36
|
-
//
|
37
|
-
// <td class="const-name"><p>MONTHNAMES</p></td>
|
38
|
-
// <td class="const-desc">
|
39
|
-
// <p>An array of strings of full month names in <a href="English.html"><code>English</code></a>. The first element is nil.</p>
|
40
|
-
// </td>
|
41
|
-
// <td><p class="click-advice">click to toggle value</p></td>
|
42
|
-
// </tr>
|
43
|
-
// <tr class="const-value">
|
44
|
-
// <td></td>
|
45
|
-
// <td><pre>mk_ary_of_str(13, monthnames)</pre></td>
|
46
|
-
// <td></td>
|
47
|
-
// </tr>
|
195
|
+
// --- toggle constant value display
|
48
196
|
|
49
197
|
function setupShowConstantValue() {
|
50
198
|
for (const node of document.querySelectorAll('#constant-list .const-display'))
|
51
199
|
node.addEventListener('click', toggleValue);
|
200
|
+
// <tr id="MONTHNAMES" class="const-display">
|
201
|
+
// <td class="const-name"><p>MONTHNAMES</p></td>
|
202
|
+
// <td class="const-desc">
|
203
|
+
// <p>An array of strings of full month names in <a href="English.html"><code>English</code></a>. The first element is nil.</p>
|
204
|
+
// </td>
|
205
|
+
// <td><p class="click-advice">click to toggle value</p></td>
|
206
|
+
// </tr>
|
207
|
+
// <tr class="const-value">
|
208
|
+
// <td></td>
|
209
|
+
// <td><pre>mk_ary_of_str(13, monthnames)</pre></td>
|
210
|
+
// <td></td>
|
211
|
+
// </tr>
|
52
212
|
}
|
53
213
|
|
54
214
|
function toggleValue(e) {
|
@@ -56,13 +216,15 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
56
216
|
toggleDisplay(e.currentTarget.nextElementSibling, 'table-row');
|
57
217
|
}
|
58
218
|
|
59
|
-
function toggleDisplay(element,
|
60
|
-
if (element.style.display !==
|
61
|
-
element.style.display =
|
219
|
+
function toggleDisplay(element, visibleDisplayValue) {
|
220
|
+
if (element.style.display !== visibleDisplayValue)
|
221
|
+
element.style.display = visibleDisplayValue;
|
62
222
|
else
|
63
223
|
element.style.display = 'none';
|
64
224
|
}
|
65
225
|
|
226
|
+
// --- toggle the display of all files where the class/module if defined
|
227
|
+
|
66
228
|
function setupShowAllFiles() {
|
67
229
|
const allFiles = document.getElementById('all-files');
|
68
230
|
if (!allFiles) return;
|
@@ -80,11 +242,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
80
242
|
});
|
81
243
|
}
|
82
244
|
|
83
|
-
|
84
|
-
const h = window.location.hash;
|
85
|
-
if (h && h.length > 1)
|
86
|
-
highlightElement(h.substring(1));
|
87
|
-
}
|
245
|
+
// --- highlight the target method when clicked from an inner method link
|
88
246
|
|
89
247
|
function setupInnerLinksHighlight() {
|
90
248
|
for (const a of document.querySelectorAll('a[href*="#"]'))
|
@@ -93,7 +251,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
93
251
|
|
94
252
|
function highlightTarget(e) {
|
95
253
|
const href = e.currentTarget.getAttribute('href');
|
96
|
-
const match
|
254
|
+
const match = /#(.*)/.exec(href);
|
97
255
|
if (match && match[1].length > 1)
|
98
256
|
highlightElement(match[1]);
|
99
257
|
}
|
@@ -101,11 +259,22 @@ document.addEventListener('DOMContentLoaded', function () {
|
|
101
259
|
function highlightElement(id) {
|
102
260
|
for (const h of document.querySelectorAll('.highlighted'))
|
103
261
|
h.classList.remove('highlighted');
|
262
|
+
if (id === 'header')
|
263
|
+
return;
|
104
264
|
const e = document.getElementById(id);
|
105
265
|
if (e)
|
106
266
|
e.classList.add('highlighted');
|
107
267
|
}
|
108
268
|
|
269
|
+
// --- highlight the method if present in the location hash
|
270
|
+
|
271
|
+
function highlightUrlHash() {
|
272
|
+
const h = window.location.hash;
|
273
|
+
if (h && h.length > 1)
|
274
|
+
highlightElement(h.substring(1));
|
275
|
+
}
|
276
|
+
|
277
|
+
// --- smooth toggling (for source code)
|
109
278
|
// from plain JS slideToggle https://github.com/ericbutler555/plain-js-slidetoggle
|
110
279
|
|
111
280
|
function slideToggle(element, duration) {
|
@@ -7,26 +7,31 @@
|
|
7
7
|
https://github.com/riklomas/quicksearch
|
8
8
|
*/
|
9
9
|
|
10
|
+
// setup quick search:
|
11
|
+
// - input: the text search box
|
12
|
+
// - paragraphs: the paragraphs to show/hide
|
10
13
|
function setupQuickSearch(input, paragraphs) {
|
11
14
|
|
12
|
-
let timeoutId;
|
13
|
-
const
|
14
|
-
const
|
15
|
-
|
16
|
-
// console.log(`setupQuickSearch(${input}, ${paragraphs.length} paragraphs)`)
|
15
|
+
let timeoutId; // setTimeout id on key up
|
16
|
+
const delay = 100; // delay for search after key up
|
17
|
+
const textCache = []; // cache of search texts (lowercase)
|
17
18
|
|
19
|
+
// fill the cache
|
18
20
|
for (const node of paragraphs)
|
19
|
-
textCache.push(node.textContent.toLowerCase().trim());
|
21
|
+
textCache.push(node.querySelector('a').textContent.toLowerCase().trim());
|
20
22
|
|
23
|
+
// filter with the current content of the input box
|
21
24
|
filter();
|
22
25
|
|
23
26
|
input.addEventListener('keyup', trigger);
|
24
27
|
|
28
|
+
// calls filter() after the delay
|
25
29
|
function trigger() {
|
26
30
|
window.clearTimeout(timeoutId);
|
27
31
|
timeoutId = window.setTimeout(filter, delay);
|
28
32
|
}
|
29
33
|
|
34
|
+
// perform filtering
|
30
35
|
function filter() {
|
31
36
|
|
32
37
|
if (!input.value) {
|
@@ -43,6 +48,7 @@ function setupQuickSearch(input, paragraphs) {
|
|
43
48
|
paragraphs[i].style.display = 'none';
|
44
49
|
}
|
45
50
|
|
51
|
+
// does text contain all words?
|
46
52
|
function containsAll(text, words) {
|
47
53
|
for (const word of words)
|
48
54
|
if (text.indexOf(word) === -1)
|