Last active
November 1, 2018 15:37
-
-
Save Tazeg/acc8a6690f2a200353c8cdab437a1012 to your computer and use it in GitHub Desktop.
Hugo search engine, see : https://en.jeffprod.com/blog/2018/build-your-own-hugo-website-search-engine/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="search" id="search"> | |
<input type="text" placeholder="Search site..." v-model="txt" @keyup="search()" @blur="close()" maxlength="50"> | |
<div class="search-results" :style="{'display': showresult?'block':'none'}"> | |
<a v-for="item in result" :href="item.url">{{ printf "{{ item.title }}" }}</a> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- modules --> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js" integrity="sha256-FtWfRI+thWlNz2sB3SJbwKx5PgMyKIVgwHCTwa3biXc=" crossorigin="anonymous"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js" integrity="sha256-mpnrJ5DpEZZkwkE1ZgkEQQJW/46CSEh/STrZKOB/qoM=" crossorigin="anonymous"></script> | |
<script> | |
let vuesearch = new Vue({ | |
el: '#search', // div ID | |
data: { | |
txt: '', // will contain the text written by user | |
timeoutID: 0, // used to detect when the user stopped typing | |
showresult: false, // show the result dropdown, or not | |
result: {}, // results to display, as JSON : {[ {"url":"", "title":""},..] } | |
bdd: [] // will contain the full JSON file created by HUGO | |
}, | |
mounted: function() { | |
// loading the full JSON to 'bdd' | |
axios.get('{{ with .Site.GetPage "/search.md" }}{{ .Permalink }}{{ end }}') | |
.then(function (response) { | |
vuesearch.bdd = response.data.results; | |
}) | |
.catch(function (error) { | |
console.log(error); | |
}); | |
}, | |
methods: { | |
close: function() { | |
// Close the dropdown when the input search loses focus | |
// with a 300ms delay to let time for the click on link to work | |
setTimeout(function() { | |
vuesearch.showresult = false; | |
vuesearch.txt = ''; | |
}, 300); | |
}, | |
search: function() { | |
// we will search when the user stopped typing for 500ms | |
clearTimeout(this.timeoutID); | |
this.timeoutID = setTimeout(this.dosearch, 500); | |
}, | |
dosearch: function() { | |
// do the search in the 'bdd' | |
this.result = []; // clear previous result | |
let words = this.txt.split(' '); // split typed text with spaces | |
let words2 = []; // words that will be searched | |
words.forEach(function(element) { // to skip empty words, if multiple spaces typed (i.e "a b c") | |
if(element) {words2.push(element);} | |
}); | |
let r; | |
let resultmp; | |
words2.forEach(function(e) { // for each word | |
r = vuesearch.bdd.filter(p => p.content.indexOf(e.toLowerCase()) !== -1); | |
if(vuesearch.result.length===0) {vuesearch.result = r.slice(); return;} | |
resultmp = []; | |
vuesearch.result.forEach(function(all1) { | |
r.forEach(function(all2) { // we want AND for words | |
if(all1.url===all2.url) {resultmp.push(all1);} | |
}); | |
}); | |
vuesearch.result = resultmp.slice(); | |
}); | |
this.result = this.result.slice(0, 10); // 10 results max | |
this.showresult = (this.result.length>0); // show results if we have one or more | |
} // dosearch | |
} // methods | |
}); // Vue | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment