split up autocomplete related functionality

This commit is contained in:
azivner 2018-03-26 21:50:47 -04:00
parent 35998058ce
commit 68bba623b6
9 changed files with 155 additions and 163 deletions

View file

@ -3,6 +3,7 @@ import cloningService from '../services/cloning.js';
import linkService from '../services/link.js';
import noteDetailService from '../services/note_detail.js';
import treeUtils from '../services/tree_utils.js';
import autocompleteService from '../services/autocomplete.js';
const $dialog = $("#add-link-dialog");
const $form = $("#add-link-form");
@ -46,13 +47,13 @@ async function showDialog() {
$linkTitle.val('');
function setDefaultLinkTitle(noteId) {
const noteTitle = treeService.getNoteTitle(noteId);
const noteTitle = treeUtils.getNoteTitle(noteId);
$linkTitle.val(noteTitle);
}
$autoComplete.autocomplete({
source: await treeService.getAutocompleteItems(),
source: await autocompleteService.getAutocompleteItems(),
minLength: 0,
change: () => {
const val = $autoComplete.val();

View file

@ -1,6 +1,7 @@
import treeService from '../services/tree.js';
import server from '../services/server.js';
import treeCache from "../services/tree_cache.js";
import treeUtils from "../services/tree_utils.js";
const $dialog = $("#edit-tree-prefix-dialog");
const $form = $("#edit-tree-prefix-form");
@ -24,7 +25,7 @@ async function showDialog() {
$treePrefixInput.val(branch.prefix).focus();
const noteTitle = treeService.getNoteTitle(currentNode.data.noteId);
const noteTitle = treeUtils.getNoteTitle(currentNode.data.noteId);
$noteTitle.html(noteTitle);
}

View file

@ -1,6 +1,7 @@
import treeService from '../services/tree.js';
import linkService from '../services/link.js';
import utils from '../services/utils.js';
import autocompleteService from '../services/autocomplete.js';
const $dialog = $("#jump-to-note-dialog");
const $autoComplete = $("#jump-to-note-autocomplete");
@ -17,7 +18,7 @@ async function showDialog() {
});
await $autoComplete.autocomplete({
source: await utils.stopWatch("building autocomplete", treeService.getAutocompleteItems),
source: await utils.stopWatch("building autocomplete", autocompleteService.getAutocompleteItems),
minLength: 0
});
}

View file

@ -2,6 +2,7 @@ import treeService from '../services/tree.js';
import messagingService from '../services/messaging.js';
import server from '../services/server.js';
import utils from "../services/utils.js";
import treeUtils from "../services/tree_utils.js";
const $dialog = $("#recent-notes-dialog");
const $searchInput = $('#recent-notes-search-input');
@ -46,7 +47,7 @@ async function showDialog() {
let noteTitle;
try {
noteTitle = await treeService.getNotePathTitle(notePath);
noteTitle = await treeUtils.getNotePathTitle(notePath);
}
catch (e) {
noteTitle = "[error - can't find note title]";

View file

@ -0,0 +1,100 @@
import treeCache from "./tree_cache.js";
import treeUtils from "./tree_utils.js";
async function getAutocompleteItems(parentNoteId, notePath, titlePath) {
if (!parentNoteId) {
parentNoteId = 'root';
}
const parentNote = await treeCache.getNote(parentNoteId);
const childNotes = await parentNote.getChildNotes();
if (!childNotes.length) {
return [];
}
if (!notePath) {
notePath = '';
}
if (!titlePath) {
titlePath = '';
}
// https://github.com/zadam/trilium/issues/46
// unfortunately not easy to implement because we don't have an easy access to note's isProtected property
const autocompleteItems = [];
for (const childNote of childNotes) {
if (childNote.hideInAutocomplete) {
continue;
}
const childNotePath = (notePath ? (notePath + '/') : '') + childNote.noteId;
const childTitlePath = (titlePath ? (titlePath + ' / ') : '') + await treeUtils.getNoteTitle(childNote.noteId, parentNoteId);
autocompleteItems.push({
value: childTitlePath + ' (' + childNotePath + ')',
label: childTitlePath
});
const childItems = await getAutocompleteItems(childNote.noteId, childNotePath, childTitlePath);
for (const childItem of childItems) {
autocompleteItems.push(childItem);
}
}
return autocompleteItems;
}
// Overrides the default autocomplete filter function to search for matched on atleast 1 word in each of the input term's words
$.ui.autocomplete.filter = (array, terms) => {
if (!terms) {
return array;
}
const startDate = new Date();
const results = [];
const tokens = terms.toLowerCase().split(" ");
for (const item of array) {
const lcLabel = item.label.toLowerCase();
const found = tokens.every(token => lcLabel.indexOf(token) !== -1);
if (!found) {
continue;
}
// this is not completely correct and might cause minor problems with note with names containing this " / "
const lastSegmentIndex = lcLabel.lastIndexOf(" / ");
if (lastSegmentIndex !== -1) {
const lastSegment = lcLabel.substr(lastSegmentIndex + 3);
// at least some token needs to be in the last segment (leaf note), otherwise this
// particular note is not that interesting (query is satisfied by parent note)
const foundInLastSegment = tokens.some(token => lastSegment.indexOf(token) !== -1);
if (!foundInLastSegment) {
continue;
}
}
results.push(item);
if (results.length > 100) {
break;
}
}
console.log("Search took " + (new Date().getTime() - startDate.getTime()) + "ms");
return results;
};
export default {
getAutocompleteItems
};

View file

@ -13,33 +13,19 @@ jQuery.hotkeys.options.filterInputAcceptingElements = false;
jQuery.hotkeys.options.filterContentEditable = false;
jQuery.hotkeys.options.filterTextInputs = false;
$(document).bind('keydown', 'alt+m', e => {
$(".hide-toggle").toggleClass("suppressed");
e.preventDefault();
});
utils.bindShortcut('alt+m', e => $(".hide-toggle").toggleClass("suppressed"));
// hide (toggle) everything except for the note content for distraction free writing
$(document).bind('keydown', 'alt+t', e => {
utils.bindShortcut('alt+t', e => {
const date = new Date();
const dateString = utils.formatDateTime(date);
linkService.addTextToEditor(dateString);
e.preventDefault();
});
$(document).bind('keydown', 'f5', () => {
utils.reloadApp();
utils.bindShortcut('f5', utils.reloadApp);
return false;
});
$(document).bind('keydown', 'ctrl+r', () => {
utils.reloadApp();
return false;
});
utils.bindShortcut('ctrl+r', utils.reloadApp);
$(document).bind('keydown', 'ctrl+shift+i', () => {
if (utils.isElectron()) {
@ -62,22 +48,18 @@ $(document).bind('keydown', 'ctrl+f', () => {
}
});
$(document).bind('keydown', "ctrl+shift+up", () => {
utils.bindShortcut("ctrl+shift+up", () => {
const node = treeService.getCurrentNode();
node.navigate($.ui.keyCode.UP, true);
$("#note-detail").focus();
return false;
});
$(document).bind('keydown', "ctrl+shift+down", () => {
utils.bindShortcut("ctrl+shift+down", () => {
const node = treeService.getCurrentNode();
node.navigate($.ui.keyCode.DOWN, true);
$("#note-detail").focus();
return false;
});
$(document).bind('keydown', 'ctrl+-', () => {
@ -110,52 +92,6 @@ $(window).on('beforeunload', () => {
noteDetailService.saveNoteIfChanged();
});
// Overrides the default autocomplete filter function to search for matched on atleast 1 word in each of the input term's words
$.ui.autocomplete.filter = (array, terms) => {
if (!terms) {
return array;
}
const startDate = new Date();
const results = [];
const tokens = terms.toLowerCase().split(" ");
for (const item of array) {
const lcLabel = item.label.toLowerCase();
const found = tokens.every(token => lcLabel.indexOf(token) !== -1);
if (!found) {
continue;
}
// this is not completely correct and might cause minor problems with note with names containing this " / "
const lastSegmentIndex = lcLabel.lastIndexOf(" / ");
if (lastSegmentIndex !== -1) {
const lastSegment = lcLabel.substr(lastSegmentIndex + 3);
// at least some token needs to be in the last segment (leaf note), otherwise this
// particular note is not that interesting (query is satisfied by parent note)
const foundInLastSegment = tokens.some(token => lastSegment.indexOf(token) !== -1);
if (!foundInLastSegment) {
continue;
}
}
results.push(item);
if (results.length > 100) {
break;
}
}
console.log("Search took " + (new Date().getTime() - startDate.getTime()) + "ms");
return results;
};
$(document).tooltip({
items: "#note-detail a",
content: function(callback) {

View file

@ -27,7 +27,7 @@ function createNoteLink(notePath, noteTitle) {
if (!noteTitle) {
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
noteTitle = treeService.getNoteTitle(noteId);
noteTitle = treeUtils.getNoteTitle(noteId);
}
const noteLink = $("<a>", {

View file

@ -23,22 +23,6 @@ const $scrollToCurrentNoteButton = $("#scroll-to-current-note-button");
let startNotePath = null;
async function getNoteTitle(noteId, parentNoteId = null) {
utils.assertArguments(noteId);
let {title} = await treeCache.getNote(noteId);
if (parentNoteId !== null) {
const branch = await treeCache.getBranchByChildParent(noteId, parentNoteId);
if (branch && branch.prefix) {
title = branch.prefix + ' - ' + title;
}
}
return title;
}
// note that if you want to access data like noteId or isProtected, you need to go into "data" property
function getCurrentNode() {
return $tree.fancytree("getActiveNode");
@ -78,7 +62,7 @@ async function setPrefix(branchId, prefix) {
}
async function setNodeTitleWithPrefix(node) {
const noteTitle = await getNoteTitle(node.data.noteId);
const noteTitle = await treeUtils.getNoteTitle(node.data.noteId);
const branch = await treeCache.getBranch(node.data.branchId);
const prefix = branch.prefix;
@ -300,7 +284,7 @@ async function showParentList(noteId, node) {
const parentNotePath = await getSomeNotePath(parentNote);
// this is to avoid having root notes leading '/'
const notePath = parentNotePath ? (parentNotePath + '/' + noteId) : noteId;
const title = await getNotePathTitle(notePath);
const title = await treeUtils.getNotePathTitle(notePath);
let item;
@ -316,22 +300,6 @@ async function showParentList(noteId, node) {
}
}
async function getNotePathTitle(notePath) {
utils.assertArguments(notePath);
const titlePath = [];
let parentNoteId = 'root';
for (const noteId of notePath.split('/')) {
titlePath.push(await getNoteTitle(noteId, parentNoteId));
parentNoteId = noteId;
}
return titlePath.join(' / ');
}
async function getSomeNotePath(note) {
utils.assertArguments(note);
@ -695,54 +663,6 @@ function setProtected(noteId, isProtected) {
setBranchBackgroundBasedOnProtectedStatus(noteId);
}
async function getAutocompleteItems(parentNoteId, notePath, titlePath) {
if (!parentNoteId) {
parentNoteId = 'root';
}
const parentNote = await treeCache.getNote(parentNoteId);
const childNotes = await parentNote.getChildNotes();
if (!childNotes.length) {
return [];
}
if (!notePath) {
notePath = '';
}
if (!titlePath) {
titlePath = '';
}
// https://github.com/zadam/trilium/issues/46
// unfortunately not easy to implement because we don't have an easy access to note's isProtected property
const autocompleteItems = [];
for (const childNote of childNotes) {
if (childNote.hideInAutocomplete) {
continue;
}
const childNotePath = (notePath ? (notePath + '/') : '') + childNote.noteId;
const childTitlePath = (titlePath ? (titlePath + ' / ') : '') + await getNoteTitle(childNote.noteId, parentNoteId);
autocompleteItems.push({
value: childTitlePath + ' (' + childNotePath + ')',
label: childTitlePath
});
const childItems = await getAutocompleteItems(childNote.noteId, childNotePath, childTitlePath);
for (const childItem of childItems) {
autocompleteItems.push(childItem);
}
}
return autocompleteItems;
}
async function setNoteTitle(noteId, title) {
utils.assertArguments(noteId);
@ -886,18 +806,15 @@ export default {
scrollToCurrentNote,
setBranchBackgroundBasedOnProtectedStatus,
setProtected,
getCurrentNode,
expandToNote,
activateNode,
getCurrentNode,
getCurrentNotePath,
getNoteTitle,
setCurrentNotePathToHash,
getAutocompleteItems,
setNoteTitle,
setPrefix,
createNewTopLevelNote,
createNote,
setPrefix,
getNotePathTitle,
removeParentChildRelation,
setParentChildRelation,
getSelectedNodes,

View file

@ -1,4 +1,5 @@
import utils from './utils.js';
import treeCache from "./tree_cache.js";
const $tree = $("#tree");
@ -30,9 +31,43 @@ function getNotePath(node) {
return path.reverse().join("/");
}
async function getNoteTitle(noteId, parentNoteId = null) {
utils.assertArguments(noteId);
let {title} = await treeCache.getNote(noteId);
if (parentNoteId !== null) {
const branch = await treeCache.getBranchByChildParent(noteId, parentNoteId);
if (branch && branch.prefix) {
title = branch.prefix + ' - ' + title;
}
}
return title;
}
async function getNotePathTitle(notePath) {
utils.assertArguments(notePath);
const titlePath = [];
let parentNoteId = 'root';
for (const noteId of notePath.split('/')) {
titlePath.push(await getNoteTitle(noteId, parentNoteId));
parentNoteId = noteId;
}
return titlePath.join(' / ');
}
export default {
getParentProtectedStatus,
getNodeByKey,
getNotePath,
getNoteIdFromNotePath,
getNoteTitle,
getNotePathTitle,
};