-
Notifications
You must be signed in to change notification settings - Fork 3.7k
/
custom.js
131 lines (100 loc) · 3.87 KB
/
custom.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* globals bootstrap:false, Prism:false */
(function () {
'use strict';
// Helper functions
function escapeHtml(html) {
return html.replace(/×/g, '×')
.replace(/«/g, '«')
.replace(/»/g, '»')
.replace(/←/g, '←')
.replace(/→/g, '→');
}
function cleanSource(html) {
// Escape HTML, split the lines to an Array, remove empty elements
// and finally remove the last element
let lines = escapeHtml(html).split('\n').filter(Boolean).slice(0, -1);
const indentSize = lines[0].length - lines[0].trim().length;
const re = new RegExp(' {' + indentSize + '}');
lines = lines.map(line => {
return re.test(line) ? line.slice(Math.max(0, indentSize)) : line;
});
return lines.join('\n');
}
// Add/remove `.navbar-transparent` on scroll; should probably be throttled later
function addNavbarTransparentClass() {
const navBarElement = document.querySelector('#home > .navbar');
if (!navBarElement) {
return;
}
window.addEventListener('scroll', () => {
const scroll = document.documentElement.scrollTop;
if (scroll > 50) {
navBarElement.classList.remove('navbar-transparent');
} else {
navBarElement.classList.add('navbar-transparent');
}
});
}
// Add source modals
function addSourceModals() {
const sourceModalElement = document.getElementById('source-modal');
if (!sourceModalElement) {
return;
}
sourceModalElement.querySelector('.btn-copy').addEventListener('click', (e) => {
if (navigator.clipboard) {
const code = sourceModalElement.querySelector('.modal-body pre').innerText;
navigator.clipboard.writeText(code);
}
const sourceModal = bootstrap.Modal.getOrCreateInstance(sourceModalElement);
sourceModal.hide();
});
document.body.addEventListener('click', event => {
if (!event.target.matches('.source-button')) {
return;
}
const sourceModal = bootstrap.Modal.getOrCreateInstance(sourceModalElement);
let html = event.target.parentNode.innerHTML;
html = Prism.highlight(cleanSource(html), Prism.languages.html, 'html');
sourceModalElement.querySelector('code').innerHTML = html;
sourceModal.show();
}, false);
}
// Toggle light and dark themes
function toggleThemeMenu() {
let themeMenu = document.querySelector('#theme-menu');
if (!themeMenu) return;
document.querySelectorAll('[data-bs-theme-value]').forEach(value => {
value.addEventListener('click', () => {
const theme = value.getAttribute('data-bs-theme-value');
document.documentElement.setAttribute('data-bs-theme', theme);
});
});
}
addNavbarTransparentClass();
addSourceModals();
toggleThemeMenu();
// Prevent empty `a` elements or `submit` buttons from navigating away
const targets = document.querySelectorAll('[href="#"], [type="submit"]');
for (const element of targets) {
element.addEventListener('click', event => {
event.preventDefault();
});
}
// Add the "View Source" buttons in each component
const bsComponents = document.querySelectorAll('.bs-component');
for (const element of bsComponents) {
const button = '<button class="source-button btn btn-primary btn-xs" type="button" tabindex="0"><i class="bi bi-code"></i></button>';
element.insertAdjacentHTML('beforeend', button);
}
// Initialize popovers
const popoverElements = document.querySelectorAll('[data-bs-toggle="popover"]');
for (const popover of popoverElements) {
new bootstrap.Popover(popover); // eslint-disable-line no-new
}
// Initialize tooltips
const tooltipElements = document.querySelectorAll('[data-bs-toggle="tooltip"]');
for (const tooltip of tooltipElements) {
new bootstrap.Tooltip(tooltip); // eslint-disable-line no-new
}
})();