From d978c64e1a59c9d57a0b2079ccd067b6e98954b2 Mon Sep 17 00:00:00 2001 From: azivner Date: Fri, 9 Nov 2018 17:11:45 +0100 Subject: [PATCH] refactoring of tree context menu into reusable component --- .../javascripts/services/context_menu.js | 65 +++++++++++++++++ .../services/note_detail_relation_map.js | 8 +-- src/public/javascripts/services/tree.js | 71 ++----------------- .../javascripts/services/tree_context_menu.js | 1 + src/views/dialogs/branch_prefix.ejs | 2 +- src/views/index.ejs | 2 +- 6 files changed, 75 insertions(+), 74 deletions(-) create mode 100644 src/public/javascripts/services/context_menu.js diff --git a/src/public/javascripts/services/context_menu.js b/src/public/javascripts/services/context_menu.js new file mode 100644 index 000000000..e2d1322f9 --- /dev/null +++ b/src/public/javascripts/services/context_menu.js @@ -0,0 +1,65 @@ +const $contextMenuContainer = $("#context-menu-container"); + +function initContextMenu(event, contextMenuItems, selectContextMenuItem) { + $contextMenuContainer.empty(); + + for (const item of contextMenuItems) { + if (item.title === '----') { + $contextMenuContainer.append($("
").addClass("dropdown-divider")); + } else { + const $icon = $(""); + + if (item.uiIcon) { + $icon.addClass("jam jam-" + item.uiIcon); + } else { + $icon.append(" "); + } + + const $item = $("") + .append($icon) + .append("   ") // some space between icon and text + .addClass("dropdown-item") + .prop("data-cmd", item.cmd) + .append(item.title); + + + if (item.enabled !== undefined && !item.enabled) { + $item.addClass("disabled"); + } + + $item.click(async function (e) { + const cmd = $(e.target).prop("data-cmd"); + + await selectContextMenuItem(e, cmd); + }); + + $contextMenuContainer.append($item); + } + } + + // code below tries to detect when dropdown would overflow from page + // in such case we'll position it above click coordinates so it will fit into client + const clickPosition = event.pageY; + const clientHeight = document.documentElement.clientHeight; + const contextMenuHeight = $contextMenuContainer.height(); + + let top; + + if (clickPosition + contextMenuHeight > clientHeight) { + top = clientHeight - contextMenuHeight - 10; + } else { + top = event.pageY - 10; + } + + $contextMenuContainer.css({ + display: "block", + top: top, + left: event.pageX - 20 + }).addClass("show"); +} + +$(document).click(() => $contextMenuContainer.hide()); + +export default { + initContextMenu +} \ No newline at end of file diff --git a/src/public/javascripts/services/note_detail_relation_map.js b/src/public/javascripts/services/note_detail_relation_map.js index 9c8e27d57..955f0accb 100644 --- a/src/public/javascripts/services/note_detail_relation_map.js +++ b/src/public/javascripts/services/note_detail_relation_map.js @@ -224,19 +224,17 @@ function initJsPlumbInstance () { $relationMapCanvas.contextmenu({ delegate: ".note-box", menu: [ - {title: "Remove note", cmd: "remove", uiIcon: "ui-icon-trash"}, - {title: "Edit title", cmd: "edit-title", uiIcon: "ui-icon-pencil"}, + {title: "Remove note", cmd: "remove", uiIcon: "trash"}, + {title: "Edit title", cmd: "edit-title", uiIcon: "pencil"}, ], select: noteContextMenuHandler }); - $.widget("moogle.contextmenuRelation", $.moogle.contextmenu, {}); - $relationMapCanvas.contextmenuRelation({ delegate: ".connection-label,.jtk-connector", autoTrigger: false, // it doesn't open automatically, needs to be triggered explicitly by .open() call menu: [ - {title: "Remove relation", cmd: "remove", uiIcon: "ui-icon-trash"} + {title: "Remove relation", cmd: "remove", uiIcon: "trash"} ], select: relationContextMenuHandler }); diff --git a/src/public/javascripts/services/tree.js b/src/public/javascripts/services/tree.js index 36d7ce3fd..6a6f9eb8d 100644 --- a/src/public/javascripts/services/tree.js +++ b/src/public/javascripts/services/tree.js @@ -1,3 +1,4 @@ +import contextMenuWidget from './context_menu.js'; import treeContextMenuService from './tree_context_menu.js'; import dragAndDropSetup from './drag_and_drop.js'; import linkService from './link.js'; @@ -15,7 +16,6 @@ import Branch from '../entities/branch.js'; import NoteShort from '../entities/note_short.js'; const $tree = $("#tree"); -const $treeContextMenu = $("#tree-context-menu"); const $createTopLevelNoteButton = $("#create-top-level-note-button"); const $collapseTreeButton = $("#collapse-tree-button"); const $scrollToCurrentNoteButton = $("#scroll-to-current-note-button"); @@ -378,73 +378,10 @@ function initFancyTree(tree) { } }); - $treeContextMenu.on('click', '.dropdown-item', function(e) { - const cmd = $(e.target).prop("data-cmd"); - - treeContextMenuService.selectContextMenuItem(e, cmd); - }); - - async function openContextMenu(e) { - $treeContextMenu.empty(); - - const contextMenuItems = await treeContextMenuService.getContextMenuItems(e); - - for (const item of contextMenuItems) { - if (item.title === '----') { - $treeContextMenu.append($("
").addClass("dropdown-divider")); - } else { - const $icon = $(""); - - if (item.uiIcon) { - $icon.addClass("jam jam-" + item.uiIcon); - } - else { - $icon.append(" "); - } - - const $item = $("") - .append($icon) - .append("   ") // some space between icon and text - .addClass("dropdown-item") - .prop("data-cmd", item.cmd) - .append(item.title); - - - - if (item.enabled !== undefined && !item.enabled) { - $item.addClass("disabled"); - } - - $treeContextMenu.append($item); - } - } - - // code below tries to detect when dropdown would overflow from page - // in such case we'll position it above click coordinates so it will fit into client - const clickPosition = e.pageY; - const clientHeight = document.documentElement.clientHeight; - const contextMenuHeight = $treeContextMenu.height(); - - let top; - - if (clickPosition + contextMenuHeight > clientHeight) { - top = clientHeight - contextMenuHeight - 10; - } - else { - top = e.pageY - 10; - } - - $treeContextMenu.css({ - display: "block", - top: top, - left: e.pageX - 20 - }).addClass("show"); - } - - $(document).click(() => $(".context-menu").hide()); - $tree.on('contextmenu', '.fancytree-node', function(e) { - openContextMenu(e); + treeContextMenuService.getContextMenuItems(e).then(contextMenuItems => { + contextMenuWidget.initContextMenu(e, contextMenuItems, treeContextMenuService.selectContextMenuItem); + }); return false; // blocks default browser right click menu }); diff --git a/src/public/javascripts/services/tree_context_menu.js b/src/public/javascripts/services/tree_context_menu.js index c6378fdfd..248aa45ff 100644 --- a/src/public/javascripts/services/tree_context_menu.js +++ b/src/public/javascripts/services/tree_context_menu.js @@ -10,6 +10,7 @@ import exportSubtreeDialog from '../dialogs/export_subtree.js'; import infoService from "./info.js"; import treeCache from "./tree_cache.js"; import syncService from "./sync.js"; +import contextMenuService from "./context_menu.js"; const $tree = $("#tree"); diff --git a/src/views/dialogs/branch_prefix.ejs b/src/views/dialogs/branch_prefix.ejs index 366e05298..36e5a44ac 100644 --- a/src/views/dialogs/branch_prefix.ejs +++ b/src/views/dialogs/branch_prefix.ejs @@ -1,5 +1,5 @@