PageSourceSearch

https://norient.com/modules/custom/norient_search/assets/js/norient_search.js?1790252031

js norient.com collected 2026-09-24 17:14:56 UTC 13,293 bytes, 350 lines download raw bytes

1jQuery(document).ready(function () {
2    nSearch.init();
3});
4
5var nSearch = function ($) {
6    var inputEle; // There are more than one possible input fields at the same time.
7    
8    var lastSearchedWord = ""; // The word that was last requested to the server.
9    var timeoutId = 0; // Used as a handbreak for fast typing. So at max every 345 milliseconds a request will be started. 
10    var cleanOutId = 0; // When sending a form, we have to wait for the last suggestion result
11
12    var currentXHR; // Used to abort an asynchronious request when the next request is started.
13    var inputTextArr = []; // Array of words found in the text input field after keyup.
14    var lastListFromServer; // List of words that came last from the server.
15    var filters = {};
16    var used = false;
17    var actingForm;
18    
19    var registerHandlers = function () {
20        // input typing handlers
21        $('body').on('keyup', 'input#edit-keywords', function (e) {
22            if (e.keyCode == 13) { // the "enter" or "return" key
23                return;
24            } else if (e.keyCode == 40 || e.keyCode == 38 ) { // up and down arrow
25                moveSelection(e.keyCode);
26                return;
27            }
28            inputEle = $(this)[0];
29            inputTextArr = $(this).val().split(' ');
30            let word = inputTextArr[inputTextArr.length - 1];
31            if (word.length > 2) {
32                // check if this word has the last searched word as prefix - so we don't need another server request.
33                if (lastSearchedWord != "" && word.substr(0, lastSearchedWord.length) == lastSearchedWord) {
34                    var sublist = [];
35                    for (var i in lastListFromServer) {
36                        if (lastListFromServer[i].indexOf(transliterate(word.toLowerCase())) !== -1) {
37                            sublist.push(lastListFromServer[i]);
38                        }
39                    }
40                    createList(sublist);
41                } else {
42                    clearTimeout(timeoutId);
43                    timeoutId = setTimeout(function () {
44                        askTheServer(word);
45                    }, 345);
46                }
47            } else if (word.length < 3) {
48                $('#search-ajax-list').remove();
49            }
50        });
51        // maybe hide suggestion list
52        $('body').on('click', function(e) {
53            let targetId = $(e.target).attr('id');
54            let parentId = $(e.target).parent().attr('id');
55            let testArr = ['edit-keywords', 'search-ajax-list'];
56            if (testArr.indexOf(targetId) === -1 && testArr.indexOf(parentId) === -1) {
57                $('#search-ajax-list').remove();
58            }
59        });
60        // fill input on click selection
61        $('body').on('click', '#search-ajax-list .item', function () {
62            fillInput($(this).text());
63        });
64        // Sometimes the input is filled after page load.
65        // But then there would be no suggestion list for the preset words.
66        $('body').on('focus', 'input#edit-keywords', function (e) {
67            if (!used) {
68                used = true;
69                $(this).val('');
70            }
71        });
72        // mark list items as selected
73        $('body').on('mouseenter', '#search-ajax-list .item', function (e) {
74            $('#search-ajax-list .item').removeClass('hover');
75            $(e.target).addClass('hover');
76        });
77        // return key selects and sanatizes before submission
78        $('body').on('keydown', 'input#edit-keywords', function(e) {
79            if (e.keyCode != 13) {
80                return;
81            }
82            // Maybe an item in the list is active.
83            // Then put it in the input field.
84            let hoverItem = $('#search-ajax-list .item.hover');
85            if (hoverItem.length) {
86                fillInput($(hoverItem).text());
87            }
88            // sanatize input
89            if (!used) {
90                return;
91            }
92            e.preventDefault();
93            actingForm = $(this).closest('form')[0];
94            testForCleanInput();
95        });
96        // sanatize before submission
97        $('body').on('click', 'edit-submit-conflux-search', function (e) {
98            if (!used) {
99                return;
100            }
101            e.preventDefault();
102            actingForm = $(this).closest('form')[0];
103            testForCleanInput();
104        });
105    };
106    
107    // wait for last ajax call to finish before submitting form
108    var testForCleanInput = function () {
109        cleanOutId = setInterval(function () {
110            if (currentXHR == undefined || currentXHR.readyState == 4) {
111                clearInterval(cleanOutId);
112                cleanInput(actingForm);
113            }
114        }, 500);
115    };
116    
117    // sanatize before submission
118    var cleanInput = function(that) {
119            let inputTextArr = $(that).find('input#edit-keywords').val().split(' ');
120            let newInput = ''; // we might alter or remove some words
121            for (var i in inputTextArr) {
122                var inputWord = inputTextArr[i].toLowerCase();
123                inputWord = transliterate(inputWord);
124                if (inputWord.length < 3) { // to short words are disregarded
125                    continue;
126                }
127                if (filters[inputWord] !== undefined) { // found words are kept
128                    newInput += inputWord + ' ';
129                } else if (inputWord.length > 3){
130                    let bestSubstitude = bestCleanWord(inputWord);
131                    if (bestSubstitude) {
132                        newInput += bestSubstitude + ' ';
133                    }
134                }
135            }
136            if (newInput != '') {
137                $(that).find('input#edit-keywords').val(newInput);
138            }
139            
140            $(that).submit();
141    };
142    
143    // provides a substitude for a not matching word
144    var bestCleanWord = function(inputWord) {
145        let foundWords = Object.keys(filters);
146        foundWords.sort(function (a, b) {
147            return a.length - b.length || a.localeCompare(b);
148        });
149        // find shortest superword
150        let shortestSuperword;
151        for (let i in foundWords) {
152            if (foundWords[i].indexOf(inputWord) != -1) {
153                shortestSuperword = foundWords[i];
154                break;
155            }
156        }
157        let longestSubword;
158        for (let i = foundWords.length - 1; i >= 0; i--) {
159            if (inputWord.indexOf(foundWords[i]) != -1) {
160                longestSubword = foundWords[i];
161                break;
162            }
163        }
164        if (!shortestSuperword && !longestSubword) {
165            return false;
166        } else if (shortestSuperword && !longestSubword) {
167            return shortestSuperword;
168        } else if (!shortestSuperword && longestSubword) {
169            return longestSubword;
170        } else {
171            let diffSubword = Math.abs(inputWord.length - longestSubword.length);
172            let diffSuperword = Math.abs(inputWord.length - shortestSuperword.length);
173            if (diffSubword == diffSuperword) {
174                return longestSubword;
175            } else if (diffSubword < diffSuperword) {
176                return longestSubword;
177            } else {
178                return shortestSuperword;
179            }
180        }
181    };
182
183    var askTheServer = function (word) {
184        if (currentXHR != undefined) {
185            currentXHR.abort();
186        }
187        let catFilters = getCatFilters();
188
189        word = transliterate(word.toLowerCase());
190        currentXHR = $.post('/search/autocomplete', {
191            searchtext: word,
192            ids: getFilterIds(),
193            type: catFilters.type,
194            format: catFilters.format
195        }
196        ).done(function (result) {
197            lastListFromServer = result.data;
198            createList(result.data);
199            for (var key in result.ids) {
200                filters[key] = result.ids[key];
201            }
202            lastSearchedWord = word;
203        });
204    };
205    
206    var getFilterIds = function() {
207        var preWords = inputTextArr.slice(0, -1);
208        let filterIds = [];
209        for (var i in preWords) {
210            var lowerCase = transliterate(preWords[i].toLowerCase());
211            if (filters[lowerCase] !== undefined) {
212                filterIds = filterIds.concat(filters[lowerCase]);
213            }
214        }
215        filterIds = filterIds.filter(function(elem, index, self) {
216            return self.indexOf(elem) === index;
217        });
218        return filterIds;
219    };
220    
221    var getCatFilters = function() {
222        var format = $('select#edit-field-norient-format').val();
223        if (format == undefined || format == 'All') {
224            format = '';
225        }
226        var type = $('select#edit-type').val();
227        if (type == undefined || type == 'All') {
228            type = '';
229        }
230        
231        return { type: type, format: format };
232    };
233    
234    var createList = function (data) {
235        $('#search-ajax-list').remove();
236        let theme = 'light';
237        if ($(inputEle).closest('form').attr('id') == 'views-exposed-form-conflux-search-block-1') {
238            theme = 'dark';
239        }
240        var html = $('<div id="search-ajax-list" class="' + theme + '"></div>');
241        let dataCopy = data.slice(0, 5);
242        for (var i in dataCopy) {
243            var inputTextArrCopy = inputTextArr;
244            inputTextArrCopy[inputTextArrCopy.length - 1] = dataCopy[i];
245            var li = $('<div class="item">' + inputTextArrCopy.join(" ") + '</div>');
246            $(html).append(li);
247        }
248        let posAndWidth = getPositionAndWidth();
249        $(html).css({
250            'position': 'absolute',
251            'top': posAndWidth.top + 'px',
252            'left': posAndWidth.left + 'px',
253            'width': posAndWidth.width
254        });
255        $('body').append(html);
256    };
257    
258    var fillInput = function (text) {
259        $(inputEle).val(text).focus();
260        $('#search-ajax-list').remove();
261    };
262    
263    var getPositionAndWidth = function () {
264        let offset = $(inputEle).offset();
265        let height = $(inputEle).height();
266        let width = $(inputEle).width();
267        return {
268            top: offset.top + height,
269            left: offset.left,
270            height: height,
271            width: width
272        };
273    };
274    
275    var moveSelection = function(keyCode) {
276        // 40 runter
277        // 38 hoch
278        if (keyCode == 40) {
279            if ($('#search-ajax-list div.hover').length) {
280                let fakeHoverEle = $('#search-ajax-list div.hover');
281                if ($(fakeHoverEle).next().length) {
282                    $(fakeHoverEle).next().addClass('hover');
283                    $(fakeHoverEle).removeClass('hover');
284                    var offsetTop = $(fakeHoverEle).next().position().top + jQuery('#search-ajax-list').scrollTop();
285                    $('#search-ajax-list').scrollTop(offsetTop);
286                } else {
287                    $(fakeHoverEle).removeClass('hover');
288                    $('#search-ajax-list div').first().addClass('hover');
289                    $('#search-ajax-list').scrollTop(0);
290                }
291            } else {
292                $('#search-ajax-list div').first().addClass('hover');
293            }
294        } else if (keyCode == 38) {
295            if ($('#search-ajax-list div.hover').length) {
296                let fakeHoverEle = $('#search-ajax-list div.hover');
297                if ($(fakeHoverEle).prev().length) {
298                    $(fakeHoverEle).prev().addClass('hover');
299                    $(fakeHoverEle).removeClass('hover');
300                    var offsetTop = $(fakeHoverEle).prev().position().top + jQuery('#search-ajax-list').scrollTop();
301                    $('#search-ajax-list').scrollTop(offsetTop);
302                } else {
303                    $(fakeHoverEle).removeClass('hover');
304                    $('#search-ajax-list div').last().addClass('hover');
305                    var offsetTop = $('#search-ajax-list div').last().position().top + jQuery('#search-ajax-list').scrollTop();
306                    $('#search-ajax-list').scrollTop(offsetTop);
307                }
308            } else {
309                $('#search-ajax-list div').last().addClass('hover');
310            }
311        }
312    };
313    
314    var transliterate = function (word) {
315        var answer = "";
316        var a = {};
317        a["ä"] = "a";
318        a["ö"] = "o";
319        a["ü"] = "u";
320        a["ß"] = "ss";
321        a["Ã¥"] = "a";
322        a["é"] = "e";
323
324        for (let i in word) {
325            if (word.hasOwnProperty(i)) {
326                if (a[word[i]] === undefined) {
327                    answer += word[i];
328                } else {
329                    answer += a[word[i]];
330                }
331            }
332        }
333        return answer;
334    };
335    
336    var exports = {};
337    exports.init = function () {
338//        try {
339//            var uid = window.drupalSettings.user.uid;
340//            var testUids = ["3", "6237", "2526", "2500", "2496", "2492", "2491"];
341//            if (testUids.indexOf(uid) === -1) {
342//                return;
343//            }
344//        } catch (e) {
345//            return;
346//        }
347        registerHandlers();
348    };
349    return exports;
350}(jQuery);

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.