- 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:
josdejong 2013-01-06 21:12:37 +01:00
parent a27423a2f2
commit 01a593ffed
6 changed files with 331 additions and 162 deletions

View File

@ -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');
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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');
}
}

View File

@ -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
}
};

View File

@ -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