| /* |
| * searchtools.js_t |
| * ~~~~~~~~~~~~~~~~ |
| * |
| * Sphinx JavaScript utilties for the full-text search. |
| * |
| * Copyright (c) 2007-2017 by the Sphinx team |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| */ |
| |
| |
| /* Non-minified version JS is _stemmer.js if file is provided */ |
| /** |
| * Porter Stemmer |
| */ |
| var Stemmer = function() { |
| |
| var step2list = { |
| ational: 'ate', |
| tional: 'tion', |
| enci: 'ence', |
| anci: 'ance', |
| izer: 'ize', |
| bli: 'ble', |
| alli: 'al', |
| entli: 'ent', |
| eli: 'e', |
| ousli: 'ous', |
| ization: 'ize', |
| ation: 'ate', |
| ator: 'ate', |
| alism: 'al', |
| iveness: 'ive', |
| fulness: 'ful', |
| ousness: 'ous', |
| aliti: 'al', |
| iviti: 'ive', |
| biliti: 'ble', |
| logi: 'log' |
| }; |
| |
| var step3list = { |
| icate: 'ic', |
| ative: '', |
| alize: 'al', |
| iciti: 'ic', |
| ical: 'ic', |
| ful: '', |
| ness: '' |
| }; |
| |
| var c = "[^aeiou]"; // consonant |
| var v = "[aeiouy]"; // vowel |
| var C = c + "[^aeiouy]*"; // consonant sequence |
| var V = v + "[aeiou]*"; // vowel sequence |
| |
| var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 |
| var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 |
| var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 |
| var s_v = "^(" + C + ")?" + v; // vowel in stem |
| |
| this.stemWord = function (w) { |
| var stem; |
| var suffix; |
| var firstch; |
| var origword = w; |
| |
| if (w.length < 3) |
| return w; |
| |
| var re; |
| var re2; |
| var re3; |
| var re4; |
| |
| firstch = w.substr(0,1); |
| if (firstch == "y") |
| w = firstch.toUpperCase() + w.substr(1); |
| |
| // Step 1a |
| re = /^(.+?)(ss|i)es$/; |
| re2 = /^(.+?)([^s])s$/; |
| |
| if (re.test(w)) |
| w = w.replace(re,"$1$2"); |
| else if (re2.test(w)) |
| w = w.replace(re2,"$1$2"); |
| |
| // Step 1b |
| re = /^(.+?)eed$/; |
| re2 = /^(.+?)(ed|ing)$/; |
| if (re.test(w)) { |
| var fp = re.exec(w); |
| re = new RegExp(mgr0); |
| if (re.test(fp[1])) { |
| re = /.$/; |
| w = w.replace(re,""); |
| } |
| } |
| else if (re2.test(w)) { |
| var fp = re2.exec(w); |
| stem = fp[1]; |
| re2 = new RegExp(s_v); |
| if (re2.test(stem)) { |
| w = stem; |
| re2 = /(at|bl|iz)$/; |
| re3 = new RegExp("([^aeiouylsz])\\1$"); |
| re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); |
| if (re2.test(w)) |
| w = w + "e"; |
| else if (re3.test(w)) { |
| re = /.$/; |
| w = w.replace(re,""); |
| } |
| else if (re4.test(w)) |
| w = w + "e"; |
| } |
| } |
| |
| // Step 1c |
| re = /^(.+?)y$/; |
| if (re.test(w)) { |
| var fp = re.exec(w); |
| stem = fp[1]; |
| re = new RegExp(s_v); |
| if (re.test(stem)) |
| w = stem + "i"; |
| } |
| |
| // Step 2 |
| re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; |
| if (re.test(w)) { |
| var fp = re.exec(w); |
| stem = fp[1]; |
| suffix = fp[2]; |
| re = new RegExp(mgr0); |
| if (re.test(stem)) |
| w = stem + step2list[suffix]; |
| } |
| |
| // Step 3 |
| re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; |
| if (re.test(w)) { |
| var fp = re.exec(w); |
| stem = fp[1]; |
| suffix = fp[2]; |
| re = new RegExp(mgr0); |
| if (re.test(stem)) |
| w = stem + step3list[suffix]; |
| } |
| |
| // Step 4 |
| re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; |
| re2 = /^(.+?)(s|t)(ion)$/; |
| if (re.test(w)) { |
| var fp = re.exec(w); |
| stem = fp[1]; |
| re = new RegExp(mgr1); |
| if (re.test(stem)) |
| w = stem; |
| } |
| else if (re2.test(w)) { |
| var fp = re2.exec(w); |
| stem = fp[1] + fp[2]; |
| re2 = new RegExp(mgr1); |
| if (re2.test(stem)) |
| w = stem; |
| } |
| |
| // Step 5 |
| re = /^(.+?)e$/; |
| if (re.test(w)) { |
| var fp = re.exec(w); |
| stem = fp[1]; |
| re = new RegExp(mgr1); |
| re2 = new RegExp(meq1); |
| re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); |
| if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) |
| w = stem; |
| } |
| re = /ll$/; |
| re2 = new RegExp(mgr1); |
| if (re.test(w) && re2.test(w)) { |
| re = /.$/; |
| w = w.replace(re,""); |
| } |
| |
| // and turn initial Y back to y |
| if (firstch == "y") |
| w = firstch.toLowerCase() + w.substr(1); |
| return w; |
| } |
| } |
| |
| |
| |
| /** |
| * Simple result scoring code. |
| */ |
| var Scorer = { |
| // Implement the following function to further tweak the score for each result |
| // The function takes a result array [filename, title, anchor, descr, score] |
| // and returns the new score. |
| /* |
| score: function(result) { |
| return result[4]; |
| }, |
| */ |
| |
| // query matches the full name of an object |
| objNameMatch: 11, |
| // or matches in the last dotted part of the object name |
| objPartialMatch: 6, |
| // Additive scores depending on the priority of the object |
| objPrio: {0: 15, // used to be importantResults |
| 1: 5, // used to be objectResults |
| 2: -5}, // used to be unimportantResults |
| // Used when the priority is not in the mapping. |
| objPrioDefault: 0, |
| |
| // query for obj |
| objFullName: 20, |
| // Highest rank obj |
| objHigh: 100, |
| // query found in title |
| title: 30, |
| // query found in terms |
| term: 5 |
| }; |
| |
| |
| /** |
| * Search Module |
| */ |
| var isPreview = false; |
| var Search = { |
| |
| _index : null, |
| _queued_query : null, |
| _pulse_status : -1, |
| |
| init : function() { |
| var params = $.getQueryParameters(); |
| if (params.q) { |
| var query = params.q[0]; |
| $('input[name="q"]')[0].value = query; |
| this.performSearch(query); |
| } |
| }, |
| |
| loadIndex : function(url) { |
| $.ajax({type: "GET", url: url, data: null, |
| dataType: "script", cache: true, |
| complete: function(jqxhr, textstatus) { |
| if (textstatus != "success") { |
| document.getElementById("searchindexloader").src = url; |
| } |
| }}); |
| }, |
| |
| setIndex : function(index) { |
| var q; |
| this._index = index; |
| if ((q = this._queued_query) !== null) { |
| this._queued_query = null; |
| Search.query(q); |
| } |
| }, |
| |
| hasIndex : function() { |
| return this._index !== null; |
| }, |
| |
| deferQuery : function(query) { |
| this._queued_query = query; |
| }, |
| |
| stopPulse : function() { |
| this._pulse_status = 0; |
| }, |
| |
| startPulse : function() { |
| if (this._pulse_status >= 0) |
| return; |
| function pulse() { |
| var i; |
| Search._pulse_status = (Search._pulse_status + 1) % 4; |
| var dotString = ''; |
| for (i = 0; i < Search._pulse_status; i++) |
| dotString += '.'; |
| Search.dots.text(dotString); |
| if (Search._pulse_status > -1) |
| window.setTimeout(pulse, 500); |
| } |
| pulse(); |
| }, |
| |
| /** |
| * perform a search for something (or wait until index is loaded) |
| */ |
| performSearch : function(query) { |
| if(!isPreview) { |
| // create the required interface elements |
| this.out = $('#search-results'); |
| this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out); |
| this.dots = $('<span></span>').appendTo(this.title); |
| this.status = $('<p style="display: none"></p>').appendTo(this.out); |
| this.output = $('<ul class="search"/>').appendTo(this.out); |
| |
| $('#search-progress').text(_('Preparing search...')); |
| this.startPulse(); |
| } |
| |
| // index already loaded, the browser was quick! |
| if (this.hasIndex()) |
| this.query(query); |
| else |
| this.deferQuery(query); |
| }, |
| |
| /** |
| * execute search (requires search index to be loaded) |
| */ |
| query : function(query) { |
| var i; |
| var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]; |
| |
| // stem the searchterms and add them to the correct list |
| var stemmer = new Stemmer(); |
| var searchterms = []; |
| var excluded = []; |
| var hlterms = []; |
| var tmp = query.split(/\s+/); |
| var objectterms = []; |
| for (i = 0; i < tmp.length; i++) { |
| if (tmp[i] !== "") { |
| objectterms.push(tmp[i].toLowerCase()); |
| } |
| |
| if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) || |
| tmp[i] === "") { |
| // skip this "word" |
| continue; |
| } |
| // stem the word |
| var word = stemmer.stemWord(tmp[i].toLowerCase()); |
| var toAppend; |
| // select the correct list |
| if (word[0] == '-') { |
| toAppend = excluded; |
| word = word.substr(1); |
| } |
| else { |
| toAppend = searchterms; |
| hlterms.push(tmp[i].toLowerCase()); |
| } |
| // only add if not already in the list |
| if (!$u.contains(toAppend, word)) |
| toAppend.push(word); |
| } |
| var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" ")); |
| |
| // console.debug('SEARCH: searching for:'); |
| // console.info('required: ', searchterms); |
| // console.info('excluded: ', excluded); |
| |
| // prepare search |
| var terms = this._index.terms; |
| var titleterms = this._index.titleterms; |
| |
| // array of [filename, title, anchor, descr, score] |
| var results = []; |
| $('#search-progress').empty(); |
| |
| // lookup as object |
| for (i = 0; i < objectterms.length; i++) { |
| var others = [].concat(objectterms.slice(0, i), |
| objectterms.slice(i+1, objectterms.length)); |
| results = results.concat(this.performObjectSearch(objectterms[i], others)); |
| } |
| |
| // lookup as search terms in fulltext |
| results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms)); |
| |
| // let the scorer override scores with a custom scoring function |
| if (Scorer.score) { |
| for (i = 0; i < results.length; i++) |
| results[i][4] = Scorer.score(results[i]); |
| } |
| |
| // now sort the results by score (in opposite order of appearance, since the |
| // display function below uses pop() to retrieve items) and then |
| // alphabetically |
| results.sort(function(a, b) { |
| var left = a[4]; |
| var right = b[4]; |
| if (left > right) { |
| return 1; |
| } else if (left < right) { |
| return -1; |
| } else { |
| // same score: sort alphabetically |
| left = a[1].toLowerCase(); |
| right = b[1].toLowerCase(); |
| return (left > right) ? -1 : ((left < right) ? 1 : 0); |
| } |
| }); |
| |
| //Render result for preview |
| if(isPreview) { |
| var prevNum = 0; |
| $('#search-preview').children().remove(); |
| if(results.length == 0) { |
| $('#search-preview').append('<p>' + 'No suggestion for your query.' + '</p>'); |
| } |
| else { |
| $('#search-preview').append('<p>' + 'Suggestions for your query. Press enter to see full results.' + '</p>'); |
| $('#search-preview').append('<ul id="preview-list"></ul>'); |
| while(prevNum < 10 && results.length > 0) { |
| var item = results.pop(); |
| if(item[0].endsWith('.md')) { |
| item[0] = item[0].substring(0, item[0].length - 3); |
| } |
| var listItem = $('<li></li>'); |
| if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') { |
| // dirhtml builder |
| var dirname = item[0] + '/'; |
| if (dirname.match(/\/index\/$/)) { |
| dirname = dirname.substring(0, dirname.length-6); |
| } else if (dirname == 'index/') { |
| dirname = ''; |
| } |
| listItem.append($('<a/>').attr('href', |
| DOCUMENTATION_OPTIONS.URL_ROOT + dirname + |
| highlightstring + item[2]).html(item[1])); |
| } else { |
| // normal html builders |
| var baseURL = window.location.protocol + '//' + window.location.hostname + '/'; |
| var urlHref = window.location.href; |
| let urlSplits = urlHref.split("/"); |
| let versionString = ''; |
| for (var idx = 0; idx < urlSplits.length; ++idx) { |
| if(urlSplits[idx] == 'versions') { |
| versionString = 'versions/' + urlSplits[idx + 1] + '/'; |
| break; |
| } |
| } |
| baseURL = baseURL.concat(versionString); |
| listItem.append($('<a/>').attr('href', |
| baseURL + item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX + |
| highlightstring + item[2]).html(item[1])); |
| } |
| var html = listItem.children().html(); |
| listItem.children().html(html.replace(RegExp(query, 'gi'), '<strong>$&</strong>')); |
| $('#preview-list').append(listItem); |
| if(prevNum < 9 && results.length > 0) $('#preview-list').append('<hr>'); |
| prevNum++; |
| } |
| } |
| $('#search-preview').show(); |
| return; |
| } |
| else $('#search-preview').hide(); |
| |
| // for debugging |
| //Search.lastresults = results.slice(); // a copy |
| //console.info('search results:', Search.lastresults); |
| |
| // print the results, at most 100 results. |
| if(results.length > 100) results = results.slice(results.length - 100, results.length); |
| var resultCount = results.length; |
| function displayNextItem() { |
| // results left, load the summary and display it |
| if (results.length) { |
| var item = results.pop(); |
| if(item[0].endsWith('.md')) { |
| item[0] = item[0].substring(0, item[0].length - 3); |
| } |
| var listItem = $('<li style="display:none"></li>'); |
| if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') { |
| // dirhtml builder |
| var dirname = item[0] + '/'; |
| if (dirname.match(/\/index\/$/)) { |
| dirname = dirname.substring(0, dirname.length-6); |
| } else if (dirname == 'index/') { |
| dirname = ''; |
| } |
| listItem.append($('<a/>').attr('href', |
| DOCUMENTATION_OPTIONS.URL_ROOT + dirname + |
| highlightstring + item[2]).html(item[1])); |
| } else { |
| // normal html builders |
| listItem.append($('<a/>').attr('href', |
| item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX + |
| highlightstring + item[2]).html(item[1])); |
| } |
| if (item[3]) { |
| listItem.append($('<span> (' + item[3] + ')</span>')); |
| Search.output.append(listItem); |
| listItem.slideDown(5, function() { |
| displayNextItem(); |
| }); |
| } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) { |
| $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[0] + '.md.txt', |
| dataType: "text", |
| complete: function(jqxhr, textstatus) { |
| var data = jqxhr.responseText; |
| if (data !== '' && data !== undefined) { |
| listItem.append(Search.makeSearchSummary(data, searchterms, hlterms)); |
| } |
| Search.output.append(listItem); |
| listItem.slideDown(5, function() { |
| displayNextItem(); |
| }); |
| }}); |
| } else { |
| // no source available, just display title |
| Search.output.append(listItem); |
| listItem.slideDown(5, function() { |
| displayNextItem(); |
| }); |
| } |
| } |
| // search finished, update title and status message |
| else { |
| Search.stopPulse(); |
| //Add pagination |
| if(resultCount > 0) { |
| var numPerPage = 10; |
| var pageEnd = Math.trunc(resultCount/numPerPage); |
| if(resultCount % numPerPage != 0) pageEnd++; |
| $('#search-results').children().slice(0, 3).remove(); |
| $('#search-results').append('<ul id="searchPage" class="pagination"></ul>'); |
| for(var k = 0; k < pageEnd; ++k) { |
| var page = $('<li class="page-item"><a class="page-link" href="#">' + (k + 1) + '</a></li>'); |
| page.click(function () { |
| $('#search-results > ul.search').children().hide(); |
| var pageNum = parseInt($(this).children().first().html()) |
| $('#search-results > ul.search').children().slice((pageNum - 1) * numPerPage, pageNum * numPerPage).show(); |
| $('#searchPage').children().removeClass('active'); |
| $(this).addClass('active'); |
| }); |
| $('ul.pagination').append(page); |
| } |
| $('#search-results > ul.search').children().hide(); |
| $('#search-results > ul.search').children().slice(0, numPerPage).show(); |
| $('#searchPage').children().first().addClass('active'); |
| } |
| Search.title.text(_('Search Results')); |
| if (!resultCount) |
| Search.status.text(_('Your search did not match any documents in this version of the documentation. You can use the dropdown selector in the navigation bar to try another version. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.')); |
| else |
| Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount)); |
| Search.status.fadeIn(500); |
| } |
| } |
| displayNextItem(); |
| }, |
| |
| /** |
| * search for object names |
| */ |
| performObjectSearch : function(object, otherterms) { |
| var filenames = this._index.filenames; |
| var objects = this._index.objects; |
| var objnames = this._index.objnames; |
| var titles = this._index.titles; |
| var objLowLimit = 10; |
| |
| var i; |
| var results = []; |
| |
| for (var prefix in objects) { |
| for (var name in objects[prefix]) { |
| var fullname = (prefix ? prefix + '.' : '') + name; |
| if (fullname.toLowerCase().indexOf(object.toLowerCase()) > -1) { |
| var score = Scorer.objFullName; |
| var parts = fullname.split('.'); |
| // check for different match types: exact matches of full name or |
| // "last name" (i.e. last dotted part) |
| if (fullname == object || parts[parts.length - 1] == object) { |
| score += Scorer.objNameMatch; |
| // matches in last name |
| } else if (parts[parts.length - 1].indexOf(object) > -1) { |
| score += Scorer.objPartialMatch; |
| } |
| var match = objects[prefix][name]; |
| var objname = objnames[match[1]][2]; |
| var title = titles[match[0]]; |
| // If more than one term searched for, we require other words to be |
| // found in the name/title/description |
| if (otherterms.length > 0) { |
| var haystack = (prefix + ' ' + name + ' ' + |
| objname + ' ' + title).toLowerCase(); |
| var allfound = true; |
| for (i = 0; i < otherterms.length; i++) { |
| if (haystack.indexOf(otherterms[i]) == -1) { |
| allfound = false; |
| break; |
| } |
| } |
| if (!allfound) { |
| continue; |
| } |
| } |
| var descr = objname + _(', in ') + title; |
| |
| var anchor = match[3]; |
| if (anchor === '') |
| anchor = fullname; |
| else if (anchor == '-') |
| anchor = objnames[match[1]][1] + '-' + fullname; |
| // add custom score for some objects according to scorer |
| if(title.toLowerCase().indexOf(object.toLowerCase()) != -1) { |
| score += Scorer.title; |
| } |
| if (Scorer.objPrio.hasOwnProperty(match[2])) { |
| score += Scorer.objPrio[match[2]]; |
| } else { |
| score += Scorer.objPrioDefault; |
| } |
| results.push([filenames[match[0]], fullname, '#'+anchor, descr, score]); |
| } |
| } |
| } |
| //If number of obj is no greater than objLowLimit, add higher priority score |
| if(results.length <= objLowLimit) { |
| for(var i = 0; i < results.length; ++i) { |
| results[i][4] += Scorer.objHigh; |
| } |
| } |
| return results; |
| }, |
| |
| /** |
| * search for full-text terms in the index |
| */ |
| performTermsSearch : function(searchterms, excluded, terms, titleterms) { |
| var filenames = this._index.filenames; |
| var titles = this._index.titles; |
| |
| var i, j, file; |
| var fileMap = {}; |
| var scoreMap = {}; |
| var results = []; |
| var scoreDict = {}; |
| |
| // perform the search on the required terms |
| for (i = 0; i < searchterms.length; i++) { |
| var word = searchterms[i]; |
| var files = []; |
| var _o = [ |
| {files: terms[word], score: Scorer.term}, |
| {files: titleterms[word], score: Scorer.title} |
| ]; |
| |
| // no match but word was a required one |
| if ($u.every(_o, function(o){return o.files === undefined;})) { |
| break; |
| } |
| // found search word in contents |
| $u.each(_o, function(o) { |
| var _files = o.files; |
| if (_files === undefined) |
| return |
| |
| if (_files.length === undefined) |
| _files = [_files]; |
| files = files.concat(_files); |
| |
| // set score for the word in each file to Scorer.term |
| for (j = 0; j < _files.length; j++) { |
| file = _files[j]; |
| if (!(file in scoreMap)) |
| scoreMap[file] = {} |
| scoreMap[file][word] = o.score; |
| } |
| }); |
| |
| // create the mapping |
| for (j = 0; j < files.length; j++) { |
| file = files[j]; |
| if (file in fileMap) |
| fileMap[file].push(word); |
| else |
| fileMap[file] = [word]; |
| } |
| } |
| |
| // now check if the files don't contain excluded terms |
| for (file in fileMap) { |
| var valid = true; |
| |
| // check if all requirements are matched |
| if (fileMap[file].length != searchterms.length) |
| continue; |
| |
| // ensure that none of the excluded terms is in the search result |
| for (i = 0; i < excluded.length; i++) { |
| if (terms[excluded[i]] == file || |
| titleterms[excluded[i]] == file || |
| $u.contains(terms[excluded[i]] || [], file) || |
| $u.contains(titleterms[excluded[i]] || [], file)) { |
| valid = false; |
| break; |
| } |
| } |
| |
| // if we have still a valid result we can add it to the result list |
| if (valid) { |
| // select one (max) score for the file. |
| // for better ranking, we should calculate ranking by using words statistics like basic tf-idf... |
| var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]})); |
| for(i = 0; i < searchterms.length; i++) { |
| var word = searchterms[i]; |
| if(word == 'ndarrai') word = 'ndarray'; |
| if(titles[file].toLowerCase().indexOf(word.toLowerCase()) != -1) { |
| score += Scorer.title; |
| } |
| } |
| |
| if(!(filenames[file] in scoreDict)) { |
| scoreDict[filenames[file]] = {}; |
| } |
| if(!(titles[file] in scoreDict[filenames[file]])) { |
| scoreDict[filenames[file]][titles[file]] = 0; |
| } |
| scoreDict[filenames[file]][titles[file]] += score; |
| } |
| } |
| |
| for(var file in scoreDict) { |
| for(var title in scoreDict[file]) { |
| results.push([file, title, '', null, scoreDict[file][title]]); |
| } |
| } |
| return results; |
| }, |
| |
| /** |
| * helper function to return a node containing the |
| * search summary for a given text. keywords is a list |
| * of stemmed words, hlwords is the list of normal, unstemmed |
| * words. the first one is used to find the occurance, the |
| * latter for highlighting it. |
| */ |
| makeSearchSummary : function(text, keywords, hlwords) { |
| var textLower = text.toLowerCase(); |
| var start = 0; |
| $.each(keywords, function() { |
| var i = textLower.indexOf(this.toLowerCase()); |
| if (i > -1) |
| start = i; |
| }); |
| start = Math.max(start - 120, 0); |
| var excerpt = ((start > 0) ? '...' : '') + |
| $.trim(text.substr(start, 240)) + |
| ((start + 240 - text.length) ? '...' : ''); |
| var rv = $('<div class="context"></div>').text(excerpt); |
| $.each(hlwords, function() { |
| rv = rv.highlightText(this, 'highlighted'); |
| }); |
| return rv; |
| } |
| }; |
| |
| $(document).ready(function() { |
| var searchBoxWidth = $('#search-input-wrap').width(); |
| var searchBoxWidthModifier = 150; |
| var focusInputColor = "white"; |
| var focusIconColor = "dimgray"; |
| var focusPlaceColor = "searchBoxExp"; |
| var normalInputColor = "transparent"; |
| var normalIconColor = "white"; |
| var normalPlaceColor = "searchBoxNorm"; |
| |
| function focusOut() { |
| $("#search-input-wrap").css('width', ''); |
| $(".searchBox").width(searchBoxWidth); |
| $(".searchBox").css("background-color", normalInputColor); |
| $('#search-input-wrap input').css("background-color", normalInputColor); |
| $(".searchBox .glyphicon-search").css("color", normalIconColor); |
| $(".searchBox").addClass(normalPlaceColor); |
| $(".searchBox").removeClass(focusPlaceColor); |
| $(".searchBox").css('width', ''); |
| $('#search-preview').hide(); |
| } |
| |
| Search.init(); |
| $('#search-input-wrap input').focus(function () { |
| var modifiedWidth = Math.max($('#navContainer').width() - searchBoxWidthModifier, searchBoxWidth); |
| $("#search-input-wrap").width(modifiedWidth); |
| $(".searchBox").width(modifiedWidth); |
| $(".searchBox").css("background-color", focusInputColor); |
| $(this).css("background-color", focusInputColor); |
| $(".searchBox .glyphicon-search").css("color", focusIconColor); |
| $(".searchBox").addClass(focusPlaceColor); |
| $(".searchBox").removeClass(normalPlaceColor); |
| if($(this).val().length > 0) { |
| isPreview = true; |
| Search.performSearch($(this).val()); |
| isPreview = false; |
| } |
| }); |
| |
| //Click to focus out |
| $('body').click(function (e) { |
| if(e.target.id == 'search-preview' || e.target.name == 'q' || $(e.target).parents("#search-preview").size()) return; |
| |
| focusOut(); |
| }); |
| |
| //Press esc to focus out |
| $(document).keyup(function(e) { |
| if (e.keyCode == 27) { // escape key maps to keycode `27` |
| $('#search-input-wrap input').blur(); |
| focusOut(); |
| } |
| }); |
| |
| //Add search result preview |
| $('#search-input-wrap input').on('input', function () { |
| if($(this).val().length == 0) { |
| $('#search-preview').hide(); |
| return; |
| } |
| isPreview = true; |
| Search.performSearch($(this).val()); |
| isPreview = false; |
| }); |
| }); |