From a9abad2cd499d0d2c108b1921d299904f93815fb Mon Sep 17 00:00:00 2001 From: jos Date: Wed, 29 May 2019 16:29:29 +0200 Subject: [PATCH] Fix #698 `node.path` sometimes null in `onCreateMenu` --- HISTORY.md | 2 ++ docs/api.md | 22 +++++++++++++++++----- examples/21_customize_context_menu.html | 3 ++- src/js/Node.js | 8 +++++++- src/js/appendNodeFactory.js | 8 +++++++- src/js/treemode.js | 10 +++++++++- 6 files changed, 44 insertions(+), 9 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 908c18f..d5fee49 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -6,6 +6,8 @@ https://github.com/josdejong/jsoneditor ## not yet published, version 5.32.6 - Fixed #697: JSON Schema enum dropdown not working inside an array. +- Fixed #698: When using `onCreateMenu`, `node.path` is null when clicking + on an append node or when multiple nodes are selected. ## 2019-04-27, version 5.32.5 diff --git a/docs/api.md b/docs/api.md index e186749..c4a890a 100644 --- a/docs/api.md +++ b/docs/api.md @@ -163,14 +163,26 @@ Constructs a new JSONEditor. See also option `schema` for JSON schema validation. -- `{function} onCreateMenu(items,{path})` +- `{function} onCreateMenu(items, node)` Customize context menus in tree mode. - - Sets a callback function to customize the context menu in tree mode. Each time the user clicks on the context menu button, an array of menu items is created. If this callback is set, the array is passed to this function along with an object containing the current path (if any). This function can customize any aspect of these menu items, including deleting them and/or adding new items. Each menu item is represented by an object, which may also contain a submenu array of items. See the source code of example 21 in the examples folder for more info on the format of the items and submenu objects. - - The function should return the final array of menu items to be displayed to the user. + Sets a callback function to customize the context menu in tree mode. Each time the user clicks on the context menu button, an array of menu items is created. If this callback is configured, the array with menu items is passed to this function. The menu items can be customized in this function in any aspect of these menu items, including deleting them and/or adding new items. The function should return the final array of menu items to be displayed to the user. + + Each menu item is represented by an object, which may also contain a submenu array of items. See the source code of example 21 in the examples folder for more info on the format of the items and submenu objects. + + The second argument `node` is an object containing the following properties: + + ``` + { + type: 'single' | 'multiple' | 'append' + path: Array, + paths: Array with paths + } + ``` + + The property `path` containing the path of the node, and `paths` contains the same path or in case there are multiple selected nodes it contains the paths of all selected nodes. + When the user opens the context menu of an append node (in an empty object or array), the `type` will be `'append'` and the `path` will contain the path of the parent node. - `{boolean} escapeUnicode` diff --git a/examples/21_customize_context_menu.html b/examples/21_customize_context_menu.html index 97ba6b7..b894df1 100644 --- a/examples/21_customize_context_menu.html +++ b/examples/21_customize_context_menu.html @@ -61,7 +61,8 @@ onCreateMenu : function (items, node) { var path = node.path - console.log(items); // log the current items for inspection + // log the current items and node for inspection + console.log('items:', items, 'node:', node); // We are going to add a menu item which returns the current node path // as a jq path selector ( https://stedolan.github.io/jq/ ). First we diff --git a/src/js/Node.js b/src/js/Node.js index 38ae2c5..847fb01 100644 --- a/src/js/Node.js +++ b/src/js/Node.js @@ -4433,7 +4433,13 @@ Node.prototype.showContextMenu = function (anchor, onClose) { } if (this.editor.options.onCreateMenu) { - items = this.editor.options.onCreateMenu(items, { path : node.getPath() }); + var path = node.getPath(); + + items = this.editor.options.onCreateMenu(items, { + type: 'single', + path: path, + paths: [path] + }); } var menu = new ContextMenu(items, {close: onClose}); diff --git a/src/js/appendNodeFactory.js b/src/js/appendNodeFactory.js index 6748e09..fd92867 100644 --- a/src/js/appendNodeFactory.js +++ b/src/js/appendNodeFactory.js @@ -202,7 +202,13 @@ function appendNodeFactory(Node) { ]; if (this.editor.options.onCreateMenu) { - items = this.editor.options.onCreateMenu(items, { path : node.getPath() }); + var path = node.parent.getPath(); + + items = this.editor.options.onCreateMenu(items, { + type: 'append', + path: path, + paths: [path] + }); } var menu = new ContextMenu(items, {close: onClose}); diff --git a/src/js/treemode.js b/src/js/treemode.js index 92cf59e..69685dd 100644 --- a/src/js/treemode.js +++ b/src/js/treemode.js @@ -1686,7 +1686,15 @@ treemode.showContextMenu = function (anchor, onClose) { }); if (this.options.onCreateMenu) { - items = this.options.onCreateMenu(items, { path : node.getPath() }); + var paths = selectedNodes.map(function (node) { + return node.getPath(); + }); + + items = this.options.onCreateMenu(items, { + type: 'multiple', + path: paths[0], + paths: paths + }); } var menu = new ContextMenu(items, {close: onClose});