github.com/criteo/command-launcher@v0.0.0-20230407142452-fb616f546e98/gh-pages/assets/js/index.js (about)

     1  var suggestions = document.getElementById('suggestions');
     2  var search = document.getElementById('search');
     3  
     4  if (search !== null) {
     5    document.addEventListener('keydown', inputFocus);
     6  }
     7  
     8  function inputFocus(e) {
     9    if (e.ctrlKey && e.key === '/' ) {
    10      e.preventDefault();
    11      search.focus();
    12    }
    13    if (e.key === 'Escape' ) {
    14      search.blur();
    15      suggestions.classList.add('d-none');
    16    }
    17  }
    18  
    19  document.addEventListener('click', function(event) {
    20  
    21    var isClickInsideElement = suggestions.contains(event.target);
    22  
    23    if (!isClickInsideElement) {
    24      suggestions.classList.add('d-none');
    25    }
    26  
    27  });
    28  
    29  /*
    30  Source:
    31    - https://dev.to/shubhamprakash/trap-focus-using-javascript-6a3
    32  */
    33  
    34  document.addEventListener('keydown',suggestionFocus);
    35  
    36  function suggestionFocus(e) {
    37    const suggestionsHidden = suggestions.classList.contains('d-none');
    38    if (suggestionsHidden) return;
    39  
    40    const focusableSuggestions= [...suggestions.querySelectorAll('a')];
    41    if (focusableSuggestions.length === 0) return;
    42  
    43    const index = focusableSuggestions.indexOf(document.activeElement);
    44  
    45    if (e.key === "ArrowUp") {
    46      e.preventDefault();
    47      const nextIndex = index > 0 ? index - 1 : 0;
    48      focusableSuggestions[nextIndex].focus();
    49    }
    50    else if (e.key === "ArrowDown") {
    51      e.preventDefault();
    52      const nextIndex= index + 1 < focusableSuggestions.length ? index + 1 : index;
    53      focusableSuggestions[nextIndex].focus();
    54    }
    55  
    56  }
    57  
    58  /*
    59  Source:
    60    - https://github.com/nextapps-de/flexsearch#index-documents-field-search
    61    - https://raw.githack.com/nextapps-de/flexsearch/master/demo/autocomplete.html
    62  */
    63  
    64  (function(){
    65  
    66    var index = new FlexSearch.Document({
    67      tokenize: "forward",
    68      cache: 100,
    69      document: {
    70        id: 'id',
    71        store: [
    72          "href", "title", "description"
    73        ],
    74        field: [
    75          'title',
    76          'description',
    77          'content',
    78        ],
    79        index: ["title", "description", "content"]
    80      }
    81    });
    82  
    83  
    84    // Not yet supported: https://github.com/nextapps-de/flexsearch#complex-documents
    85  
    86    /*
    87    var docs = [
    88      {{ range $index, $page := (where .Site.Pages "Section" "docs") -}}
    89        {
    90          id: {{ $index }},
    91          href: "{{ .Permalink }}",
    92          title: {{ .Title | jsonify }},
    93          description: {{ .Params.description | jsonify }},
    94          content: {{ .Content | jsonify }}
    95        },
    96      {{ end -}}
    97    ];
    98    */
    99  
   100    // https://discourse.gohugo.io/t/range-length-or-last-element/3803/2
   101  
   102    {{ $list := slice }}
   103    {{- if and (isset .Site.Params.options "searchsectionsindex") (not (eq (len .Site.Params.options.searchSectionsIndex) 0)) }}
   104    {{- if eq .Site.Params.options.searchSectionsIndex "ALL" }}
   105    {{- $list = .Site.Pages }}
   106    {{- else }}
   107    {{- $list = (where .Site.Pages "Type" "in" .Site.Params.options.searchSectionsIndex) }}
   108    {{- if (in .Site.Params.options.searchSectionsIndex "HomePage") }}
   109    {{ $list = $list | append .Site.Home }}
   110    {{- end }}
   111    {{- end }}
   112    {{- else }}
   113    {{- $list = (where .Site.Pages "Section" "docs") }}
   114    {{- end }}
   115  
   116    {{ $len := (len $list) -}}
   117  
   118    {{ range $index, $element := $list -}}
   119      index.add(
   120        {
   121          id: {{ $index }},
   122          href: "{{ .Permalink | absURL }}",
   123          title: {{ .Title | jsonify }},
   124          {{ with .Description -}}
   125            description: {{ . | jsonify }},
   126          {{ else -}}
   127            description: {{ .Summary | plainify | jsonify }},
   128          {{ end -}}
   129          content: {{ .Plain | jsonify }}
   130        }
   131      );
   132    {{ end -}}
   133  
   134    search.addEventListener('input', show_results, true);
   135  
   136    function show_results(){
   137      const maxResult = 5;
   138      var searchQuery = this.value;
   139      var results = index.search(searchQuery, {limit: maxResult, enrich: true});
   140  
   141      // flatten results since index.search() returns results for each indexed field
   142      const flatResults = new Map(); // keyed by href to dedupe results
   143      for (const result of results.flatMap(r => r.result)) {
   144        if (flatResults.has(result.doc.href)) continue;
   145        flatResults.set(result.doc.href, result.doc);
   146      }
   147  
   148      suggestions.innerHTML = "";
   149      suggestions.classList.remove('d-none');
   150  
   151      // inform user that no results were found
   152      if (flatResults.size === 0 && searchQuery) {
   153        const noResultsMessage = document.createElement('div')
   154        noResultsMessage.innerHTML = `No results for "<strong>${searchQuery}</strong>"`
   155        noResultsMessage.classList.add("suggestion__no-results");
   156        suggestions.appendChild(noResultsMessage);
   157        return;
   158      }
   159  
   160      // construct a list of suggestions
   161      for(const [href, doc] of flatResults) {
   162          const entry = document.createElement('div');
   163          suggestions.appendChild(entry);
   164  
   165          const a = document.createElement('a');
   166          a.href = href;
   167          entry.appendChild(a);
   168  
   169          const title = document.createElement('span');
   170          title.textContent = doc.title;
   171          title.classList.add("suggestion__title");
   172          a.appendChild(title);
   173  
   174          const description = document.createElement('span');
   175          description.textContent = doc.description;
   176          description.classList.add("suggestion__description");
   177          a.appendChild(description);
   178  
   179          suggestions.appendChild(entry);
   180  
   181          if(suggestions.childElementCount == maxResult) break;
   182      }
   183    }
   184  }());