forked from executablebooks/sphinx-book-theme
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
227 lines (213 loc) · 6.78 KB
/
index.js
File metadata and controls
227 lines (213 loc) · 6.78 KB
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
// Import CSS variables
// ref: https://css-tricks.com/getting-javascript-to-talk-to-css-and-sass/
import "../styles/index.scss";
/**
* A helper function to load scripts when the DOM is loaded.
* This waits for everything to be on the page first before running, since
* some functionality doesn't behave properly until everything is ready.
*/
var sbRunWhenDOMLoaded = (cb) => {
if (document.readyState != "loading") {
cb();
} else if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", cb);
} else {
document.attachEvent("onreadystatechange", function () {
if (document.readyState == "complete") cb();
});
}
};
/**
* Toggle full-screen with button
*
* There are some browser-specific hacks in here:
* - Safari requires a `webkit` prefix, so this uses conditionals to check for that
* ref: https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API
*/
var toggleFullScreen = () => {
var isInFullScreen =
(document.fullscreenElement && document.fullscreenElement !== null) ||
(document.webkitFullscreenElement &&
document.webkitFullscreenElement !== null);
let docElm = document.documentElement;
if (!isInFullScreen) {
console.log("[SBT]: Entering full screen");
if (docElm.requestFullscreen) {
docElm.requestFullscreen();
} else if (docElm.webkitRequestFullscreen) {
docElm.webkitRequestFullscreen();
}
} else {
console.log("[SBT]: Exiting full screen");
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
}
}
};
/**
* Sidebar scroll on load.
*
* Detect the active page in the sidebar, and scroll so that it is centered on
* the screen.
*/
var scrollToActive = () => {
var navbar = document.getElementById("site-navigation");
var active_pages = navbar.querySelectorAll(".active");
var active_page = active_pages[active_pages.length - 1];
// Only scroll the navbar if the active link is lower than 50% of the page
if (
active_page !== undefined &&
active_page.offsetTop > $(window).height() * 0.5
) {
navbar.scrollTop = active_page.offsetTop - $(window).height() * 0.2;
}
};
/**
* Called when the "print to PDF" button is clicked.
* This is a hack to prevent tooltips from showing up in the printed PDF.
*/
var printPdf = (el) => {
// Detach the tooltip text from DOM to hide in PDF
// and then reattach it for HTML
let tooltipID = $(el).attr("aria-describedby");
let tooltipTextDiv = $("#" + tooltipID).detach();
window.print();
$("body").append(tooltipTextDiv);
};
/**
* Manage scrolling behavior. This is primarily two things:
*
* 1. Hide the Table of Contents any time sidebar content is on the screen.
*
* This will be triggered any time a sidebar item enters or exits the screen.
* It adds/removes items from an array if they have entered the screen, and
* removes them when they exit the screen. It hides the TOC if anything is
* on-screen.
*
* ref: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
*
* 2. Add a `scrolled` class to <body> to trigger CSS changes.
*/
var initTocHide = () => {
var onScreenItems = [];
let hideTocCallback = (entries, observer) => {
// Check whether any sidebar item is displayed
entries.forEach((entry) => {
if (entry.isIntersecting) {
// If an element just came on screen, add it our list
onScreenItems.push(entry.target);
} else {
// Otherwise, if it's in our list then remove it
for (let ii = 0; ii < onScreenItems.length; ii++) {
if (onScreenItems[ii] === entry.target) {
onScreenItems.splice(ii, 1);
break;
}
}
}
});
// Hide the TOC if any margin content is displayed on the screen
if (onScreenItems.length > 0) {
$("div.bd-toc").removeClass("show");
} else {
$("div.bd-toc").addClass("show");
}
};
let manageScrolledClassOnBody = (entries, observer) => {
// The pixel is at the top, so if we're < 0 that it means we've scrolled
if (entries[0].boundingClientRect.y < 0) {
document.body.classList.add("scrolled");
} else {
document.body.classList.remove("scrolled");
}
};
// Set up the intersection observer to watch all margin content
let tocObserver = new IntersectionObserver(hideTocCallback);
const selectorClasses = [
"marginnote",
"sidenote",
"margin",
"margin-caption",
"full-width",
"sidebar",
"popout",
];
let marginSelector = [];
selectorClasses.forEach((ii) => {
// Use three permutations of each class name because `tag_` and `_` used to be supported
marginSelector.push(
...[
`.${ii}`,
`.tag_${ii}`,
`.${ii.replace("-", "_")}`,
`.tag_${ii.replace("-", "_")}`,
]
);
});
document.querySelectorAll(marginSelector.join(", ")).forEach((ii) => {
tocObserver.observe(ii);
});
// Set up the observer to check if we've scrolled from top of page
let scrollObserver = new IntersectionObserver(manageScrolledClassOnBody);
scrollObserver.observe(document.querySelector(".sbt-scroll-pixel-helper"));
};
/**
* Activate Thebe with a custom button click.
*/
var initThebeSBT = () => {
var title = $("div.section h1")[0];
if (!$(title).next().hasClass("thebe-launch-button")) {
$("<button class='thebe-launch-button'></button>").insertAfter($(title));
}
initThebe();
};
/**
* Use Bootstrap helper function to enable tooltips.
*/
var initTooltips = () => {
$(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip({
trigger: "hover",
delay: { show: 500, hide: 100 },
});
});
};
/**
* MutationObserver to move the ReadTheDocs button
*/
function initRTDObserver() {
const mutatedCallback = (mutationList, observer) => {
mutationList.forEach((mutation) => {
// Check whether the mutation is for RTD, which will have a specific structure
if (mutation.addedNodes.length === 0) {
return;
}
if (mutation.addedNodes[0].data === undefined) {
return;
}
if (mutation.addedNodes[0].data.search("Inserted RTD Footer") != -1) {
mutation.addedNodes.forEach((node) => {
document.getElementById("rtd-footer-container").append(node);
});
}
});
};
const observer = new MutationObserver(mutatedCallback);
const config = { childList: true };
observer.observe(document.body, config);
}
/**
* Set up callback functions for UI click actions
*/
window.initThebeSBT = initThebeSBT;
window.printPdf = printPdf;
window.toggleFullScreen = toggleFullScreen;
/**
* Set up functions to load when the DOM is ready
*/
sbRunWhenDOMLoaded(initTooltips);
sbRunWhenDOMLoaded(scrollToActive);
sbRunWhenDOMLoaded(initTocHide);
sbRunWhenDOMLoaded(initRTDObserver);