finished jump to autocomplete, now with token highlighting, #203

This commit is contained in:
azivner 2018-11-07 09:35:29 +01:00
parent 3c23d7085e
commit 1febf5136c
6 changed files with 46 additions and 52 deletions

View File

@ -21,51 +21,29 @@ async function showDialog() {
appendTo: document.querySelector('body'), appendTo: document.querySelector('body'),
hint: false, hint: false,
autoselect: true, autoselect: true,
openOnFocus: true openOnFocus: true,
minLength: 0
}, [ }, [
{ {
source: noteautocompleteService.autocompleteSource, source: noteautocompleteService.autocompleteSource,
displayKey: 'label', displayKey: 'title',
templates: { templates: {
suggestion: function(suggestion) { suggestion: function(suggestion) {
return suggestion.label; return suggestion.title;
} }
} }
} }
]).on('autocomplete:selected', function(event, suggestion, dataset) { ]).on('autocomplete:selected', function(event, suggestion, dataset) {
console.log("selected: ", event, suggestion, dataset); if (!suggestion.path) {
return;
if (ui.item.value === 'No results') {
return false; return false;
} }
const notePath = linkService.getNotePathFromLabel(ui.item.value); treeService.activateNote(suggestion.path);
treeService.activateNote(notePath);
$dialog.modal('hide'); $dialog.modal('hide');
}); });
// await $autoComplete.autocomplete({ showRecentNotes();
// source: noteautocompleteService.autocompleteSource,
// focus: event => event.preventDefault(),
// minLength: 0,
// autoFocus: true,
// select: function (event, ui) {
// if (ui.item.value === 'No results') {
// return false;
// }
//
// const notePath = linkService.getNotePathFromLabel(ui.item.value);
//
// treeService.activateNote(notePath);
//
// $dialog.modal('hide');
// }
// });
//showRecentNotes();
} }
function showInFullText(e) { function showInFullText(e) {
@ -83,7 +61,8 @@ function showInFullText(e) {
} }
function showRecentNotes() { function showRecentNotes() {
$autoComplete.autocomplete("search", ""); $autoComplete.autocomplete("val", "");
$autoComplete.autocomplete("open");
} }
$showInFullTextButton.click(showInFullText); $showInFullTextButton.click(showInFullText);

View File

@ -6,20 +6,14 @@ async function autocompleteSource(term, cb) {
+ '?query=' + encodeURIComponent(term) + '?query=' + encodeURIComponent(term)
+ '&currentNoteId=' + noteDetailService.getCurrentNoteId()); + '&currentNoteId=' + noteDetailService.getCurrentNoteId());
if (result.length > 0) { if (result.length === 0) {
cb(result.map(row => { result.push({
return { title: "No results",
label: row.label, path: ""
value: row.label + ' (' + row.value + ')' });
}
}));
}
else {
cb([{
label: "No results",
value: "No results"
}]);
} }
cb(result);
} }
async function initNoteAutocomplete($el) { async function initNoteAutocomplete($el) {

View File

@ -25,12 +25,7 @@ async function getAutocomplete(req) {
log.info(`Slow autocomplete took ${msTaken}ms`); log.info(`Slow autocomplete took ${msTaken}ms`);
} }
return results.map(res => { return results;
return {
value: res.path,
label: res.title
}
});
} }
async function getRecentNotes(currentNoteId) { async function getRecentNotes(currentNoteId) {

View File

@ -35,12 +35,31 @@ async function load() {
loaded = true; loaded = true;
} }
function highlightResults(results, allTokens) {
// we remove < signs because they can cause trouble in matching and overwriting existing highlighted chunks
// which would make the resulting HTML string invalid.
allTokens = allTokens.map(token => token.replace('/</g', ''));
// sort by the longest so we first highlight longest matches
allTokens.sort((a, b) => a.length > b.length ? -1 : 1);
for (const token of allTokens) {
const tokenRegex = new RegExp("(" + utils.escapeRegExp(token) + ")", "gi");
for (const result of results) {
result.title = result.title.replace(tokenRegex, "<b>$1</b>");
}
}
}
function findNotes(query) { function findNotes(query) {
if (!noteTitles || !query.length) { if (!noteTitles || !query.length) {
return []; return [];
} }
const tokens = query.toLowerCase().split(" "); // trim is necessary because even with .split() trailing spaces are tokens which causes havoc
const allTokens = query.trim().toLowerCase().split(" ");
const tokens = allTokens.slice();
const results = []; const results = [];
let noteIds = Object.keys(noteTitles); let noteIds = Object.keys(noteTitles);
@ -91,6 +110,8 @@ function findNotes(query) {
results.sort((a, b) => a.title < b.title ? -1 : 1); results.sort((a, b) => a.title < b.title ? -1 : 1);
highlightResults(results, allTokens);
return results; return results;
} }

View File

@ -114,6 +114,10 @@ function union(a, b) {
return res; return res;
} }
function escapeRegExp(str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
}
module.exports = { module.exports = {
randomSecureToken, randomSecureToken,
randomString, randomString,
@ -132,5 +136,6 @@ module.exports = {
toObject, toObject,
stripTags, stripTags,
intersection, intersection,
union union,
escapeRegExp
}; };

View File

@ -1,4 +1,4 @@
<div id="jump-to-note-dialog" class="modal fade mx-auto" tabindex="-1" role="dialog"> <div id="jump-to-note-dialog" class="modal mx-auto" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" role="document"> <div class="modal-dialog modal-lg" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">