@@ -4,6 +4,7 @@ const MAX_SUBSTRING_LIMIT = 100;
4
4
const ANIMATION_TIME = 200 ;
5
5
const FETCH_RESULTS_DELAY = 250 ;
6
6
const CLEAR_RESULTS_DELAY = 300 ;
7
+ const RTD_SEARCH_PARAMETER = "rtd_search" ;
7
8
8
9
/**
9
10
* Debounce the function.
@@ -42,7 +43,7 @@ const debounce = (func, wait) => {
42
43
43
44
/**
44
45
* Wrapper around underscorejs's template function.
45
- *
46
+ *
46
47
* This is to make it work with new and old versions.
47
48
*/
48
49
const render_template = ( template , data ) => {
@@ -55,69 +56,21 @@ const render_template = (template, data) => {
55
56
return result ;
56
57
} ;
57
58
58
- /**
59
- * Take an object as parameter and convert it to
60
- * url params string.
61
- *
62
- * Eg. if ``obj = { 'a': 1, 'b': 2, 'c': ['hello', 'world'] }``, then it will return
63
- * the string ``a=1&b=2&c=hello,world``
64
- *
65
- * @param {Object } obj the object to be converted
66
- * @return {String|Array } object in url params form
67
- */
68
- const convertObjToUrlParams = obj => {
69
- let params = Object . keys ( obj ) . map ( function ( key ) {
70
- if ( _is_string ( key ) ) {
71
- const s = key + "=" + encodeURI ( obj [ key ] ) ;
72
- return s ;
73
- }
74
- } ) ;
75
-
76
- // removing empty strings from the 'params' array
77
- let final_params = [ ] ;
78
- for ( let i = 0 ; i < params . length ; ++ i ) {
79
- if ( _is_string ( params [ i ] ) ) {
80
- final_params . push ( params [ i ] ) ;
81
- }
82
- }
83
- if ( final_params . length === 1 ) {
84
- return final_params [ 0 ] ;
85
- } else {
86
- let final_url_params = final_params . join ( "&" ) ;
87
- return final_url_params ;
88
- }
89
- } ;
90
-
91
59
92
60
/**
93
61
* Adds/removes "rtd_search" url parameter to the url.
94
62
*/
95
63
const updateUrl = ( ) => {
96
- let origin = window . location . origin ;
97
- let path = window . location . pathname ;
98
- let url_params = $ . getQueryParameters ( ) ;
99
- let hash = window . location . hash ;
64
+ let parsed_url = new URL ( window . location . href ) ;
100
65
let search_query = getSearchTerm ( ) ;
101
- // search_query should not be an empty string
66
+ // search_query should not be an empty string.
102
67
if ( search_query . length > 0 ) {
103
- url_params . rtd_search = search_query ;
68
+ parsed_url . searchParams . set ( RTD_SEARCH_PARAMETER , search_query ) ;
104
69
} else {
105
- delete url_params . rtd_search ;
70
+ parsed_url . searchParams . delete ( RTD_SEARCH_PARAMETER ) ;
106
71
}
107
-
108
- let window_location_search = convertObjToUrlParams ( url_params ) + hash ;
109
-
110
- // this happens during the tests,
111
- // when window.location.origin is "null" in Firefox
112
- // then correct URL is contained by window.location.pathname
113
- // which starts with "file://"
114
- let url = path + "?" + window_location_search ;
115
- if ( origin . substring ( 0 , 4 ) === "http" ) {
116
- url = origin + url ;
117
- }
118
-
119
- // update url
120
- window . history . pushState ( { } , null , url ) ;
72
+ // Update url.
73
+ window . history . pushState ( { } , null , parsed_url . toString ( ) ) ;
121
74
} ;
122
75
123
76
@@ -172,18 +125,6 @@ const _is_string = str => {
172
125
}
173
126
} ;
174
127
175
- /**
176
- * Checks if data type is a non-empty array
177
- * @param {* } data data whose type is to be checked
178
- * @return {Boolean } returns true if data is non-empty array, else returns false
179
- */
180
- const _is_array = arr => {
181
- if ( Array . isArray ( arr ) && arr . length > 0 ) {
182
- return true ;
183
- } else {
184
- return false ;
185
- }
186
- } ;
187
128
188
129
/**
189
130
* Generate and return html structure
@@ -538,11 +479,12 @@ const getErrorDiv = err_msg => {
538
479
* and appends the results to <div class="search__outer"> node,
539
480
* which is already created when the page was loaded.
540
481
*
541
- * @param {String } search_url url on which request will be sent
542
- * @param {String } projectName name (slug) of the project
482
+ * @param {String } api_endpoint: API endpoint
483
+ * @param {Object } parameters: search parameters
484
+ * @param {String } projectName: name (slug) of the project
543
485
* @return {Function } debounced function with debounce time of 500ms
544
486
*/
545
- const fetchAndGenerateResults = ( search_url , projectName ) => {
487
+ const fetchAndGenerateResults = ( api_endpoint , parameters , projectName ) => {
546
488
let search_outer = document . querySelector ( ".search__outer" ) ;
547
489
548
490
// Removes all results (if there is any),
@@ -553,52 +495,48 @@ const fetchAndGenerateResults = (search_url, projectName) => {
553
495
search_loding . innerHTML = "<strong>Searching ....</strong>" ;
554
496
search_outer . appendChild ( search_loding ) ;
555
497
556
- let ajaxFunc = ( ) => {
498
+ let fetchFunc = ( ) => {
557
499
// Update URL just before fetching the results
558
500
updateUrl ( ) ;
559
501
updateSearchBar ( ) ;
560
502
561
- $ . ajax ( {
562
- url : search_url ,
563
- crossDomain : true ,
564
- xhrFields : {
565
- withCredentials : true
566
- } ,
567
- complete : ( resp , status_code ) => {
568
- if (
569
- status_code === "success" ||
570
- typeof resp . responseJSON !== "undefined"
571
- ) {
572
- if ( resp . responseJSON . results . length > 0 ) {
573
- let search_result_box = generateSuggestionsList (
574
- resp . responseJSON ,
575
- projectName
576
- ) ;
577
- removeResults ( ) ;
578
- search_outer . appendChild ( search_result_box ) ;
579
-
580
- // remove active classes from all suggestions
581
- // if the mouse hovers, otherwise styles from
582
- // :hover and .active will clash.
583
- search_outer . addEventListener ( "mouseenter" , e => {
584
- removeAllActive ( ) ;
585
- } ) ;
586
- } else {
587
- removeResults ( ) ;
588
- let err_div = getErrorDiv ( "No results found" ) ;
589
- search_outer . appendChild ( err_div ) ;
590
- }
591
- }
592
- } ,
593
- error : ( resp , status_code , error ) => {
503
+ const url = api_endpoint + "?" + new URLSearchParams ( parameters ) . toString ( ) ;
504
+
505
+ fetch ( url , { method : "GET" } )
506
+ . then ( response => {
507
+ if ( ! response . ok ) {
508
+ throw new Error ( ) ;
509
+ }
510
+ return response . json ( ) ;
511
+ } )
512
+ . then ( data => {
513
+ if ( data . results . length > 0 ) {
514
+ let search_result_box = generateSuggestionsList (
515
+ data ,
516
+ projectName
517
+ ) ;
518
+ removeResults ( ) ;
519
+ search_outer . appendChild ( search_result_box ) ;
520
+
521
+ // remove active classes from all suggestions
522
+ // if the mouse hovers, otherwise styles from
523
+ // :hover and .active will clash.
524
+ search_outer . addEventListener ( "mouseenter" , e => {
525
+ removeAllActive ( ) ;
526
+ } ) ;
527
+ } else {
594
528
removeResults ( ) ;
595
- let err_div = getErrorDiv ( "There was an error. Please try again. " ) ;
529
+ let err_div = getErrorDiv ( "No results found " ) ;
596
530
search_outer . appendChild ( err_div ) ;
597
531
}
532
+ } )
533
+ . catch ( error => {
534
+ removeResults ( ) ;
535
+ let err_div = getErrorDiv ( "There was an error. Please try again." ) ;
536
+ search_outer . appendChild ( err_div ) ;
598
537
} ) ;
599
538
} ;
600
- ajaxFunc = debounce ( ajaxFunc , FETCH_RESULTS_DELAY ) ;
601
- return ajaxFunc ;
539
+ return debounce ( fetchFunc , FETCH_RESULTS_DELAY ) ;
602
540
} ;
603
541
604
542
/**
@@ -696,7 +634,6 @@ window.addEventListener("DOMContentLoaded", () => {
696
634
if ( window . hasOwnProperty ( "READTHEDOCS_DATA" ) ) {
697
635
const project = READTHEDOCS_DATA . project ;
698
636
const version = READTHEDOCS_DATA . version ;
699
- const language = READTHEDOCS_DATA . language || "en" ;
700
637
const api_host = READTHEDOCS_DATA . proxied_api_host || '/_' ;
701
638
702
639
let initialHtml = generateAndReturnInitialHtml ( ) ;
@@ -720,25 +657,18 @@ window.addEventListener("DOMContentLoaded", () => {
720
657
721
658
search_outer_input . addEventListener ( "input" , e => {
722
659
let search_query = getSearchTerm ( ) ;
723
-
724
- let search_params = {
725
- q : search_query ,
726
- project : project ,
727
- version : version ,
728
- language : language ,
729
- } ;
730
-
731
- const search_url =
732
- api_host +
733
- "/api/v2/search/?" +
734
- convertObjToUrlParams ( search_params ) ;
735
-
736
660
if ( search_query . length > 0 ) {
737
661
if ( current_request !== null ) {
738
662
// cancel previous ajax request.
739
663
current_request . cancel ( ) ;
740
664
}
741
- current_request = fetchAndGenerateResults ( search_url , project ) ;
665
+ const search_endpoint = api_host + "/api/v2/search/" ;
666
+ const search_params = {
667
+ q : search_query ,
668
+ project : project ,
669
+ version : version ,
670
+ } ;
671
+ current_request = fetchAndGenerateResults ( search_endpoint , search_params , project ) ;
742
672
current_request ( ) ;
743
673
} else {
744
674
// if the last request returns the results,
@@ -825,9 +755,9 @@ window.addEventListener("DOMContentLoaded", () => {
825
755
// if "rtd_search" is present in URL parameters,
826
756
// then open the search modal and show the results
827
757
// for the value of "rtd_search"
828
- let url_params = $ . getQueryParameters ( ) ;
829
- if ( _is_array ( url_params . rtd_search ) ) {
830
- let query = decodeURIComponent ( url_params . rtd_search ) ;
758
+ const url_params = new URLSearchParams ( document . location . search ) ;
759
+ const query = url_params . get ( RTD_SEARCH_PARAMETER ) ;
760
+ if ( query !== null ) {
831
761
showSearchModal ( query ) ;
832
762
search_outer_input . value = query ;
833
763
0 commit comments