PageSourceSearch

https://www.browserstack.com/blog/assets/js/docs_search/docs_search.js?v=enGkAWv3qZ3okcyC

js browserstack.com collected 2026-10-01 06:56:41 UTC 17,696 bytes, 447 lines download raw bytes

1// IIFE implementation
2(function () {
3  /**
4   * This class is added to adjust the location of search icon on the menu bar.
5   * Currently this code is added from VWO.
6   */
7  // document.body.classList.add('docs-search-auth-user');
8
9  var docSearchInputBox = getQuerySelector('#doc-search-box input'),
10    docSearchMenuIcon = document.querySelectorAll('.doc-search-menu-icon'),
11    docSearchContainerOverlay = getQuerySelector('#doc-search-overlay'),
12    body = getQuerySelector('html'),
13    docResetButton = getQuerySelector('.ds__input__handle--reset'),
14    searchContainer = getQuerySelector('#doc-search-container'),
15    docInputHandle = getQuerySelector('#ds-input-handle'),
16    docSearchInputContainer = getByClassName('ds__input__container'),
17    docTopBar = getQuerySelector('.ds__container .ds__top-bar'),
18    docSubmitButton = getQuerySelector('.ds__input__handle--submit'),
19    docCloseIcon = getQuerySelector('.ds--close'),
20    docSearchContainer = document.querySelector('#doc-search-container'),
21    globalSearchFlag = true,
22    localSearchFlag = true,
23    searchModalFirstFocusElement = null,
24    searchModalLastFocusElement = null;
25    
26  function getQuerySelector(id) {
27    return document.querySelector(id);
28  }
29  function getByClassName(className) {
30    return document.getElementsByClassName(className);
31  }
32  // Events to hide and show search container
33  if (docSearchMenuIcon && docSearchContainerOverlay && docCloseIcon) {
34    docSearchMenuIcon.forEach(function (node) {
35      node.addEventListener('click', function (e) {
36        e.preventDefault();
37        searchContainer.classList.add('show-doc');
38        body.classList.add('doc-search-enabled');
39        docSearchInputBox.focus();
40      });
41    });
42    init();
43  }
44  function init() {
45    // Input Box OnKeyUp Event to hide and show Dropdown
46    if (docSearchInputBox) {
47      docSearchInputBox.addEventListener('keyup', function (e) {
48        if (!e.target.value) {
49          docInputHandle.classList.add('hide');
50        } else if (window.innerWidth > 979) {
51          docInputHandle.classList.remove('hide');
52        }
53      });
54      docSearchInputBox.addEventListener('focus', function () {
55        docSearchInputContainer[0].classList.add('input-box-focused');
56        if (docSubmitButton.classList.contains('hide')) {
57          docSubmitButton.classList.remove('hide');
58        }
59      });
60      docSearchInputBox.addEventListener('focusout', function (e) {
61        docSearchInputContainer[0].classList.remove('input-box-focused');
62      });
63      if (docResetButton) {
64        docResetButton.addEventListener('click', function () {
65          docInputHandle.classList.add('hide');
66          docSearchInputBox.focus();
67        });
68      }
69    }
70
71    if (docSearchContainer) {
72      var searchModalElement = getFirstAndLastFocusableElementOfParent('#doc-search-container');
73      searchModalFirstFocusElement = searchModalElement.firstElement;
74      searchModalLastFocusElement = searchModalElement.lastElement;
75      docSearchContainer.addEventListener('keydown', function (event) {
76        trapFocusInElement(event, searchModalFirstFocusElement, searchModalLastFocusElement);
77      });
78    }
79    
80    function getFirstAndLastFocusableElementOfParent(element) {
81      var allFocusableItemsInElement = document.querySelector(element).querySelectorAll('a, button, input'),
82        lengthOfAllFocusableItemsInElement = allFocusableItemsInElement.length;
83      return {
84        firstElement: allFocusableItemsInElement[0],
85        lastElement: allFocusableItemsInElement[lengthOfAllFocusableItemsInElement - 1]
86      };
87    }
88
89    // Function to close search box and initialize values
90    function resetDocSearchToInitialState() {
91      searchContainer.classList.remove('show-doc');
92      body.classList.remove('doc-search-enabled');
93      docInputHandle.classList.add('hide');
94      docSearchInputBox.value = '';
95    }
96    docSearchContainerOverlay.addEventListener('click', function () {
97      resetDocSearchToInitialState();
98    });
99    docCloseIcon.addEventListener('click', function () {
100      resetDocSearchToInitialState();
101    });
102    //  events to make dropdown list navigate and redirect using keyboard buttons
103    document.addEventListener('keydown', function (event) {
104      if (event.key === 'Escape' || event.keyCode === 27) {
105        resetDocSearchToInitialState();
106      }
107    });
108    // event for default state
109    docTopBar.addEventListener('click', function (event) {
110      var classListNode = event.target.classList;
111      if (classListNode.contains('container') || classListNode.contains('ds__top-bar')) {
112        docSearchInputContainer[0].classList.remove('input-box-focused');
113        docSubmitButton.classList.add('hide');
114      }
115    });
116
117    function reportWindowSize() {
118      if (window.innerWidth < 979) {
119        docInputHandle.classList.add('hide');
120      } else {
121        docInputHandle.classList.remove('hide');
122      }
123    }
124    // window resize
125    window.onresize = reportWindowSize;
126
127    /** Enable Search for everyone.
128     * Except ie and Ipad two and three.
129     * Except of enterprise customer and algolia js is blocked for him.
130     */
131    function showHideSearchIcon(param) {
132      var searchMenuIcon = document.querySelectorAll('.doc-search-menu-icon');
133      if (param) {
134        searchMenuIcon[0] && searchMenuIcon[0].classList.add('hide');
135        searchMenuIcon[1] && searchMenuIcon[1].classList.add('hide');
136      } else {
137        searchMenuIcon[0] && searchMenuIcon[0].classList.remove('hide');
138        searchMenuIcon[1] && searchMenuIcon[1].classList.remove('hide');
139      }
140    }
141
142    // Detect IE11 and iPad
143    function detectIe11AndIpadTwoAndThree() {
144      return (
145        (!!window.MSInputMethodContext && !!document.documentMode) ||
146        (navigator.userAgent.search('iPad') >= 0 &&
147          (navigator.userAgent.match(/8.0/i) || navigator.userAgent.match(/7.0/i)))
148      );
149    }
150
151    if (detectIe11AndIpadTwoAndThree()) {
152      showHideSearchIcon('hide-search');
153      if (document.body.classList.contains('docs-search-auth-user')) {
154        document.body.classList.remove('docs-search-auth-user');
155      }
156    } else {
157      document.body.classList.add('docs-search-auth-user');
158    }
159    
160    window.validateSearchForm = function () {
161      return docSearchInputBox.value.trim() !== '';
162    };
163
164    // Dynamic Results Algolia Search Functionality
165    function isNoResults(hits) {
166      return hits.length === 0;
167    }
168    
169    function getNoResultsUi() {
170      return "<li class='global-search__no-results-container'>No results found</li>";
171    }
172
173    (function handleKeyboardNavigation() {
174      var list = document.getElementById('global-search-autocomplete'),
175        searchInput = document.getElementById('doc-search-box-input'),
176        items = list.getElementsByTagName('a'),
177        selectedItem = null;
178    
179      searchInput.addEventListener('keydown', function(event) {
180        if (items.length > 0 && event.key === 'ArrowDown') {
181          items[0].focus();
182          selectedItem = items[0];
183        }
184      });
185    
186      list.addEventListener('keydown', function(event) {
187        if (event.key === 'ArrowDown') {
188          // Move focus to the next list item
189          selectedItem = getNextItem(selectedItem);
190          selectedItem.focus();
191          event.preventDefault();
192        } else if (event.key === 'ArrowUp') {
193          // Move focus to the previous list item
194          selectedItem = getPreviousItem(selectedItem);
195          selectedItem.focus();
196          event.preventDefault();
197        }
198      });
199    
200      // Helper function to get the next list item
201      function getNextItem(item) {
202        if (!item) {
203          return items[0];
204        }
205        if (item.nextElementSibling) {
206          return item.nextElementSibling;
207        }
208        return items[0];
209      }
210    
211      // Helper function to get the previous list item
212      function getPreviousItem(item) {
213        if (!item) {
214          return items[0];
215        }
216        if (item.previousElementSibling) {
217          return item.previousElementSibling;
218        }
219        return items[items.length - 1];
220      }
221    })();
222    
223    // recursive function to determine the parent anchor element of the suggestion list
224    function findTargetAnchor(target) {
225      if (target) {
226        if (target.nodeName.toLowerCase() === 'a') {
227          return target;
228        }
229        return findTargetAnchor(target.parentNode);
230      }
231    }
232
233    function initGlobalSearch() {
234      var client = algoliasearch(
235          'YNHF55KPOX',
236          'MDI3NWM0YzhmZWI0N2U4NzBkYTgxMjYxYWIyNzUzN2EyYWMwNTNmODgwMTVlZjM0OTZiMTM0MGYzODBjNGEyMGZpbHRlcnM9aGFzX2NvZGVfc25pcHBldCUzQWZhbHNl'
237        ),
238        index = client.initIndex(AlgoliaSearchConfig),
239        searchInput = document.getElementById('doc-search-box-input'),
240        searchFAQInput = document.querySelectorAll('.faq-support__search-input, .search-support__search-input, .support-nav__nav-search-input'),
241        faqAutoComplete = document.getElementById('local-search-autocomplete'),
242        faqNavAutoComplete = document.getElementById('local-nav-search-autocomplete'),
243        autocomplete = document.getElementById('global-search-autocomplete');
244    
245      // global search
246      if (searchInput) {
247        searchInput.addEventListener('input', function() {
248          try {
249            var query = searchInput.value;
250            if (query.length > 3) {
251              index.search(query, { hitsPerPage: 5, clickAnalytics: true }).then(function(response) {
252                var hits = response.hits,
253                  nbHits = response.nbHits;
254      
255                autocomplete.innerHTML = '';
256                if (isNoResults(hits)) {
257                  autocomplete.innerHTML = getNoResultsUi();
258                  if (globalSearchFlag) {
259                    globalSearchFlag = false;
260                  }
261                } else {
262                  hits.forEach(function(hit, idx) {
263                    var heading = hit.headings.h1 || hit.headings.h2 || hit.headings.h3 || hit.headings.h4 || hit.headings.h5,
264                      titledHeading = heading && heading.length === 0 ? hit.title : heading,
265                      finalHeading = titledHeading || heading,
266                      suggestionContainerSkeleton =
267                        "<a href = '" +
268                        hit.url +
269                        "' class = 'global-search__search-suggestion' role = 'option' tabindex = '0' data-index = " +
270                        idx +
271                        ' data-title = ' +
272                        JSON.stringify(finalHeading) +
273                        ' data-query=' +
274                        query +
275                        ' data-category=' +
276                        hit.breadcrumb[0] +
277                        "><div class = 'global-search__search-suggestion-left'><div class = 'global-search__search-suggestion-title'>" +
278                        finalHeading +
279                        "</div><div class = 'global-search__search-suggestion-description'>" +
280                        hit.description +
281                        "</div></div><div class = 'global-search__search-suggestion-category' data-category=" +
282                        hit.breadcrumb[0] +
283                        '>' +
284                        hit.breadcrumb[0] +
285                        '</div></a>';
286      
287                    autocomplete.innerHTML += suggestionContainerSkeleton;
288                    if (globalSearchFlag) {
289                      globalSearchFlag = false;
290                    }
291                  });
292                }
293      
294                if (nbHits > 5) {
295                  var seeAllResults =
296                    "<a href = '/search?query=" +
297                    query +
298                    "&type=all' class = 'global-search__search-suggestion global-search__see-all-result' role = 'option' data-title = 'See All' tabindex='0' data-index= " +
299                    hits.length +
300                    ' data-query=' +
301                    query +
302                    '>See all (' +
303                    nbHits +
304                    ') results</li>';
305                  autocomplete.innerHTML += seeAllResults;
306                }
307              });
308            }
309          } catch (e) {}
310        });
311      }
312      
313      // local faq search
314      if (searchFAQInput.length > 0) {
315        for (var n = 0; n < searchFAQInput.length; n++) {
316          searchFAQInput[n].addEventListener('input', function() {
317            try {
318              var that = this,
319              query = that.value;
320              if (query.length > 3) {
321                index.search(query, {
322                    hitsPerPage: 5,
323                    clickAnalytics: true,
324                    filters: '(type:documentation OR type:support)',
325                    optionalFilters: [
326                      'type:support'
327                    ]
328                  }).then(function(response) {
329                  var hits = response.hits,
330                    nbHits = response.nbHits;
331
332                  if (that.nextElementSibling.classList.contains("global-search__faq")) {
333                    faqAutoComplete = that.nextElementSibling;  
334                  }
335      
336                  faqAutoComplete.innerHTML = '';
337                  faqAutoComplete.classList.remove("hide");
338                  if (isNoResults(hits)) {
339                    faqAutoComplete.innerHTML = getNoResultsUi();
340                    if (localSearchFlag) {
341                      localSearchFlag = false;
342                    }
343                  } else {
344                    hits.forEach(function(hit, idx) {
345                      var heading = hit.headings.h1 || hit.headings.h2 || hit.headings.h3 || hit.headings.h4 || hit.headings.h5,
346                        titledHeading = heading && heading.length === 0 ? hit.title : heading,
347                        finalHeading = titledHeading || heading,
348                        suggestionContainerSkeleton =
349                          "<a href = '" +
350                          hit.url +
351                          "' class = 'global-search__search-suggestion' role = 'option' tabindex = '0' data-index = " +
352                          idx +
353                          ' data-title = ' +
354                          JSON.stringify(finalHeading) +
355                          ' data-query=' +
356                          query +
357                          ' data-category=' +
358                          hit.breadcrumb[0] +
359                          "><div class = 'global-search__search-suggestion-left'><div class = 'global-search__search-suggestion-title'>" +
360                          finalHeading +
361                          "</div><div class = 'global-search__search-suggestion-description'>" +
362                          hit.description +
363                          "</div></div><div class = 'global-search__search-suggestion-category' data-category=" +
364                          hit.breadcrumb[0] +
365                          '>' +
366                          hit.breadcrumb[0] +
367                          '</div></a>';
368        
369                      faqAutoComplete.innerHTML += suggestionContainerSkeleton;
370                      if (localSearchFlag) {
371                        localSearchFlag = false;
372                      }
373                    });
374                  }
375        
376                  if (nbHits > 5) {
377                    var seeAllResults =
378                      "<a href = '/search?query=" +
379                      query +
380                      "&type=all' class = 'global-search__search-suggestion global-search__see-all-result' role = 'option' data-title = 'See All' tabindex='0' data-index= " +
381                      hits.length +
382                      ' data-query=' +
383                      query +
384                      '>See all (' +
385                      nbHits +
386                      ') results</li>';
387                    faqAutoComplete.innerHTML += seeAllResults;
388                  }
389                });
390              }
391            } catch (e) {}
392          });
393        }
394
395        // On Esc reset the flag for dynamic event
396        document.addEventListener('keydown', function(event) {
397          if (event.key === 'Escape' || event.keyCode === 27) {
398            localSearchFlag = true;
399          }
400        });
401      }
402      
403      // On Doc click empty the search results
404      document.addEventListener('click', function(event) {
405        if (autocomplete && !autocomplete.contains(event.target)) {
406          autocomplete.innerHTML = '';
407          globalSearchFlag = true;
408        }
409        if (faqAutoComplete && !faqAutoComplete.contains(event.target)) {
410          faqAutoComplete.innerHTML = '';
411          faqAutoComplete.classList.add("hide");
412          localSearchFlag = true;
413        }
414        if (faqNavAutoComplete && !faqNavAutoComplete.contains(event.target)) {
415          faqNavAutoComplete.innerHTML = '';
416          faqNavAutoComplete.classList.add("hide");
417          localSearchFlag = true;
418        }
419      });
420    }
421    
422    function trapFocusInElement(event, firstFocusElement, lastFocusElement) {
423      if (event.key === 'Tab' || event.keyCode === 9) {
424        // tab keycode is 9
425        if (event.shiftKey) {
426          if (document.activeElement === firstFocusElement) {
427            lastFocusElement.focus();
428            event.preventDefault();
429          }
430        } else if (document.activeElement === lastFocusElement) {
431          firstFocusElement.focus();
432          event.preventDefault();
433        }
434      }
435    }
436
437    window.onresize = function() {
438      if (window.innerWidth > 767) {
439        initGlobalSearch();
440      }
441    };
442
443    if (window.innerWidth > 767) {
444      initGlobalSearch();
445    }
446  }
447})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.