1 /* global addClass, hasClass, removeClass, onEachLazy */
6 // Number of lines shown when code viewer is not expanded.
7 // DEFAULT is the first example shown by default, while HIDDEN is
8 // the examples hidden beneath the "More examples" toggle.
10 // NOTE: these values MUST be synchronized with certain rules in rustdoc.css!
11 const DEFAULT_MAX_LINES = 5;
12 const HIDDEN_MAX_LINES = 10;
14 // Scroll code block to the given code location
15 function scrollToLoc(elt, loc, isHidden) {
16 const lines = elt.querySelector(".src-line-numbers");
19 // If the block is greater than the size of the viewer,
20 // then scroll to the top of the block. Otherwise scroll
21 // to the middle of the block.
22 const maxLines = isHidden ? HIDDEN_MAX_LINES : DEFAULT_MAX_LINES;
23 if (loc[1] - loc[0] > maxLines) {
24 const line = Math.max(0, loc[0] - 1);
25 scrollOffset = lines.children[line].offsetTop;
27 const wrapper = elt.querySelector(".code-wrapper");
28 const halfHeight = wrapper.offsetHeight / 2;
29 const offsetTop = lines.children[loc[0]].offsetTop;
30 const lastLine = lines.children[loc[1]];
31 const offsetBot = lastLine.offsetTop + lastLine.offsetHeight;
32 const offsetMid = (offsetTop + offsetBot) / 2;
33 scrollOffset = offsetMid - halfHeight;
36 lines.scrollTo(0, scrollOffset);
37 elt.querySelector(".rust").scrollTo(0, scrollOffset);
40 function updateScrapedExample(example, isHidden) {
41 const locs = JSON.parse(example.attributes.getNamedItem("data-locs").textContent);
43 const highlights = Array.prototype.slice.call(example.querySelectorAll(".highlight"));
44 const link = example.querySelector(".scraped-example-title a");
46 if (locs.length > 1) {
47 // Toggle through list of examples in a given file
48 const onChangeLoc = changeIndex => {
49 removeClass(highlights[locIndex], "focus");
51 scrollToLoc(example, locs[locIndex][0], isHidden);
52 addClass(highlights[locIndex], "focus");
54 const url = locs[locIndex][1];
55 const title = locs[locIndex][2];
58 link.innerHTML = title;
61 example.querySelector(".prev")
62 .addEventListener("click", () => {
64 locIndex = (locIndex - 1 + locs.length) % locs.length;
68 example.querySelector(".next")
69 .addEventListener("click", () => {
71 locIndex = (locIndex + 1) % locs.length;
76 const expandButton = example.querySelector(".expand");
78 expandButton.addEventListener("click", () => {
79 if (hasClass(example, "expanded")) {
80 removeClass(example, "expanded");
81 scrollToLoc(example, locs[0][0], isHidden);
83 addClass(example, "expanded");
88 // Start with the first example in view
89 scrollToLoc(example, locs[0][0], isHidden);
92 const firstExamples = document.querySelectorAll(".scraped-example-list > .scraped-example");
93 onEachLazy(firstExamples, el => updateScrapedExample(el, false));
94 onEachLazy(document.querySelectorAll(".more-examples-toggle"), toggle => {
95 // Allow users to click the left border of the <details> section to close it,
96 // since the section can be large and finding the [+] button is annoying.
97 onEachLazy(toggle.querySelectorAll(".toggle-line, .hide-more"), button => {
98 button.addEventListener("click", () => {
103 const moreExamples = toggle.querySelectorAll(".scraped-example");
104 toggle.querySelector("summary").addEventListener("click", () => {
105 // Wrapping in setTimeout ensures the update happens after the elements are actually
106 // visible. This is necessary since updateScrapedExample calls scrollToLoc which
107 // depends on offsetHeight, a property that requires an element to be visible to
108 // compute correctly.
110 onEachLazy(moreExamples, el => updateScrapedExample(el, true));