PageSourceSearch

https://help.anthology.com/ally-lms/js/html5.fuse.search.js

js anthology.com collected 2026-09-24 08:26:31 UTC 9,702 bytes, 297 lines download raw bytes

1$(document).on('search.ready', function () {
2    initFuseSearch();
3});
4
5$(document).ajaxComplete(function() {
6  initFuseSearch();
7});
8
9function initFuseSearch(){
10        //Stop arrow keys from default behaviour of moving before or after text so result selection can be done below
11    $('form .search-field').on('keydown', function (e) {
12        var _this = $(this);
13        if(e.keyCode == '13' && enterKey === 'search'){
14            search(e, _this);
15            return false;
16        }
17        else if (e.keyCode == '38') {
18            return false;
19        } else if (e.keyCode == '40') {
20            return false;
21        }
22    });
23
24    if(enterKey === 'search'){
25        var searchfield = $('form .search-field');
26        $(".portal-search .btn").click(function (e) {
27            search(e, searchfield.filter(':visible'));
28            return false;
29        });
30    }
31    else{
32        //Disable, only keyup used
33        $(".portal-search .btn").prop("disabled", true);
34    }
35
36
37    addSearch();
38
39    var timeout;
40    var delay = 200;
41
42    if(enterKey !== 'search'){
43        //Unbind the keyup and focus events so we can select a new index for fuse for portal page:
44        $('input#search').off('keyup focus');
45
46        //on keydown, clear the countdown for the keypress search delay
47        $('input#search').on('keydown', function () {
48            clearTimeout(timeout);
49        });
50
51        $('input#search').on('keyup focus', function (e) {
52            var _this = $(this);
53            clearTimeout(timeout);
54            timeout = setTimeout(function () {
55                if(enterKey === 'select'){
56                    //If the user is only using arrow keys to browse results, return false:
57                    var isSearch = selectResults(e);
58                    if (isSearch === false) {
59                        return false;
60                    }
61                }
62                search(e, _this);
63            },
64            delay);
65        });
66    }
67}
68
69var searchHighlighter;
70
71var $resultcontainer;
72
73var fuse;
74
75function addSearch() {
76
77    //For legacy HTML5:
78    if ($('ul#page-tools').length) {
79        $('ul#page-tools > li:first').html('<input placeholder="Search" type="text" class="form-control" id="search">');
80    } else {
81        //For new HTML5: Only adds to the search field actually used in the current page
82        $('.portal-search .search-field, .navbar-form .search-field, .site-sidebar-search .search-field, .tool-search-form .search-field').attr('id', 'search');
83    }
84
85    //For legacy, where the search container is not already there
86    if ($('.search-container').length == 0) {
87        $resultcontainer = $('<div id="search-container"><h2>Search results</h2><ul class="searchresults"></ul></div>');
88        $resultcontainer.appendTo($('#content-wrapper, .content-wrapper'));
89    } else {
90        if ($("*[data-portal-language]").length) {
91            $resultcontainer = $("*[data-portal-language='" + portalLanguage + "'] .portal-search-result");
92        } else {
93            $resultcontainer = $('.search-container');
94        }
95    }
96
97    //Make sure it has the id, even if it's for 'preloaded' variant
98    $resultcontainer.attr('id', 'search-container');
99
100    searchHighlighter = new Mark("ul.searchresults");
101
102    $resultcontainer.click(function () {
103        hideSearch($resultcontainer);
104    });
105
106    $('.portal-content, .site-content').click(function (e) {
107        if($(e.target).closest('.toolbar').length === 0){
108            hideSearch($resultcontainer);
109        }
110    });
111
112    hideSearch($resultcontainer);
113
114    var options = {
115        shouldSort: true,
116        threshold: fuse_threshold,
117        location: 10,
118        distance: 100000,
119        maxPatternLength: 32,
120        minMatchCharLength: 4,
121        keys:[ {
122            name: 'title',
123            weight: 0.7
124        }, {
125            name: 'body',
126            weight: 0.3
127        }]
128    };
129
130    //The index variable is created by xslt in the fuzzydata.js file.
131    if (typeof index == "undefined") {
132        fuse = new Fuse(indexDict[portalLanguage], options)
133    } else {
134        fuse = new Fuse(index, options)
135    }
136}
137
138function search(e, searchfield) {
139        // Get query
140        var query = searchfield.val();
141        // Search for it
142        var result = fuse.search(query);
143
144        var $ul = $('ul.searchresults', $resultcontainer);
145
146        // Output it
147        if (query === '') {
148            $ul.empty();
149            hideSearch($resultcontainer);
150        } else if (result.length === 0) {
151            $ul.empty();
152            $('.noresults').show();
153            showSearch($resultcontainer);
154        } else {
155            // Show results
156            $ul.empty();
157            $('.noresults').hide();
158            if ($('.portal-search-result').length) {
159                $('footer[data-portal-language="' + portalLanguage + '"]').hide();
160            }
161
162            for (var item in result) {
163                //For permalinks: data-topic-level will only be set if produce.permalink = 1 in XSLT
164                var topiclevel = $('section[data-topic-level]').first().attr('data-topic-level');
165                var up = '';
166
167                if (topiclevel != '') {
168                    for (i = 1; i < parseInt(topiclevel);
169                    i++) {
170                        up += '../';
171                    }
172                }
173
174                var url = up + result[item].url;
175
176                //If this is the portal/index page:
177                if ($('.portal-search-result').length) {
178                    url = portalLanguage + '/' + result[item].url;
179                }
180
181                var pathdisplay = '';
182                var breadcrumbs = result[item].breadcrumbs;
183                if (typeof breadcrumbs !== "undefined") {
184                    pathdisplay = '<p class="search-result-breadcrumbs">' + result[item].breadcrumbs + '</p>';
185                } else {
186                    pathdisplay = '<p class="search-result-url">' + url + '</p>';
187                }
188
189                //If there's a video in the topic it has the string [video]:
190                var checkvideo = result[item].body.substring(0,7);
191                var videosearchicon = '';
192                if(checkvideo == '[video]'){
193                    //console.log('video');
194                    videosearchicon = '<span class="video-search-icon" style="margin-left: 0.5em"><i class="fa fa-film" aria-hidden="true"></i></span>'
195                }
196
197                if (result[item].snippet !== '') {
198                    var $li = $('<li></li>')
199                        .addClass('searchresultitem');
200
201                    var $a = $('<a></a>')
202                        .attr('href', url);
203
204                    var $h3 = $('<h3></h3>')
205                        .addClass('searchresulttitle')
206                        .html(result[item].title + videosearchicon);
207
208                    var $p = $('<p></p>')
209                        .addClass('searchresultsnippet')
210                        .text(result[item].snippet);
211
212                    $a
213                        .append($h3)
214                        .append($p)
215                        .append(pathdisplay)
216                        .appendTo($li);
217                } else {
218                    var $li = $('<li></li>')
219                        .addClass('searchresultitem-nosnippet');
220
221                    var $a = $('<a></a>')
222                        .attr('href', url)
223                        .text(result[item].title);
224
225                    $li.append($a);
226                }
227
228                $ul.append($li);
229            }
230
231            showSearch($resultcontainer);
232
233            searchHighlighter.mark(query, {
234                "className": "search-highlight"
235            });
236        }
237    }
238
239function showSearch($resultcontainer) {
240    $resultcontainer.show();
241    if(enterKey === 'select'){
242        $('.searchresults .searchresultitem:first').addClass('selected-searchresultitem');
243    }
244    $('#topic-content').hide();
245}
246
247function hideSearch($resultcontainer) {
248    var input = $('form .search-field:visible');
249    //Do not hide results if the input has focus and is not empty
250    if (input.is(":focus") && input.val() !== '') {
251        return;
252    }
253    $resultcontainer.hide();
254    if ($('.portal-search-result').length) {
255        $('footer[data-portal-language="' + portalLanguage + '"]').show();
256    }
257    $('.noresults').hide();
258
259    $('#topic-content').show();
260}
261
262function selectResults(e) {
263    //Let the user browse search results by arrow keys and select by Enter (handled in html5-2-mp-common.js).
264    if (e.keyCode == '38') {
265        if ($('.selected-searchresultitem').is(':first-child')) {
266            return false;
267        } else {
268            var _this = $('.selected-searchresultitem');
269            _this.removeClass('selected-searchresultitem');
270            _this.prev().addClass('selected-searchresultitem');
271            var _new = $('.selected-searchresultitem');
272            if (_new.index() <= 1) {
273                $(window).scrollTop(0);
274            } else {
275                _new[0].scrollIntoView();
276                window.scrollBy(0, -80);
277            }
278            return false;
279        }
280    } else if (e.keyCode == '40') {
281        if ($('.selected-searchresultitem').is(':last-child')) {
282            return false;
283        } else {
284            var _this = $('.selected-searchresultitem');
285            _this.removeClass('selected-searchresultitem');
286            _this.next().addClass('selected-searchresultitem');
287            var _new = $('.selected-searchresultitem');
288            if (_new.index() > 1) {
289                _new[0].scrollIntoView();
290                window.scrollBy(0, -80);
291            }
292
293            return false;
294        }
295    }
296    return true;
297}

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.