Implemented keyboard shortcuts to select multiple fields
This commit is contained in:
parent
fe5a413f23
commit
96c4204b1c
|
@ -5,7 +5,8 @@
|
|||
Key | Description
|
||||
----------------------- | ------------------------------------------------
|
||||
Alt+Arrows | Move the caret up/down/left/right between fields
|
||||
Shift+Alt+Arrows | Move field up/down/left/right
|
||||
Shift+Alt+Arrows | Move current field or selected fields up/down/left/right
|
||||
Shift+Arrow Up/Down | Select multiple fields
|
||||
Ctrl+D | Duplicate field
|
||||
Ctrl+Del | Remove field
|
||||
Ctrl+Enter | Open link when on a field containing an url
|
||||
|
|
|
@ -233,7 +233,8 @@ tr.jsoneditor-selected button.jsoneditor-contextmenu {
|
|||
visibility: hidden;
|
||||
}
|
||||
|
||||
tr.jsoneditor-selected.jsoneditor-first button {
|
||||
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea,
|
||||
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
|
|
|
@ -2004,6 +2004,8 @@ Node.prototype.onKeyDown = function (event) {
|
|||
var editable = this.editor.options.mode === 'tree';
|
||||
var oldSelection;
|
||||
var oldBeforeNode;
|
||||
var nodes;
|
||||
var multiselection;
|
||||
|
||||
// util.log(ctrlKey, keynum, event.charCode); // TODO: cleanup
|
||||
if (keynum == 13) { // Enter
|
||||
|
@ -2027,7 +2029,10 @@ Node.prototype.onKeyDown = function (event) {
|
|||
}
|
||||
else if (keynum == 68) { // D
|
||||
if (ctrlKey && editable) { // Ctrl+D
|
||||
Node.onDuplicate(this);
|
||||
nodes = this.editor.multiselection.nodes.length > 0
|
||||
? this.editor.multiselection.nodes
|
||||
: this;
|
||||
Node.onDuplicate(nodes);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
@ -2046,7 +2051,10 @@ Node.prototype.onKeyDown = function (event) {
|
|||
}
|
||||
else if (keynum == 46 && editable) { // Del
|
||||
if (ctrlKey) { // Ctrl+Del
|
||||
Node.onRemove(this);
|
||||
nodes = this.editor.multiselection.nodes.length > 0
|
||||
? this.editor.multiselection.nodes
|
||||
: this;
|
||||
Node.onRemove(nodes);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
@ -2127,10 +2135,25 @@ Node.prototype.onKeyDown = function (event) {
|
|||
// find the previous node
|
||||
prevNode = this._previousNode();
|
||||
if (prevNode) {
|
||||
this.editor.deselect(true);
|
||||
prevNode.focus(Node.focusElement || this._getElementName(target));
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
else if (!altKey && shiftKey) { // Shift + Arrow Up
|
||||
// select multiple nodes
|
||||
prevNode = this._previousNode();
|
||||
if (prevNode) {
|
||||
multiselection = this.editor.multiselection;
|
||||
multiselection.start = multiselection.start || this;
|
||||
multiselection.end = prevNode;
|
||||
nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end);
|
||||
|
||||
this.editor.select(nodes);
|
||||
prevNode.focus('field'); // select field as we know this always exists
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
else if (altKey && shiftKey) { // Alt + Shift + Arrow Up
|
||||
// find the previous node
|
||||
prevNode = this._previousNode();
|
||||
|
@ -2191,10 +2214,25 @@ Node.prototype.onKeyDown = function (event) {
|
|||
// find the next node
|
||||
nextNode = this._nextNode();
|
||||
if (nextNode) {
|
||||
this.editor.deselect(true);
|
||||
nextNode.focus(Node.focusElement || this._getElementName(target));
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
else if (!altKey && shiftKey) { // Shift + Arrow Down
|
||||
// select multiple nodes
|
||||
nextNode = this._nextNode();
|
||||
if (nextNode) {
|
||||
multiselection = this.editor.multiselection;
|
||||
multiselection.start = multiselection.start || this;
|
||||
multiselection.end = nextNode;
|
||||
nodes = this.editor._findTopLevelNodes(multiselection.start, multiselection.end);
|
||||
|
||||
this.editor.select(nodes);
|
||||
nextNode.focus('field'); // select field as we know this always exists
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Down
|
||||
// find the 2nd next node and move before that one
|
||||
if (this.expanded) {
|
||||
|
@ -2310,7 +2348,7 @@ Node.onDuplicate = function(nodes) {
|
|||
var parent = lastNode.parent;
|
||||
var editor = lastNode.editor;
|
||||
|
||||
editor.deselect(editor.multiselect.nodes);
|
||||
editor.deselect(editor.multiselection.nodes);
|
||||
|
||||
// duplicate the nodes
|
||||
var oldSelection = editor.getSelection();
|
||||
|
|
|
@ -36,7 +36,9 @@ treemode.create = function (container, options) {
|
|||
this.dom = {};
|
||||
this.highlighter = new Highlighter();
|
||||
this.selection = undefined; // will hold the last input selection
|
||||
this.multiselection = [];
|
||||
this.multiselection = {
|
||||
nodes: []
|
||||
};
|
||||
|
||||
this._setOptions(options);
|
||||
|
||||
|
@ -422,7 +424,7 @@ treemode.getSelection = function () {
|
|||
return {
|
||||
dom: domFocus,
|
||||
range: range,
|
||||
nodes: this.multiselection.slice(0),
|
||||
nodes: this.multiselection.nodes.slice(0),
|
||||
scrollTop: this.content ? this.content.scrollTop : 0
|
||||
};
|
||||
};
|
||||
|
@ -656,7 +658,7 @@ treemode._onEvent = function (event) {
|
|||
|
||||
if (event.type == 'mousedown') {
|
||||
// drag multiple nodes
|
||||
Node.onDragStart(this.multiselection, event);
|
||||
Node.onDragStart(this.multiselection.nodes, event);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -682,10 +684,10 @@ treemode._onEvent = function (event) {
|
|||
treemode._onMultiSelectStart = function (event) {
|
||||
var node = Node.getNodeFromTarget(event.target);
|
||||
|
||||
this.multiselection = [];
|
||||
this.drag = {
|
||||
this.multiselection = {
|
||||
start: node || null,
|
||||
end: null
|
||||
end: null,
|
||||
nodes: []
|
||||
};
|
||||
|
||||
var editor = this;
|
||||
|
@ -708,27 +710,28 @@ treemode._onMultiSelect = function (event) {
|
|||
var node = Node.getNodeFromTarget(event.target);
|
||||
|
||||
if (node) {
|
||||
if (this.drag.start == null) {
|
||||
this.drag.start = node;
|
||||
if (this.multiselection.start == null) {
|
||||
this.multiselection.start = node;
|
||||
}
|
||||
this.drag.end = node;
|
||||
this.multiselection.end = node;
|
||||
}
|
||||
|
||||
// deselect previous selection
|
||||
this.deselect();
|
||||
|
||||
// find the selected nodes in the range from first to last
|
||||
var start = this.drag.start;
|
||||
var end = this.drag.end || this.drag.start;
|
||||
var start = this.multiselection.start;
|
||||
var end = this.multiselection.end || this.multiselection.start;
|
||||
if (start && end) {
|
||||
// find the top level childs, all having the same parent
|
||||
this.multiselection = this._findTopLevelNodes(start, end);
|
||||
this.select(this.multiselection);
|
||||
this.multiselection.nodes = this._findTopLevelNodes(start, end);
|
||||
this.select(this.multiselection.nodes);
|
||||
}
|
||||
};
|
||||
|
||||
treemode._onMultiSelectEnd = function (event) {
|
||||
delete this.drag;
|
||||
this.multiselection.start = null;
|
||||
this.multiselection.end = null;
|
||||
|
||||
// cleanup global event listeners
|
||||
if (this.mousemove) {
|
||||
|
@ -743,13 +746,18 @@ treemode._onMultiSelectEnd = function (event) {
|
|||
|
||||
/**
|
||||
* deselect currently selected nodes
|
||||
* @param {boolean} [clearStartAndEnd=false] If true, the `start` and `end`
|
||||
* state is cleared too.
|
||||
*/
|
||||
treemode.deselect = function () {
|
||||
if (this.multiselection) {
|
||||
this.multiselection.forEach(function (node) {
|
||||
node.setSelected(false);
|
||||
});
|
||||
this.multiselection = [];
|
||||
treemode.deselect = function (clearStartAndEnd) {
|
||||
this.multiselection.nodes.forEach(function (node) {
|
||||
node.setSelected(false);
|
||||
});
|
||||
this.multiselection.nodes = [];
|
||||
|
||||
if (clearStartAndEnd) {
|
||||
this.multiselection.start = null;
|
||||
this.multiselection.end = null;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -765,7 +773,7 @@ treemode.select = function (nodes) {
|
|||
if (nodes) {
|
||||
this.deselect();
|
||||
|
||||
this.multiselection = nodes.slice(0);
|
||||
this.multiselection.nodes = nodes.slice(0);
|
||||
|
||||
var first = nodes[0];
|
||||
nodes.forEach(function (node) {
|
||||
|
@ -935,7 +943,7 @@ treemode.showContextMenu = function (anchor, onClose) {
|
|||
title: 'Duplicate selected fields (Ctrl+D)',
|
||||
className: 'jsoneditor-duplicate',
|
||||
click: function () {
|
||||
Node.onDuplicate(editor.multiselection);
|
||||
Node.onDuplicate(editor.multiselection.nodes);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -945,7 +953,7 @@ treemode.showContextMenu = function (anchor, onClose) {
|
|||
title: 'Remove selected fields (Ctrl+Del)',
|
||||
className: 'jsoneditor-remove',
|
||||
click: function () {
|
||||
Node.onRemove(editor.multiselection);
|
||||
Node.onRemove(editor.multiselection.nodes);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue