mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-11-09 02:41:39 +08:00
Merge pull request #659 from TriliumNext/quick_search_in_autocomplete
Add full text search in autocomplete
This commit is contained in:
commit
29b062660d
@ -30,10 +30,22 @@ async function autocompleteSourceForCKEditor(queryText) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function autocompleteSource(term, cb, options = {}) {
|
async function autocompleteSource(term, cb, options = {}) {
|
||||||
|
const fastSearch = options.fastSearch === false ? false : true;
|
||||||
|
if (fastSearch === false) {
|
||||||
|
if (term.trim().length === 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cb(
|
||||||
|
[{
|
||||||
|
noteTitle: term,
|
||||||
|
highlightedNotePathTitle: `Searching...`
|
||||||
|
}]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const activeNoteId = appContext.tabManager.getActiveContextNoteId();
|
const activeNoteId = appContext.tabManager.getActiveContextNoteId();
|
||||||
|
|
||||||
let results = await server.get(`autocomplete?query=${encodeURIComponent(term)}&activeNoteId=${activeNoteId}`);
|
let results = await server.get(`autocomplete?query=${encodeURIComponent(term)}&activeNoteId=${activeNoteId}&fastSearch=${fastSearch}`);
|
||||||
|
|
||||||
if (term.trim().length >= 1 && options.allowCreatingNotes) {
|
if (term.trim().length >= 1 && options.allowCreatingNotes) {
|
||||||
results = [
|
results = [
|
||||||
{
|
{
|
||||||
@ -45,7 +57,7 @@ async function autocompleteSource(term, cb, options = {}) {
|
|||||||
].concat(results);
|
].concat(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (term.trim().length >= 1 && options.allowSearchNotes) {
|
if (term.trim().length >= 1 && options.allowJumpToSearchNotes) {
|
||||||
results = results.concat([
|
results = results.concat([
|
||||||
{
|
{
|
||||||
action: 'search-notes',
|
action: 'search-notes',
|
||||||
@ -95,12 +107,22 @@ function showRecentNotes($el) {
|
|||||||
|
|
||||||
$el.setSelectedNotePath("");
|
$el.setSelectedNotePath("");
|
||||||
$el.autocomplete("val", "");
|
$el.autocomplete("val", "");
|
||||||
|
$el.autocomplete('open');
|
||||||
$el.trigger('focus');
|
$el.trigger('focus');
|
||||||
|
}
|
||||||
|
|
||||||
// simulate pressing down arrow to trigger autocomplete
|
function fullTextSearch($el, options){
|
||||||
const e = $.Event('keydown');
|
const searchString = $el.autocomplete('val');
|
||||||
e.which = 40; // arrow down
|
if (options.fastSearch === false || searchString.trim().length === 0) {
|
||||||
$el.trigger(e);
|
return;
|
||||||
|
}
|
||||||
|
$el.trigger('focus');
|
||||||
|
options.fastSearch = false;
|
||||||
|
$el.autocomplete('val', '');
|
||||||
|
$el.setSelectedNotePath("");
|
||||||
|
$el.autocomplete('val', searchString);
|
||||||
|
// Set a delay to avoid resetting to true before full text search (await server.get) is called.
|
||||||
|
setTimeout(() => { options.fastSearch = true; }, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function initNoteAutocomplete($el, options) {
|
function initNoteAutocomplete($el, options) {
|
||||||
@ -123,10 +145,14 @@ function initNoteAutocomplete($el, options) {
|
|||||||
.addClass("input-group-text show-recent-notes-button bx bx-time")
|
.addClass("input-group-text show-recent-notes-button bx bx-time")
|
||||||
.prop("title", "Show recent notes");
|
.prop("title", "Show recent notes");
|
||||||
|
|
||||||
|
const $fullTextSearchButton = $("<button>")
|
||||||
|
.addClass("input-group-text full-text-search-button bx bx-search")
|
||||||
|
.prop("title", "Full text search (Shift+Enter)");
|
||||||
|
|
||||||
const $goToSelectedNoteButton = $("<button>")
|
const $goToSelectedNoteButton = $("<button>")
|
||||||
.addClass("input-group-text go-to-selected-note-button bx bx-arrow-to-right");
|
.addClass("input-group-text go-to-selected-note-button bx bx-arrow-to-right");
|
||||||
|
|
||||||
$el.after($clearTextButton).after($showRecentNotesButton);
|
$el.after($clearTextButton).after($showRecentNotesButton).after($fullTextSearchButton);
|
||||||
|
|
||||||
if (!options.hideGoToSelectedNoteButton) {
|
if (!options.hideGoToSelectedNoteButton) {
|
||||||
$el.after($goToSelectedNoteButton);
|
$el.after($goToSelectedNoteButton);
|
||||||
@ -142,13 +168,18 @@ function initNoteAutocomplete($el, options) {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$fullTextSearchButton.on('click', e => {
|
||||||
|
fullTextSearch($el, options);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
let autocompleteOptions = {};
|
let autocompleteOptions = {};
|
||||||
if (options.container) {
|
if (options.container) {
|
||||||
autocompleteOptions.dropdownMenuContainer = options.container;
|
autocompleteOptions.dropdownMenuContainer = options.container;
|
||||||
autocompleteOptions.debug = true; // don't close on blur
|
autocompleteOptions.debug = true; // don't close on blur
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.allowSearchNotes) {
|
if (options.allowJumpToSearchNotes) {
|
||||||
$el.on('keydown', (event) => {
|
$el.on('keydown', (event) => {
|
||||||
if (event.ctrlKey && event.key === 'Enter') {
|
if (event.ctrlKey && event.key === 'Enter') {
|
||||||
// Prevent Ctrl + Enter from triggering autoComplete.
|
// Prevent Ctrl + Enter from triggering autoComplete.
|
||||||
@ -158,6 +189,14 @@ function initNoteAutocomplete($el, options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
$el.on('keydown', async (event) => {
|
||||||
|
if (event.shiftKey && event.key === 'Enter') {
|
||||||
|
// Prevent Enter from triggering autoComplete.
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
fullTextSearch($el,options)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$el.autocomplete({
|
$el.autocomplete({
|
||||||
...autocompleteOptions,
|
...autocompleteOptions,
|
||||||
|
|||||||
@ -58,7 +58,7 @@ export default class JumpToNoteDialog extends BasicWidget {
|
|||||||
noteAutocompleteService.initNoteAutocomplete(this.$autoComplete, {
|
noteAutocompleteService.initNoteAutocomplete(this.$autoComplete, {
|
||||||
allowCreatingNotes: true,
|
allowCreatingNotes: true,
|
||||||
hideGoToSelectedNoteButton: true,
|
hideGoToSelectedNoteButton: true,
|
||||||
allowSearchNotes: true,
|
allowJumpToSearchNotes: true,
|
||||||
container: this.$results
|
container: this.$results
|
||||||
})
|
})
|
||||||
// clear any event listener added in previous invocation of this function
|
// clear any event listener added in previous invocation of this function
|
||||||
|
|||||||
@ -70,7 +70,7 @@ export default class EmptyTypeWidget extends TypeWidget {
|
|||||||
noteAutocompleteService.initNoteAutocomplete(this.$autoComplete, {
|
noteAutocompleteService.initNoteAutocomplete(this.$autoComplete, {
|
||||||
hideGoToSelectedNoteButton: true,
|
hideGoToSelectedNoteButton: true,
|
||||||
allowCreatingNotes: true,
|
allowCreatingNotes: true,
|
||||||
allowSearchNotes: true,
|
allowJumpToSearchNotes: true,
|
||||||
container: this.$results
|
container: this.$results
|
||||||
})
|
})
|
||||||
.on('autocomplete:noteselected', function(event, suggestion, dataset) {
|
.on('autocomplete:noteselected', function(event, suggestion, dataset) {
|
||||||
|
|||||||
@ -448,7 +448,7 @@ pre:not(.CodeMirror-line):not(.hljs) {
|
|||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.show-recent-notes-button {
|
.show-recent-notes-button, .full-text-search-button {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
|
|||||||
@ -14,6 +14,8 @@ function getAutocomplete(req: Request) {
|
|||||||
throw new ValidationError("Invalid query data type.");
|
throw new ValidationError("Invalid query data type.");
|
||||||
}
|
}
|
||||||
const query = (req.query.query || "").trim();
|
const query = (req.query.query || "").trim();
|
||||||
|
const fastSearch = String(req.query.fastSearch).toLowerCase() === "false" ? false : true;
|
||||||
|
|
||||||
const activeNoteId = req.query.activeNoteId || 'none';
|
const activeNoteId = req.query.activeNoteId || 'none';
|
||||||
|
|
||||||
let results;
|
let results;
|
||||||
@ -24,7 +26,7 @@ function getAutocomplete(req: Request) {
|
|||||||
results = getRecentNotes(activeNoteId);
|
results = getRecentNotes(activeNoteId);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
results = searchService.searchNotesForAutocomplete(query);
|
results = searchService.searchNotesForAutocomplete(query, fastSearch);
|
||||||
}
|
}
|
||||||
|
|
||||||
const msTaken = Date.now() - timestampStarted;
|
const msTaken = Date.now() - timestampStarted;
|
||||||
|
|||||||
@ -340,9 +340,9 @@ function findFirstNoteWithQuery(query: string, searchContext: SearchContext): BN
|
|||||||
return searchResults.length > 0 ? becca.notes[searchResults[0].noteId] : null;
|
return searchResults.length > 0 ? becca.notes[searchResults[0].noteId] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchNotesForAutocomplete(query: string) {
|
function searchNotesForAutocomplete(query: string, fastSearch: boolean = true) {
|
||||||
const searchContext = new SearchContext({
|
const searchContext = new SearchContext({
|
||||||
fastSearch: true,
|
fastSearch: fastSearch,
|
||||||
includeArchivedNotes: false,
|
includeArchivedNotes: false,
|
||||||
includeHiddenNotes: true,
|
includeHiddenNotes: true,
|
||||||
fuzzyAttributeSearch: true,
|
fuzzyAttributeSearch: true,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user