autocomplete for add link dialog, #203

This commit is contained in:
azivner 2018-11-07 17:16:33 +01:00
parent a0f362457e
commit 90dbe637ed
6 changed files with 39 additions and 56 deletions

View File

@ -15,7 +15,6 @@ const $prefixFormGroup = $("#add-link-prefix-form-group");
const $linkTypeDiv = $("#add-link-type-div");
const $linkTypes = $("input[name='add-link-type']");
const $linkTypeHtml = $linkTypes.filter('input[value="html"]');
const $showRecentNotesButton = $dialog.find(".show-recent-notes-button");
function setLinkType(linkType) {
$linkTypes.each(function () {
@ -51,50 +50,31 @@ async function showDialog() {
$linkTitle.val(noteTitle);
}
await $autoComplete.autocomplete({
source: noteAutocompleteService.autocompleteSource,
minLength: 0,
change: async (event, ui) => {
if (!ui.item) {
return;
}
noteAutocompleteService.initNoteAutocomplete($autoComplete);
const notePath = linkService.getNotePathFromLabel(ui.item.value);
$autoComplete.on('autocomplete:selected', function(event, suggestion, dataset) {
if (!suggestion.path) {
return false;
}
if (!notePath) {
return;
}
const noteId = treeUtils.getNoteIdFromNotePath(suggestion.path);
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
if (noteId) {
await setDefaultLinkTitle(noteId);
}
},
select: function (event, ui) {
if (ui.item.value === 'No results') {
return false;
}
},
// this is called when user goes through autocomplete list with keyboard
// at this point the item isn't selected yet so we use supplied ui.item to see WHERE the cursor is
focus: async (event, ui) => {
const notePath = linkService.getNotePathFromLabel(ui.item.value);
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
await setDefaultLinkTitle(noteId);
event.preventDefault();
if (noteId) {
setDefaultLinkTitle(noteId);
}
});
showRecentNotes();
$autoComplete.on('autocomplete:cursorchanged', function(event, suggestion, dataset) {
const noteId = treeUtils.getNoteIdFromNotePath(suggestion.path);
setDefaultLinkTitle(noteId);
});
noteAutocompleteService.showRecentNotes($autoComplete);
}
$form.submit(() => {
const value = $autoComplete.val();
const notePath = linkService.getNotePathFromLabel(value);
const notePath = $autoComplete.getSelectedPath();
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
if (notePath) {
@ -131,6 +111,9 @@ $form.submit(() => {
$dialog.modal('hide');
}
}
else {
console.error("No path to add link.");
}
return false;
});
@ -152,14 +135,8 @@ function linkTypeChanged() {
$linkTypeDiv.toggle(!hasSelection());
}
function showRecentNotes() {
$autoComplete.autocomplete("search", "");
}
$linkTypes.change(linkTypeChanged);
$showRecentNotesButton.click(showRecentNotes);
export default {
showDialog
};

View File

@ -5,7 +5,6 @@ import noteAutocompleteService from '../services/note_autocomplete.js';
const $dialog = $("#jump-to-note-dialog");
const $autoComplete = $("#jump-to-note-autocomplete");
const $showInFullTextButton = $("#show-in-full-text-button");
const $showRecentNotesButton = $dialog.find(".show-recent-notes-button");
$dialog.on("shown.bs.modal", e => $autoComplete.focus());
@ -45,11 +44,8 @@ function showInFullText(e) {
}
$showInFullTextButton.click(showInFullText);
$showRecentNotesButton.click(noteAutocompleteService.showRecentNotes);
$dialog.bind('keydown', 'ctrl+return', showInFullText);
export default {

View File

@ -44,11 +44,17 @@ function initNoteAutocomplete($el) {
displayKey: 'title',
templates: {
suggestion: function(suggestion) {
return suggestion.title;
return suggestion.highlighted;
}
}
}
]);
$el.on('autocomplete:selected', function(event, suggestion, dataset) {
$el.prop("data-selected-path", suggestion.path);
});
$el.getSelectedPath = () => $el.prop("data-selected-path");
}
return $el;

View File

@ -44,9 +44,12 @@ async function getRecentNotes(currentNoteId) {
LIMIT 200`, [currentNoteId]);
return recentNotes.map(rn => {
const title = noteCacheService.getNoteTitleForPath(rn.notePath.split('/'));
return {
path: rn.notePath,
title: noteCacheService.getNoteTitleForPath(rn.notePath.split('/'))
title: title,
highlighted: title
};
});
}

View File

@ -43,11 +43,15 @@ function highlightResults(results, allTokens) {
// sort by the longest so we first highlight longest matches
allTokens.sort((a, b) => a.length > b.length ? -1 : 1);
for (const result of results) {
result.highlighted = result.title;
}
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>");
result.highlighted = result.highlighted.replace(tokenRegex, "<b>$1</b>");
}
}
}
@ -58,7 +62,8 @@ function findNotes(query) {
}
// trim is necessary because even with .split() trailing spaces are tokens which causes havoc
const allTokens = query.trim().toLowerCase().split(" ");
// filtering '/' because it's used as separator
const allTokens = query.trim().toLowerCase().split(" ").filter(token => token !== '/');
const tokens = allTokens.slice();
const results = [];

View File

@ -1,4 +1,4 @@
<div id="add-link-dialog" class="modal fade mx-auto" tabindex="-1" role="dialog">
<div id="add-link-dialog" class="modal mx-auto" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" style="max-width: 1000px" role="document">
<div class="modal-content">
<div class="modal-header">
@ -28,10 +28,6 @@
<div class="input-group">
<input id="note-autocomplete" class="form-control" placeholder="search for note by its name">
<div class="input-group-append">
<span class="input-group-text show-recent-notes-button" title="Show recent notes"></span>
</div>
</div>
</div>
@ -46,7 +42,7 @@
</div>
</div>
<div class="modal-footer" style="display: flex; justify-content: space-between;">
<button class="btn btn-primary">Add note link <kbd>enter</kbd></button>
<button type="submit" class="btn btn-primary">Add note link <kbd>enter</kbd></button>
<button class="btn btn-sm" type="button" data-help-page="Links">
<i class="glyphicon glyphicon-info-sign"></i> Help