rdoc-babel 1.2.1 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/HISTORY.rdoc +16 -0
- data/README.rdoc +17 -16
- data/lib/rdoc/generator/babel.rb +82 -15
- data/lib/rdoc/generator/ruby-lang/class-page.html.erb +33 -45
- data/lib/rdoc/generator/ruby-lang/file-page.html.erb +8 -5
- 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 +193 -71
- 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 +11 -5
- 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
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)
|