• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* global addClass, hasClass, removeClass, onEachLazy */
2
3"use strict";
4
5(function() {
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.
9    //
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;
13
14    // Scroll code block to the given code location
15    function scrollToLoc(elt, loc, isHidden) {
16        const lines = elt.querySelector(".src-line-numbers");
17        let scrollOffset;
18
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;
26        } else {
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;
34        }
35
36        lines.scrollTo(0, scrollOffset);
37        elt.querySelector(".rust").scrollTo(0, scrollOffset);
38    }
39
40    function updateScrapedExample(example, isHidden) {
41        const locs = JSON.parse(example.attributes.getNamedItem("data-locs").textContent);
42        let locIndex = 0;
43        const highlights = Array.prototype.slice.call(example.querySelectorAll(".highlight"));
44        const link = example.querySelector(".scraped-example-title a");
45
46        if (locs.length > 1) {
47            // Toggle through list of examples in a given file
48            const onChangeLoc = changeIndex => {
49                removeClass(highlights[locIndex], "focus");
50                changeIndex();
51                scrollToLoc(example, locs[locIndex][0], isHidden);
52                addClass(highlights[locIndex], "focus");
53
54                const url = locs[locIndex][1];
55                const title = locs[locIndex][2];
56
57                link.href = url;
58                link.innerHTML = title;
59            };
60
61            example.querySelector(".prev")
62                .addEventListener("click", () => {
63                    onChangeLoc(() => {
64                        locIndex = (locIndex - 1 + locs.length) % locs.length;
65                    });
66                });
67
68            example.querySelector(".next")
69                .addEventListener("click", () => {
70                    onChangeLoc(() => {
71                        locIndex = (locIndex + 1) % locs.length;
72                    });
73                });
74        }
75
76        const expandButton = example.querySelector(".expand");
77        if (expandButton) {
78            expandButton.addEventListener("click", () => {
79                if (hasClass(example, "expanded")) {
80                    removeClass(example, "expanded");
81                    scrollToLoc(example, locs[0][0], isHidden);
82                } else {
83                    addClass(example, "expanded");
84                }
85            });
86        }
87
88        // Start with the first example in view
89        scrollToLoc(example, locs[0][0], isHidden);
90    }
91
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", () => {
99                toggle.open = false;
100            });
101        });
102
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.
109            setTimeout(() => {
110                onEachLazy(moreExamples, el => updateScrapedExample(el, true));
111            });
112        }, {once: true});
113    });
114})();
115