mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
finished jump to autocomplete, now with token highlighting, #203
This commit is contained in:
parent
3c23d7085e
commit
1febf5136c
@ -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);
|
||||||
|
@ -6,20 +6,14 @@ async function autocompleteSource(term, cb) {
|
|||||||
+ '?query=' + encodeURIComponent(term)
|
+ '?query=' + encodeURIComponent(term)
|
||||||
+ '¤tNoteId=' + noteDetailService.getCurrentNoteId());
|
+ '¤tNoteId=' + 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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
};
|
};
|
@ -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">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user