|
1 |
| -"use strict"; |
2 |
| - |
3 |
| -(function () { |
4 |
| - var searchBox = document.getElementById("search-query"); |
5 |
| - var spinner = document.getElementById("search-spinner"); |
6 |
| - var searchResultsContainer = document.getElementById("search-results"); |
7 |
| - |
8 |
| - // Use a worker to download and setup the index in the background. |
9 |
| - var worker = new Worker("/js/search-worker.js"); |
10 |
| - worker.onmessage = function (message) { |
11 |
| - var payload = message.data.payload; |
12 |
| - displaySearchResults(payload.results); |
13 |
| - }; |
14 |
| - |
15 |
| - // Extract the query from the browser's URL. |
16 |
| - var query = getQueryVariable("q"); |
17 |
| - if (query) { |
18 |
| - // Set the search-box's value to the query. |
19 |
| - searchBox.value = query; |
20 |
| - // Update the page title to include the query. |
21 |
| - document.title = query + " - Pulumi"; |
22 |
| - // Kick-off the search by sending a message to the worker. |
23 |
| - worker.postMessage({ type: "search", payload: query }); |
24 |
| - } else { |
25 |
| - // If no query, display empty results. |
26 |
| - displaySearchResults([]); |
27 |
| - } |
28 |
| - |
29 |
| - // Display the results of the search. |
30 |
| - function displaySearchResults(results) { |
31 |
| - // Hide the spinner. |
32 |
| - spinner.style.display = "none"; |
33 |
| - |
34 |
| - if (results.length) { |
35 |
| - // Group the results by category. |
36 |
| - var categoryMap = {}; |
37 |
| - for (var i = 0; i < results.length; i++) { |
38 |
| - var result = results[i]; |
39 |
| - var categoryName = getCategoryName(result.url); |
40 |
| - var category = categoryMap[categoryName] = categoryMap[categoryName] || []; |
41 |
| - prepareResult(result, categoryName); |
42 |
| - category.push(result); |
43 |
| - } |
44 |
| - |
45 |
| - // Build up the HTML to display. |
46 |
| - var appendString = ""; |
47 |
| - for (var i = 0; i < categories.length; i++) { |
48 |
| - var categoryName = categories[i].name; |
49 |
| - var category = categoryMap[categoryName]; |
50 |
| - if (category && category.length > 0) { |
51 |
| - appendString += buildCategoryString(categoryName, category); |
| 1 | +// Swiftype appends the autocomplete results container to the body element, which prevents us |
| 2 | +// from being able to position it in a way that scrolls alongside the other content in the L2 nav. |
| 3 | +// So we listen for DOM changes, and when Swiftype appends the element, we reposition it below the |
| 4 | +// input field. |
| 5 | + |
| 6 | +// Only bother doing this if we're on a page with a search box. |
| 7 | +if (document.querySelector("#search-container")) { |
| 8 | + const observer = new MutationObserver((mutations, observer) => { |
| 9 | + var [ mutation ] = mutations; |
| 10 | + |
| 11 | + // Only bother when nodes are added. |
| 12 | + if (mutation && mutation.addedNodes && mutation.addedNodes.length > 0) { |
| 13 | + const [ newNode ] = mutation.addedNodes; |
| 14 | + |
| 15 | + if (newNode && (typeof newNode.getAttribute === "function") && newNode.getAttribute("id") === "st-injected-content") { |
| 16 | + |
| 17 | + // Find our results container and reparent the Swiftype container with it. |
| 18 | + var resultsContainer = document.querySelector("#search-results"); |
| 19 | + if (resultsContainer) { |
| 20 | + resultsContainer.appendChild(newNode); |
52 | 21 | }
|
| 22 | + |
| 23 | + // Stop listening. |
| 24 | + observer.disconnect(); |
53 | 25 | }
|
54 |
| - searchResultsContainer.innerHTML = appendString; |
55 |
| - } else { |
56 |
| - searchResultsContainer.innerHTML = "<p>No results found.</p>"; |
57 | 26 | }
|
58 |
| - } |
| 27 | + }); |
59 | 28 |
|
60 |
| - var defaultCategory = "Other"; |
61 |
| - var categories = [ |
| 29 | + // Start listening for DOM mutation events. |
| 30 | + observer.observe( |
| 31 | + document.querySelector("body"), |
62 | 32 | {
|
63 |
| - name: "APIs", |
64 |
| - predicate: function (url) { |
65 |
| - return url.startsWith("/docs/reference/pkg/"); |
66 |
| - } |
| 33 | + attributes: false, |
| 34 | + childList: true, // New childNodes are all we care about. |
| 35 | + subtree: false, |
67 | 36 | },
|
68 |
| - { |
69 |
| - name: "CLI", |
70 |
| - predicate: function (url) { |
71 |
| - return url.startsWith("/docs/reference/cli/"); |
72 |
| - } |
73 |
| - }, |
74 |
| - { |
75 |
| - name: "Tutorials", |
76 |
| - predicate: function (url) { |
77 |
| - return url.startsWith("/docs/get-started/") || |
78 |
| - url.startsWith("/docs/tutorials/") || |
79 |
| - url.startsWith("/docs/guides/"); |
80 |
| - } |
81 |
| - }, |
82 |
| - { |
83 |
| - name: defaultCategory, |
84 |
| - predicate: function (url) { |
85 |
| - return true; |
86 |
| - } |
87 |
| - }, |
88 |
| - ]; |
89 |
| - |
90 |
| - function getCategoryName(url) { |
91 |
| - for (var i = 0; i < categories.length; i++) { |
92 |
| - var category = categories[i]; |
93 |
| - if (category.predicate(url)) { |
94 |
| - return category.name; |
95 |
| - } |
96 |
| - } |
97 |
| - return defaultCategory; |
98 |
| - } |
99 |
| - |
100 |
| - function prepareResult(result, categoryName) { |
101 |
| - switch (categoryName) { |
102 |
| - case "APIs": |
103 |
| - if (result.title.startsWith("Module ")) { |
104 |
| - result.display = result.title.substring("Module ".length); |
105 |
| - result.type = "module"; |
106 |
| - return; |
107 |
| - } else if (result.title.startsWith("Package ")) { |
108 |
| - result.display = result.title.substring("Package ".length); |
109 |
| - result.type = "package"; |
110 |
| - return; |
111 |
| - } |
112 |
| - break; |
113 |
| - |
114 |
| - case "CLI": |
115 |
| - if (result.title.length === 0 && result.url.startsWith("/docs/reference/cli/")) { |
116 |
| - var regex = /\/docs\/reference\/cli\/([a-z_]+)/gm; |
117 |
| - var match = regex.exec(result.url) |
118 |
| - if (match !== null) { |
119 |
| - result.display = match[1].replace(/_/g, " "); |
120 |
| - return; |
121 |
| - } |
122 |
| - } |
123 |
| - break; |
124 |
| - } |
125 |
| - |
126 |
| - result.display = result.title || result.url; |
127 |
| - } |
128 |
| - |
129 |
| - function buildCategoryString(categoryName, category) { |
130 |
| - var appendString = "<div class='search-results-category'><h2>" + categoryName + " (" + category.length + ")</h2>"; |
131 |
| - |
132 |
| - // Display the top 5 results first. |
133 |
| - appendString += "<ul>"; |
134 |
| - var topResults = category.splice(0, 5); |
135 |
| - for (var i = 0; i < topResults.length; i++) { |
136 |
| - var item = topResults[i]; |
137 |
| - var prefix = getPrefix(item, categoryName); |
138 |
| - appendString += "<li><a href='" + item.url + "' title='" + item.display + "'>" + prefix + item.display + "</a>"; |
139 |
| - } |
140 |
| - appendString += "</ul>"; |
141 |
| - |
142 |
| - // Now display any remaining results, sorted alphabetically. |
143 |
| - if (category.length > 0) { |
144 |
| - category.sort(function (l, r) { |
145 |
| - return l.display.toUpperCase() > r.display.toUpperCase() ? 1 : -1; |
146 |
| - }); |
147 |
| - appendString += "<ul>"; |
148 |
| - for (var i = 0; i < category.length; i++) { |
149 |
| - var item = category[i]; |
150 |
| - var prefix = getPrefix(item, categoryName); |
151 |
| - appendString += "<li><a href='" + item.url + "'>" + prefix + item.display + "</a>"; |
152 |
| - } |
153 |
| - appendString += "</ul>"; |
154 |
| - } |
155 |
| - |
156 |
| - appendString += "</div>"; |
157 |
| - return appendString; |
158 |
| - } |
159 |
| - |
160 |
| - function getPrefix(result, categoryName) { |
161 |
| - if (result.type) { |
162 |
| - switch (result.type) { |
163 |
| - case "module": |
164 |
| - return "<span class='symbol module' title='Module'></span>"; |
165 |
| - case "package": |
166 |
| - return "<span class='symbol package' title='Package'></span>" |
167 |
| - } |
168 |
| - } |
169 |
| - |
170 |
| - return ""; |
171 |
| - } |
172 |
| -})(); |
| 37 | + ); |
| 38 | +} |
0 commit comments