FEATURE: up/down arrow will highlight search result
Then you can use enter to visit result.
This commit is contained in:
parent
f9ff06b9d4
commit
304379d436
|
@ -20,13 +20,18 @@ class Highlighted extends RawHtml {
|
||||||
function createSearchResult({ type, linkField, builder }) {
|
function createSearchResult({ type, linkField, builder }) {
|
||||||
return createWidget(`search-result-${type}`, {
|
return createWidget(`search-result-${type}`, {
|
||||||
html(attrs) {
|
html(attrs) {
|
||||||
return attrs.results.map(r => {
|
|
||||||
|
|
||||||
|
let i=-1;
|
||||||
|
|
||||||
|
return attrs.results.map(r => {
|
||||||
|
i+=1;
|
||||||
let searchResultId;
|
let searchResultId;
|
||||||
if (type === "topic") {
|
if (type === "topic") {
|
||||||
searchResultId = r.get('topic_id');
|
searchResultId = r.get('topic_id');
|
||||||
}
|
}
|
||||||
return h('li', this.attach('link', {
|
let className = i === attrs.selected ? '.selected' : '';
|
||||||
|
|
||||||
|
return h('li' + className, { attributes: { tabindex: '-1' } }, this.attach('link', {
|
||||||
href: r.get(linkField),
|
href: r.get(linkField),
|
||||||
contents: () => builder.call(this, r, attrs.term),
|
contents: () => builder.call(this, r, attrs.term),
|
||||||
className: 'search-link',
|
className: 'search-link',
|
||||||
|
@ -126,7 +131,8 @@ createWidget('search-menu-results', {
|
||||||
searchContextEnabled: attrs.searchContextEnabled,
|
searchContextEnabled: attrs.searchContextEnabled,
|
||||||
searchLogId: attrs.results.grouped_search_result.search_log_id,
|
searchLogId: attrs.results.grouped_search_result.search_log_id,
|
||||||
results: rt.results,
|
results: rt.results,
|
||||||
term: attrs.term
|
term: attrs.term,
|
||||||
|
selected: (attrs.selected && attrs.selected.type === rt.type) ? attrs.selected.index : -1
|
||||||
})),
|
})),
|
||||||
h('div.no-results', more)
|
h('div.no-results', more)
|
||||||
];
|
];
|
||||||
|
|
|
@ -9,7 +9,8 @@ const searchData = {
|
||||||
noResults: false,
|
noResults: false,
|
||||||
term: undefined,
|
term: undefined,
|
||||||
typeFilter: null,
|
typeFilter: null,
|
||||||
invalidTerm: false
|
invalidTerm: false,
|
||||||
|
selected: null
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helps with debouncing and cancelling promises
|
// Helps with debouncing and cancelling promises
|
||||||
|
@ -132,7 +133,8 @@ export default createWidget('search-menu', {
|
||||||
noResults: searchData.noResults,
|
noResults: searchData.noResults,
|
||||||
results: searchData.results,
|
results: searchData.results,
|
||||||
invalidTerm: searchData.invalidTerm,
|
invalidTerm: searchData.invalidTerm,
|
||||||
searchContextEnabled: searchData.contextEnabled
|
searchContextEnabled: searchData.contextEnabled,
|
||||||
|
selected: searchData.selected
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,6 +171,81 @@ export default createWidget('search-menu', {
|
||||||
this.sendWidgetAction('toggleSearchMenu');
|
this.sendWidgetAction('toggleSearchMenu');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
keyDown(e) {
|
||||||
|
if (searchData.loading || searchData.noResults) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.which === 13 /*enter*/ && searchData.selected) {
|
||||||
|
searchData.selected = null;
|
||||||
|
$('header .results li.selected a').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.which === 38 /*arrow up*/ || e.which === 40 /*arrow down*/) {
|
||||||
|
this.moveSelected(e.which === 38 ? -1 : 1);
|
||||||
|
|
||||||
|
this.scheduleRerender();
|
||||||
|
|
||||||
|
Em.run.next(()=>{
|
||||||
|
if (searchData.selected) {
|
||||||
|
|
||||||
|
// so we do not clear selected
|
||||||
|
$('header .results li').off('blur');
|
||||||
|
|
||||||
|
let selected = $('header .results li.selected')
|
||||||
|
.focus()
|
||||||
|
.on('blur', ()=> {
|
||||||
|
searchData.selected = null;
|
||||||
|
this.scheduleRerender();
|
||||||
|
selected.off('blur');
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$('#search-term').focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
moveSelected(offset) {
|
||||||
|
|
||||||
|
if (offset === 1 && !searchData.selected) {
|
||||||
|
searchData.selected = {type: searchData.results.resultTypes[0].type, index: 0};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!searchData.selected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeIndex = _.findIndex(searchData.results.resultTypes, item => item.type === searchData.selected.type);
|
||||||
|
|
||||||
|
if (typeIndex === 0 && searchData.selected.index === 0 && offset === -1) {
|
||||||
|
searchData.selected = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentResults = searchData.results.resultTypes[typeIndex].results;
|
||||||
|
let newPosition = searchData.selected.index + offset;
|
||||||
|
|
||||||
|
if (newPosition < currentResults.length && newPosition >= 0) {
|
||||||
|
searchData.selected.index = newPosition;
|
||||||
|
} else {
|
||||||
|
// possibly move to next type
|
||||||
|
let newTypeIndex = typeIndex + offset;
|
||||||
|
if (newTypeIndex >= 0 && newTypeIndex < searchData.results.resultTypes.length) {
|
||||||
|
newPosition = 0;
|
||||||
|
if (offset === -1) {
|
||||||
|
newPosition = searchData.results.resultTypes[newTypeIndex].results.length - 1;
|
||||||
|
}
|
||||||
|
searchData.selected = {type: searchData.results.resultTypes[newTypeIndex].type, index: newPosition};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
triggerSearch() {
|
triggerSearch() {
|
||||||
searchData.noResults = false;
|
searchData.noResults = false;
|
||||||
this.searchService().set('highlightTerm', searchData.term);
|
this.searchService().set('highlightTerm', searchData.term);
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-panel {
|
.menu-panel {
|
||||||
border: 1px solid $primary-low;
|
border: 1px solid $primary-low;
|
||||||
box-shadow: 0 2px 2px rgba(0,0,0, .25);
|
box-shadow: 0 2px 2px rgba(0,0,0, .25);
|
||||||
background-color: $secondary;
|
background-color: $secondary;
|
||||||
z-index: 1100;
|
z-index: 1100;
|
||||||
|
@ -148,6 +148,13 @@
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li.selected {
|
||||||
|
background-color: $highlight-medium;
|
||||||
|
}
|
||||||
|
li:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
.filter {
|
.filter {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
&:hover {background: transparent;}
|
&:hover {background: transparent;}
|
||||||
|
|
Loading…
Reference in New Issue