mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	moved tree initialization into the widget
This commit is contained in:
		@@ -4,10 +4,11 @@ const $contextMenuContainer = $("#context-menu-container");
 | 
				
			|||||||
let dateContextMenuOpenedMs = 0;
 | 
					let dateContextMenuOpenedMs = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
					 * @param {NoteTreeWidget} treeWidget
 | 
				
			||||||
 * @param event - originating click event (used to get coordinates to display menu at position)
 | 
					 * @param event - originating click event (used to get coordinates to display menu at position)
 | 
				
			||||||
 * @param {object} contextMenu - needs to have getContextMenuItems() and selectContextMenuItem(e, cmd)
 | 
					 * @param {object} contextMenu - needs to have getContextMenuItems() and selectContextMenuItem(e, cmd)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
async function initContextMenu(event, contextMenu) {
 | 
					async function initContextMenu(treeWidget, event, contextMenu) {
 | 
				
			||||||
    event.stopPropagation();
 | 
					    event.stopPropagation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $contextMenuContainer.empty();
 | 
					    $contextMenuContainer.empty();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,6 +18,10 @@ import keyboardActionService from "./keyboard_actions.js";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
let tree;
 | 
					let tree;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function setTree(treeInstance) {
 | 
				
			||||||
 | 
					    tree = treeInstance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let setFrontendAsLoaded;
 | 
					let setFrontendAsLoaded;
 | 
				
			||||||
const frontendLoaded = new Promise(resolve => { setFrontendAsLoaded = resolve; });
 | 
					const frontendLoaded = new Promise(resolve => { setFrontendAsLoaded = resolve; });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -424,104 +428,6 @@ async function treeInitialized() {
 | 
				
			|||||||
    setFrontendAsLoaded();
 | 
					    setFrontendAsLoaded();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function initFancyTree($tree, treeData) {
 | 
					 | 
				
			||||||
    utils.assertArguments(treeData);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $tree.fancytree({
 | 
					 | 
				
			||||||
        autoScroll: true,
 | 
					 | 
				
			||||||
        keyboard: false, // we takover keyboard handling in the hotkeys plugin
 | 
					 | 
				
			||||||
        extensions: ["hotkeys", "dnd5", "clones"],
 | 
					 | 
				
			||||||
        source: treeData,
 | 
					 | 
				
			||||||
        scrollParent: $tree,
 | 
					 | 
				
			||||||
        minExpandLevel: 2, // root can't be collapsed
 | 
					 | 
				
			||||||
        click: (event, data) => {
 | 
					 | 
				
			||||||
            const targetType = data.targetType;
 | 
					 | 
				
			||||||
            const node = data.node;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (targetType === 'title' || targetType === 'icon') {
 | 
					 | 
				
			||||||
                if (event.shiftKey) {
 | 
					 | 
				
			||||||
                    node.setSelected(!node.isSelected());
 | 
					 | 
				
			||||||
                    node.setFocus(true);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                else if (event.ctrlKey) {
 | 
					 | 
				
			||||||
                    noteDetailService.loadNoteDetail(node.data.noteId, { newTab: true });
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                else {
 | 
					 | 
				
			||||||
                    node.setActive();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    clearSelectedNodes();
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                return false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        activate: async (event, data) => {
 | 
					 | 
				
			||||||
            // click event won't propagate so let's close context menu manually
 | 
					 | 
				
			||||||
            contextMenuWidget.hideContextMenu();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const notePath = await treeUtils.getNotePath(data.node);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            noteDetailService.switchToNote(notePath);
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        expand: (event, data) => setExpandedToServer(data.node.data.branchId, true),
 | 
					 | 
				
			||||||
        collapse: (event, data) => setExpandedToServer(data.node.data.branchId, false),
 | 
					 | 
				
			||||||
        init: (event, data) => treeInitialized(), // don't collapse to short form
 | 
					 | 
				
			||||||
        hotkeys: {
 | 
					 | 
				
			||||||
            keydown: await treeKeyBindingService.getKeyboardBindings()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        dnd5: dragAndDropSetup,
 | 
					 | 
				
			||||||
        lazyLoad: function(event, data) {
 | 
					 | 
				
			||||||
            const noteId = data.node.data.noteId;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            data.result = treeCache.getNote(noteId).then(note => treeBuilder.prepareBranch(note));
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        clones: {
 | 
					 | 
				
			||||||
            highlightActiveClones: true
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        enhanceTitle: async function (event, data) {
 | 
					 | 
				
			||||||
            const node = data.node;
 | 
					 | 
				
			||||||
            const $span = $(node.span);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (node.data.noteId !== 'root'
 | 
					 | 
				
			||||||
                && node.data.noteId === await hoistedNoteService.getHoistedNoteId()
 | 
					 | 
				
			||||||
                && $span.find('.unhoist-button').length === 0) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                const unhoistButton = $('<span>  (<a class="unhoist-button">unhoist</a>)</span>');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                $span.append(unhoistButton);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const note = await treeCache.getNote(node.data.noteId);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (note.type === 'search' && $span.find('.refresh-search-button').length === 0) {
 | 
					 | 
				
			||||||
                const refreshSearchButton = $('<span>  <span class="refresh-search-button bx bx-recycle" title="Refresh saved search results"></span></span>');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                $span.append(refreshSearchButton);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        // this is done to automatically lazy load all expanded search notes after tree load
 | 
					 | 
				
			||||||
        loadChildren: (event, data) => {
 | 
					 | 
				
			||||||
            data.node.visit((subNode) => {
 | 
					 | 
				
			||||||
                // Load all lazy/unloaded child nodes
 | 
					 | 
				
			||||||
                // (which will trigger `loadChildren` recursively)
 | 
					 | 
				
			||||||
                if (subNode.isUndefined() && subNode.isExpanded()) {
 | 
					 | 
				
			||||||
                    subNode.load();
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $tree.on('contextmenu', '.fancytree-node', function(e) {
 | 
					 | 
				
			||||||
        const node = $.ui.fancytree.getNode(e);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        contextMenuWidget.initContextMenu(e, new TreeContextMenu(node));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return false; // blocks default browser right click menu
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tree = $.ui.fancytree.getTree("#tree");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function reload() {
 | 
					async function reload() {
 | 
				
			||||||
    const notes = await loadTreeData();
 | 
					    const notes = await loadTreeData();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -745,12 +651,6 @@ async function sortAlphabetically(noteId) {
 | 
				
			|||||||
    await reload();
 | 
					    await reload();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function showTree($tree) {
 | 
					 | 
				
			||||||
    const treeData = await loadTreeData();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    await initFancyTree($tree, treeData);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ws.subscribeToMessages(message => {
 | 
					ws.subscribeToMessages(message => {
 | 
				
			||||||
   if (message.type === 'refresh-tree') {
 | 
					   if (message.type === 'refresh-tree') {
 | 
				
			||||||
       reload();
 | 
					       reload();
 | 
				
			||||||
@@ -908,7 +808,6 @@ export default {
 | 
				
			|||||||
    getSelectedOrActiveNodes,
 | 
					    getSelectedOrActiveNodes,
 | 
				
			||||||
    clearSelectedNodes,
 | 
					    clearSelectedNodes,
 | 
				
			||||||
    sortAlphabetically,
 | 
					    sortAlphabetically,
 | 
				
			||||||
    showTree,
 | 
					 | 
				
			||||||
    loadTreeData,
 | 
					    loadTreeData,
 | 
				
			||||||
    treeInitialized,
 | 
					    treeInitialized,
 | 
				
			||||||
    setExpandedToServer,
 | 
					    setExpandedToServer,
 | 
				
			||||||
@@ -923,5 +822,6 @@ export default {
 | 
				
			|||||||
    scrollToActiveNote,
 | 
					    scrollToActiveNote,
 | 
				
			||||||
    createNewTopLevelNote,
 | 
					    createNewTopLevelNote,
 | 
				
			||||||
    duplicateNote,
 | 
					    duplicateNote,
 | 
				
			||||||
    getNodeByKey
 | 
					    getNodeByKey,
 | 
				
			||||||
 | 
					    setTree
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -12,7 +12,12 @@ import protectedSessionHolder from "./protected_session_holder.js";
 | 
				
			|||||||
import searchNotesService from "./search_notes.js";
 | 
					import searchNotesService from "./search_notes.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TreeContextMenu {
 | 
					class TreeContextMenu {
 | 
				
			||||||
    constructor(node) {
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param {NoteTreeWidget} treeWidget
 | 
				
			||||||
 | 
					     * @param {FancytreeNode} node
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    constructor(treeWidget, node) {
 | 
				
			||||||
 | 
					        this.treeWidget = treeWidget;
 | 
				
			||||||
        this.node = node;
 | 
					        this.node = node;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -37,7 +42,7 @@ class TreeContextMenu {
 | 
				
			|||||||
        // some actions don't support multi-note so they are disabled when notes are selected
 | 
					        // some actions don't support multi-note so they are disabled when notes are selected
 | 
				
			||||||
        // the only exception is when the only selected note is the one that was right-clicked, then
 | 
					        // the only exception is when the only selected note is the one that was right-clicked, then
 | 
				
			||||||
        // it's clear what the user meant to do.
 | 
					        // it's clear what the user meant to do.
 | 
				
			||||||
        const selNodes = treeService.getSelectedNodes();
 | 
					        const selNodes = this.treeWidget.getSelectedNodes();
 | 
				
			||||||
        const noSelectedNotes = selNodes.length === 0
 | 
					        const noSelectedNotes = selNodes.length === 0
 | 
				
			||||||
                || (selNodes.length === 1 && selNodes[0] === this.node);
 | 
					                || (selNodes.length === 1 && selNodes[0] === this.node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -128,19 +133,19 @@ class TreeContextMenu {
 | 
				
			|||||||
            protectedSessionService.protectSubtree(this.node.data.noteId, false);
 | 
					            protectedSessionService.protectSubtree(this.node.data.noteId, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (cmd === "copy") {
 | 
					        else if (cmd === "copy") {
 | 
				
			||||||
            clipboard.copy(treeService.getSelectedOrActiveNodes(this.node));
 | 
					            clipboard.copy(this.treeWidget.getSelectedOrActiveNodes(this.node));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (cmd === "cloneTo") {
 | 
					        else if (cmd === "cloneTo") {
 | 
				
			||||||
            const nodes = treeService.getSelectedOrActiveNodes(this.node);
 | 
					            const nodes = this.treeWidget.getSelectedOrActiveNodes(this.node);
 | 
				
			||||||
            const noteIds = nodes.map(node => node.data.noteId);
 | 
					            const noteIds = nodes.map(node => node.data.noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            import("../dialogs/clone_to.js").then(d => d.showDialog(noteIds));
 | 
					            import("../dialogs/clone_to.js").then(d => d.showDialog(noteIds));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (cmd === "cut") {
 | 
					        else if (cmd === "cut") {
 | 
				
			||||||
            clipboard.cut(treeService.getSelectedOrActiveNodes(this.node));
 | 
					            clipboard.cut(this.treeWidget.getSelectedOrActiveNodes(this.node));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (cmd === "moveTo") {
 | 
					        else if (cmd === "moveTo") {
 | 
				
			||||||
            const nodes = treeService.getSelectedOrActiveNodes(this.node);
 | 
					            const nodes = this.treeWidget.getSelectedOrActiveNodes(this.node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            import("../dialogs/move_to.js").then(d => d.showDialog(nodes));
 | 
					            import("../dialogs/move_to.js").then(d => d.showDialog(nodes));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -151,7 +156,7 @@ class TreeContextMenu {
 | 
				
			|||||||
            clipboard.pasteInto(this.node);
 | 
					            clipboard.pasteInto(this.node);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (cmd === "delete") {
 | 
					        else if (cmd === "delete") {
 | 
				
			||||||
            treeChangesService.deleteNodes(treeService.getSelectedOrActiveNodes(this.node));
 | 
					            treeChangesService.deleteNodes(this.treeWidget.getSelectedOrActiveNodes(this.node));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (cmd === "export") {
 | 
					        else if (cmd === "export") {
 | 
				
			||||||
            const exportDialog = await import('../dialogs/export.js');
 | 
					            const exportDialog = await import('../dialogs/export.js');
 | 
				
			||||||
@@ -162,7 +167,7 @@ class TreeContextMenu {
 | 
				
			|||||||
            importDialog.showDialog(this.node);
 | 
					            importDialog.showDialog(this.node);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (cmd === "collapseSubtree") {
 | 
					        else if (cmd === "collapseSubtree") {
 | 
				
			||||||
            treeService.collapseTree(this.node);
 | 
					            this.treeWidget.collapseTree(this.node);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (cmd === "forceNoteSync") {
 | 
					        else if (cmd === "forceNoteSync") {
 | 
				
			||||||
            syncService.forceNoteSync(this.node.data.noteId);
 | 
					            syncService.forceNoteSync(this.node.data.noteId);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,13 @@ import keyboardActionService from "../services/keyboard_actions.js";
 | 
				
			|||||||
import treeService from "../services/tree.js";
 | 
					import treeService from "../services/tree.js";
 | 
				
			||||||
import treeUtils from "../services/tree_utils.js";
 | 
					import treeUtils from "../services/tree_utils.js";
 | 
				
			||||||
import noteDetailService from "../services/note_detail.js";
 | 
					import noteDetailService from "../services/note_detail.js";
 | 
				
			||||||
 | 
					import utils from "../services/utils.js";
 | 
				
			||||||
 | 
					import contextMenuWidget from "../services/context_menu.js";
 | 
				
			||||||
 | 
					import treeKeyBindingService from "../services/tree_keybindings.js";
 | 
				
			||||||
 | 
					import dragAndDropSetup from "../services/drag_and_drop.js";
 | 
				
			||||||
 | 
					import treeCache from "../services/tree_cache.js";
 | 
				
			||||||
 | 
					import treeBuilder from "../services/tree_builder.js";
 | 
				
			||||||
 | 
					import TreeContextMenu from "../services/tree_context_menu.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const TPL = `
 | 
					const TPL = `
 | 
				
			||||||
<style>
 | 
					<style>
 | 
				
			||||||
@@ -22,16 +29,25 @@ const TPL = `
 | 
				
			|||||||
`;
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class NoteTreeWidget extends BasicWidget {
 | 
					export default class NoteTreeWidget extends BasicWidget {
 | 
				
			||||||
 | 
					    constructor(appContext) {
 | 
				
			||||||
 | 
					        super(appContext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.tree = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async doRender($widget) {
 | 
					    async doRender($widget) {
 | 
				
			||||||
        $widget.append($(TPL));
 | 
					        $widget.append($(TPL));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const $tree = $widget.find('#tree');
 | 
					        const $tree = $widget.find('#tree');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await treeService.showTree($tree);
 | 
					        const treeData = await treeService.loadTreeData();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await this.initFancyTree($tree, treeData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $tree.on("click", ".unhoist-button", hoistedNoteService.unhoist);
 | 
					        $tree.on("click", ".unhoist-button", hoistedNoteService.unhoist);
 | 
				
			||||||
        $tree.on("click", ".refresh-search-button", searchNotesService.refreshSearch);
 | 
					        $tree.on("click", ".refresh-search-button", searchNotesService.refreshSearch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // this does not belong here ...
 | 
				
			||||||
        keyboardActionService.setGlobalActionHandler('CollapseTree', () => treeService.collapseTree()); // don't use shortened form since collapseTree() accepts argument
 | 
					        keyboardActionService.setGlobalActionHandler('CollapseTree', () => treeService.collapseTree()); // don't use shortened form since collapseTree() accepts argument
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // fancytree doesn't support middle click so this is a way to support it
 | 
					        // fancytree doesn't support middle click so this is a way to support it
 | 
				
			||||||
@@ -51,15 +67,137 @@ export default class NoteTreeWidget extends BasicWidget {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    createTopLevelNoteListener() {
 | 
					    async initFancyTree($tree, treeData) {
 | 
				
			||||||
        treeService.createNewTopLevelNote();
 | 
					        utils.assertArguments(treeData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $tree.fancytree({
 | 
				
			||||||
 | 
					            autoScroll: true,
 | 
				
			||||||
 | 
					            keyboard: false, // we takover keyboard handling in the hotkeys plugin
 | 
				
			||||||
 | 
					            extensions: ["hotkeys", "dnd5", "clones"],
 | 
				
			||||||
 | 
					            source: treeData,
 | 
				
			||||||
 | 
					            scrollParent: $tree,
 | 
				
			||||||
 | 
					            minExpandLevel: 2, // root can't be collapsed
 | 
				
			||||||
 | 
					            click: (event, data) => {
 | 
				
			||||||
 | 
					                const targetType = data.targetType;
 | 
				
			||||||
 | 
					                const node = data.node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (targetType === 'title' || targetType === 'icon') {
 | 
				
			||||||
 | 
					                    if (event.shiftKey) {
 | 
				
			||||||
 | 
					                        node.setSelected(!node.isSelected());
 | 
				
			||||||
 | 
					                        node.setFocus(true);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else if (event.ctrlKey) {
 | 
				
			||||||
 | 
					                        noteDetailService.loadNoteDetail(node.data.noteId, { newTab: true });
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else {
 | 
				
			||||||
 | 
					                        node.setActive();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        treeService.clearSelectedNodes();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            activate: async (event, data) => {
 | 
				
			||||||
 | 
					                // click event won't propagate so let's close context menu manually
 | 
				
			||||||
 | 
					                contextMenuWidget.hideContextMenu();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const notePath = await treeUtils.getNotePath(data.node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                noteDetailService.switchToNote(notePath);
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            expand: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, true),
 | 
				
			||||||
 | 
					            collapse: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, false),
 | 
				
			||||||
 | 
					            init: (event, data) => treeService.treeInitialized(),
 | 
				
			||||||
 | 
					            hotkeys: {
 | 
				
			||||||
 | 
					                keydown: await treeKeyBindingService.getKeyboardBindings()
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            dnd5: dragAndDropSetup,
 | 
				
			||||||
 | 
					            lazyLoad: function(event, data) {
 | 
				
			||||||
 | 
					                const noteId = data.node.data.noteId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                data.result = treeCache.getNote(noteId).then(note => treeBuilder.prepareBranch(note));
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            clones: {
 | 
				
			||||||
 | 
					                highlightActiveClones: true
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            enhanceTitle: async function (event, data) {
 | 
				
			||||||
 | 
					                const node = data.node;
 | 
				
			||||||
 | 
					                const $span = $(node.span);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (node.data.noteId !== 'root'
 | 
				
			||||||
 | 
					                    && node.data.noteId === await hoistedNoteService.getHoistedNoteId()
 | 
				
			||||||
 | 
					                    && $span.find('.unhoist-button').length === 0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    const unhoistButton = $('<span>  (<a class="unhoist-button">unhoist</a>)</span>');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    $span.append(unhoistButton);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const note = await treeCache.getNote(node.data.noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (note.type === 'search' && $span.find('.refresh-search-button').length === 0) {
 | 
				
			||||||
 | 
					                    const refreshSearchButton = $('<span>  <span class="refresh-search-button bx bx-recycle" title="Refresh saved search results"></span></span>');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    $span.append(refreshSearchButton);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            // this is done to automatically lazy load all expanded search notes after tree load
 | 
				
			||||||
 | 
					            loadChildren: (event, data) => {
 | 
				
			||||||
 | 
					                data.node.visit((subNode) => {
 | 
				
			||||||
 | 
					                    // Load all lazy/unloaded child nodes
 | 
				
			||||||
 | 
					                    // (which will trigger `loadChildren` recursively)
 | 
				
			||||||
 | 
					                    if (subNode.isUndefined() && subNode.isExpanded()) {
 | 
				
			||||||
 | 
					                        subNode.load();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $tree.on('contextmenu', '.fancytree-node', e => {
 | 
				
			||||||
 | 
					            const node = $.ui.fancytree.getNode(e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            contextMenuWidget.initContextMenu(this, e, new TreeContextMenu(this, node));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return false; // blocks default browser right click menu
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.tree = $.ui.fancytree.getTree("#tree");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        treeService.setTree(this.tree);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    collapseTreeListener() {
 | 
					    /** @return {FancytreeNode[]} */
 | 
				
			||||||
        treeService.collapseTree();
 | 
					    getSelectedNodes(stopOnParents = false) {
 | 
				
			||||||
 | 
					        return this.tree.getSelectedNodes(stopOnParents);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    scrollToActiveNoteListener() {
 | 
					    /** @return {FancytreeNode[]} */
 | 
				
			||||||
        treeService.scrollToActiveNote();
 | 
					    getSelectedOrActiveNodes(node) {
 | 
				
			||||||
 | 
					        let notes = this.getSelectedNodes(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (notes.length === 0) {
 | 
				
			||||||
 | 
					            notes.push(node);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return notes;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async collapseTree(node = null) {
 | 
				
			||||||
 | 
					        if (!node) {
 | 
				
			||||||
 | 
					            const hoistedNoteId = await hoistedNoteService.getHoistedNoteId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            node = getNodesByNoteId(hoistedNoteId)[0];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        node.setExpanded(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        node.visit(node => node.setExpanded(false));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    createTopLevelNoteListener() { treeService.createNewTopLevelNote(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    collapseTreeListener() { this.collapseTree(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    scrollToActiveNoteListener() { treeService.scrollToActiveNote(); }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user