|
5 | 5 | var allItems = []; |
6 | 6 | var isEmbedded = false; |
7 | 7 | var isOpen = false; |
| 8 | + var triggersBound = false; |
8 | 9 |
|
9 | 10 | function $(sel, root) { |
10 | 11 | return (root || document).querySelector(sel); |
|
72 | 73 |
|
73 | 74 | function absUrl(url, base) { |
74 | 75 | if (!url) return '#'; |
| 76 | + var root = (base || '/').replace(/"/g, '').replace(/\/+$/, ''); |
75 | 77 | if (/^https?:\/\//.test(url)) return url; |
76 | | - if (url.charAt(0) === '/') return base.replace(/\/?$/, '') + url; |
77 | | - return base + url; |
| 78 | + if (url.charAt(0) === '/') return root + url; |
| 79 | + return root + '/' + url; |
78 | 80 | } |
79 | 81 |
|
80 | 82 | function highlight(text, q) { |
|
127 | 129 | resultsList.hidden = false; |
128 | 130 |
|
129 | 131 | var base = (window.CFD_SEARCH && window.CFD_SEARCH.baseURL) || '/'; |
130 | | - matches.slice(0, 24).forEach(function (item, i) { |
| 132 | + matches.slice(0, 24).forEach(function (item) { |
131 | 133 | var li = document.createElement('li'); |
132 | 134 | li.setAttribute('role', 'option'); |
133 | 135 | var a = document.createElement('a'); |
|
183 | 185 | } |
184 | 186 | } |
185 | 187 |
|
| 188 | + function closeMobileMenu() { |
| 189 | + var menuBtn = document.getElementById('mobile-menu-btn'); |
| 190 | + var menu = document.getElementById('mobile-menu'); |
| 191 | + if (menuBtn && menu && menuBtn.getAttribute('aria-expanded') === 'true') { |
| 192 | + menuBtn.click(); |
| 193 | + } |
| 194 | + } |
| 195 | + |
186 | 196 | function open(query) { |
187 | | - if (!palette || isOpen) return; |
| 197 | + if (!palette) return; |
| 198 | + if (isEmbedded) { |
| 199 | + if (input) { |
| 200 | + input.focus(); |
| 201 | + runSearch(query || input.value || ''); |
| 202 | + } |
| 203 | + return; |
| 204 | + } |
| 205 | + if (isOpen) return; |
| 206 | + |
| 207 | + closeMobileMenu(); |
188 | 208 | isOpen = true; |
| 209 | + palette.removeAttribute('hidden'); |
189 | 210 | palette.hidden = false; |
190 | 211 | palette.setAttribute('aria-hidden', 'false'); |
191 | 212 | document.body.classList.add('search-palette-open'); |
192 | | - if (!isEmbedded) { |
193 | | - requestAnimationFrame(function () { |
194 | | - palette.classList.add('is-visible'); |
195 | | - }); |
196 | | - } else { |
197 | | - palette.classList.add('is-visible', 'search-palette--embedded'); |
198 | | - } |
| 213 | + requestAnimationFrame(function () { |
| 214 | + palette.classList.add('is-visible'); |
| 215 | + }); |
199 | 216 | if (input) { |
200 | 217 | input.value = query || ''; |
201 | 218 | input.focus(); |
202 | 219 | runSearch(input.value); |
203 | 220 | } |
204 | | - var url = new URL(window.location.href); |
205 | | - if (query) url.searchParams.set('q', query); |
206 | | - if (isEmbedded) window.history.replaceState({}, '', url); |
207 | 221 | } |
208 | 222 |
|
209 | 223 | function close() { |
|
214 | 228 | document.body.classList.remove('search-palette-open'); |
215 | 229 | setTimeout(function () { |
216 | 230 | palette.hidden = true; |
| 231 | + palette.setAttribute('hidden', ''); |
217 | 232 | if (input) input.value = ''; |
218 | 233 | renderResults([], ''); |
219 | 234 | }, 200); |
|
237 | 252 | } |
238 | 253 |
|
239 | 254 | function bindTriggers() { |
240 | | - document.querySelectorAll('[data-search-open]').forEach(function (btn) { |
241 | | - btn.addEventListener('click', function (e) { |
242 | | - e.preventDefault(); |
243 | | - open(''); |
244 | | - }); |
245 | | - }); |
246 | | - document.querySelectorAll('[data-search-close]').forEach(function (el) { |
247 | | - el.addEventListener('click', close); |
248 | | - }); |
249 | | - } |
| 255 | + if (triggersBound) return; |
| 256 | + triggersBound = true; |
250 | 257 |
|
251 | | - function init() { |
252 | | - if (!window.CFD_SEARCH) return; |
| 258 | + document.addEventListener( |
| 259 | + 'click', |
| 260 | + function (e) { |
| 261 | + var openBtn = e.target.closest('[data-search-open]'); |
| 262 | + if (openBtn) { |
| 263 | + e.preventDefault(); |
| 264 | + e.stopPropagation(); |
| 265 | + open(''); |
| 266 | + return; |
| 267 | + } |
| 268 | + if (e.target.closest('[data-search-close]')) { |
| 269 | + e.preventDefault(); |
| 270 | + close(); |
| 271 | + } |
| 272 | + }, |
| 273 | + true |
| 274 | + ); |
| 275 | + } |
253 | 276 |
|
254 | | - palette = document.getElementById('search-palette'); |
| 277 | + function bindPalette() { |
255 | 278 | if (!palette) return; |
256 | 279 |
|
257 | | - backdrop = $('.search-palette__backdrop', palette); |
258 | | - dialog = $('.search-palette__dialog', palette); |
259 | | - input = document.getElementById('search-palette-input'); |
260 | | - resultsList = document.getElementById('search-palette-results'); |
261 | | - defaultPanel = document.getElementById('search-palette-default'); |
262 | | - emptyPanel = document.getElementById('search-palette-empty'); |
263 | | - isEmbedded = |
264 | | - document.body.classList.contains('search-palette-page') || |
265 | | - /^\/search\/?$/.test(window.location.pathname); |
266 | | - |
267 | | - allItems = buildIndex(window.CFD_SEARCH.data); |
268 | | - initKbdLabels(); |
269 | | - bindTriggers(); |
| 280 | + document.querySelectorAll('[data-search-close]').forEach(function (el) { |
| 281 | + el.addEventListener('click', close); |
| 282 | + }); |
270 | 283 |
|
271 | 284 | if (input) { |
272 | 285 | var debounce; |
|
300 | 313 | } |
301 | 314 | }); |
302 | 315 | } |
| 316 | + } |
| 317 | + |
| 318 | + function init() { |
| 319 | + if (!window.CFD_SEARCH || !window.CFD_SEARCH.data) { |
| 320 | + return false; |
| 321 | + } |
| 322 | + |
| 323 | + palette = document.getElementById('search-palette'); |
| 324 | + if (!palette) { |
| 325 | + return false; |
| 326 | + } |
| 327 | + |
| 328 | + backdrop = $('.search-palette__backdrop', palette); |
| 329 | + dialog = $('.search-palette__dialog', palette); |
| 330 | + input = document.getElementById('search-palette-input'); |
| 331 | + resultsList = document.getElementById('search-palette-results'); |
| 332 | + defaultPanel = document.getElementById('search-palette-default'); |
| 333 | + emptyPanel = document.getElementById('search-palette-empty'); |
| 334 | + isEmbedded = |
| 335 | + document.body.classList.contains('search-palette-page') || |
| 336 | + /^\/search\/?$/.test(window.location.pathname); |
| 337 | + |
| 338 | + allItems = buildIndex(window.CFD_SEARCH.data); |
| 339 | + initKbdLabels(); |
| 340 | + bindTriggers(); |
| 341 | + bindPalette(); |
303 | 342 |
|
304 | 343 | document.addEventListener('keydown', function (e) { |
305 | 344 | if ((e.metaKey || e.ctrlKey) && e.key === 'k') { |
|
312 | 351 | }); |
313 | 352 |
|
314 | 353 | if (isEmbedded) { |
| 354 | + palette.removeAttribute('hidden'); |
315 | 355 | palette.hidden = false; |
316 | 356 | palette.classList.add('is-visible', 'search-palette--embedded'); |
317 | 357 | isOpen = true; |
|
324 | 364 | } |
325 | 365 |
|
326 | 366 | window.cfdSearchPalette = { open: open, close: close }; |
| 367 | + return true; |
| 368 | + } |
| 369 | + |
| 370 | + function boot() { |
| 371 | + bindTriggers(); |
| 372 | + if (init()) return; |
| 373 | + var attempts = 0; |
| 374 | + var timer = setInterval(function () { |
| 375 | + attempts += 1; |
| 376 | + if (init() || attempts > 40) clearInterval(timer); |
| 377 | + }, 50); |
327 | 378 | } |
328 | 379 |
|
329 | 380 | if (document.readyState === 'loading') { |
330 | | - document.addEventListener('DOMContentLoaded', init); |
| 381 | + document.addEventListener('DOMContentLoaded', boot); |
331 | 382 | } else { |
332 | | - init(); |
| 383 | + boot(); |
333 | 384 | } |
334 | 385 | })(); |
0 commit comments