CR Fix: tree selection - use serializable node as parameters
This commit is contained in:
parent
7e90161057
commit
39e8d36f72
17
docs/api.md
17
docs/api.md
|
@ -216,7 +216,10 @@ Constructs a new JSONEditor.
|
||||||
callback signature should be:
|
callback signature should be:
|
||||||
```js
|
```js
|
||||||
/**
|
/**
|
||||||
* @param {Array<Node>} nodes selected nodes
|
* @typedef {{field: String, value: String|Object|Number|Boolean, path: Array.<String|Number>} SerializableNode
|
||||||
|
*
|
||||||
|
* @param {SerializableNode=} start
|
||||||
|
* @param {SerializableNode=} end
|
||||||
*/
|
*/
|
||||||
function onSelectionChange(nodes) {
|
function onSelectionChange(nodes) {
|
||||||
...
|
...
|
||||||
|
@ -374,9 +377,9 @@ Get the current selected nodes, Only applicable for mode 'tree'.
|
||||||
|
|
||||||
*Returns:*
|
*Returns:*
|
||||||
|
|
||||||
- `{Array<Node>} nodes`
|
- `{{start:SerializableNode, end: SerializableNode}}`
|
||||||
|
|
||||||
#### `JSONEditor.setSelection(startNode, endNode)`
|
#### `JSONEditor.setSelection(start, end)`
|
||||||
|
|
||||||
Set selection for a range of nodes, Only applicable for mode 'tree'.
|
Set selection for a range of nodes, Only applicable for mode 'tree'.
|
||||||
|
|
||||||
|
@ -386,13 +389,13 @@ Set selection for a range of nodes, Only applicable for mode 'tree'.
|
||||||
|
|
||||||
*Parameters:*
|
*Parameters:*
|
||||||
|
|
||||||
- `{Node} startNode`
|
- `{{path: Array.<String>}} start`
|
||||||
|
|
||||||
Node instance for selection start
|
Path for the start node
|
||||||
|
|
||||||
- `{Node} endNode`
|
- `{{path: Array.<String>}} end`
|
||||||
|
|
||||||
Node instance for selection end
|
Path for the end node
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
|
|
|
@ -33,15 +33,15 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Selection indication was done using the <code>on{Text/Node}SelectionChange</code> listeners.<br/>
|
Selection indication was done using the <code>on[Text]SelectionChange</code> listeners.<br/>
|
||||||
you can try the following calls in the console of your browser:<br/>
|
you can try the following calls in the console of your browser:<br/>
|
||||||
<code class="multiline">
|
<code class="multiline">
|
||||||
// text and code modes:
|
// text and code modes:
|
||||||
editor.getTextSelection()
|
editor.getTextSelection()
|
||||||
editor.setTextSelection(startPos,endPos)
|
editor.setTextSelection(startPos, endPos)
|
||||||
// tree mode:
|
// tree mode:
|
||||||
editor.getSelection()
|
editor.getSelection()
|
||||||
editor.setSelection(Node1,Node2)
|
editor.setSelection(startNode, endNode)
|
||||||
</code>
|
</code>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
<b>Text:</b><div id="selectedText"></div>
|
<b>Text:</b><div id="selectedText"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="treeModeSelection">
|
<div id="treeModeSelection">
|
||||||
<b>Selection: </b><span id="selectedCount"></span>
|
<b>Selection:</b>
|
||||||
<div id="selectedNodes"></div>
|
<div id="selectedNodes"></div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -91,15 +91,15 @@
|
||||||
var textEl = document.getElementById('selectedText');
|
var textEl = document.getElementById('selectedText');
|
||||||
textEl.innerHTML = text;
|
textEl.innerHTML = text;
|
||||||
},
|
},
|
||||||
onSelectionChange: function(nodes) {
|
onSelectionChange: function(start, end) {
|
||||||
var nodesEl = document.getElementById('selectedNodes');
|
var nodesEl = document.getElementById('selectedNodes');
|
||||||
var nodesCountEl = document.getElementById('selectedCount');
|
nodesEl.innerHTML = '';
|
||||||
nodesCountEl.innerHTML = nodes.length + ' nodes selected';
|
if (start) {
|
||||||
nodesEl.innerHTML = nodes.map(function(node) {
|
nodesEl.innerHTML = ('start: ' + JSON.stringify(start));
|
||||||
return node.field !== undefined
|
if (end) {
|
||||||
? node._escapeHTML(node.field)
|
nodesEl.innerHTML += ('<br/>end: ' + JSON.stringify(end));
|
||||||
: (isNaN(node.index) ? node.type : node.index);
|
}
|
||||||
}).join(", ");
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -80,12 +80,7 @@ Node.prototype.getPath = function () {
|
||||||
var node = this;
|
var node = this;
|
||||||
var path = [];
|
var path = [];
|
||||||
while (node) {
|
while (node) {
|
||||||
var field = !node.parent
|
var field = node.getName();
|
||||||
? undefined // do not add an (optional) field name of the root node
|
|
||||||
: (node.parent.type != 'array')
|
|
||||||
? node.field
|
|
||||||
: node.index;
|
|
||||||
|
|
||||||
if (field !== undefined) {
|
if (field !== undefined) {
|
||||||
path.unshift(field);
|
path.unshift(field);
|
||||||
}
|
}
|
||||||
|
@ -94,6 +89,54 @@ Node.prototype.getPath = function () {
|
||||||
return path;
|
return path;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get node serializable name
|
||||||
|
* @returns {String|Number}
|
||||||
|
*/
|
||||||
|
Node.prototype.getName = function () {
|
||||||
|
return !this.parent
|
||||||
|
? undefined // do not add an (optional) field name of the root node
|
||||||
|
: (this.parent.type != 'array')
|
||||||
|
? this.field
|
||||||
|
: this.index;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find child node by serializable path
|
||||||
|
* @param {Array<String>} path
|
||||||
|
*/
|
||||||
|
Node.prototype.findNodeByPath = function (path) {
|
||||||
|
if (!path) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.length == 0) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.length && this.childs && this.childs.length) {
|
||||||
|
for (var i=0; i < this.childs.length; ++i) {
|
||||||
|
if (path[0] === '' + this.childs[i].getName()) {
|
||||||
|
return this.childs[i].findNodeByPath(path.slice(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {{field: String, value: String|Object|Number|Boolean, path: Array.<String|Number>} SerializableNode
|
||||||
|
*
|
||||||
|
* Returns serializable representation for the node
|
||||||
|
* @return {SerializedNode}
|
||||||
|
*/
|
||||||
|
Node.prototype.serialize = function () {
|
||||||
|
return {
|
||||||
|
field: this.getField(),
|
||||||
|
value: this.getValue(),
|
||||||
|
path: this.getPath()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a Node from a JSON path like '.items[3].name'
|
* Find a Node from a JSON path like '.items[3].name'
|
||||||
* @param {string} jsonPath
|
* @param {string} jsonPath
|
||||||
|
|
|
@ -1088,7 +1088,7 @@ treemode.deselect = function (clearStartAndEnd) {
|
||||||
|
|
||||||
if (selectionChanged) {
|
if (selectionChanged) {
|
||||||
if (this._selectionChangedHandler) {
|
if (this._selectionChangedHandler) {
|
||||||
this._selectionChangedHandler([]);
|
this._selectionChangedHandler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1113,7 +1113,8 @@ treemode.select = function (nodes) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this._selectionChangedHandler) {
|
if (this._selectionChangedHandler) {
|
||||||
this._selectionChangedHandler(nodes);
|
var selection = this.getSelection();
|
||||||
|
this._selectionChangedHandler(selection.start, selection.end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1340,10 +1341,18 @@ treemode.showContextMenu = function (anchor, onClose) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current selected nodes
|
* Get current selected nodes
|
||||||
* @return {Array<Node>}
|
* @return {{start:SerializableNode, end: SerializableNode}} if no selection an empty object will be retured
|
||||||
*/
|
*/
|
||||||
treemode.getSelection = function () {
|
treemode.getSelection = function () {
|
||||||
return this.multiselection.nodes || [];
|
var selection = {};
|
||||||
|
if (this.multiselection.nodes && this.multiselection.nodes.length) {
|
||||||
|
selection.start = this.multiselection.nodes[0].serialize();
|
||||||
|
|
||||||
|
if (this.multiselection.nodes.length > 1) {
|
||||||
|
selection.end = this.multiselection.nodes[this.multiselection.nodes.length - 1].serialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selection;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1351,7 +1360,8 @@ treemode.getSelection = function () {
|
||||||
* @param {selectionCallback} callback
|
* @param {selectionCallback} callback
|
||||||
*
|
*
|
||||||
* @callback selectionCallback
|
* @callback selectionCallback
|
||||||
* @param {Array<Node>} nodes selected nodes
|
* @param {SerializableNode=} start
|
||||||
|
* @param {SerializableNode=} end
|
||||||
*/
|
*/
|
||||||
treemode.onSelectionChange = function (callback) {
|
treemode.onSelectionChange = function (callback) {
|
||||||
if (typeof callback === 'function') {
|
if (typeof callback === 'function') {
|
||||||
|
@ -1361,18 +1371,28 @@ treemode.onSelectionChange = function (callback) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select range of nodes.
|
* Select range of nodes.
|
||||||
* For selecting single node send only the first node parameter
|
* For selecting single node send only the start parameter
|
||||||
* For clear selection do not send any parameter
|
* For clear the selection do not send any parameter
|
||||||
* If the nodes are not from the same level the first common parent will be selected
|
* If the nodes are not from the same level the first common parent will be selected
|
||||||
* @param {Node} [startNode] node for selection start
|
* @param {{path: Array.<String>}} start object contains the path for selection start
|
||||||
* @param {Node} [endNode] node for selection end
|
* @param {{path: Array.<String>}=} end object contains the path for selection end
|
||||||
*/
|
*/
|
||||||
treemode.setSelection = function (startNode, endNode) {
|
treemode.setSelection = function (start, end) {
|
||||||
// check for old usage
|
// check for old usage
|
||||||
if (startNode.dom && startNode.range) {
|
if (start && start.dom && start.range) {
|
||||||
console.warn('setSelection/getSelection usage for text selection is depracated and should not be used, see documantaion for supported selection options');
|
console.warn('setSelection/getSelection usage for text selection is depracated and should not be used, see documantaion for supported selection options');
|
||||||
this.setDomSelection(startNode);
|
this.setDomSelection(startNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var startNode, endNode;
|
||||||
|
|
||||||
|
if (start && start.path) {
|
||||||
|
startNode = this.node.findNodeByPath(start.path);
|
||||||
|
if (end && end.path) {
|
||||||
|
endNode = this.node.findNodeByPath(end.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var nodes = [];
|
var nodes = [];
|
||||||
if (startNode instanceof Node) {
|
if (startNode instanceof Node) {
|
||||||
if (endNode instanceof Node && endNode !== startNode) {
|
if (endNode instanceof Node && endNode !== startNode) {
|
||||||
|
|
Loading…
Reference in New Issue