@qubit-ltd/json 1.2.2 → 1.2.3

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.
Files changed (37) hide show
  1. package/dist/json.cjs +188 -20
  2. package/dist/json.cjs.map +1 -1
  3. package/dist/json.min.cjs +1 -1
  4. package/dist/json.min.cjs.map +1 -1
  5. package/dist/json.min.mjs +1 -1
  6. package/dist/json.min.mjs.map +1 -1
  7. package/dist/json.mjs +188 -20
  8. package/dist/json.mjs.map +1 -1
  9. package/doc/api/Json.html +42 -0
  10. package/doc/api/LosslessNumber.html +3 -3
  11. package/doc/api/data/search.json +1 -1
  12. package/doc/api/global.html +3 -3
  13. package/doc/api/index.html +4 -4
  14. package/doc/api/scripts/core.js +719 -726
  15. package/doc/api/scripts/core.min.js +23 -23
  16. package/doc/api/scripts/resize.js +90 -90
  17. package/doc/api/scripts/search.js +267 -265
  18. package/doc/api/scripts/search.min.js +5 -5
  19. package/doc/api/scripts/third-party/Apache-License-2.0.txt +202 -202
  20. package/doc/api/scripts/third-party/fuse.js +1749 -9
  21. package/doc/api/scripts/third-party/hljs-line-num-original.js +367 -369
  22. package/doc/api/scripts/third-party/hljs-line-num.js +1 -1
  23. package/doc/api/scripts/third-party/hljs-original.js +5260 -5171
  24. package/doc/api/scripts/third-party/hljs.js +1 -1
  25. package/doc/api/scripts/third-party/popper.js +1287 -5
  26. package/doc/api/scripts/third-party/tippy.js +1499 -1
  27. package/doc/api/scripts/third-party/tocbot.js +757 -672
  28. package/doc/api/scripts/third-party/tocbot.min.js +1 -1
  29. package/doc/api/styles/clean-jsdoc-theme-base.css +1257 -1159
  30. package/doc/api/styles/clean-jsdoc-theme-dark.css +412 -412
  31. package/doc/api/styles/clean-jsdoc-theme-light.css +482 -482
  32. package/doc/api/styles/clean-jsdoc-theme-scrollbar.css +29 -29
  33. package/doc/api/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -1
  34. package/doc/api/styles/clean-jsdoc-theme.min.css +1 -1
  35. package/doc/json.min.visualization.html +15 -15
  36. package/doc/json.visualization.html +15 -15
  37. package/package.json +20 -20
@@ -1,672 +1,757 @@
1
- /* eslint no-var: off */
2
- var defaultOptions = {
3
- ignoreSelector: '.js-toc-ignore',
4
- linkClass: 'toc-link',
5
- extraLinkClasses: '',
6
- activeLinkClass: 'is-active-link',
7
- listClass: 'toc-list',
8
- extraListClasses: '',
9
- isCollapsedClass: 'is-collapsed',
10
- collapsibleClass: 'is-collapsible',
11
- listItemClass: 'toc-list-item',
12
- activeListItemClass: 'is-active-li',
13
- collapseDepth: 0,
14
- scrollSmooth: true,
15
- scrollSmoothDuration: 420,
16
- scrollSmoothOffset: 0,
17
- scrollEndCallback: function (e) { },
18
- throttleTimeout: 50,
19
- positionFixedSelector: null,
20
- positionFixedClass: 'is-position-fixed',
21
- fixedSidebarOffset: 'auto',
22
- includeHtml: false,
23
- includeTitleTags: false,
24
- orderedList: true,
25
- scrollContainer: null,
26
- skipRendering: false,
27
- headingLabelCallback: false,
28
- ignoreHiddenElements: false,
29
- headingObjectCallback: null,
30
- basePath: '',
31
- disableTocScrollSync: false
32
- }
33
-
34
- function ParseContent(options) {
35
- var reduce = [].reduce
36
-
37
- /**
38
- * Get the last item in an array and return a reference to it.
39
- * @param {Array} array
40
- * @return {Object}
41
- */
42
- function getLastItem(array) {
43
- return array[array.length - 1]
44
- }
45
-
46
- /**
47
- * Get heading level for a heading dom node.
48
- * @param {HTMLElement} heading
49
- * @return {Number}
50
- */
51
- function getHeadingLevel(heading) {
52
- return +heading.nodeName.toUpperCase().replace('H', '')
53
- }
54
-
55
- /**
56
- * Get important properties from a heading element and store in a plain object.
57
- * @param {HTMLElement} heading
58
- * @return {Object}
59
- */
60
- function getHeadingObject(heading) {
61
- // each node is processed twice by this method because nestHeadingsArray() and addNode() calls it
62
- // first time heading is real DOM node element, second time it is obj
63
- // that is causing problem so I am processing only original DOM node
64
- if (!(heading instanceof window.HTMLElement)) return heading
65
-
66
- if (options.ignoreHiddenElements && (!heading.offsetHeight || !heading.offsetParent)) {
67
- return null
68
- }
69
-
70
- const headingLabel = heading.getAttribute('data-heading-label') ||
71
- (options.headingLabelCallback ? String(options.headingLabelCallback(heading.textContent)) : heading.textContent.trim())
72
- var obj = {
73
- id: heading.id,
74
- children: [],
75
- nodeName: heading.nodeName,
76
- headingLevel: getHeadingLevel(heading),
77
- textContent: headingLabel
78
- }
79
-
80
- if (options.includeHtml) {
81
- obj.childNodes = heading.childNodes
82
- }
83
-
84
- if (options.headingObjectCallback) {
85
- return options.headingObjectCallback(obj, heading)
86
- }
87
-
88
- return obj
89
- }
90
-
91
- /**
92
- * Add a node to the nested array.
93
- * @param {Object} node
94
- * @param {Array} nest
95
- * @return {Array}
96
- */
97
- function addNode(node, nest) {
98
- var obj = getHeadingObject(node)
99
- var level = obj.headingLevel
100
- var array = nest
101
- var lastItem = getLastItem(array)
102
- var lastItemLevel = lastItem
103
- ? lastItem.headingLevel
104
- : 0
105
- var counter = level - lastItemLevel
106
-
107
- while (counter > 0) {
108
- lastItem = getLastItem(array)
109
- // Handle case where there are multiple h5+ in a row.
110
- if (lastItem && level === lastItem.headingLevel) {
111
- break
112
- } else if (lastItem && lastItem.children !== undefined) {
113
- array = lastItem.children
114
- }
115
- counter--
116
- }
117
-
118
- if (level >= options.collapseDepth) {
119
- obj.isCollapsed = true
120
- }
121
-
122
- array.push(obj)
123
- return array
124
- }
125
-
126
- /**
127
- * Select headings in content area, exclude any selector in options.ignoreSelector
128
- * @param {HTMLElement} contentElement
129
- * @param {Array} headingSelector
130
- * @return {Array}
131
- */
132
- function selectHeadings(contentElement, headingSelector) {
133
- var selectors = headingSelector
134
- if (options.ignoreSelector) {
135
- selectors = headingSelector.split(',')
136
- .map(function mapSelectors(selector) {
137
- return selector.trim() + ':not(' + options.ignoreSelector + ')'
138
- })
139
- }
140
- try {
141
- return contentElement.querySelectorAll(selectors)
142
- } catch (e) {
143
- console.warn('Headers not found with selector: ' + selectors); // eslint-disable-line
144
- return null
145
- }
146
- }
147
-
148
- /**
149
- * Nest headings array into nested arrays with 'children' property.
150
- * @param {Array} headingsArray
151
- * @return {Object}
152
- */
153
- function nestHeadingsArray(headingsArray) {
154
- return reduce.call(headingsArray, function reducer(prev, curr) {
155
- var currentHeading = getHeadingObject(curr)
156
- if (currentHeading) {
157
- addNode(currentHeading, prev.nest)
158
- }
159
- return prev
160
- }, {
161
- nest: []
162
- })
163
- }
164
-
165
- return {
166
- nestHeadingsArray: nestHeadingsArray,
167
- selectHeadings: selectHeadings
168
- }
169
- }
170
-
171
- function BuildHtml(options) {
172
- var forEach = [].forEach
173
- var some = [].some
174
- var body = document.body
175
- var tocElement
176
- var mainContainer = document.querySelector(options.contentSelector)
177
- var currentlyHighlighting = true
178
- var SPACE_CHAR = ' '
179
-
180
- /**
181
- * Create link and list elements.
182
- * @param {Object} d
183
- * @param {HTMLElement} container
184
- * @return {HTMLElement}
185
- */
186
- function createEl(d, container) {
187
- var link = container.appendChild(createLink(d))
188
- if (d.children.length) {
189
- var list = createList(d.isCollapsed)
190
- d.children.forEach(function (child) {
191
- createEl(child, list)
192
- })
193
- link.appendChild(list)
194
- }
195
- }
196
-
197
- /**
198
- * Render nested heading array data into a given element.
199
- * @param {HTMLElement} parent Optional. If provided updates the {@see tocElement} to match.
200
- * @param {Array} data
201
- * @return {HTMLElement}
202
- */
203
- function render(parent, data) {
204
- var collapsed = false
205
- var container = createList(collapsed)
206
-
207
- data.forEach(function (d) {
208
- createEl(d, container)
209
- })
210
-
211
- // Return if no TOC element is provided or known.
212
- tocElement = parent || tocElement
213
- if (tocElement === null) {
214
- return
215
- }
216
-
217
- // Remove existing child if it exists.
218
- if (tocElement.firstChild) {
219
- tocElement.removeChild(tocElement.firstChild)
220
- }
221
-
222
- // Just return the parent and don't append the list if no links are found.
223
- if (data.length === 0) {
224
- return tocElement
225
- }
226
-
227
- // Append the Elements that have been created
228
- return tocElement.appendChild(container)
229
- }
230
-
231
- /**
232
- * Create link element.
233
- * @param {Object} data
234
- * @return {HTMLElement}
235
- */
236
- function createLink(data) {
237
- var item = document.createElement('li')
238
- var a = document.createElement('a')
239
- if (options.listItemClass) {
240
- item.setAttribute('class', options.listItemClass)
241
- }
242
-
243
- if (options.onClick) {
244
- a.onclick = options.onClick
245
- }
246
-
247
- if (options.includeTitleTags) {
248
- a.setAttribute('title', data.textContent)
249
- }
250
-
251
- if (options.includeHtml && data.childNodes.length) {
252
- forEach.call(data.childNodes, function (node) {
253
- a.appendChild(node.cloneNode(true))
254
- })
255
- } else {
256
- // Default behavior.
257
- a.textContent = data.textContent
258
- }
259
- a.setAttribute('href', options.basePath + '#' + data.id)
260
- a.setAttribute('class', options.linkClass +
261
- SPACE_CHAR + 'node-name--' + data.nodeName +
262
- SPACE_CHAR + options.extraLinkClasses)
263
- item.appendChild(a)
264
- return item
265
- }
266
-
267
- /**
268
- * Create list element.
269
- * @param {Boolean} isCollapsed
270
- * @return {HTMLElement}
271
- */
272
- function createList(isCollapsed) {
273
- var listElement = (options.orderedList) ? 'ol' : 'ul'
274
- var list = document.createElement(listElement)
275
- var classes = options.listClass +
276
- SPACE_CHAR + options.extraListClasses
277
- if (isCollapsed) {
278
- classes += SPACE_CHAR + options.collapsibleClass
279
- classes += SPACE_CHAR + options.isCollapsedClass
280
- }
281
- list.setAttribute('class', classes)
282
- return list
283
- }
284
-
285
- /**
286
- * Update fixed sidebar class.
287
- * @return {HTMLElement}
288
- */
289
- function updateFixedSidebarClass() {
290
- if (options.scrollContainer && document.querySelector(options.scrollContainer)) {
291
- var top
292
- top = document.querySelector(options.scrollContainer).scrollTop
293
- } else {
294
- top = document.documentElement.scrollTop || body.scrollTop
295
- }
296
- var posFixedEl = document.querySelector(options.positionFixedSelector)
297
-
298
- if (options.fixedSidebarOffset === 'auto') {
299
- options.fixedSidebarOffset = tocElement.offsetTop
300
- }
301
-
302
- if (top > options.fixedSidebarOffset) {
303
- if (posFixedEl.className.indexOf(options.positionFixedClass) === -1) {
304
- posFixedEl.className += SPACE_CHAR + options.positionFixedClass
305
- }
306
- } else {
307
- posFixedEl.className = posFixedEl.className.split(SPACE_CHAR + options.positionFixedClass).join('')
308
- }
309
- }
310
-
311
- /**
312
- * Get top position of heading
313
- * @param {HTMLElement} obj
314
- * @return {int} position
315
- */
316
- function getHeadingTopPos(obj) {
317
- var position = 0
318
- if (obj !== null) {
319
- position = obj.offsetTop
320
- if (options.hasInnerContainers) { position += getHeadingTopPos(obj.offsetParent) }
321
- }
322
- return position
323
- }
324
-
325
-
326
- function updateListActiveElement(topHeader) {
327
- var forEach = [].forEach
328
-
329
- var tocLinks = tocElement
330
- .querySelectorAll('.' + options.linkClass)
331
- forEach.call(tocLinks, function (tocLink) {
332
- tocLink.className = tocLink.className.split(SPACE_CHAR + options.activeLinkClass).join('')
333
- })
334
- var tocLis = tocElement
335
- .querySelectorAll('.' + options.listItemClass)
336
- forEach.call(tocLis, function (tocLi) {
337
- tocLi.className = tocLi.className.split(SPACE_CHAR + options.activeListItemClass).join('')
338
- })
339
-
340
- // Add the active class to the active tocLink.
341
- var activeTocLink = tocElement
342
- .querySelector('.' + options.linkClass +
343
- '.node-name--' + topHeader.nodeName +
344
- '[href="' + options.basePath + '#' + topHeader.id.replace(/([ #;&,.+*~':"!^$[\]()=>|/@])/g, '\\$1') + '"]')
345
- if (activeTocLink && activeTocLink.className.indexOf(options.activeLinkClass) === -1) {
346
- activeTocLink.className += SPACE_CHAR + options.activeLinkClass
347
- }
348
- var li = activeTocLink && activeTocLink.parentNode
349
- if (li && li.className.indexOf(options.activeListItemClass) === -1) {
350
- li.className += SPACE_CHAR + options.activeListItemClass
351
- }
352
-
353
- var tocLists = tocElement
354
- .querySelectorAll('.' + options.listClass + '.' + options.collapsibleClass)
355
-
356
- // Collapse the other collapsible lists.
357
- forEach.call(tocLists, function (list) {
358
- if (list.className.indexOf(options.isCollapsedClass) === -1) {
359
- list.className += SPACE_CHAR + options.isCollapsedClass
360
- }
361
- })
362
-
363
- // Expand the active link's collapsible list and its sibling if applicable.
364
- if (activeTocLink && activeTocLink.nextSibling && activeTocLink.nextSibling.className.indexOf(options.isCollapsedClass) !== -1) {
365
- activeTocLink.nextSibling.className = activeTocLink.nextSibling.className.split(SPACE_CHAR + options.isCollapsedClass).join('')
366
- }
367
- removeCollapsedFromParents(activeTocLink && activeTocLink.parentNode.parentNode)
368
- }
369
-
370
- /**
371
- * Update TOC highlighting and collpased groupings.
372
- */
373
- function updateToc(headingsArray) {
374
- // If a fixed content container was set
375
- if (options.scrollContainer && document.querySelector(options.scrollContainer)) {
376
- var top
377
- top = document.querySelector(options.scrollContainer).scrollTop
378
- } else {
379
- top = document.documentElement.scrollTop || body.scrollTop
380
- }
381
-
382
- // Add fixed class at offset
383
- if (options.positionFixedSelector) {
384
- updateFixedSidebarClass()
385
- }
386
-
387
- // Get the top most heading currently visible on the page so we know what to highlight.
388
- var headings = headingsArray
389
- var topHeader
390
- // Using some instead of each so that we can escape early.
391
- if (currentlyHighlighting &&
392
- tocElement !== null &&
393
- headings.length > 0) {
394
- some.call(headings, function (heading, i) {
395
- var modifiedTopOffset = top + 10
396
- if (mainContainer) {
397
- modifiedTopOffset += mainContainer.clientHeight * (mainContainer.scrollTop) / (mainContainer.scrollHeight - mainContainer.clientHeight)
398
- }
399
- if (getHeadingTopPos(heading) > modifiedTopOffset) {
400
- // Don't allow negative index value.
401
- var index = (i === 0) ? i : i - 1
402
- topHeader = headings[index]
403
- return true
404
- } else if (i === headings.length - 1) {
405
- // This allows scrolling for the last heading on the page.
406
- topHeader = headings[headings.length - 1]
407
- return true
408
- }
409
- })
410
-
411
- // Remove the active class from the other tocLinks.
412
- updateListActiveElement(topHeader)
413
- }
414
- }
415
-
416
- /**
417
- * Remove collpased class from parent elements.
418
- * @param {HTMLElement} element
419
- * @return {HTMLElement}
420
- */
421
- function removeCollapsedFromParents(element) {
422
- if (element && element.className.indexOf(options.collapsibleClass) !== -1 && element.className.indexOf(options.isCollapsedClass) !== -1) {
423
- element.className = element.className.split(SPACE_CHAR + options.isCollapsedClass).join('')
424
- return removeCollapsedFromParents(element.parentNode.parentNode)
425
- }
426
- return element
427
- }
428
-
429
- /**
430
- * Disable TOC Animation when a link is clicked.
431
- * @param {Event} event
432
- */
433
- function disableTocAnimation(event) {
434
- var target = event.target || event.srcElement
435
- if (typeof target.className !== 'string' || target.className.indexOf(options.linkClass) === -1) {
436
- return
437
- }
438
- // Bind to tocLink clicks to temporarily disable highlighting
439
- // while smoothScroll is animating.
440
- currentlyHighlighting = false
441
- }
442
-
443
- /**
444
- * Enable TOC Animation.
445
- */
446
- function enableTocAnimation() {
447
- currentlyHighlighting = true
448
- }
449
-
450
- return {
451
- enableTocAnimation: enableTocAnimation,
452
- disableTocAnimation: disableTocAnimation,
453
- render: render,
454
- updateToc: updateToc,
455
- updateListActiveElement: updateListActiveElement
456
- }
457
- }
458
-
459
- function updateTocScroll(options) {
460
- var toc = options.tocElement || document.querySelector(options.tocSelector)
461
- if (toc && toc.scrollHeight > toc.clientHeight) {
462
- var activeItem = toc.querySelector('.' + options.activeListItemClass)
463
- if (activeItem) {
464
- var topOffset = toc.getBoundingClientRect().top
465
- toc.scrollTop = activeItem.offsetTop - topOffset
466
- }
467
- }
468
- }
469
-
470
- (function (root, factory) {
471
- if (typeof define === 'function' && define.amd) {
472
- define([], factory(root))
473
- } else if (typeof exports === 'object') {
474
- module.exports = factory(root)
475
- } else {
476
- root.tocbot = factory(root)
477
- }
478
- })(typeof global !== 'undefined' ? global : this.window || this.global, function (root) {
479
- 'use strict'
480
-
481
- var options = {}
482
- var tocbot = {}
483
- var buildHtml
484
- var parseContent
485
-
486
- // Just return if its not a browser.
487
- var supports = !!root && !!root.document && !!root.document.querySelector && !!root.addEventListener // Feature test
488
- if (typeof window === 'undefined' && !supports) {
489
- return
490
- }
491
- var headingsArray
492
-
493
- // From: https://github.com/Raynos/xtend
494
- var hasOwnProperty = Object.prototype.hasOwnProperty
495
- function extend() {
496
- var target = {}
497
- for (var i = 0; i < arguments.length; i++) {
498
- var source = arguments[i]
499
- for (var key in source) {
500
- if (hasOwnProperty.call(source, key)) {
501
- target[key] = source[key]
502
- }
503
- }
504
- }
505
- return target
506
- }
507
-
508
- // From: https://remysharp.com/2010/07/21/throttling-function-calls
509
- function throttle(fn, threshhold, scope) {
510
- threshhold || (threshhold = 250)
511
- var last
512
- var deferTimer
513
- return function () {
514
- var context = scope || this
515
- var now = +new Date()
516
- var args = arguments
517
- if (last && now < last + threshhold) {
518
- // hold on to it
519
- clearTimeout(deferTimer)
520
- deferTimer = setTimeout(function () {
521
- last = now
522
- fn.apply(context, args)
523
- }, threshhold)
524
- } else {
525
- last = now
526
- fn.apply(context, args)
527
- }
528
- }
529
- }
530
-
531
- function getContentElement(options) {
532
- try {
533
- return options.contentElement || document.querySelector(options.contentSelector)
534
- } catch (e) {
535
- console.warn('Contents element not found: ' + options.contentSelector) // eslint-disable-line
536
- return null
537
- }
538
- }
539
-
540
- function getTocElement(options) {
541
- try {
542
- return options.tocElement || document.querySelector(options.tocSelector)
543
- } catch (e) {
544
- console.warn('TOC element not found: ' + options.tocSelector) // eslint-disable-line
545
- return null
546
- }
547
- }
548
-
549
- /**
550
- * Destroy tocbot.
551
- */
552
- tocbot.destroy = function () {
553
- var tocElement = getTocElement(options)
554
- if (tocElement === null) {
555
- return
556
- }
557
-
558
- if (!options.skipRendering) {
559
- // Clear HTML.
560
- if (tocElement) {
561
- tocElement.innerHTML = ''
562
- }
563
- }
564
-
565
- // Remove event listeners.
566
- if (options.scrollContainer && document.querySelector(options.scrollContainer)) {
567
- document.querySelector(options.scrollContainer).removeEventListener('scroll', this._scrollListener, false)
568
- document.querySelector(options.scrollContainer).removeEventListener('resize', this._scrollListener, false)
569
- } else {
570
- document.removeEventListener('scroll', this._scrollListener, false)
571
- document.removeEventListener('resize', this._scrollListener, false)
572
- }
573
- }
574
-
575
- /**
576
- * Initialize tocbot.
577
- * @param {object} customOptions
578
- */
579
- tocbot.init = function (customOptions) {
580
- // feature test
581
- if (!supports) {
582
- return
583
- }
584
-
585
- // Merge defaults with user options.
586
- // Set to options variable at the top.
587
- options = extend(defaultOptions, customOptions || {})
588
- this.options = options
589
- this.state = {}
590
-
591
- // Init smooth scroll if enabled (default).
592
- if (options.scrollSmooth) {
593
- options.duration = options.scrollSmoothDuration
594
- options.offset = options.scrollSmoothOffset
595
- }
596
-
597
- // Pass options to these modules.
598
- buildHtml = BuildHtml(options)
599
- parseContent = ParseContent(options)
600
-
601
- // For testing purposes.
602
- this._buildHtml = buildHtml
603
- this._parseContent = parseContent
604
- this._headingsArray = headingsArray
605
- this.updateTocListActiveElement = buildHtml.updateListActiveElement
606
-
607
- // Destroy it if it exists first.
608
- tocbot.destroy()
609
-
610
- var contentElement = getContentElement(options)
611
- if (contentElement === null) {
612
- return
613
- }
614
-
615
- var tocElement = getTocElement(options)
616
- if (tocElement === null) {
617
- return
618
- }
619
-
620
- // Get headings array.
621
- headingsArray = parseContent.selectHeadings(contentElement, options.headingSelector)
622
- // Return if no headings are found.
623
- if (headingsArray === null) {
624
- return
625
- }
626
-
627
- // Build nested headings array.
628
- var nestedHeadingsObj = parseContent.nestHeadingsArray(headingsArray)
629
- var nestedHeadings = nestedHeadingsObj.nest
630
-
631
- // Render.
632
- if (!options.skipRendering) {
633
- buildHtml.render(tocElement, nestedHeadings)
634
- }
635
-
636
- // Update Sidebar and bind listeners.
637
- this._scrollListener = throttle(function (e) {
638
- buildHtml.updateToc(headingsArray)
639
- !options.disableTocScrollSync && updateTocScroll(options)
640
- var isTop = e && e.target && e.target.scrollingElement && e.target.scrollingElement.scrollTop === 0
641
- if ((e && (e.eventPhase === 0 || e.currentTarget === null)) || isTop) {
642
- buildHtml.updateToc(headingsArray)
643
- if (options.scrollEndCallback) {
644
- options.scrollEndCallback(e)
645
- }
646
- }
647
- }, options.throttleTimeout)
648
- this._scrollListener()
649
- if (options.scrollContainer && document.querySelector(options.scrollContainer)) {
650
- document.querySelector(options.scrollContainer).addEventListener('scroll', this._scrollListener, false)
651
- document.querySelector(options.scrollContainer).addEventListener('resize', this._scrollListener, false)
652
- } else {
653
- document.addEventListener('scroll', this._scrollListener, false)
654
- document.addEventListener('resize', this._scrollListener, false)
655
- }
656
-
657
- return this
658
- }
659
-
660
- /**
661
- * Refresh tocbot.
662
- */
663
- tocbot.refresh = function (customOptions) {
664
- tocbot.destroy()
665
- tocbot.init(customOptions || this.options)
666
- }
667
-
668
- // Make tocbot available globally.
669
- root.tocbot = tocbot
670
-
671
- return tocbot
672
- })
1
+ /* eslint no-var: off */
2
+ var defaultOptions = {
3
+ ignoreSelector: ".js-toc-ignore",
4
+ linkClass: "toc-link",
5
+ extraLinkClasses: "",
6
+ activeLinkClass: "is-active-link",
7
+ listClass: "toc-list",
8
+ extraListClasses: "",
9
+ isCollapsedClass: "is-collapsed",
10
+ collapsibleClass: "is-collapsible",
11
+ listItemClass: "toc-list-item",
12
+ activeListItemClass: "is-active-li",
13
+ collapseDepth: 0,
14
+ scrollSmooth: true,
15
+ scrollSmoothDuration: 420,
16
+ scrollSmoothOffset: 0,
17
+ scrollEndCallback: function (e) {},
18
+ throttleTimeout: 50,
19
+ positionFixedSelector: null,
20
+ positionFixedClass: "is-position-fixed",
21
+ fixedSidebarOffset: "auto",
22
+ includeHtml: false,
23
+ includeTitleTags: false,
24
+ orderedList: true,
25
+ scrollContainer: null,
26
+ skipRendering: false,
27
+ headingLabelCallback: false,
28
+ ignoreHiddenElements: false,
29
+ headingObjectCallback: null,
30
+ basePath: "",
31
+ disableTocScrollSync: false,
32
+ };
33
+
34
+ function ParseContent(options) {
35
+ var reduce = [].reduce;
36
+
37
+ /**
38
+ * Get the last item in an array and return a reference to it.
39
+ * @param {Array} array
40
+ * @return {Object}
41
+ */
42
+ function getLastItem(array) {
43
+ return array[array.length - 1];
44
+ }
45
+
46
+ /**
47
+ * Get heading level for a heading dom node.
48
+ * @param {HTMLElement} heading
49
+ * @return {Number}
50
+ */
51
+ function getHeadingLevel(heading) {
52
+ return Number(heading.nodeName.toUpperCase().replace("H", ""));
53
+ }
54
+
55
+ /**
56
+ * Get important properties from a heading element and store in a plain object.
57
+ * @param {HTMLElement} heading
58
+ * @return {Object}
59
+ */
60
+ function getHeadingObject(heading) {
61
+ // each node is processed twice by this method because nestHeadingsArray() and addNode() calls it
62
+ // first time heading is real DOM node element, second time it is obj
63
+ // that is causing problem so I am processing only original DOM node
64
+ if (!(heading instanceof window.HTMLElement)) return heading;
65
+
66
+ if (
67
+ options.ignoreHiddenElements &&
68
+ (!heading.offsetHeight || !heading.offsetParent)
69
+ ) {
70
+ return null;
71
+ }
72
+
73
+ const headingLabel =
74
+ heading.getAttribute("data-heading-label") ||
75
+ (options.headingLabelCallback
76
+ ? String(options.headingLabelCallback(heading.textContent))
77
+ : heading.textContent.trim());
78
+ var obj = {
79
+ id: heading.id,
80
+ children: [],
81
+ nodeName: heading.nodeName,
82
+ headingLevel: getHeadingLevel(heading),
83
+ textContent: headingLabel,
84
+ };
85
+
86
+ if (options.includeHtml) {
87
+ obj.childNodes = heading.childNodes;
88
+ }
89
+
90
+ if (options.headingObjectCallback) {
91
+ return options.headingObjectCallback(obj, heading);
92
+ }
93
+
94
+ return obj;
95
+ }
96
+
97
+ /**
98
+ * Add a node to the nested array.
99
+ * @param {Object} node
100
+ * @param {Array} nest
101
+ * @return {Array}
102
+ */
103
+ function addNode(node, nest) {
104
+ var obj = getHeadingObject(node);
105
+ var level = obj.headingLevel;
106
+ var array = nest;
107
+ var lastItem = getLastItem(array);
108
+ var lastItemLevel = lastItem ? lastItem.headingLevel : 0;
109
+ var counter = level - lastItemLevel;
110
+
111
+ while (counter > 0) {
112
+ lastItem = getLastItem(array);
113
+ // Handle case where there are multiple h5+ in a row.
114
+ if (lastItem && level === lastItem.headingLevel) {
115
+ break;
116
+ } else if (lastItem && lastItem.children !== undefined) {
117
+ array = lastItem.children;
118
+ }
119
+ counter--;
120
+ }
121
+
122
+ if (level >= options.collapseDepth) {
123
+ obj.isCollapsed = true;
124
+ }
125
+
126
+ array.push(obj);
127
+ return array;
128
+ }
129
+
130
+ /**
131
+ * Select headings in content area, exclude any selector in options.ignoreSelector
132
+ * @param {HTMLElement} contentElement
133
+ * @param {Array} headingSelector
134
+ * @return {Array}
135
+ */
136
+ function selectHeadings(contentElement, headingSelector) {
137
+ var selectors = headingSelector;
138
+ if (options.ignoreSelector) {
139
+ selectors = headingSelector
140
+ .split(",")
141
+ .map(function mapSelectors(selector) {
142
+ return selector.trim() + ":not(" + options.ignoreSelector + ")";
143
+ });
144
+ }
145
+ try {
146
+ return contentElement.querySelectorAll(selectors);
147
+ } catch (e) {
148
+ console.warn('Headers not found with selector: ' + selectors); // eslint-disable-line
149
+ return null;
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Nest headings array into nested arrays with 'children' property.
155
+ * @param {Array} headingsArray
156
+ * @return {Object}
157
+ */
158
+ function nestHeadingsArray(headingsArray) {
159
+ return reduce.call(
160
+ headingsArray,
161
+ function reducer(prev, curr) {
162
+ var currentHeading = getHeadingObject(curr);
163
+ if (currentHeading) {
164
+ addNode(currentHeading, prev.nest);
165
+ }
166
+ return prev;
167
+ },
168
+ {
169
+ nest: [],
170
+ }
171
+ );
172
+ }
173
+
174
+ return {
175
+ nestHeadingsArray: nestHeadingsArray,
176
+ selectHeadings: selectHeadings,
177
+ };
178
+ }
179
+
180
+ function BuildHtml(options) {
181
+ var forEach = [].forEach;
182
+ var some = [].some;
183
+ var body = document.body;
184
+ var tocElement;
185
+ var mainContainer = document.querySelector(options.contentSelector);
186
+ var currentlyHighlighting = true;
187
+ var SPACE_CHAR = " ";
188
+
189
+ /**
190
+ * Create link and list elements.
191
+ * @param {Object} d
192
+ * @param {HTMLElement} container
193
+ * @return {HTMLElement}
194
+ */
195
+ function createEl(d, container) {
196
+ var link = container.appendChild(createLink(d));
197
+ if (d.children.length) {
198
+ var list = createList(d.isCollapsed);
199
+ d.children.forEach(function (child) {
200
+ createEl(child, list);
201
+ });
202
+ link.appendChild(list);
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Render nested heading array data into a given element.
208
+ * @param {HTMLElement} parent Optional. If provided updates the {@see tocElement} to match.
209
+ * @param {Array} data
210
+ * @return {HTMLElement}
211
+ */
212
+ function render(parent, data) {
213
+ var collapsed = false;
214
+ var container = createList(collapsed);
215
+
216
+ data.forEach(function (d) {
217
+ createEl(d, container);
218
+ });
219
+
220
+ // Return if no TOC element is provided or known.
221
+ tocElement = parent || tocElement;
222
+ if (tocElement === null) {
223
+ return;
224
+ }
225
+
226
+ // Remove existing child if it exists.
227
+ if (tocElement.firstChild) {
228
+ tocElement.removeChild(tocElement.firstChild);
229
+ }
230
+
231
+ // Just return the parent and don't append the list if no links are found.
232
+ if (data.length === 0) {
233
+ return tocElement;
234
+ }
235
+
236
+ // Append the Elements that have been created
237
+ return tocElement.appendChild(container);
238
+ }
239
+
240
+ /**
241
+ * Create link element.
242
+ * @param {Object} data
243
+ * @return {HTMLElement}
244
+ */
245
+ function createLink(data) {
246
+ var item = document.createElement("li");
247
+ var a = document.createElement("a");
248
+ if (options.listItemClass) {
249
+ item.setAttribute("class", options.listItemClass);
250
+ }
251
+
252
+ if (options.onClick) {
253
+ a.onclick = options.onClick;
254
+ }
255
+
256
+ if (options.includeTitleTags) {
257
+ a.setAttribute("title", data.textContent);
258
+ }
259
+
260
+ if (options.includeHtml && data.childNodes.length) {
261
+ forEach.call(data.childNodes, function (node) {
262
+ a.appendChild(node.cloneNode(true));
263
+ });
264
+ } else {
265
+ // Default behavior.
266
+ a.textContent = data.textContent;
267
+ }
268
+ a.setAttribute("href", options.basePath + "#" + data.id);
269
+ a.setAttribute(
270
+ "class",
271
+ options.linkClass +
272
+ SPACE_CHAR +
273
+ "node-name--" +
274
+ data.nodeName +
275
+ SPACE_CHAR +
276
+ options.extraLinkClasses
277
+ );
278
+ item.appendChild(a);
279
+ return item;
280
+ }
281
+
282
+ /**
283
+ * Create list element.
284
+ * @param {Boolean} isCollapsed
285
+ * @return {HTMLElement}
286
+ */
287
+ function createList(isCollapsed) {
288
+ var listElement = options.orderedList ? "ol" : "ul";
289
+ var list = document.createElement(listElement);
290
+ var classes = options.listClass + SPACE_CHAR + options.extraListClasses;
291
+ if (isCollapsed) {
292
+ classes += SPACE_CHAR + options.collapsibleClass;
293
+ classes += SPACE_CHAR + options.isCollapsedClass;
294
+ }
295
+ list.setAttribute("class", classes);
296
+ return list;
297
+ }
298
+
299
+ /**
300
+ * Update fixed sidebar class.
301
+ * @return {HTMLElement}
302
+ */
303
+ function updateFixedSidebarClass() {
304
+ if (
305
+ options.scrollContainer &&
306
+ document.querySelector(options.scrollContainer)
307
+ ) {
308
+ var top;
309
+ top = document.querySelector(options.scrollContainer).scrollTop;
310
+ } else {
311
+ top = document.documentElement.scrollTop || body.scrollTop;
312
+ }
313
+ var posFixedEl = document.querySelector(options.positionFixedSelector);
314
+
315
+ if (options.fixedSidebarOffset === "auto") {
316
+ options.fixedSidebarOffset = tocElement.offsetTop;
317
+ }
318
+
319
+ if (top > options.fixedSidebarOffset) {
320
+ if (posFixedEl.className.indexOf(options.positionFixedClass) === -1) {
321
+ posFixedEl.className += SPACE_CHAR + options.positionFixedClass;
322
+ }
323
+ } else {
324
+ posFixedEl.className = posFixedEl.className
325
+ .split(SPACE_CHAR + options.positionFixedClass)
326
+ .join("");
327
+ }
328
+ }
329
+
330
+ /**
331
+ * Get top position of heading
332
+ * @param {HTMLElement} obj
333
+ * @return {int} position
334
+ */
335
+ function getHeadingTopPos(obj) {
336
+ var position = 0;
337
+ if (obj !== null) {
338
+ position = obj.offsetTop;
339
+ if (options.hasInnerContainers) {
340
+ position += getHeadingTopPos(obj.offsetParent);
341
+ }
342
+ }
343
+ return position;
344
+ }
345
+
346
+ function updateListActiveElement(topHeader) {
347
+ var forEach = [].forEach;
348
+
349
+ var tocLinks = tocElement.querySelectorAll("." + options.linkClass);
350
+ forEach.call(tocLinks, function (tocLink) {
351
+ tocLink.className = tocLink.className
352
+ .split(SPACE_CHAR + options.activeLinkClass)
353
+ .join("");
354
+ });
355
+ var tocLis = tocElement.querySelectorAll("." + options.listItemClass);
356
+ forEach.call(tocLis, function (tocLi) {
357
+ tocLi.className = tocLi.className
358
+ .split(SPACE_CHAR + options.activeListItemClass)
359
+ .join("");
360
+ });
361
+
362
+ // Add the active class to the active tocLink.
363
+ var activeTocLink = tocElement.querySelector(
364
+ "." +
365
+ options.linkClass +
366
+ ".node-name--" +
367
+ topHeader.nodeName +
368
+ '[href="' +
369
+ options.basePath +
370
+ "#" +
371
+ topHeader.id.replace(/([ #;&,.+*~':"!^$[\]()=>|/@])/g, "\\$1") +
372
+ '"]'
373
+ );
374
+ if (
375
+ activeTocLink &&
376
+ activeTocLink.className.indexOf(options.activeLinkClass) === -1
377
+ ) {
378
+ activeTocLink.className += SPACE_CHAR + options.activeLinkClass;
379
+ }
380
+ var li = activeTocLink && activeTocLink.parentNode;
381
+ if (li && li.className.indexOf(options.activeListItemClass) === -1) {
382
+ li.className += SPACE_CHAR + options.activeListItemClass;
383
+ }
384
+
385
+ var tocLists = tocElement.querySelectorAll(
386
+ "." + options.listClass + "." + options.collapsibleClass
387
+ );
388
+
389
+ // Collapse the other collapsible lists.
390
+ forEach.call(tocLists, function (list) {
391
+ if (list.className.indexOf(options.isCollapsedClass) === -1) {
392
+ list.className += SPACE_CHAR + options.isCollapsedClass;
393
+ }
394
+ });
395
+
396
+ // Expand the active link's collapsible list and its sibling if applicable.
397
+ if (
398
+ activeTocLink &&
399
+ activeTocLink.nextSibling &&
400
+ activeTocLink.nextSibling.className.indexOf(options.isCollapsedClass) !==
401
+ -1
402
+ ) {
403
+ activeTocLink.nextSibling.className = activeTocLink.nextSibling.className
404
+ .split(SPACE_CHAR + options.isCollapsedClass)
405
+ .join("");
406
+ }
407
+ removeCollapsedFromParents(
408
+ activeTocLink && activeTocLink.parentNode.parentNode
409
+ );
410
+ }
411
+
412
+ /**
413
+ * Update TOC highlighting and collpased groupings.
414
+ */
415
+ function updateToc(headingsArray) {
416
+ // If a fixed content container was set
417
+ if (
418
+ options.scrollContainer &&
419
+ document.querySelector(options.scrollContainer)
420
+ ) {
421
+ var top;
422
+ top = document.querySelector(options.scrollContainer).scrollTop;
423
+ } else {
424
+ top = document.documentElement.scrollTop || body.scrollTop;
425
+ }
426
+
427
+ // Add fixed class at offset
428
+ if (options.positionFixedSelector) {
429
+ updateFixedSidebarClass();
430
+ }
431
+
432
+ // Get the top most heading currently visible on the page so we know what to highlight.
433
+ var headings = headingsArray;
434
+ var topHeader;
435
+ // Using some instead of each so that we can escape early.
436
+ if (currentlyHighlighting && tocElement !== null && headings.length > 0) {
437
+ some.call(headings, function (heading, i) {
438
+ var modifiedTopOffset = top + 10;
439
+ if (mainContainer) {
440
+ modifiedTopOffset +=
441
+ (mainContainer.clientHeight * mainContainer.scrollTop) /
442
+ (mainContainer.scrollHeight - mainContainer.clientHeight);
443
+ }
444
+ if (getHeadingTopPos(heading) > modifiedTopOffset) {
445
+ // Don't allow negative index value.
446
+ var index = i === 0 ? i : i - 1;
447
+ topHeader = headings[index];
448
+ return true;
449
+ } else if (i === headings.length - 1) {
450
+ // This allows scrolling for the last heading on the page.
451
+ topHeader = headings[headings.length - 1];
452
+ return true;
453
+ }
454
+ });
455
+
456
+ // Remove the active class from the other tocLinks.
457
+ updateListActiveElement(topHeader);
458
+ }
459
+ }
460
+
461
+ /**
462
+ * Remove collpased class from parent elements.
463
+ * @param {HTMLElement} element
464
+ * @return {HTMLElement}
465
+ */
466
+ function removeCollapsedFromParents(element) {
467
+ if (
468
+ element &&
469
+ element.className.indexOf(options.collapsibleClass) !== -1 &&
470
+ element.className.indexOf(options.isCollapsedClass) !== -1
471
+ ) {
472
+ element.className = element.className
473
+ .split(SPACE_CHAR + options.isCollapsedClass)
474
+ .join("");
475
+ return removeCollapsedFromParents(element.parentNode.parentNode);
476
+ }
477
+ return element;
478
+ }
479
+
480
+ /**
481
+ * Disable TOC Animation when a link is clicked.
482
+ * @param {Event} event
483
+ */
484
+ function disableTocAnimation(event) {
485
+ var target = event.target || event.srcElement;
486
+ if (
487
+ typeof target.className !== "string" ||
488
+ target.className.indexOf(options.linkClass) === -1
489
+ ) {
490
+ return;
491
+ }
492
+ // Bind to tocLink clicks to temporarily disable highlighting
493
+ // while smoothScroll is animating.
494
+ currentlyHighlighting = false;
495
+ }
496
+
497
+ /**
498
+ * Enable TOC Animation.
499
+ */
500
+ function enableTocAnimation() {
501
+ currentlyHighlighting = true;
502
+ }
503
+
504
+ return {
505
+ enableTocAnimation: enableTocAnimation,
506
+ disableTocAnimation: disableTocAnimation,
507
+ render: render,
508
+ updateToc: updateToc,
509
+ updateListActiveElement: updateListActiveElement,
510
+ };
511
+ }
512
+
513
+ function updateTocScroll(options) {
514
+ var toc = options.tocElement || document.querySelector(options.tocSelector);
515
+ if (toc && toc.scrollHeight > toc.clientHeight) {
516
+ var activeItem = toc.querySelector("." + options.activeListItemClass);
517
+ if (activeItem) {
518
+ var topOffset = toc.getBoundingClientRect().top;
519
+ toc.scrollTop = activeItem.offsetTop - topOffset;
520
+ }
521
+ }
522
+ }
523
+
524
+ (function (root, factory) {
525
+ if (typeof define === "function" && define.amd) {
526
+ define([], factory(root));
527
+ } else if (typeof exports === "object") {
528
+ module.exports = factory(root);
529
+ } else {
530
+ root.tocbot = factory(root);
531
+ }
532
+ })(
533
+ typeof global !== "undefined" ? global : this.window || this.global,
534
+ function (root) {
535
+ var options = {};
536
+ var tocbot = {};
537
+ var buildHtml;
538
+ var parseContent;
539
+
540
+ // Just return if its not a browser.
541
+ var supports =
542
+ Boolean(root) &&
543
+ Boolean(root.document) &&
544
+ Boolean(root.document.querySelector) &&
545
+ Boolean(root.addEventListener); // Feature test
546
+ if (typeof window === "undefined" && !supports) {
547
+ return;
548
+ }
549
+ var headingsArray;
550
+
551
+ // From: https://github.com/Raynos/xtend
552
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
553
+ function extend() {
554
+ var target = {};
555
+ for (var i = 0; i < arguments.length; i++) {
556
+ var source = arguments[i];
557
+ for (var key in source) {
558
+ if (hasOwnProperty.call(source, key)) {
559
+ target[key] = source[key];
560
+ }
561
+ }
562
+ }
563
+ return target;
564
+ }
565
+
566
+ // From: https://remysharp.com/2010/07/21/throttling-function-calls
567
+ function throttle(fn, threshhold, scope) {
568
+ threshhold || (threshhold = 250);
569
+ var last;
570
+ var deferTimer;
571
+ return function () {
572
+ var context = scope || this;
573
+ var now = Number(new Date());
574
+ var args = arguments;
575
+ if (last && now < last + threshhold) {
576
+ // hold on to it
577
+ clearTimeout(deferTimer);
578
+ deferTimer = setTimeout(function () {
579
+ last = now;
580
+ fn.apply(context, args);
581
+ }, threshhold);
582
+ } else {
583
+ last = now;
584
+ fn.apply(context, args);
585
+ }
586
+ };
587
+ }
588
+
589
+ function getContentElement(options) {
590
+ try {
591
+ return (
592
+ options.contentElement ||
593
+ document.querySelector(options.contentSelector)
594
+ );
595
+ } catch (e) {
596
+ console.warn('Contents element not found: ' + options.contentSelector) // eslint-disable-line
597
+ return null;
598
+ }
599
+ }
600
+
601
+ function getTocElement(options) {
602
+ try {
603
+ return (
604
+ options.tocElement || document.querySelector(options.tocSelector)
605
+ );
606
+ } catch (e) {
607
+ console.warn('TOC element not found: ' + options.tocSelector) // eslint-disable-line
608
+ return null;
609
+ }
610
+ }
611
+
612
+ /**
613
+ * Destroy tocbot.
614
+ */
615
+ tocbot.destroy = function () {
616
+ var tocElement = getTocElement(options);
617
+ if (tocElement === null) {
618
+ return;
619
+ }
620
+
621
+ if (!options.skipRendering) {
622
+ // Clear HTML.
623
+ if (tocElement) {
624
+ tocElement.innerHTML = "";
625
+ }
626
+ }
627
+
628
+ // Remove event listeners.
629
+ if (
630
+ options.scrollContainer &&
631
+ document.querySelector(options.scrollContainer)
632
+ ) {
633
+ document
634
+ .querySelector(options.scrollContainer)
635
+ .removeEventListener("scroll", this._scrollListener, false);
636
+ document
637
+ .querySelector(options.scrollContainer)
638
+ .removeEventListener("resize", this._scrollListener, false);
639
+ } else {
640
+ document.removeEventListener("scroll", this._scrollListener, false);
641
+ document.removeEventListener("resize", this._scrollListener, false);
642
+ }
643
+ };
644
+
645
+ /**
646
+ * Initialize tocbot.
647
+ * @param {object} customOptions
648
+ */
649
+ tocbot.init = function (customOptions) {
650
+ // feature test
651
+ if (!supports) {
652
+ return;
653
+ }
654
+
655
+ // Merge defaults with user options.
656
+ // Set to options variable at the top.
657
+ options = extend(defaultOptions, customOptions || {});
658
+ this.options = options;
659
+ this.state = {};
660
+
661
+ // Init smooth scroll if enabled (default).
662
+ if (options.scrollSmooth) {
663
+ options.duration = options.scrollSmoothDuration;
664
+ options.offset = options.scrollSmoothOffset;
665
+ }
666
+
667
+ // Pass options to these modules.
668
+ buildHtml = BuildHtml(options);
669
+ parseContent = ParseContent(options);
670
+
671
+ // For testing purposes.
672
+ this._buildHtml = buildHtml;
673
+ this._parseContent = parseContent;
674
+ this._headingsArray = headingsArray;
675
+ this.updateTocListActiveElement = buildHtml.updateListActiveElement;
676
+
677
+ // Destroy it if it exists first.
678
+ tocbot.destroy();
679
+
680
+ var contentElement = getContentElement(options);
681
+ if (contentElement === null) {
682
+ return;
683
+ }
684
+
685
+ var tocElement = getTocElement(options);
686
+ if (tocElement === null) {
687
+ return;
688
+ }
689
+
690
+ // Get headings array.
691
+ headingsArray = parseContent.selectHeadings(
692
+ contentElement,
693
+ options.headingSelector
694
+ );
695
+ // Return if no headings are found.
696
+ if (headingsArray === null) {
697
+ return;
698
+ }
699
+
700
+ // Build nested headings array.
701
+ var nestedHeadingsObj = parseContent.nestHeadingsArray(headingsArray);
702
+ var nestedHeadings = nestedHeadingsObj.nest;
703
+
704
+ // Render.
705
+ if (!options.skipRendering) {
706
+ buildHtml.render(tocElement, nestedHeadings);
707
+ }
708
+
709
+ // Update Sidebar and bind listeners.
710
+ this._scrollListener = throttle(function (e) {
711
+ buildHtml.updateToc(headingsArray);
712
+ !options.disableTocScrollSync && updateTocScroll(options);
713
+ var isTop =
714
+ e &&
715
+ e.target &&
716
+ e.target.scrollingElement &&
717
+ e.target.scrollingElement.scrollTop === 0;
718
+ if ((e && (e.eventPhase === 0 || e.currentTarget === null)) || isTop) {
719
+ buildHtml.updateToc(headingsArray);
720
+ if (options.scrollEndCallback) {
721
+ options.scrollEndCallback(e);
722
+ }
723
+ }
724
+ }, options.throttleTimeout);
725
+ this._scrollListener();
726
+ if (
727
+ options.scrollContainer &&
728
+ document.querySelector(options.scrollContainer)
729
+ ) {
730
+ document
731
+ .querySelector(options.scrollContainer)
732
+ .addEventListener("scroll", this._scrollListener, false);
733
+ document
734
+ .querySelector(options.scrollContainer)
735
+ .addEventListener("resize", this._scrollListener, false);
736
+ } else {
737
+ document.addEventListener("scroll", this._scrollListener, false);
738
+ document.addEventListener("resize", this._scrollListener, false);
739
+ }
740
+
741
+ return this;
742
+ };
743
+
744
+ /**
745
+ * Refresh tocbot.
746
+ */
747
+ tocbot.refresh = function (customOptions) {
748
+ tocbot.destroy();
749
+ tocbot.init(customOptions || this.options);
750
+ };
751
+
752
+ // Make tocbot available globally.
753
+ root.tocbot = tocbot;
754
+
755
+ return tocbot;
756
+ }
757
+ );