diff --git a/_includes/javascript.html b/_includes/javascript.html
index ad25c0a5..d25c1e75 100644
--- a/_includes/javascript.html
+++ b/_includes/javascript.html
@@ -9,3 +9,13 @@
+
+
+
+
diff --git a/_includes/navbar.html b/_includes/navbar.html
index 6b51efd4..d94b3aef 100644
--- a/_includes/navbar.html
+++ b/_includes/navbar.html
@@ -14,7 +14,7 @@
-
diff --git a/assets/css/powsybl/_navbar.scss b/assets/css/powsybl/_navbar.scss
index 63b9b9ff..7688e974 100644
--- a/assets/css/powsybl/_navbar.scss
+++ b/assets/css/powsybl/_navbar.scss
@@ -11,3 +11,8 @@
.content {
margin-top: $navbar-height;
}
+
+/* navbar has z-index: 1030 */
+ul.ui-autocomplete {
+ z-index: 1040;
+}
diff --git a/assets/js/search.js b/assets/js/search.js
index 06cc4aaa..70c81fef 100644
--- a/assets/js/search.js
+++ b/assets/js/search.js
@@ -17,6 +17,17 @@
}
}
+ function displaySearchException(searchException) {
+ var searchResults = document.getElementById('search-results');
+ var displayString = "ERROR
";
+ if (searchException.name == "QueryParseError") {
+ displayString += "Your query contains an error.
" + searchException + "
For a description of the query syntax and query special characters ('*', ':', '^', '~', '+', '-'), please visit https://lunrjs.com/guides/searching.html";
+ } else {
+ displayString += searchException;
+ }
+ searchResults.innerHTML = displayString;
+ }
+
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
@@ -32,6 +43,21 @@
var searchTerm = getQueryVariable('query');
+ // Initalize lunr with the fields it will be searching on. I've given title
+ // a boost of 10 to indicate matches on this field are more important.
+ var idx = lunr(function () {
+ this.field('id');
+ this.field('title', { boost: 10 });
+ this.field('content');
+
+ for (var key in window.store) { // Add the data to lunr
+ this.add({
+ 'id': key,
+ 'title': window.store[key].title,
+ 'content': window.store[key].content
+ });
+ }
+ });
if (searchTerm) {
document.getElementById('search-box').setAttribute("value", searchTerm);
@@ -51,7 +77,88 @@
}
});
- var results = idx.search(searchTerm); // Get lunr to perform a search
- displaySearchResults(results, window.store); // We'll write this in the next section
+ try {
+ var results = idx.search(searchTerm); // Get lunr to perform a search
+ displaySearchResults(results, window.store); // We'll write this in the next section
+ } catch (searchException) {
+ displaySearchException(searchException);
+ }
}
+
+ $(document).ready(function() {
+ const storeUnstemmed = function(builder) {
+
+ // Define a pipeline function that keeps the unstemmed word
+ const pipelineFunction = function(token) {
+ token.metadata['unstemmed'] = token.toString();
+ return token;
+ };
+
+ // Register the pipeline function so the index can be serialised
+ lunr.Pipeline.registerFunction(pipelineFunction, 'storeUnstemmed');
+
+ // Add the pipeline function to both the indexing pipeline and the searching pipeline
+ builder.pipeline.before(lunr.stemmer, pipelineFunction);
+
+ // Whitelist the unstemmed metadata key
+ builder.metadataWhitelist.push('unstemmed');
+ };
+
+ lunr.tokenizer.separator = /\W+/
+ const index = lunr(function() {
+ this.use(storeUnstemmed);
+ this.field('id');
+ this.field('title', { boost: 10 });
+ this.field('content');
+
+ for (var key in window.store) { // Add the data to lunr
+ this.add({
+ 'id': key,
+ 'title': window.store[key].title,
+ 'content': window.store[key].content
+ });
+ }
+ });
+ const autoComplete = function (searchTerm) {
+ const results = index.query(function(q) {
+ // exact matches should have the highest boost
+ q.term(searchTerm, { boost : 100 })
+ // wildcard matches should be boosted slightly
+ q.term(searchTerm, {
+ boost : 10,
+ usePipeline : true,
+ wildcard : lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING
+ })
+ // finally, try a fuzzy search, without any boost
+ q.term(searchTerm, { boost : 1, usePipeline : false, editDistance : 1 })
+ });
+ if (!results.length) {
+ return "";
+ }
+ return results.map(function(v, i, a) { // extract unstemmed terms
+ const unstemmedTerms = {};
+ Object.keys(v.matchData.metadata).forEach(function(term) {
+ Object.keys(v.matchData.metadata[term]).forEach(function(field) {
+ v.matchData.metadata[term][field].unstemmed.forEach(function(word) {
+ unstemmedTerms[word] = true;
+ });
+ });
+ });
+ return Object.keys(unstemmedTerms);
+ }).reduce(function(a, b) { // flatten
+ return a.concat(b);
+ }).filter(function(v, i, a) { // uniq
+ return a.indexOf(v) === i;
+ }).slice(0, 10);
+ }
+
+ $( "#search-box" ).autocomplete({
+ source: function(request, response) {
+ var results = autoComplete(request.term);
+ response(results);
+ },
+ select: function(event, ui) { $("#search-box").val(ui.item.value); $("#search-form").submit(); }
+ });
+ });
+
})();
diff --git a/search.md b/search.md
index e367edd4..75918630 100644
--- a/search.md
+++ b/search.md
@@ -4,19 +4,17 @@ title: Search
---
-
-
-