Search results + suggestions
This commit is contained in:
@@ -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
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+24
-26
File diff suppressed because one or more lines are too long
+3
-19
@@ -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
|
||||||
@@ -91,3 +73,5 @@ jQuery( document ).ready(function( $ ) {
|
|||||||
|
|
||||||
//=include helpers/form.js
|
//=include helpers/form.js
|
||||||
//=include helpers/pages.js
|
//=include helpers/pages.js
|
||||||
|
|
||||||
|
//=include components/alerts.js
|
||||||
@@ -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: "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;
|
||||||
|
}
|
||||||
@@ -27,6 +27,11 @@ #notifload {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#search-input {
|
||||||
|
max-width: 300px;
|
||||||
|
width: 33vw;
|
||||||
|
}
|
||||||
|
|
||||||
.searchresults {
|
.searchresults {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 45px;
|
top: 45px;
|
||||||
@@ -35,5 +40,9 @@ .searchresults {
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 500px;
|
width: 500px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
//display: none;
|
|
||||||
|
&.slideInDown {
|
||||||
|
@include prefix(animation-duration, .6s);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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: [
|
||||||
|
|||||||
+29
-2
@@ -50,16 +50,43 @@ module.exports = {
|
|||||||
.toLower()
|
.toLower()
|
||||||
.trim()
|
.trim()
|
||||||
.replace(/[^a-z0-9 ]/g, '')
|
.replace(/[^a-z0-9 ]/g, '')
|
||||||
|
.value();
|
||||||
|
|
||||||
|
let arrTerms = _.chain(terms)
|
||||||
.split(' ')
|
.split(' ')
|
||||||
.filter((f) => { return !_.isEmpty(f); })
|
.filter((f) => { return !_.isEmpty(f); })
|
||||||
.value();
|
.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: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -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"
|
||||||
},
|
},
|
||||||
|
|||||||
+12
-6
@@ -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 }}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user