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