- Implemented restoring focus on undo/redo.
- Implemented more shortcutkeys. - Implemented selection of all text on tab and after insert/append.
This commit is contained in:
parent
a27423a2f2
commit
01a593ffed
|
@ -182,7 +182,6 @@ jsoneditor.AppendNode.prototype.showContextMenu = function (onClose) {
|
|||
'className': 'jsoneditor-type-string',
|
||||
'title': titles.string,
|
||||
'click': function () {
|
||||
// TODO: settings type string does not work, will become auto
|
||||
node._onAppend('field', 'value', 'string');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,92 +32,92 @@ jsoneditor.History = function (editor) {
|
|||
// map with all supported actions
|
||||
this.actions = {
|
||||
'editField': {
|
||||
'undo': function (obj) {
|
||||
obj.params.node.updateField(obj.params.oldValue);
|
||||
'undo': function (params) {
|
||||
params.node.updateField(params.oldValue);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.node.updateField(obj.params.newValue);
|
||||
'redo': function (params) {
|
||||
params.node.updateField(params.newValue);
|
||||
}
|
||||
},
|
||||
'editValue': {
|
||||
'undo': function (obj) {
|
||||
obj.params.node.updateValue(obj.params.oldValue);
|
||||
'undo': function (params) {
|
||||
params.node.updateValue(params.oldValue);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.node.updateValue(obj.params.newValue);
|
||||
'redo': function (params) {
|
||||
params.node.updateValue(params.newValue);
|
||||
}
|
||||
},
|
||||
'appendNode': {
|
||||
'undo': function (obj) {
|
||||
obj.params.parent.removeChild(obj.params.node);
|
||||
'undo': function (params) {
|
||||
params.parent.removeChild(params.node);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.parent.appendChild(obj.params.node);
|
||||
'redo': function (params) {
|
||||
params.parent.appendChild(params.node);
|
||||
}
|
||||
},
|
||||
'insertBeforeNode': {
|
||||
'undo': function (obj) {
|
||||
obj.params.parent.removeChild(obj.params.node);
|
||||
'undo': function (params) {
|
||||
params.parent.removeChild(params.node);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.parent.insertBefore(obj.params.node, obj.params.beforeNode);
|
||||
'redo': function (params) {
|
||||
params.parent.insertBefore(params.node, params.beforeNode);
|
||||
}
|
||||
},
|
||||
'insertAfterNode': {
|
||||
'undo': function (obj) {
|
||||
obj.params.parent.removeChild(obj.params.node);
|
||||
'undo': function (params) {
|
||||
params.parent.removeChild(params.node);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.parent.insertAfter(obj.params.node, obj.params.afterNode);
|
||||
'redo': function (params) {
|
||||
params.parent.insertAfter(params.node, params.afterNode);
|
||||
}
|
||||
},
|
||||
'removeNode': {
|
||||
'undo': function (obj) {
|
||||
var parent = obj.params.parent;
|
||||
var beforeNode = parent.childs[obj.params.index] || parent.append;
|
||||
parent.insertBefore(obj.params.node, beforeNode);
|
||||
'undo': function (params) {
|
||||
var parent = params.parent;
|
||||
var beforeNode = parent.childs[params.index] || parent.append;
|
||||
parent.insertBefore(params.node, beforeNode);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.parent.removeChild(obj.params.node);
|
||||
'redo': function (params) {
|
||||
params.parent.removeChild(params.node);
|
||||
}
|
||||
},
|
||||
'duplicateNode': {
|
||||
'undo': function (obj) {
|
||||
obj.params.parent.removeChild(obj.params.clone);
|
||||
'undo': function (params) {
|
||||
params.parent.removeChild(params.clone);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.parent.insertAfter(obj.params.clone, obj.params.node);
|
||||
'redo': function (params) {
|
||||
params.parent.insertAfter(params.clone, params.node);
|
||||
}
|
||||
},
|
||||
'changeType': {
|
||||
'undo': function (obj) {
|
||||
obj.params.node.changeType(obj.params.oldType);
|
||||
'undo': function (params) {
|
||||
params.node.changeType(params.oldType);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.node.changeType(obj.params.newType);
|
||||
'redo': function (params) {
|
||||
params.node.changeType(params.newType);
|
||||
}
|
||||
},
|
||||
'moveNode': {
|
||||
'undo': function (obj) {
|
||||
obj.params.startParent.moveTo(obj.params.node, obj.params.startIndex);
|
||||
'undo': function (params) {
|
||||
params.startParent.moveTo(params.node, params.startIndex);
|
||||
},
|
||||
'redo': function (obj) {
|
||||
obj.params.endParent.moveTo(obj.params.node, obj.params.endIndex);
|
||||
'redo': function (params) {
|
||||
params.endParent.moveTo(params.node, params.endIndex);
|
||||
}
|
||||
},
|
||||
'sort': {
|
||||
'undo': function (obj) {
|
||||
var node = obj.params.node;
|
||||
'undo': function (params) {
|
||||
var node = params.node;
|
||||
node.hideChilds();
|
||||
node.sort = obj.params.oldSort;
|
||||
node.childs = obj.params.oldChilds;
|
||||
node.sort = params.oldSort;
|
||||
node.childs = params.oldChilds;
|
||||
node.showChilds();
|
||||
},
|
||||
'redo': function (obj) {
|
||||
var node = obj.params.node;
|
||||
'redo': function (params) {
|
||||
var node = params.node;
|
||||
node.hideChilds();
|
||||
node.sort = obj.params.newSort;
|
||||
node.childs = obj.params.newChilds;
|
||||
node.sort = params.newSort;
|
||||
node.childs = params.newChilds;
|
||||
node.showChilds();
|
||||
}
|
||||
}
|
||||
|
@ -197,7 +197,10 @@ jsoneditor.History.prototype.undo = function () {
|
|||
if (obj) {
|
||||
var action = this.actions[obj.action];
|
||||
if (action && action.undo) {
|
||||
action.undo(obj);
|
||||
action.undo(obj.params);
|
||||
if (obj.params.oldSelection) {
|
||||
this.editor.setSelection(obj.params.oldSelection);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log('Error: unknown action "' + obj.action + '"');
|
||||
|
@ -219,15 +222,16 @@ jsoneditor.History.prototype.redo = function () {
|
|||
|
||||
var obj = this.history[this.index];
|
||||
if (obj) {
|
||||
if (obj) {
|
||||
var action = this.actions[obj.action];
|
||||
if (action && action.redo) {
|
||||
action.redo(obj);
|
||||
}
|
||||
else {
|
||||
console.log('Error: unknown action "' + obj.action + '"');
|
||||
var action = this.actions[obj.action];
|
||||
if (action && action.redo) {
|
||||
action.redo(obj.params);
|
||||
if (obj.params.newSelection) {
|
||||
this.editor.setSelection(obj.params.newSelection);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log('Error: unknown action "' + obj.action + '"');
|
||||
}
|
||||
}
|
||||
|
||||
// fire onchange event
|
||||
|
|
|
@ -284,8 +284,9 @@ jsoneditor.JSONEditor.prototype.collapseAll = function () {
|
|||
* example for "editValue" the Node, old value, and new
|
||||
* value are provided). params contains all information
|
||||
* needed to undo or redo the action.
|
||||
* @private
|
||||
*/
|
||||
jsoneditor.JSONEditor.prototype.onAction = function (action, params) {
|
||||
jsoneditor.JSONEditor.prototype._onAction = function (action, params) {
|
||||
// add an action to the history
|
||||
if (this.history) {
|
||||
this.history.add(action, params);
|
||||
|
@ -359,52 +360,72 @@ jsoneditor.JSONEditor.prototype.stopAutoScroll = function () {
|
|||
|
||||
|
||||
/**
|
||||
* Set the focus to the JSONEditor. A hidden input field will be created
|
||||
* which captures key events
|
||||
* Set the focus to an element in the JSONEditor, set text selection, and
|
||||
* set scroll position.
|
||||
* @param {Object} selection An object containing fields:
|
||||
* {Element | undefined} dom The dom element
|
||||
* which has focus
|
||||
* {Range | TextRange} range A text selection
|
||||
* {Number} scrollTop Scroll position
|
||||
*/
|
||||
// TODO: use the focus method?
|
||||
jsoneditor.JSONEditor.prototype.focus = function () {
|
||||
/*
|
||||
if (!this.dom.focus) {
|
||||
this.dom.focus = document.createElement('input');
|
||||
this.dom.focus.className = 'jsoneditor-hidden-focus';
|
||||
|
||||
var editor = this;
|
||||
this.dom.focus.onblur = function () {
|
||||
// remove itself
|
||||
if (editor.dom.focus) {
|
||||
var focus = editor.dom.focus;
|
||||
delete editor.dom.focus;
|
||||
editor.frame.removeChild(focus);
|
||||
}
|
||||
};
|
||||
|
||||
// attach the hidden input box to the DOM
|
||||
if (this.frame.firstChild) {
|
||||
this.frame.insertBefore(this.dom.focus, this.frame.firstChild);
|
||||
}
|
||||
else {
|
||||
this.frame.appendChild(this.dom.focus);
|
||||
}
|
||||
jsoneditor.JSONEditor.prototype.setSelection = function (selection) {
|
||||
if (!selection) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ('scrollTop' in selection && this.content) {
|
||||
// TODO: animated scroll
|
||||
this.content.scrollTop = selection.scrollTop;
|
||||
}
|
||||
/*
|
||||
if (selection.range) {
|
||||
// FIXME: does not work after a DOM element is removed and restored again
|
||||
jsoneditor.util.setSelection(selection.range);
|
||||
}
|
||||
this.dom.focus.focus();
|
||||
*/
|
||||
if (selection.dom) {
|
||||
selection.dom.focus();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current focus
|
||||
* @return {Object} selection An object containing fields:
|
||||
* {Element | undefined} dom The dom element
|
||||
* which has focus
|
||||
* {Range | TextRange} range A text selection
|
||||
* {Number} scrollTop Scroll position
|
||||
*/
|
||||
jsoneditor.JSONEditor.prototype.getSelection = function () {
|
||||
return {
|
||||
dom: jsoneditor.JSONEditor.domFocus,
|
||||
scrollTop: this.content ? this.content.scrollTop : 0,
|
||||
range: jsoneditor.util.getSelection()
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Adjust the scroll position such that given top position is shown at 1/4
|
||||
* of the window height.
|
||||
* @param {Number} top
|
||||
* @param {function(boolean)} [callback] Callback, executed when animation is
|
||||
* finished. The callback returns true
|
||||
* when animation is finished, or false
|
||||
* when not.
|
||||
*/
|
||||
jsoneditor.JSONEditor.prototype.scrollTo = function (top) {
|
||||
jsoneditor.JSONEditor.prototype.scrollTo = function (top, callback) {
|
||||
var content = this.content;
|
||||
if (content) {
|
||||
// cancel any running animation
|
||||
var editor = this;
|
||||
// cancel any running animation
|
||||
if (editor.animateTimeout) {
|
||||
clearTimeout(editor.animateTimeout);
|
||||
delete editor.animateTimeout;
|
||||
}
|
||||
if (editor.animateCallback) {
|
||||
editor.animateCallback(false);
|
||||
delete editor.animateCallback;
|
||||
}
|
||||
|
||||
// calculate final scroll position
|
||||
var height = content.clientHeight;
|
||||
|
@ -417,11 +438,26 @@ jsoneditor.JSONEditor.prototype.scrollTo = function (top) {
|
|||
var diff = (finalScrollTop - scrollTop);
|
||||
if (Math.abs(diff) > 3) {
|
||||
content.scrollTop += diff / 3;
|
||||
editor.animateCallback = callback;
|
||||
editor.animateTimeout = setTimeout(animate, 50);
|
||||
}
|
||||
else {
|
||||
// finished
|
||||
if (callback) {
|
||||
callback(true);
|
||||
}
|
||||
content.scrollTop = finalScrollTop;
|
||||
delete editor.animateTimeout;
|
||||
delete editor.animateCallback;
|
||||
}
|
||||
};
|
||||
animate();
|
||||
}
|
||||
else {
|
||||
if (callback) {
|
||||
callback(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -437,19 +473,8 @@ jsoneditor.JSONEditor.prototype._createFrame = function () {
|
|||
|
||||
// create one global event listener to handle all events from all nodes
|
||||
var editor = this;
|
||||
// TODO: move this onEvent to jsoneditor.JSONEditor.prototype.onEvent
|
||||
var onEvent = function (event) {
|
||||
event = event || window.event;
|
||||
var target = event.target || event.srcElement;
|
||||
|
||||
if (event.type == 'keydown') {
|
||||
editor.onKeyDown(event);
|
||||
}
|
||||
|
||||
var node = jsoneditor.Node.getNodeFromTarget(target);
|
||||
if (node) {
|
||||
node.onEvent(event);
|
||||
}
|
||||
editor._onEvent(event);
|
||||
};
|
||||
this.frame.onclick = function (event) {
|
||||
onEvent(event);
|
||||
|
@ -570,16 +595,48 @@ jsoneditor.JSONEditor.prototype._onRedo = function () {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Event handler
|
||||
* @param event
|
||||
* @private
|
||||
*/
|
||||
jsoneditor.JSONEditor.prototype._onEvent = function (event) {
|
||||
event = event || window.event;
|
||||
var target = event.target || event.srcElement;
|
||||
|
||||
if (event.type == 'keydown') {
|
||||
this._onKeyDown(event);
|
||||
}
|
||||
|
||||
if (event.type == 'focus') {
|
||||
jsoneditor.JSONEditor.domFocus = target;
|
||||
}
|
||||
|
||||
var node = jsoneditor.Node.getNodeFromTarget(target);
|
||||
if (node) {
|
||||
node.onEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Event handler for keydown. Handles shortcut keys
|
||||
* @param {Event} event
|
||||
* @private
|
||||
*/
|
||||
jsoneditor.JSONEditor.prototype.onKeyDown = function (event) {
|
||||
jsoneditor.JSONEditor.prototype._onKeyDown = function (event) {
|
||||
var keynum = event.which || event.keyCode;
|
||||
var ctrlKey = event.ctrlKey;
|
||||
var shiftKey = event.shiftKey;
|
||||
var handled = false;
|
||||
|
||||
if (keynum == 9) { // Tab
|
||||
// FIXME: selecting all text on tab key does not work on IE8
|
||||
setTimeout(function () {
|
||||
// select all text when moving focus to an editable div
|
||||
jsoneditor.util.selectContentEditable(jsoneditor.JSONEditor.domFocus);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
if (this.searchBox) {
|
||||
if (ctrlKey && keynum == 70) { // Ctrl+F
|
||||
this.searchBox.dom.search.focus();
|
||||
|
@ -597,7 +654,7 @@ jsoneditor.JSONEditor.prototype.onKeyDown = function (event) {
|
|||
}
|
||||
|
||||
// set selection to the current
|
||||
this.searchBox.focusActiveResult();
|
||||
this.searchBox._focusActiveResult();
|
||||
|
||||
handled = true;
|
||||
}
|
||||
|
|
|
@ -587,8 +587,9 @@ jsoneditor.Node.prototype.search = function(text) {
|
|||
/**
|
||||
* Move the scroll position such that this node is in the visible area.
|
||||
* The node will not get the focus
|
||||
* @param {function(boolean)} [callback]
|
||||
*/
|
||||
jsoneditor.Node.prototype.scrollTo = function() {
|
||||
jsoneditor.Node.prototype.scrollTo = function(callback) {
|
||||
if (!this.dom.tr || !this.dom.tr.parentNode) {
|
||||
// if the node is not visible, expand its parents
|
||||
var parent = this.parent;
|
||||
|
@ -600,12 +601,12 @@ jsoneditor.Node.prototype.scrollTo = function() {
|
|||
}
|
||||
|
||||
if (this.dom.tr && this.dom.tr.parentNode) {
|
||||
this.editor.scrollTo(this.dom.tr.offsetTop);
|
||||
this.editor.scrollTo(this.dom.tr.offsetTop, callback);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set focus to the value of this node
|
||||
* Set focus to this node
|
||||
* @param {String} [field] The field name of the element to get the focus
|
||||
* available values: 'field', 'value'
|
||||
*/
|
||||
|
@ -615,12 +616,14 @@ jsoneditor.Node.prototype.focus = function(field) {
|
|||
var domField = this.dom.field;
|
||||
if (domField) {
|
||||
domField.focus();
|
||||
jsoneditor.util.selectContentEditable(domField);
|
||||
}
|
||||
}
|
||||
else {
|
||||
var domValue = this.dom.value;
|
||||
if (domValue) {
|
||||
domValue.focus();
|
||||
jsoneditor.util.selectContentEditable(domValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -888,7 +891,7 @@ jsoneditor.Node.prototype._getDomValue = function(silent) {
|
|||
if (value !== this.value) {
|
||||
var oldValue = this.value;
|
||||
this.value = value;
|
||||
this.editor.onAction('editValue', {
|
||||
this.editor._onAction('editValue', {
|
||||
'node': this,
|
||||
'oldValue': oldValue,
|
||||
'newValue': value
|
||||
|
@ -1025,7 +1028,7 @@ jsoneditor.Node.prototype._getDomField = function(silent) {
|
|||
if (field !== this.field) {
|
||||
var oldField = this.field;
|
||||
this.field = field;
|
||||
this.editor.onAction('editField', {
|
||||
this.editor._onAction('editField', {
|
||||
'node': this,
|
||||
'oldValue': oldField,
|
||||
'newValue': field
|
||||
|
@ -1303,7 +1306,7 @@ jsoneditor.Node.prototype._onDragEnd = function (event) {
|
|||
if ((params.startParent != params.endParent) ||
|
||||
(params.startIndex != params.endIndex)) {
|
||||
// only register this action if the node is actually moved to another place
|
||||
this.editor.onAction('moveNode', params);
|
||||
this.editor._onAction('moveNode', params);
|
||||
}
|
||||
|
||||
document.body.style.cursor = this.drag.oldCursor;
|
||||
|
@ -1646,7 +1649,6 @@ jsoneditor.Node.prototype.onEvent = function (event) {
|
|||
this.editor.highlighter.highlight(this);
|
||||
}
|
||||
else if (type == 'mouseout') {
|
||||
// TODO: onmouseout of menu must only execute unhighlight when no contextmenu is visible
|
||||
this.editor.highlighter.unhighlight();
|
||||
}
|
||||
}
|
||||
|
@ -1796,23 +1798,18 @@ jsoneditor.Node.prototype.onKeyDown = function (event) {
|
|||
this._onDuplicate();
|
||||
handled = true;
|
||||
}
|
||||
/* TODO: implement shortcut keys
|
||||
else if (ctrlKey && keynum == 46) { // Ctrl+Del
|
||||
this._onRemove();
|
||||
handled = true;
|
||||
// TODO: focus to the next node
|
||||
}
|
||||
else if (ctrlKey && !shiftKey && keynum == 45) { // Ctrl+Ins
|
||||
this._onInsertBefore(); // Ctrl+Ins
|
||||
handled = true;
|
||||
// TODO: focus to the next node
|
||||
}
|
||||
else if (ctrlKey && shiftKey && keynum == 45) { // Ctrl+Shift+Ins
|
||||
this._onInsertAfter();
|
||||
handled = true;
|
||||
// TODO: focus to the next node
|
||||
}
|
||||
*/
|
||||
else if (ctrlKey && keynum == 46) { // Ctrl+Del
|
||||
this._onRemove();
|
||||
handled = true;
|
||||
}
|
||||
else if (ctrlKey && !shiftKey && keynum == 45) { // Ctrl+Ins
|
||||
this._onInsertBefore(); // Ctrl+Ins
|
||||
handled = true;
|
||||
}
|
||||
else if (ctrlKey && shiftKey && keynum == 45) { // Ctrl+Shift+Ins
|
||||
this._onInsertAfter();
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
jsoneditor.util.preventDefault(event);
|
||||
|
@ -1886,14 +1883,32 @@ jsoneditor.Node.types = [
|
|||
*/
|
||||
jsoneditor.Node.prototype._onRemove = function() {
|
||||
this.editor.highlighter.unhighlight();
|
||||
var index = this.parent.childs.indexOf(this);
|
||||
var childs = this.parent.childs;
|
||||
var index = childs.indexOf(this);
|
||||
|
||||
// adjust the focus
|
||||
var oldSelection = this.editor.getSelection();
|
||||
if (childs[index + 1]) {
|
||||
childs[index + 1].focus();
|
||||
}
|
||||
else if (childs[index - 1]) {
|
||||
childs[index - 1].focus();
|
||||
}
|
||||
else {
|
||||
this.parent.focus();
|
||||
}
|
||||
var newSelection = this.editor.getSelection();
|
||||
|
||||
// remove the node
|
||||
this.parent._remove(this);
|
||||
|
||||
this.editor.onAction('removeNode', {
|
||||
// store history action
|
||||
this.editor._onAction('removeNode', {
|
||||
'node': this,
|
||||
'parent': this.parent,
|
||||
'index': index
|
||||
'index': index,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1902,12 +1917,17 @@ jsoneditor.Node.prototype._onRemove = function() {
|
|||
* @private
|
||||
*/
|
||||
jsoneditor.Node.prototype._onDuplicate = function() {
|
||||
var oldSelection = this.editor.getSelection();
|
||||
var clone = this.parent._duplicate(this);
|
||||
clone.focus();
|
||||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor.onAction('duplicateNode', {
|
||||
this.editor._onAction('duplicateNode', {
|
||||
'node': this,
|
||||
'clone': clone,
|
||||
'parent': this.parent
|
||||
'parent': this.parent,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1919,6 +1939,8 @@ jsoneditor.Node.prototype._onDuplicate = function() {
|
|||
* @private
|
||||
*/
|
||||
jsoneditor.Node.prototype._onInsertBefore = function (field, value, type) {
|
||||
var oldSelection = this.editor.getSelection();
|
||||
|
||||
var newNode = new jsoneditor.Node(this.editor, {
|
||||
'field': (value != undefined) ? field : 'field',
|
||||
'value': (value != undefined) ? value : 'value',
|
||||
|
@ -1928,11 +1950,14 @@ jsoneditor.Node.prototype._onInsertBefore = function (field, value, type) {
|
|||
this.parent.insertBefore(newNode, this);
|
||||
this.editor.highlighter.unhighlight();
|
||||
newNode.focus();
|
||||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor.onAction('insertBeforeNode', {
|
||||
this.editor._onAction('insertBeforeNode', {
|
||||
'node': newNode,
|
||||
'beforeNode': this,
|
||||
'parent': this.parent
|
||||
'parent': this.parent,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1944,6 +1969,8 @@ jsoneditor.Node.prototype._onInsertBefore = function (field, value, type) {
|
|||
* @private
|
||||
*/
|
||||
jsoneditor.Node.prototype._onInsertAfter = function (field, value, type) {
|
||||
var oldSelection = this.editor.getSelection();
|
||||
|
||||
var newNode = new jsoneditor.Node(this.editor, {
|
||||
'field': (value != undefined) ? field : 'field',
|
||||
'value': (value != undefined) ? value : 'value',
|
||||
|
@ -1953,11 +1980,14 @@ jsoneditor.Node.prototype._onInsertAfter = function (field, value, type) {
|
|||
this.parent.insertAfter(newNode, this);
|
||||
this.editor.highlighter.unhighlight();
|
||||
newNode.focus();
|
||||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor.onAction('insertAfterNode', {
|
||||
this.editor._onAction('insertAfterNode', {
|
||||
'node': newNode,
|
||||
'afterNode': this,
|
||||
'parent': this.parent
|
||||
'parent': this.parent,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1969,6 +1999,8 @@ jsoneditor.Node.prototype._onInsertAfter = function (field, value, type) {
|
|||
* @private
|
||||
*/
|
||||
jsoneditor.Node.prototype._onAppend = function (field, value, type) {
|
||||
var oldSelection = this.editor.getSelection();
|
||||
|
||||
var newNode = new jsoneditor.Node(this.editor, {
|
||||
'field': (value != undefined) ? field : 'field',
|
||||
'value': (value != undefined) ? value : 'value',
|
||||
|
@ -1978,10 +2010,13 @@ jsoneditor.Node.prototype._onAppend = function (field, value, type) {
|
|||
this.parent.appendChild(newNode);
|
||||
this.editor.highlighter.unhighlight();
|
||||
newNode.focus();
|
||||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor.onAction('appendNode', {
|
||||
this.editor._onAction('appendNode', {
|
||||
'node': newNode,
|
||||
'parent': this.parent
|
||||
'parent': this.parent,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1993,12 +2028,16 @@ jsoneditor.Node.prototype._onAppend = function (field, value, type) {
|
|||
jsoneditor.Node.prototype._onChangeType = function (newType) {
|
||||
var oldType = this.type;
|
||||
if (newType != oldType) {
|
||||
var oldSelection = this.editor.getSelection();
|
||||
this.changeType(newType);
|
||||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor.onAction('changeType', {
|
||||
this.editor._onAction('changeType', {
|
||||
'node': this,
|
||||
'oldType': oldType,
|
||||
'newType': newType
|
||||
'newType': newType,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -2029,7 +2068,7 @@ jsoneditor.Node.prototype._onSort = function (direction) {
|
|||
});
|
||||
this.sort = (order == 1) ? 'asc' : 'desc';
|
||||
|
||||
this.editor.onAction('sort', {
|
||||
this.editor._onAction('sort', {
|
||||
'node': this,
|
||||
'oldChilds': oldChilds,
|
||||
'oldSort': oldSort,
|
||||
|
@ -2057,6 +2096,7 @@ jsoneditor.Node.prototype.getAppend = function () {
|
|||
* Find the node from an event target
|
||||
* @param {Node} target
|
||||
* @return {jsoneditor.Node | undefined} node or undefined when not found
|
||||
* @static
|
||||
*/
|
||||
jsoneditor.Node.getNodeFromTarget = function (target) {
|
||||
while (target) {
|
||||
|
@ -2093,7 +2133,6 @@ jsoneditor.Node.prototype.showContextMenu = function (onClose) {
|
|||
var titles = jsoneditor.Node.TYPE_TITLES;
|
||||
var items = [];
|
||||
|
||||
// TODO: add titles for all context menu items
|
||||
items.push({
|
||||
'text': 'Type',
|
||||
'title': 'Change the type of this field',
|
||||
|
@ -2215,7 +2254,6 @@ jsoneditor.Node.prototype.showContextMenu = function (onClose) {
|
|||
'className': 'jsoneditor-type-string',
|
||||
'title': titles.string,
|
||||
'click': function () {
|
||||
// TODO: settings type string does not work, will become auto
|
||||
node._onAppend('field', 'value', 'string');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,16 +84,16 @@ jsoneditor.SearchBox = function(editor, container) {
|
|||
this.dom.search = search;
|
||||
search.className = 'jsoneditor-search';
|
||||
search.oninput = function (event) {
|
||||
searchBox.onDelayedSearch(event);
|
||||
searchBox._onDelayedSearch(event);
|
||||
};
|
||||
search.onchange = function (event) { // For IE 8
|
||||
searchBox.onSearch(event);
|
||||
searchBox._onSearch(event);
|
||||
};
|
||||
search.onkeydown = function (event) {
|
||||
searchBox.onKeyDown(event);
|
||||
searchBox._onKeyDown(event);
|
||||
};
|
||||
search.onkeyup = function (event) {
|
||||
searchBox.onKeyUp(event);
|
||||
searchBox._onKeyUp(event);
|
||||
};
|
||||
refreshSearch.onclick = function (event) {
|
||||
search.select();
|
||||
|
@ -135,7 +135,7 @@ jsoneditor.SearchBox.prototype.next = function() {
|
|||
if (index > this.results.length - 1) {
|
||||
index = 0;
|
||||
}
|
||||
this.setActiveResult(index);
|
||||
this._setActiveResult(index);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -149,15 +149,16 @@ jsoneditor.SearchBox.prototype.previous = function() {
|
|||
if (index < 0) {
|
||||
index = max;
|
||||
}
|
||||
this.setActiveResult(index);
|
||||
this._setActiveResult(index);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set new value for the current active result
|
||||
* @param {Number} index
|
||||
* @private
|
||||
*/
|
||||
jsoneditor.SearchBox.prototype.setActiveResult = function(index) {
|
||||
jsoneditor.SearchBox.prototype._setActiveResult = function(index) {
|
||||
// de-activate current active result
|
||||
if (this.activeResult) {
|
||||
var prevNode = this.activeResult.node;
|
||||
|
@ -198,8 +199,9 @@ jsoneditor.SearchBox.prototype.setActiveResult = function(index) {
|
|||
/**
|
||||
* Set the focus to the currently active result. If there is no currently
|
||||
* active result, the next search result will get focus
|
||||
* @private
|
||||
*/
|
||||
jsoneditor.SearchBox.prototype.focusActiveResult = function() {
|
||||
jsoneditor.SearchBox.prototype._focusActiveResult = function() {
|
||||
if (!this.activeResult) {
|
||||
this.next();
|
||||
}
|
||||
|
@ -211,8 +213,9 @@ jsoneditor.SearchBox.prototype.focusActiveResult = function() {
|
|||
|
||||
/**
|
||||
* Cancel any running onDelayedSearch.
|
||||
* @private
|
||||
*/
|
||||
jsoneditor.SearchBox.prototype.clearDelay = function() {
|
||||
jsoneditor.SearchBox.prototype._clearDelay = function() {
|
||||
if (this.timeout != undefined) {
|
||||
clearTimeout(this.timeout);
|
||||
delete this.timeout;
|
||||
|
@ -223,14 +226,15 @@ jsoneditor.SearchBox.prototype.clearDelay = function() {
|
|||
* Start a timer to execute a search after a short delay.
|
||||
* Used for reducing the number of searches while typing.
|
||||
* @param {Event} event
|
||||
* @private
|
||||
*/
|
||||
jsoneditor.SearchBox.prototype.onDelayedSearch = function (event) {
|
||||
jsoneditor.SearchBox.prototype._onDelayedSearch = function (event) {
|
||||
// execute the search after a short delay (reduces the number of
|
||||
// search actions while typing in the search text box)
|
||||
this.clearDelay();
|
||||
this._clearDelay();
|
||||
var searchBox = this;
|
||||
this.timeout = setTimeout(function (event) {
|
||||
searchBox.onSearch(event);
|
||||
searchBox._onSearch(event);
|
||||
},
|
||||
this.delay);
|
||||
};
|
||||
|
@ -241,9 +245,10 @@ jsoneditor.SearchBox.prototype.onDelayedSearch = function (event) {
|
|||
* @param {boolean} [forceSearch] If true, search will be executed again even
|
||||
* when the search text is not changed.
|
||||
* Default is false.
|
||||
* @private
|
||||
*/
|
||||
jsoneditor.SearchBox.prototype.onSearch = function (event, forceSearch) {
|
||||
this.clearDelay();
|
||||
jsoneditor.SearchBox.prototype._onSearch = function (event, forceSearch) {
|
||||
this._clearDelay();
|
||||
|
||||
var value = this.dom.search.value;
|
||||
var text = (value.length > 0) ? value : undefined;
|
||||
|
@ -251,7 +256,7 @@ jsoneditor.SearchBox.prototype.onSearch = function (event, forceSearch) {
|
|||
// only search again when changed
|
||||
this.lastText = text;
|
||||
this.results = this.editor.search(text);
|
||||
this.setActiveResult(undefined);
|
||||
this._setActiveResult(undefined);
|
||||
|
||||
// display search results
|
||||
if (text != undefined) {
|
||||
|
@ -271,20 +276,21 @@ jsoneditor.SearchBox.prototype.onSearch = function (event, forceSearch) {
|
|||
/**
|
||||
* Handle onKeyDown event in the input box
|
||||
* @param {Event} event
|
||||
* @private
|
||||
*/
|
||||
jsoneditor.SearchBox.prototype.onKeyDown = function (event) {
|
||||
jsoneditor.SearchBox.prototype._onKeyDown = function (event) {
|
||||
event = event || window.event;
|
||||
var keynum = event.which || event.keyCode;
|
||||
if (keynum == 27) { // ESC
|
||||
this.dom.search.value = ''; // clear search
|
||||
this.onSearch(event);
|
||||
this._onSearch(event);
|
||||
jsoneditor.util.preventDefault(event);
|
||||
jsoneditor.util.stopPropagation(event);
|
||||
}
|
||||
else if (keynum == 13) { // Enter
|
||||
if (event.ctrlKey) {
|
||||
// force to search again
|
||||
this.onSearch(event, true);
|
||||
this._onSearch(event, true);
|
||||
}
|
||||
else if (event.shiftKey) {
|
||||
// move to the previous search result
|
||||
|
@ -302,11 +308,12 @@ jsoneditor.SearchBox.prototype.onKeyDown = function (event) {
|
|||
/**
|
||||
* Handle onKeyUp event in the input box
|
||||
* @param {Event} event
|
||||
* @private
|
||||
*/
|
||||
jsoneditor.SearchBox.prototype.onKeyUp = function (event) {
|
||||
jsoneditor.SearchBox.prototype._onKeyUp = function (event) {
|
||||
event = event || window.event;
|
||||
var keynum = event.which || event.keyCode;
|
||||
if (keynum != 27 && keynum != 13) { // !show and !Enter
|
||||
this.onDelayedSearch(event); // For IE 8
|
||||
this._onDelayedSearch(event); // For IE 8
|
||||
}
|
||||
};
|
||||
|
|
|
@ -247,7 +247,7 @@ jsoneditor.util.stripFormatting = function (divElement) {
|
|||
* code from Nico Burns
|
||||
* http://stackoverflow.com/users/140293/nico-burns
|
||||
* http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity
|
||||
* @param {Element} contentEditableElement
|
||||
* @param {Element} contentEditableElement A content editable div
|
||||
*/
|
||||
jsoneditor.util.setEndOfContentEditable = function (contentEditableElement) {
|
||||
var range, selection;
|
||||
|
@ -267,6 +267,64 @@ jsoneditor.util.setEndOfContentEditable = function (contentEditableElement) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Select all text of a content editable div.
|
||||
* http://stackoverflow.com/a/3806004/1262753
|
||||
* @param {Element} contentEditableElement A content editable div
|
||||
*/
|
||||
jsoneditor.util.selectContentEditable = function (contentEditableElement) {
|
||||
if (!contentEditableElement || contentEditableElement.nodeName != 'DIV') {
|
||||
return;
|
||||
}
|
||||
|
||||
var sel, range;
|
||||
if (window.getSelection && document.createRange) {
|
||||
range = document.createRange();
|
||||
range.selectNodeContents(contentEditableElement);
|
||||
sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(range);
|
||||
} else if (document.body.createTextRange) {
|
||||
range = document.body.createTextRange();
|
||||
range.moveToElementText(contentEditableElement);
|
||||
range.select();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get text selection
|
||||
* http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore
|
||||
* @return {Range | TextRange | null} range
|
||||
*/
|
||||
jsoneditor.util.getSelection = function () {
|
||||
if (window.getSelection) {
|
||||
var sel = window.getSelection();
|
||||
if (sel.getRangeAt && sel.rangeCount) {
|
||||
return sel.getRangeAt(0);
|
||||
}
|
||||
} else if (document.selection && document.selection.createRange) {
|
||||
return document.selection.createRange();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set text selection
|
||||
* http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore
|
||||
* @param {Range | TextRange | null} range
|
||||
*/
|
||||
jsoneditor.util.setSelection = function (range) {
|
||||
if (range) {
|
||||
if (window.getSelection) {
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(range);
|
||||
} else if (document.selection && range.select) {
|
||||
range.select();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the inner text of an HTML element (for example a div element)
|
||||
* @param {Element} element
|
||||
|
@ -344,9 +402,8 @@ jsoneditor.util.getInnerText = function (element, buffer) {
|
|||
* Source: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx
|
||||
* @return {Number} Internet Explorer version, or -1 in case of an other browser
|
||||
*/
|
||||
var _ieVersion = undefined;
|
||||
jsoneditor.util.getInternetExplorerVersion = function() {
|
||||
if (_ieVersion == undefined) {
|
||||
if (_ieVersion == -1) {
|
||||
var rv = -1; // Return value assumes failure.
|
||||
if (navigator.appName == 'Microsoft Internet Explorer')
|
||||
{
|
||||
|
@ -363,6 +420,13 @@ jsoneditor.util.getInternetExplorerVersion = function() {
|
|||
return _ieVersion;
|
||||
};
|
||||
|
||||
/**
|
||||
* cached internet explorer version
|
||||
* @type {Number}
|
||||
* @private
|
||||
*/
|
||||
var _ieVersion = -1;
|
||||
|
||||
/**
|
||||
* Add and event listener. Works for all browsers
|
||||
* @param {Element} element An html element
|
||||
|
|
Loading…
Reference in New Issue