Search results + suggestions

This commit is contained in:
NGPixel 2016-09-05 14:11:51 -04:00
parent 7945d024ad
commit dca6b71610
12 changed files with 171 additions and 65 deletions

View File

@ -27,6 +27,6 @@
- [ ] Markdown Editor - [ ] Markdown Editor
- [x] Navigation - [x] Navigation
- [x] Parsing / Tree / Metadata - [x] Parsing / Tree / Metadata
- [ ] Search - [x] Search
- [x] UI - [x] UI
- [x] View Entry Source - [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

View File

@ -58,25 +58,7 @@ jQuery( document ).ready(function( $ ) {
var socket = io(ioHost); var socket = io(ioHost);
var vueHeader = new Vue({ //=include components/search.js
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: {
}
});
// ==================================== // ====================================
// Pages logic // Pages logic
@ -90,4 +72,6 @@ jQuery( document ).ready(function( $ ) {
}); });
//=include helpers/form.js //=include helpers/form.js
//=include helpers/pages.js //=include helpers/pages.js
//=include components/alerts.js

View 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);
}
});

View File

@ -6,4 +6,8 @@ html {
} }
//$family-sans-serif: "Roboto", "Helvetica", "Arial", sans-serif; //$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"; $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;
}

View File

@ -27,6 +27,11 @@ h2.nav-item {
} }
#search-input {
max-width: 300px;
width: 33vw;
}
.searchresults { .searchresults {
position: fixed; position: fixed;
top: 45px; top: 45px;
@ -35,5 +40,9 @@ h2.nav-item {
margin: 0 auto; margin: 0 auto;
width: 500px; width: 500px;
z-index: 1; z-index: 1;
//display: none;
&.slideInDown {
@include prefix(animation-duration, .6s);
}
} }

View File

@ -31,7 +31,6 @@ var paths = {
'./node_modules/lodash/lodash.min.js' './node_modules/lodash/lodash.min.js'
], ],
scriptapps: [ scriptapps: [
'./client/js/components/*.js',
'./client/js/app.js' './client/js/app.js'
], ],
scriptapps_watch: [ scriptapps_watch: [

View File

@ -50,16 +50,43 @@ module.exports = {
.toLower() .toLower()
.trim() .trim()
.replace(/[^a-z0-9 ]/g, '') .replace(/[^a-z0-9 ]/g, '')
.split(' ')
.filter((f) => { return !_.isEmpty(f); })
.value(); .value();
let arrTerms = _.chain(terms)
.split(' ')
.filter((f) => { return !_.isEmpty(f); })
.value();
return self._si.searchAsync({ return self._si.searchAsync({
query: { query: {
AND: [{ '*': terms }] AND: [{ '*': arrTerms }]
}, },
pageSize: 10 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: []
};
}
});
}, },

View File

@ -32,7 +32,7 @@
"dependencies": { "dependencies": {
"auto-load": "^2.1.0", "auto-load": "^2.1.0",
"bcryptjs-then": "^1.0.1", "bcryptjs-then": "^1.0.1",
"bluebird": "^3.4.5", "bluebird": "^3.4.6",
"body-parser": "^1.15.2", "body-parser": "^1.15.2",
"bson": "^0.5.4", "bson": "^0.5.4",
"cheerio": "^0.22.0", "cheerio": "^0.22.0",
@ -48,7 +48,7 @@
"express-brute-loki": "^1.0.0", "express-brute-loki": "^1.0.0",
"express-session": "^1.14.1", "express-session": "^1.14.1",
"express-validator": "^2.20.8", "express-validator": "^2.20.8",
"farmhash": "^1.2.0", "farmhash": "^1.2.1",
"fs-extra": "^0.30.0", "fs-extra": "^0.30.0",
"git-wrapper2-promise": "^0.2.9", "git-wrapper2-promise": "^0.2.9",
"highlight.js": "^9.6.0", "highlight.js": "^9.6.0",
@ -77,7 +77,8 @@
"serve-favicon": "^2.3.0", "serve-favicon": "^2.3.0",
"simplemde": "^1.11.2", "simplemde": "^1.11.2",
"socket.io": "^1.4.8", "socket.io": "^1.4.8",
"validator": "^5.5.0", "sticky-js": "^1.0.7",
"validator": "^5.6.0",
"validator-as-promised": "^1.0.2", "validator-as-promised": "^1.0.2",
"winston": "^2.2.0" "winston": "^2.2.0"
}, },

View File

@ -9,8 +9,9 @@
h1.title Wiki h1.title Wiki
.nav-center .nav-center
block rootNavCenter block rootNavCenter
p.nav-item .nav-item
input.input(type='text', v-model='searchq', debounce='500' placeholder='Search...', style= { 'max-width': '300px', width: '33vw' }) 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.nav-toggle
span span
span span
@ -32,14 +33,19 @@
i.fa.fa-plus i.fa.fa-plus
span Create span Create
.box.searchresults .box.searchresults.animated(v-show='searchactive', transition='slide', v-cloak, style={'display':'none'})
.menu .menu
p.menu-label p.menu-label
| Search Results | Search Results
ul.menu-list ul.menu-list
li(v-if="searchres.length === 0")
a: em No results matching your query
li(v-for='sres in searchres') li(v-for='sres in searchres')
a(href='#') {{ sres.document.title }} a(href='/{{ sres.document.entryPath }}', v-bind:class="{ 'is-active': searchmovekey === 'res.' + sres.document.entryPath }") {{ sres.document.title }}
p.menu-label p.menu-label(v-if='searchsuggest.length > 0')
| Do you mean...? | Did you mean...?
ul.menu-list(v-if='searchsuggest.length > 0')
li(v-for='sug in searchsuggest')
a(v-on:click="useSuggestion(sug)") {{ sug }}