@@ -6,6 +6,16 @@ const FETCH_RESULTS_DELAY = 250;
6
6
const CLEAR_RESULTS_DELAY = 300 ;
7
7
const RTD_SEARCH_PARAMETER = "rtd_search" ;
8
8
9
+ /**
10
+ * Parse the search query and return an array with the query and the options.
11
+ *
12
+ * This is a simplified version of our parser
13
+ * https://github.com/readthedocs/readthedocs.org/blob/main/readthedocs/search/api/v3/queryparser.py.
14
+ * All `foo:bar` terms are considered options, and the rest are considered part of the query.
15
+ *
16
+ * @param {String } search_query
17
+ * @return {Array } [query, options]
18
+ */
9
19
function parseQuery ( search_query ) {
10
20
let query = [ ] ;
11
21
let options = { } ;
@@ -131,6 +141,11 @@ const updateSearchBar = () => {
131
141
} ;
132
142
133
143
144
+ /**
145
+ * Set the search query in the modal.
146
+ *
147
+ * @param {String } query
148
+ */
134
149
function setSearchQuery ( query ) {
135
150
let search_outer_input = document . querySelector ( ".search__outer__input" ) ;
136
151
search_outer_input . value = query ;
@@ -297,13 +312,16 @@ const generateSingleResult = (resultData, projectName, id) => {
297
312
let h2_element = createDomNode ( "h2" , { class : "search__result__title" } ) ;
298
313
h2_element . innerHTML = page_title ;
299
314
300
- // If the result is not from the same project,
301
- // then it's from a subproject .
315
+ // Results can belong to different projects.
316
+ // If the result isn't from the current project, add a note about it .
302
317
const project_slug = resultData . project . slug
303
318
if ( projectName !== project_slug ) {
304
319
let subtitle = createDomNode ( "small" , { class : "rtd_ui_search_subtitle" } ) ;
305
320
subtitle . innerText = ` (from project ${ project_slug } )` ;
306
321
h2_element . appendChild ( subtitle ) ;
322
+ // If the result isn't from the current project,
323
+ // then we create an absolute link to the page.
324
+ page_link = `${ resultData . domain } ${ page_link } ` ;
307
325
}
308
326
h2_element . appendChild ( createDomNode ( "br" ) )
309
327
@@ -577,7 +595,8 @@ const fetchAndGenerateResults = (api_endpoint, parameters) => {
577
595
* This html structure will serve as the boilerplate
578
596
* to show our search results.
579
597
*
580
- * @param {Array } filters: filters to be applied to the search
598
+ * @param {Array } filters: filters to be applied to the search.
599
+ * {["Filter name", "Filter value"]}
581
600
* @return {String } initial html structure
582
601
*/
583
602
const generateAndReturnInitialHtml = ( filters ) => {
@@ -597,35 +616,53 @@ const generateAndReturnInitialHtml = (filters) => {
597
616
</div>
598
617
</div>
599
618
<div class="rtd__search__credits">
600
- Search by <a href="https://readthedocs.org/">Read the Docs</a> & <a href="https://readthedocs-sphinx-search.readthedocs.io/en/latest/">readthedocs-sphinx-search</a>
619
+ Search by <a href="https://readthedocs.org/">Read the Docs</a> & <a href="https://readthedocs-sphinx-search.readthedocs.io/en/latest/">readthedocs-sphinx-search</a>.
620
+ <a href="https://docs.readthedocs.io/page/server-side-search/syntax.html">Search syntax</a>.
601
621
</div>
602
622
` ;
603
623
604
624
let div = createDomNode ( "div" , {
605
625
class : "search__outer__wrapper search__backdrop" ,
606
626
} ) ;
607
627
div . innerHTML = innerHTML ;
628
+
608
629
let filters_list = div . querySelector ( ".search__filters ul" ) ;
609
630
const config = getConfig ( ) ;
610
- for ( const [ filter , value ] of filters ) {
611
- let li = createDomNode ( "li" ) ;
612
- let button = createDomNode ( "button" ) ;
613
- button . innerText = filter ;
614
- button . value = value ;
615
- button . addEventListener ( "click" , event => {
616
- event . preventDefault ( ) ;
617
- let search_query = getSearchTerm ( ) ;
618
- let [ query , _ ] = parseQuery ( search_query ) ;
619
- setSearchQuery ( event . target . value + " " + query ) ;
620
- const search_params = {
621
- q : search_query ,
622
- project : config . project ,
623
- version : config . version ,
624
- } ;
625
- fetchAndGenerateResults ( config . api_endpoint , search_params ) ( ) ;
626
- } ) ;
627
- li . appendChild ( button ) ;
628
- filters_list . appendChild ( li ) ;
631
+ // Add filters below the search box if present.
632
+ if ( filters . length > 0 ) {
633
+ let li = createDomNode ( "li" , { "class" : "search__filters__title" } ) ;
634
+ li . innerText = "Filters:" ;
635
+ filters_list . appendChild ( li ) ;
636
+ }
637
+ // Each filter is a button in the filters list.
638
+ // Each button contains the index of the filter,
639
+ // so we can get the proper filter when clicked.
640
+ for ( let i = 0 , len = filters . length ; i < len ; i ++ ) {
641
+ const [ name , filter ] = filters [ i ] ;
642
+ let li = createDomNode ( "li" ) ;
643
+ let button = createDomNode ( "button" ) ;
644
+ button . innerText = name ;
645
+ button . value = i ;
646
+ button . title = filter ;
647
+ button . addEventListener ( "click" , event => {
648
+ event . preventDefault ( ) ;
649
+ // To apply a filter, we extract the current query and
650
+ // replace the current options with the selected filter.
651
+ let filter = filters [ parseInt ( event . target . value ) ] [ 1 ] ;
652
+ let search_query = getSearchTerm ( ) ;
653
+ let [ query , _ ] = parseQuery ( search_query ) ;
654
+ search_query = filter + " " + query ;
655
+ setSearchQuery ( search_query ) ;
656
+ // Perform the search with the new query.
657
+ const search_params = {
658
+ q : search_query ,
659
+ project : config . project ,
660
+ version : config . version ,
661
+ } ;
662
+ fetchAndGenerateResults ( config . api_endpoint , search_params ) ( ) ;
663
+ } ) ;
664
+ li . appendChild ( button ) ;
665
+ filters_list . appendChild ( li ) ;
629
666
}
630
667
return div ;
631
668
} ;
@@ -767,6 +804,8 @@ window.addEventListener("DOMContentLoaded", () => {
767
804
// cancel previous ajax request.
768
805
current_request . cancel ( ) ;
769
806
}
807
+ // If the query doesn't have options,
808
+ // use the default filter.
770
809
let [ query , options ] = parseQuery ( search_query ) ;
771
810
if ( Object . keys ( options ) . length == 0 ) {
772
811
search_query = config . default_filter + " " + query ;
0 commit comments