Skip to content

Commit 24efa4a

Browse files
committed
perf: move zzo scripts to js files
1 parent 80f10e3 commit 24efa4a

12 files changed

Lines changed: 1612 additions & 0 deletions

File tree

assets/scripts/custom-code-wrappers.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ Array.from(
33
)
44
.forEach((element) => {
55
const codeContainer = element.querySelector(".chroma td:nth-child(2) code");
6+
if (!codeContainer) {
7+
return;
8+
}
69
const label = element.getAttribute("data-code-block-label-override");
10+
if (!label) {
11+
return;
12+
}
713
codeContainer.setAttribute("data-lang", label);
814
});

assets/scripts/params.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
var decodeEntities = (function () {
2+
// this prevents any overhead from creating the object each time
3+
var element = document.createElement("div");
4+
5+
function decodeHTMLEntities(str: string) {
6+
if (str && typeof str === "string") {
7+
// strip script/html tags
8+
str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, "");
9+
str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, "");
10+
element.innerHTML = str;
11+
str = element.textContent;
12+
element.textContent = "";
13+
}
14+
15+
return str;
16+
}
17+
18+
return decodeHTMLEntities;
19+
})();
20+
21+
export const loadParams = (): ParamGetter => {
22+
const dataAttrs = Array.from(document.currentScript!.attributes)
23+
.filter((attr) => attr.name.startsWith("data-"))
24+
.map((
25+
attr,
26+
) => [
27+
attr.name.slice("data-".length).toLowerCase(),
28+
decodeEntities(attr.value),
29+
]);
30+
const _ = new Map(
31+
dataAttrs
32+
.map(([name, value]) => [name, JSON.parse(value)]),
33+
);
34+
return (name: string) => _.get(name.toLowerCase());
35+
};
36+
37+
export type ParamGetter = (name: string) => any;

assets/scripts/zzo/_polyfills.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// forEach
2+
if (window.NodeList && !NodeList.prototype.forEach) {
3+
NodeList.prototype.forEach = Array.prototype.forEach;
4+
}
5+
6+
// includes
7+
if (!String.prototype.includes) {
8+
String.prototype.includes = function (search, start) {
9+
"use strict";
10+
11+
if (search instanceof RegExp) {
12+
throw TypeError("first argument must not be a RegExp");
13+
}
14+
if (start === undefined) start = 0;
15+
return this.indexOf(search, start) !== -1;
16+
};
17+
}
18+
19+
// append
20+
Document.prototype.append = Element.prototype.append = function append() {
21+
this.appendChild(_mutation(arguments));
22+
};
23+
function _mutation(nodes) {
24+
if (!nodes.length) {
25+
throw new Error("DOM Exception 8");
26+
} else if (nodes.length === 1) {
27+
return typeof nodes[0] === "string"
28+
? document.createTextNode(nodes[0])
29+
: nodes[0];
30+
} else {
31+
var fragment = document.createDocumentFragment(),
32+
length = nodes.length,
33+
index = -1,
34+
node;
35+
36+
while (++index < length) {
37+
node = nodes[index];
38+
39+
fragment.appendChild(
40+
typeof node === "string" ? document.createTextNode(node) : node,
41+
);
42+
}
43+
44+
return fragment;
45+
}
46+
}
47+
48+
// startsWith
49+
if (!String.prototype.startsWith) {
50+
String.prototype.startsWith = function (searchString, position) {
51+
position = position || 0;
52+
return this.indexOf(searchString, position) === position;
53+
};
54+
}

assets/scripts/zzo/dom.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export const requiredBySelector = <T extends Element>(selector: string) => {
2+
const elem = document.querySelector<T>(selector);
3+
if (elem) {
4+
return elem;
5+
}
6+
throw new Error(`Missing ${selector}`);
7+
};
8+
export const requiredById = <T extends Element>(id: string) => {
9+
const elem = document.getElementById(id);
10+
if (elem) {
11+
return elem as unknown as T;
12+
}
13+
throw new Error(`Missing ${id}`);
14+
};
15+
let cache: { navbar: HTMLElement };
16+
export const getDom = () => {
17+
if (!cache) {
18+
cache = {
19+
navbar: requiredBySelector<HTMLElement>(".navbar"),
20+
};
21+
}
22+
return cache;
23+
};

assets/scripts/zzo/index.ts

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
// ========================== poiyfill ==========================
2+
import "./_polyfills";
3+
import { loadParams } from "../params";
4+
import { initScroll } from "./scroll";
5+
import { initSearchDesktop } from "./search-desktop";
6+
import { initSearchMobile } from "./search-mobile";
7+
import { initTheme } from "./theme";
8+
import { getDom, requiredById } from "./dom";
9+
// ===============================================================
10+
11+
const param = loadParams();
12+
13+
document.addEventListener("DOMContentLoaded", function () {
14+
// ===================== navbar collapse ======================
15+
const navCollapseBtn = document.querySelector<HTMLElement>(".navbar__burger");
16+
navCollapseBtn
17+
? navCollapseBtn.addEventListener("click", function (e) {
18+
var navCollapse = document.querySelector<HTMLElement>(
19+
".navbarm__collapse",
20+
);
21+
22+
if (navCollapse) {
23+
var dataOpen = navCollapse.getAttribute("data-open");
24+
25+
if (dataOpen === "true") {
26+
navCollapse.setAttribute("data-open", "false");
27+
navCollapse.style.maxHeight = "0";
28+
navCollapseBtn.classList.remove("is-active");
29+
} else {
30+
navCollapse.setAttribute("data-open", "true");
31+
navCollapse.style.maxHeight = navCollapse.scrollHeight + "px";
32+
navCollapseBtn.classList.add("is-active");
33+
}
34+
}
35+
})
36+
: null;
37+
// ============================================================
38+
39+
// ======================== markdown table ====================
40+
var tables = document.querySelectorAll(".single__contents > table");
41+
for (let i = 0; i < tables.length; i++) {
42+
var table = tables[i];
43+
var wrapper = document.createElement("div");
44+
wrapper.className = "table-wrapper";
45+
table.parentElement?.replaceChild(wrapper, table);
46+
wrapper.appendChild(table);
47+
}
48+
// ============================================================
49+
50+
// ========================== foot notes ======================
51+
const { navbar } = getDom();
52+
var footNoteRefs = document.querySelectorAll<HTMLElement>(".footnote-ref");
53+
54+
footNoteRefs
55+
? footNoteRefs.forEach(function (elem, idx) {
56+
elem.onmouseenter = function () {
57+
if (navbar.classList.contains("scrolling")) {
58+
navbar.classList.remove("scrolling");
59+
}
60+
};
61+
62+
elem.onmouseleave = function () {
63+
if (!navbar.classList.contains("scrolling")) {
64+
setTimeout(function () {
65+
navbar.classList.add("scrolling");
66+
}, 100);
67+
}
68+
};
69+
70+
elem.onclick = function () {
71+
if (!navbar.classList.contains("scrolling")) {
72+
navbar.classList.remove("navbar--show");
73+
navbar.classList.remove("navbar--hide");
74+
navbar.classList.add("navbar--hide");
75+
}
76+
};
77+
})
78+
: null;
79+
80+
var footNoteBackRefs = document.querySelectorAll<HTMLElement>(
81+
".footnote-backref",
82+
);
83+
footNoteBackRefs
84+
? footNoteBackRefs.forEach(function (elem, idx) {
85+
elem.onmouseenter = function () {
86+
if (navbar.classList.contains("scrolling")) {
87+
navbar.classList.remove("scrolling");
88+
}
89+
};
90+
91+
elem.onmouseleave = function () {
92+
if (!navbar.classList.contains("scrolling")) {
93+
setTimeout(function () {
94+
navbar.classList.add("scrolling");
95+
}, 100);
96+
}
97+
};
98+
99+
elem.onclick = function () {
100+
if (!navbar.classList.contains("scrolling")) {
101+
navbar.classList.remove("navbar--show");
102+
navbar.classList.remove("navbar--hide");
103+
navbar.classList.add("navbar--hide");
104+
}
105+
};
106+
})
107+
: null;
108+
// ============================================================
109+
110+
// ============================ tab ============================
111+
document.querySelectorAll(".tab")
112+
? document.querySelectorAll(".tab").forEach(function (elem, idx) {
113+
var containerId = elem.getAttribute("id");
114+
var containerElem = elem;
115+
var tabLinks = elem.querySelectorAll<HTMLElement>(".tab__link");
116+
var tabContents = elem.querySelectorAll(".tab__content");
117+
var ids = [];
118+
119+
tabLinks && tabLinks.length > 0
120+
? tabLinks.forEach(function (link, index, self) {
121+
link.onclick = function (e) {
122+
for (var i = 0; i < self.length; i++) {
123+
if (index === parseInt(i, 10)) {
124+
if (!self[i].classList.contains("active")) {
125+
self[i].classList.add("active");
126+
tabContents[i].style.display = "block";
127+
}
128+
} else {
129+
self[i].classList.remove("active");
130+
tabContents[i].style.display = "none";
131+
}
132+
}
133+
};
134+
})
135+
: null;
136+
})
137+
: null;
138+
// =============================================================
139+
140+
// ========================== codetab ==========================
141+
document.querySelectorAll(".codetab")
142+
? document.querySelectorAll(".codetab").forEach(function (elem, idx) {
143+
var containerId = elem.getAttribute("id");
144+
var containerElem = elem;
145+
var codetabLinks = elem.querySelectorAll(".codetab__link");
146+
var codetabContents = elem.querySelectorAll(".codetab__content");
147+
var ids = [];
148+
149+
codetabLinks && codetabLinks.length > 0
150+
? codetabLinks.forEach(function (link, index, self) {
151+
link.onclick = function (e) {
152+
for (var i = 0; i < self.length; i++) {
153+
if (index === parseInt(i, 10)) {
154+
if (!self[i].classList.contains("active")) {
155+
self[i].classList.add("active");
156+
codetabContents[i].style.display = "block";
157+
}
158+
} else {
159+
self[i].classList.remove("active");
160+
codetabContents[i].style.display = "none";
161+
}
162+
}
163+
};
164+
})
165+
: null;
166+
})
167+
: null;
168+
// =============================================================
169+
170+
// ========================= go to top =========================
171+
var gttBtn = requiredById<HTMLElement>("gtt");
172+
gttBtn.style.display = "none";
173+
gttBtn.addEventListener("click", function () {
174+
if (window.document.documentMode) {
175+
document.documentElement.scrollTop = 0;
176+
} else {
177+
scrollToTop(250);
178+
}
179+
});
180+
181+
function scrollToTop(scrollDuration: number) {
182+
var scrollStep = -window.scrollY / (scrollDuration / 15);
183+
var scrollInterval = setInterval(function () {
184+
if (window.scrollY != 0) {
185+
window.scrollBy(0, scrollStep);
186+
} else clearInterval(scrollInterval);
187+
}, 15);
188+
}
189+
// ============================================================
190+
191+
// ========================== expand ==========================
192+
var expandBtn = document.querySelectorAll<HTMLElement>(".expand__button");
193+
194+
for (let i = 0; i < expandBtn.length; i++) {
195+
expandBtn[i].addEventListener("click", function () {
196+
var content = this.nextElementSibling;
197+
if (!content) {
198+
return;
199+
}
200+
if (content.style.maxHeight) {
201+
content.style.maxHeight = null;
202+
this.querySelector("svg").classList.add("expand-icon__right");
203+
this.querySelector("svg").classList.remove("expand-icon__down");
204+
} else {
205+
content.style.maxHeight = content.scrollHeight + "px";
206+
this.querySelector("svg").classList.remove("expand-icon__right");
207+
this.querySelector("svg").classList.add("expand-icon__down");
208+
}
209+
});
210+
}
211+
// ============================================================
212+
213+
// ========================== scroll ==========================
214+
initScroll(param);
215+
// ============================================================
216+
217+
// ======================= theme change =======================
218+
initTheme(param);
219+
// ============================================================
220+
221+
// ========================== search ==========================
222+
initSearchDesktop(param);
223+
// ============================================================
224+
225+
// ====================== mobile search =======================
226+
initSearchMobile();
227+
// ============================================================
228+
229+
// =================== search-result desktop ==================
230+
// ============================================================
231+
});

0 commit comments

Comments
 (0)