RED.contextMenu = (function() { let menu; function createMenu() { // menu = RED.popover.menu({ // options: [ // { // label: 'delete selection', // onselect: function() { // RED.actions.invoke('core:delete-selection') // RED.view.focus() // } // }, // { label: 'world' } // ], // width: 200, // }) } function disposeMenu() { $(document).off("mousedown.red-ui-workspace-context-menu"); if (menu) { menu.remove(); } menu = null; } function show(options) { if (menu) { menu.remove() } const selection = RED.view.selection() const hasSelection = (selection.nodes && selection.nodes.length > 0); const hasMultipleSelection = hasSelection && selection.nodes.length > 1; const hasLinks = selection.links && selection.links.length > 0; const isSingleLink = !hasSelection && hasLinks && selection.links.length === 1 const isMultipleLinks = !hasSelection && hasLinks && selection.links.length > 1 const canDelete = hasSelection || hasLinks const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group' const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g const offset = $("#red-ui-workspace-chart").offset() let addX = options.x - offset.left + $("#red-ui-workspace-chart").scrollLeft() let addY = options.y - offset.top + $("#red-ui-workspace-chart").scrollTop() if (RED.view.snapGrid) { const gridSize = RED.view.gridSize() addX = gridSize*Math.floor(addX/gridSize) addY = gridSize*Math.floor(addY/gridSize) } const menuItems = [ { onselect: 'core:show-action-list', onpostselect: function() {} }, { label: RED._("contextMenu.insert"), options: [ { label: RED._("contextMenu.node"), onselect: function() { RED.view.showQuickAddDialog({ position: [ addX, addY ], touchTrigger: true, splice: isSingleLink?selection.links[0]:undefined, // spliceMultiple: isMultipleLinks }) } }, ( hasSelection || hasLinks ) ? { label: RED._("contextMenu.junction"), onselect: 'core:split-wires-with-junctions', disabled: !hasLinks } : { label: RED._("contextMenu.junction"), onselect: function() { const nn = { _def: {defaults:{}}, type: 'junction', z: RED.workspaces.active(), id: RED.nodes.id(), x: addX, y: addY, w: 0, h: 0, outputs: 1, inputs: 1, dirty: true } const historyEvent = { dirty: RED.nodes.dirty(), t:'add', junctions:[nn] } RED.nodes.addJunction(nn); RED.history.push(historyEvent); RED.nodes.dirty(true); RED.view.redraw(true) } }, { label: RED._("contextMenu.linkNodes"), onselect: 'core:split-wire-with-link-nodes', disabled: !hasLinks } ] } ] // menuItems.push( // { // label: (isSingleLink || isMultipleLinks)?'Insert into wire...':'Add node...', // onselect: function() { // RED.view.showQuickAddDialog({ // position: [ options.x - offset.left, options.y - offset.top ], // touchTrigger: true, // splice: isSingleLink?selection.links[0]:undefined, // spliceMultiple: isMultipleLinks // }) // } // }, // ) // if (hasLinks && !hasSelection) { // menuItems.push({ onselect: 'core:split-wires-with-junctions', label: 'Insert junction'}) // } menuItems.push( null, { onselect: 'core:undo', disabled: RED.history.list().length === 0 }, { onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 }, null, { onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !hasSelection}, { onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection }, { onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !RED.view.clipboard() }, { onselect: 'core:delete-selection', disabled: !canDelete }, { onselect: 'core:show-export-dialog', label: RED._("menu.label.export") }, { onselect: 'core:select-all-nodes' } ) if (hasSelection) { menuItems.push( null, isGroup ? { onselect: 'core:ungroup-selection', disabled: !isGroup } : { onselect: 'core:group-selection', disabled: !hasSelection } ) if (canRemoveFromGroup) { menuItems.push({ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") }) } } menu = RED.menu.init({ direction: 'right', onpreselect: function() { disposeMenu() }, onpostselect: function() { RED.view.focus() }, options: menuItems }); menu.attr("id","red-ui-workspace-context-menu"); menu.css({ position: "absolute" }) menu.appendTo("body"); // TODO: prevent the menu from overflowing the window. var top = options.y var left = options.x if (top+menu.height()-$(document).scrollTop() > $(window).height()) { top -= (top+menu.height())-$(window).height() + 22; } if (left+menu.width()-$(document).scrollLeft() > $(window).width()) { left -= (left+menu.width())-$(window).width() + 18; } menu.css({ top: top+"px", left: left+"px" }) $(".red-ui-menu.red-ui-menu-dropdown").hide(); $(document).on("mousedown.red-ui-workspace-context-menu", function(evt) { if (menu && menu[0].contains(evt.target)) { return } disposeMenu() }); menu.show(); // menu.show({ // target: $('#red-ui-main-container'), // x: options.x, // y: options.y // }) } return { show: show, hide: disposeMenu } })()