@@ -367,172 +367,190 @@ function worker_function(documenterSearchIndex, documenterBaseURL, filters) {
367367 } ;
368368}
369369
370- // `worker = Threads.@spawn worker_function(documenterSearchIndex)`, but in JavaScript!
371- const filters = [
372- ...new Set ( documenterSearchIndex [ "docs" ] . map ( ( x ) => x . category ) ) ,
373- ] ;
374- const worker_str =
375- "(" +
376- worker_function . toString ( ) +
377- ")(" +
378- JSON . stringify ( documenterSearchIndex [ "docs" ] ) +
379- "," +
380- JSON . stringify ( documenterBaseURL ) +
381- "," +
382- JSON . stringify ( filters ) +
383- ")" ;
384- const worker_blob = new Blob ( [ worker_str ] , { type : "text/javascript" } ) ;
385- const worker = new Worker ( URL . createObjectURL ( worker_blob ) ) ;
386-
387370/////// SEARCH MAIN ///////
388371
389- // Whether the worker is currently handling a search. This is a boolean
390- // as the worker only ever handles 1 or 0 searches at a time.
391- var worker_is_running = false ;
392-
393- // The last search text that was sent to the worker. This is used to determine
394- // if the worker should be launched again when it reports back results.
395- var last_search_text = "" ;
396-
397- // The results of the last search. This, in combination with the state of the filters
398- // in the DOM, is used compute the results to display on calls to update_search.
399- var unfiltered_results = [ ] ;
400-
401- // Which filter is currently selected
402- var selected_filter = "" ;
403-
404- $ ( document ) . on ( "input" , ".documenter-search-input" , function ( event ) {
405- if ( ! worker_is_running ) {
406- launch_search ( ) ;
407- }
408- } ) ;
409-
410- function launch_search ( ) {
411- worker_is_running = true ;
412- last_search_text = $ ( ".documenter-search-input" ) . val ( ) ;
413- worker . postMessage ( last_search_text ) ;
414- }
415-
416- worker . onmessage = function ( e ) {
417- if ( last_search_text !== $ ( ".documenter-search-input" ) . val ( ) ) {
418- launch_search ( ) ;
419- } else {
420- worker_is_running = false ;
421- }
422-
423- unfiltered_results = e . data ;
424- update_search ( ) ;
425- } ;
372+ function runSearchMainCode ( ) {
373+ // `worker = Threads.@spawn worker_function(documenterSearchIndex)`, but in JavaScript!
374+ const filters = [
375+ ...new Set ( documenterSearchIndex [ "docs" ] . map ( ( x ) => x . category ) ) ,
376+ ] ;
377+ const worker_str =
378+ "(" +
379+ worker_function . toString ( ) +
380+ ")(" +
381+ JSON . stringify ( documenterSearchIndex [ "docs" ] ) +
382+ "," +
383+ JSON . stringify ( documenterBaseURL ) +
384+ "," +
385+ JSON . stringify ( filters ) +
386+ ")" ;
387+ const worker_blob = new Blob ( [ worker_str ] , { type : "text/javascript" } ) ;
388+ const worker = new Worker ( URL . createObjectURL ( worker_blob ) ) ;
389+
390+ // Whether the worker is currently handling a search. This is a boolean
391+ // as the worker only ever handles 1 or 0 searches at a time.
392+ var worker_is_running = false ;
393+
394+ // The last search text that was sent to the worker. This is used to determine
395+ // if the worker should be launched again when it reports back results.
396+ var last_search_text = "" ;
397+
398+ // The results of the last search. This, in combination with the state of the filters
399+ // in the DOM, is used compute the results to display on calls to update_search.
400+ var unfiltered_results = [ ] ;
401+
402+ // Which filter is currently selected
403+ var selected_filter = "" ;
404+
405+ $ ( document ) . on ( "input" , ".documenter-search-input" , function ( event ) {
406+ if ( ! worker_is_running ) {
407+ launch_search ( ) ;
408+ }
409+ } ) ;
426410
427- $ ( document ) . on ( "click" , ".search-filter" , function ( ) {
428- if ( $ ( this ) . hasClass ( "search-filter-selected" ) ) {
429- selected_filter = "" ;
430- } else {
431- selected_filter = $ ( this ) . text ( ) . toLowerCase ( ) ;
411+ function launch_search ( ) {
412+ worker_is_running = true ;
413+ last_search_text = $ ( ".documenter-search-input" ) . val ( ) ;
414+ worker . postMessage ( last_search_text ) ;
432415 }
433416
434- // This updates search results and toggles classes for UI:
435- update_search ( ) ;
436- } ) ;
417+ worker . onmessage = function ( e ) {
418+ if ( last_search_text !== $ ( ".documenter-search-input" ) . val ( ) ) {
419+ launch_search ( ) ;
420+ } else {
421+ worker_is_running = false ;
422+ }
437423
438- /**
439- * Make/Update the search component
440- */
441- function update_search ( ) {
442- let querystring = $ ( ".documenter-search-input" ) . val ( ) ;
424+ unfiltered_results = e . data ;
425+ update_search ( ) ;
426+ } ;
443427
444- if ( querystring . trim ( ) ) {
445- if ( selected_filter == "" ) {
446- results = unfiltered_results ;
428+ $ ( document ) . on ( "click" , ".search-filter" , function ( ) {
429+ if ( $ ( this ) . hasClass ( "search-filter-selected" ) ) {
430+ selected_filter = "" ;
447431 } else {
448- results = unfiltered_results . filter ( ( result ) => {
449- return selected_filter == result . category . toLowerCase ( ) ;
450- } ) ;
432+ selected_filter = $ ( this ) . text ( ) . toLowerCase ( ) ;
451433 }
452434
453- let search_result_container = `` ;
454- let modal_filters = make_modal_body_filters ( ) ;
455- let search_divider = `<div class="search-divider w-100"></div>` ;
435+ // This updates search results and toggles classes for UI:
436+ update_search ( ) ;
437+ } ) ;
456438
457- if ( results . length ) {
458- let links = [ ] ;
459- let count = 0 ;
460- let search_results = "" ;
461-
462- for ( var i = 0 , n = results . length ; i < n && count < 200 ; ++ i ) {
463- let result = results [ i ] ;
464- if ( result . location && ! links . includes ( result . location ) ) {
465- search_results += result . div ;
466- count ++ ;
467- links . push ( result . location ) ;
468- }
469- }
439+ /**
440+ * Make/Update the search component
441+ */
442+ function update_search ( ) {
443+ let querystring = $ ( ".documenter-search-input" ) . val ( ) ;
470444
471- if ( count == 1 ) {
472- count_str = "1 result" ;
473- } else if ( count == 200 ) {
474- count_str = "200+ results" ;
445+ if ( querystring . trim ( ) ) {
446+ if ( selected_filter == "" ) {
447+ results = unfiltered_results ;
475448 } else {
476- count_str = count + " results" ;
449+ results = unfiltered_results . filter ( ( result ) => {
450+ return selected_filter == result . category . toLowerCase ( ) ;
451+ } ) ;
477452 }
478- let result_count = `<div class="is-size-6">${ count_str } </div>` ;
479453
480- search_result_container = `
454+ let search_result_container = `` ;
455+ let modal_filters = make_modal_body_filters ( ) ;
456+ let search_divider = `<div class="search-divider w-100"></div>` ;
457+
458+ if ( results . length ) {
459+ let links = [ ] ;
460+ let count = 0 ;
461+ let search_results = "" ;
462+
463+ for ( var i = 0 , n = results . length ; i < n && count < 200 ; ++ i ) {
464+ let result = results [ i ] ;
465+ if ( result . location && ! links . includes ( result . location ) ) {
466+ search_results += result . div ;
467+ count ++ ;
468+ links . push ( result . location ) ;
469+ }
470+ }
471+
472+ if ( count == 1 ) {
473+ count_str = "1 result" ;
474+ } else if ( count == 200 ) {
475+ count_str = "200+ results" ;
476+ } else {
477+ count_str = count + " results" ;
478+ }
479+ let result_count = `<div class="is-size-6">${ count_str } </div>` ;
480+
481+ search_result_container = `
482+ <div class="is-flex is-flex-direction-column gap-2 is-align-items-flex-start">
483+ ${ modal_filters }
484+ ${ search_divider }
485+ ${ result_count }
486+ <div class="is-clipped w-100 is-flex is-flex-direction-column gap-2 is-align-items-flex-start has-text-justified mt-1">
487+ ${ search_results }
488+ </div>
489+ </div>
490+ ` ;
491+ } else {
492+ search_result_container = `
481493 <div class="is-flex is-flex-direction-column gap-2 is-align-items-flex-start">
482494 ${ modal_filters }
483495 ${ search_divider }
484- ${ result_count }
485- <div class="is-clipped w-100 is-flex is-flex-direction-column gap-2 is-align-items-flex-start has-text-justified mt-1">
486- ${ search_results }
487- </div>
488- </div>
496+ <div class="is-size-6">0 result(s)</div>
497+ </div>
498+ <div class="has-text-centered my-5 py-5">No result found!</div>
489499 ` ;
490- } else {
491- search_result_container = `
492- <div class="is-flex is-flex-direction-column gap-2 is-align-items-flex-start">
493- ${ modal_filters }
494- ${ search_divider }
495- <div class="is-size-6">0 result(s)</div>
496- </div>
497- <div class="has-text-centered my-5 py-5">No result found!</div>
498- ` ;
499- }
500+ }
500501
501- if ( $ ( ".search-modal-card-body" ) . hasClass ( "is-justify-content-center" ) ) {
502- $ ( ".search-modal-card-body" ) . removeClass ( "is-justify-content-center" ) ;
503- }
502+ if ( $ ( ".search-modal-card-body" ) . hasClass ( "is-justify-content-center" ) ) {
503+ $ ( ".search-modal-card-body" ) . removeClass ( "is-justify-content-center" ) ;
504+ }
504505
505- $ ( ".search-modal-card-body" ) . html ( search_result_container ) ;
506- } else {
507- if ( ! $ ( ".search-modal-card-body" ) . hasClass ( "is-justify-content-center" ) ) {
508- $ ( ".search-modal-card-body" ) . addClass ( "is-justify-content-center" ) ;
506+ $ ( ".search-modal-card-body" ) . html ( search_result_container ) ;
507+ } else {
508+ if ( ! $ ( ".search-modal-card-body" ) . hasClass ( "is-justify-content-center" ) ) {
509+ $ ( ".search-modal-card-body" ) . addClass ( "is-justify-content-center" ) ;
510+ }
511+
512+ $ ( ".search-modal-card-body" ) . html ( `
513+ <div class="has-text-centered my-5 py-5">Type something to get started!</div>
514+ ` ) ;
509515 }
516+ }
510517
511- $ ( ".search-modal-card-body" ) . html ( `
512- <div class="has-text-centered my-5 py-5">Type something to get started!</div>
513- ` ) ;
518+ /**
519+ * Make the modal filter html
520+ *
521+ * @returns string
522+ */
523+ function make_modal_body_filters ( ) {
524+ let str = filters
525+ . map ( ( val ) => {
526+ if ( selected_filter == val . toLowerCase ( ) ) {
527+ return `<a href="javascript:;" class="search-filter search-filter-selected"><span>${ val } </span></a>` ;
528+ } else {
529+ return `<a href="javascript:;" class="search-filter"><span>${ val } </span></a>` ;
530+ }
531+ } )
532+ . join ( "" ) ;
533+
534+ return `
535+ <div class="is-flex gap-2 is-flex-wrap-wrap is-justify-content-flex-start is-align-items-center search-filters">
536+ <span class="is-size-6">Filters:</span>
537+ ${ str }
538+ </div>` ;
514539 }
515540}
516541
517- /**
518- * Make the modal filter html
519- *
520- * @returns string
521- */
522- function make_modal_body_filters ( ) {
523- let str = filters
524- . map ( ( val ) => {
525- if ( selected_filter == val . toLowerCase ( ) ) {
526- return `<a href="javascript:;" class="search-filter search-filter-selected"><span>${ val } </span></a>` ;
527- } else {
528- return `<a href="javascript:;" class="search-filter"><span>${ val } </span></a>` ;
529- }
530- } )
531- . join ( "" ) ;
532-
533- return `
534- <div class="is-flex gap-2 is-flex-wrap-wrap is-justify-content-flex-start is-align-items-center search-filters">
535- <span class="is-size-6">Filters:</span>
536- ${ str }
537- </div>` ;
542+ function waitUntilSearchIndexAvailable ( ) {
543+ // It is possible that the documenter.js script runs before the page
544+ // has finished loading and documenterSearchIndex gets defined.
545+ // So we need to wait until the search index actually loads before setting
546+ // up all the search-related stuff.
547+ if ( typeof documenterSearchIndex !== "undefined" ) {
548+ runSearchMainCode ( ) ;
549+ } else {
550+ console . warn ( "Search Index not available, waiting" ) ;
551+ setTimeout ( waitUntilSearchIndexAvailable , 1000 ) ;
552+ }
538553}
554+
555+ // The actual entry point to the search code
556+ waitUntilSearchIndexAvailable ( ) ;
0 commit comments