This repository has been archived by the owner on Feb 2, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 230
/
Copy pathsidebar.js
96 lines (86 loc) · 3.52 KB
/
sidebar.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
export default function sidebar({headersContainer, sidebarContainer, headerStartLevel}) {
const headers = headersContainer.querySelectorAll('h2, h3');
const select = document.createElement('select');
const list = document.createElement('ul');
const startLevel = headerStartLevel; // we start at h2
list.classList.add('no-mobile');
let currentList = list;
let currentLevel = startLevel;
[...headers].forEach(header => {
const level = parseInt(header.tagName.split('')[1], 10);
if (level > currentLevel) {
// we enter a sublist
currentLevel = level;
currentList = currentList.lastChild.appendChild(document.createElement('ul'));
} else if (level < currentLevel) {
// we exit a sublit
currentLevel = level;
currentList = currentList.parentNode.parentNode;
}
const title = header.textContent;
const listItem = document.createElement('li');
const link = document.createElement('a');
link.setAttribute('href', `#${header.getAttribute('id')}`);
link.textContent = title;
listItem.appendChild(link);
currentList.appendChild(listItem);
const option = document.createElement('option');
option.setAttribute('value', link.getAttribute('href'));
option.textContent = `${spacer(currentLevel - startLevel)}${title}`;
select.classList.add('display-on-small');
select.appendChild(option);
});
select.addEventListener('change', e => window.location = e.target.value);
sidebarContainer.appendChild(list);
sidebarContainer.appendChild(select);
sidebarFollowScroll(sidebarContainer);
activeLinks(sidebarContainer);
}
function sidebarFollowScroll(sidebarContainer) {
document.addEventListener('scroll', () => {
// The following code is used to change the color of the navigation
// depending the level of page scroll.
const hero = document.querySelector('.hero-section');
const footer = document.querySelector('.footer-section');
const navigation = document.querySelector('.navigation');
const menu = document.querySelector('.sidebar > ul');
const heroHeight = hero.offsetHeight;
const navHeight = navigation.offsetHeight;
const height = document.body.scrollHeight;
const footerHeight = footer.offsetHeight;
const menuHeight = menu.offsetHeight;
const currentScroll = window.pageYOffset;
const doc = document.querySelector('.documentation-section');
let paddingDoc = window.getComputedStyle(doc, null).getPropertyValue('padding-top').split('px')[0];
paddingDoc = parseInt(paddingDoc, 10);
// Fix the sidebar navigation
if (currentScroll > ((heroHeight - navHeight) + paddingDoc)) {
const fold = height - footerHeight - menuHeight - paddingDoc - 50;
if (currentScroll > fold) {
sidebarContainer.style.top = (fold - currentScroll) + 'px';
} else {
sidebarContainer.style.top = null;
}
sidebarContainer.classList.add('fixed');
} else {
sidebarContainer.classList.remove('fixed');
}
});
}
// The Following code is used to set active items
// On the documentation sidebar depending on the
// clicked item
function activeLinks(sidebarContainer) {
const linksContainer = sidebarContainer.querySelector('ul');
linksContainer.addEventListener('click', e => {
if (e.target.tagName === 'A') {
[...linksContainer.querySelectorAll('a')].forEach(item => item.classList.remove('active'));
e.target.classList.add('active');
}
});
}
function spacer(n) {
if (n === 0) return '';
const arr = new Array(n + 1);
return `${arr.join('-')}> `;
}