Search results + suggestions
This commit is contained in:
parent
7945d024ad
commit
dca6b71610
@ -27,6 +27,6 @@
|
||||
- [ ] Markdown Editor
|
||||
- [x] Navigation
|
||||
- [x] Parsing / Tree / Metadata
|
||||
- [ ] Search
|
||||
- [x] Search
|
||||
- [x] UI
|
||||
- [x] View Entry Source
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -58,25 +58,7 @@ jQuery( document ).ready(function( $ ) {
|
||||
|
||||
var socket = io(ioHost);
|
||||
|
||||
var vueHeader = new Vue({
|
||||
el: '#header-container',
|
||||
data: {
|
||||
searchq: '',
|
||||
searchres: []
|
||||
},
|
||||
watch: {
|
||||
searchq: (val, oldVal) => {
|
||||
if(val.length >= 3) {
|
||||
socket.emit('search', { terms: val }, (data) => {
|
||||
vueHeader.$set('searchres', data);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
});
|
||||
//=include components/search.js
|
||||
|
||||
// ====================================
|
||||
// Pages logic
|
||||
@ -91,3 +73,5 @@ jQuery( document ).ready(function( $ ) {
|
||||
|
||||
//=include helpers/form.js
|
||||
//=include helpers/pages.js
|
||||
|
||||
//=include components/alerts.js
|
78
client/js/components/search.js
Normal file
78
client/js/components/search.js
Normal file
@ -0,0 +1,78 @@
|
||||
"use strict";
|
||||
|
||||
jQuery( document ).ready(function( $ ) {
|
||||
|
||||
if($('#search-input').length) {
|
||||
|
||||
$('#search-input').focus();
|
||||
|
||||
Vue.transition('slide', {
|
||||
enterClass: 'slideInDown',
|
||||
leaveClass: 'fadeOutUp'
|
||||
});
|
||||
|
||||
$('.searchresults').css('display', 'block');
|
||||
|
||||
var vueHeader = new Vue({
|
||||
el: '#header-container',
|
||||
data: {
|
||||
searchq: '',
|
||||
searchres: [],
|
||||
searchsuggest: [],
|
||||
searchload: 0,
|
||||
searchactive: false,
|
||||
searchmoveidx: 0,
|
||||
searchmovekey: '',
|
||||
searchmovearr: []
|
||||
},
|
||||
watch: {
|
||||
searchq: (val, oldVal) => {
|
||||
searchmoveidx: 0;
|
||||
if(val.length >= 3) {
|
||||
vueHeader.searchactive = true;
|
||||
vueHeader.searchload++;
|
||||
socket.emit('search', { terms: val }, (data) => {
|
||||
vueHeader.searchres = data.match;
|
||||
vueHeader.searchsuggest = data.suggest;
|
||||
if(vueHeader.searchload > 0) { vueHeader.searchload--; }
|
||||
});
|
||||
} else {
|
||||
vueHeader.searchactive = false;
|
||||
vueHeader.searchres = [];
|
||||
vueHeader.searchsuggest = [];
|
||||
vueHeader.searchload = 0;
|
||||
}
|
||||
},
|
||||
searchmoveidx: (val, oldVal) => {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
useSuggestion: (sug) => {
|
||||
vueHeader.searchq = sug;
|
||||
},
|
||||
closeSearch: () => {
|
||||
vueHeader.searchq = '';
|
||||
vueHeader.searchactive = false;
|
||||
},
|
||||
moveSelectSearch: () => {
|
||||
|
||||
},
|
||||
moveDownSearch: () => {
|
||||
if(vueHeader.searchmoveidx < vueHeader.searchmovearr) {
|
||||
vueHeader.searchmoveidx++;
|
||||
}
|
||||
},
|
||||
moveUpSearch: () => {
|
||||
if(vueHeader.searchmoveidx > 0) {
|
||||
vueHeader.searchmoveidx--;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('main').on('click', vueHeader.closeSearch);
|
||||
|
||||
}
|
||||
|
||||
});
|
@ -7,3 +7,7 @@ html {
|
||||
|
||||
//$family-sans-serif: "Roboto", "Helvetica", "Arial", sans-serif;
|
||||
$family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
|
||||
[v-cloak] {
|
||||
display: none;
|
||||
}
|
@ -27,6 +27,11 @@ h2.nav-item {
|
||||
|
||||
}
|
||||
|
||||
#search-input {
|
||||
max-width: 300px;
|
||||
width: 33vw;
|
||||
}
|
||||
|
||||
.searchresults {
|
||||
position: fixed;
|
||||
top: 45px;
|
||||
@ -35,5 +40,9 @@ h2.nav-item {
|
||||
margin: 0 auto;
|
||||
width: 500px;
|
||||
z-index: 1;
|
||||
//display: none;
|
||||
|
||||
&.slideInDown {
|
||||
@include prefix(animation-duration, .6s);
|
||||
}
|
||||
|
||||
}
|
@ -31,7 +31,6 @@ var paths = {
|
||||
'./node_modules/lodash/lodash.min.js'
|
||||
],
|
||||
scriptapps: [
|
||||
'./client/js/components/*.js',
|
||||
'./client/js/app.js'
|
||||
],
|
||||
scriptapps_watch: [
|
||||
|
@ -50,16 +50,43 @@ module.exports = {
|
||||
.toLower()
|
||||
.trim()
|
||||
.replace(/[^a-z0-9 ]/g, '')
|
||||
.split(' ')
|
||||
.filter((f) => { return !_.isEmpty(f); })
|
||||
.value();
|
||||
|
||||
let arrTerms = _.chain(terms)
|
||||
.split(' ')
|
||||
.filter((f) => { return !_.isEmpty(f); })
|
||||
.value();
|
||||
|
||||
|
||||
return self._si.searchAsync({
|
||||
query: {
|
||||
AND: [{ '*': terms }]
|
||||
AND: [{ '*': arrTerms }]
|
||||
},
|
||||
pageSize: 10
|
||||
}).get('hits');
|
||||
}).get('hits').then((hits) => {
|
||||
|
||||
if(hits.length < 5) {
|
||||
return self._si.matchAsync({
|
||||
beginsWith: terms,
|
||||
threshold: 3,
|
||||
limit: 5,
|
||||
type: 'simple'
|
||||
}).then((matches) => {
|
||||
|
||||
return {
|
||||
match: hits,
|
||||
suggest: matches
|
||||
};
|
||||
|
||||
});
|
||||
} else {
|
||||
return {
|
||||
match: hits,
|
||||
suggest: []
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
"dependencies": {
|
||||
"auto-load": "^2.1.0",
|
||||
"bcryptjs-then": "^1.0.1",
|
||||
"bluebird": "^3.4.5",
|
||||
"bluebird": "^3.4.6",
|
||||
"body-parser": "^1.15.2",
|
||||
"bson": "^0.5.4",
|
||||
"cheerio": "^0.22.0",
|
||||
@ -48,7 +48,7 @@
|
||||
"express-brute-loki": "^1.0.0",
|
||||
"express-session": "^1.14.1",
|
||||
"express-validator": "^2.20.8",
|
||||
"farmhash": "^1.2.0",
|
||||
"farmhash": "^1.2.1",
|
||||
"fs-extra": "^0.30.0",
|
||||
"git-wrapper2-promise": "^0.2.9",
|
||||
"highlight.js": "^9.6.0",
|
||||
@ -77,7 +77,8 @@
|
||||
"serve-favicon": "^2.3.0",
|
||||
"simplemde": "^1.11.2",
|
||||
"socket.io": "^1.4.8",
|
||||
"validator": "^5.5.0",
|
||||
"sticky-js": "^1.0.7",
|
||||
"validator": "^5.6.0",
|
||||
"validator-as-promised": "^1.0.2",
|
||||
"winston": "^2.2.0"
|
||||
},
|
||||
|
@ -9,8 +9,9 @@
|
||||
h1.title Wiki
|
||||
.nav-center
|
||||
block rootNavCenter
|
||||
p.nav-item
|
||||
input.input(type='text', v-model='searchq', debounce='500' placeholder='Search...', style= { 'max-width': '300px', width: '33vw' })
|
||||
.nav-item
|
||||
p.control(v-bind:class="{ 'is-loading': searchload > 0 }")
|
||||
input.input#search-input(type='text', v-model='searchq', @keyup.esc='closeSearch', @keyup.down='moveDownSearch', @keyup.up='moveUpSearch', debounce='400', placeholder='Search...')
|
||||
span.nav-toggle
|
||||
span
|
||||
span
|
||||
@ -32,14 +33,19 @@
|
||||
i.fa.fa-plus
|
||||
span Create
|
||||
|
||||
.box.searchresults
|
||||
.box.searchresults.animated(v-show='searchactive', transition='slide', v-cloak, style={'display':'none'})
|
||||
.menu
|
||||
p.menu-label
|
||||
| Search Results
|
||||
ul.menu-list
|
||||
li(v-if="searchres.length === 0")
|
||||
a: em No results matching your query
|
||||
li(v-for='sres in searchres')
|
||||
a(href='#') {{ sres.document.title }}
|
||||
p.menu-label
|
||||
| Do you mean...?
|
||||
a(href='/{{ sres.document.entryPath }}', v-bind:class="{ 'is-active': searchmovekey === 'res.' + sres.document.entryPath }") {{ sres.document.title }}
|
||||
p.menu-label(v-if='searchsuggest.length > 0')
|
||||
| Did you mean...?
|
||||
ul.menu-list(v-if='searchsuggest.length > 0')
|
||||
li(v-for='sug in searchsuggest')
|
||||
a(v-on:click="useSuggestion(sug)") {{ sug }}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user