import server from "./server.js"; import appContext from "../components/app_context.js"; import utils from './utils.js'; import noteCreateService from './note_create.js'; import froca from "./froca.js"; // this key needs to have this value, so it's hit by the tooltip const SELECTED_NOTE_PATH_KEY = "data-note-path"; const SELECTED_EXTERNAL_LINK_KEY = "data-external-link"; async function autocompleteSourceForCKEditor(queryText) { return await new Promise((res, rej) => { autocompleteSource(queryText, rows => { res(rows.map(row => { return { action: row.action, noteTitle: row.noteTitle, id: `@${row.notePathTitle}`, name: row.notePathTitle, link: `#${row.notePath}`, notePath: row.notePath, highlightedNotePathTitle: row.highlightedNotePathTitle } })); }, { allowCreatingNotes: true }); }); } async function autocompleteSource(term, cb, options = {}, fastSearch = true) { const activeNoteId = appContext.tabManager.getActiveContextNoteId(); let results = await server.get(`autocomplete?query=${encodeURIComponent(term)}&activeNoteId=${activeNoteId}&fastSearch=${fastSearch}`); if (term.trim().length >= 1 && options.allowCreatingNotes) { results = [ { action: 'create-note', noteTitle: term, parentNoteId: activeNoteId || 'root', highlightedNotePathTitle: `Create and link child note "${utils.escapeHtml(term)}"` } ].concat(results); } if (term.trim().length >= 1 && options.allowJumpToSearchNotes) { results = results.concat([ { action: 'search-notes', noteTitle: term, highlightedNotePathTitle: `Search for "${utils.escapeHtml(term)}" Ctrl+Enter` } ]); } if (term.match(/^[a-z]+:\/\/.+/i) && options.allowExternalLinks) { results = [ { action: 'external-link', externalLink: term, highlightedNotePathTitle: `Insert external link to "${utils.escapeHtml(term)}"` } ].concat(results); } cb(results); } function clearText($el) { if (utils.isMobile()) { return; } $el.setSelectedNotePath(""); $el.autocomplete("val", "").trigger('change'); } function setText($el, text) { if (utils.isMobile()) { return; } $el.setSelectedNotePath(""); $el .autocomplete("val", text.trim()) .autocomplete("open"); } function showRecentNotes($el) { if (utils.isMobile()) { return; } $el.setSelectedNotePath(""); $el.autocomplete("val", ""); $el.autocomplete('open'); $el.trigger('focus'); } async function fullTextSearch($el, options){ if (!options.container) { // If no container is specified, the dropdown might remain closed. Calling `$el.autocomplete('open')` triggers a search by name and needs to wait for completion. Otherwise, if `$el.autocomplete('open')` executes too slowly, it will overwrite the full-text search results. $el.autocomplete('open'); await new Promise(resolve => setTimeout(resolve, 100)); } const searchString = $el.autocomplete('val'); if (searchString.trim().length >= 1) { $el.setSelectedNotePath(""); autocompleteSource(searchString, $el.data('autocompleteCallback'), options, false); $el.trigger('focus'); } } function initNoteAutocomplete($el, options) { if ($el.hasClass("note-autocomplete-input") || utils.isMobile()) { // clear any event listener added in previous invocation of this function $el.off('autocomplete:noteselected'); return $el; } options = options || {}; $el.addClass("note-autocomplete-input"); const $clearTextButton = $("