Improved error handling
This commit is contained in:
parent
9d5aab339b
commit
a8d26fd113
|
@ -6,6 +6,7 @@ http://jsoneditoronline.org
|
||||||
|
|
||||||
- Unified JSONFormatter and JSONEditor in one editor with a switchable mode.
|
- Unified JSONFormatter and JSONEditor in one editor with a switchable mode.
|
||||||
- Urls are navigable now.
|
- Urls are navigable now.
|
||||||
|
- Improved error and log handling.
|
||||||
- Added jsoneditor to npm and bower.
|
- Added jsoneditor to npm and bower.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ app.CodeToTree = function() {
|
||||||
treeEditor.set(codeEditor.get());
|
treeEditor.set(codeEditor.get());
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
app.notify.showError(err);
|
app.notify.showError(app.formatError(err));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ app.treeToCode = function () {
|
||||||
codeEditor.set(treeEditor.get());
|
codeEditor.set(treeEditor.get());
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
app.notify.showError(err);
|
app.notify.showError(app.formatError(err));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -103,12 +103,12 @@ app.load = function() {
|
||||||
mode: 'code',
|
mode: 'code',
|
||||||
change: function () {
|
change: function () {
|
||||||
app.lastChanged = codeEditor;
|
app.lastChanged = codeEditor;
|
||||||
|
},
|
||||||
|
error: function (err) {
|
||||||
|
app.notify.showError(app.formatError(err));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
codeEditor.set(json);
|
codeEditor.set(json);
|
||||||
codeEditor.onError = function (err) {
|
|
||||||
app.notify.showError(err);
|
|
||||||
};
|
|
||||||
|
|
||||||
// tree editor
|
// tree editor
|
||||||
container = document.getElementById("treeEditor");
|
container = document.getElementById("treeEditor");
|
||||||
|
@ -116,6 +116,9 @@ app.load = function() {
|
||||||
mode: 'tree',
|
mode: 'tree',
|
||||||
change: function () {
|
change: function () {
|
||||||
app.lastChanged = treeEditor;
|
app.lastChanged = treeEditor;
|
||||||
|
},
|
||||||
|
error: function (err) {
|
||||||
|
app.notify.showError(app.formatError(err));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
treeEditor.set(json);
|
treeEditor.set(json);
|
||||||
|
@ -212,7 +215,7 @@ app.openCallback = function (err, data) {
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
treeEditor.set({});
|
treeEditor.set({});
|
||||||
app.notify.showError(err);
|
app.notify.showError(app.formatError(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,6 +270,22 @@ app.saveFile = function () {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a JSON parse/stringify error as HTML
|
||||||
|
* @param {Error} err
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
app.formatError = function (err) {
|
||||||
|
var message = '<pre class="error">' + err.toString() + '</pre>';
|
||||||
|
if (typeof(jsonlint) != 'undefined') {
|
||||||
|
message +=
|
||||||
|
'<a class="error" href="http://zaach.github.com/jsonlint/" target="_blank">' +
|
||||||
|
'validated by jsonlint' +
|
||||||
|
'</a>';
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the current file
|
* Clear the current file
|
||||||
*/
|
*/
|
||||||
|
|
File diff suppressed because one or more lines are too long
215
jsoneditor.js
215
jsoneditor.js
|
@ -173,35 +173,43 @@ JSONEditor.prototype.setMode = function (mode) {
|
||||||
options.mode = mode;
|
options.mode = mode;
|
||||||
var config = JSONEditor.modes[mode];
|
var config = JSONEditor.modes[mode];
|
||||||
if (config) {
|
if (config) {
|
||||||
if (config.data == 'text') {
|
try {
|
||||||
// text
|
if (config.data == 'text') {
|
||||||
name = this.getName();
|
// text
|
||||||
data = this.getText();
|
name = this.getName();
|
||||||
|
data = this.getText();
|
||||||
|
|
||||||
this._delete();
|
this._delete();
|
||||||
util.clear(this);
|
util.clear(this);
|
||||||
util.extend(this, config.editor.prototype);
|
util.extend(this, config.editor.prototype);
|
||||||
this._create(container, options);
|
this._create(container, options);
|
||||||
|
|
||||||
this.setName(name);
|
this.setName(name);
|
||||||
this.setText(data);
|
this.setText(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// json
|
||||||
|
name = this.getName();
|
||||||
|
data = this.get();
|
||||||
|
|
||||||
|
this._delete();
|
||||||
|
util.clear(this);
|
||||||
|
util.extend(this, config.editor.prototype);
|
||||||
|
this._create(container, options);
|
||||||
|
|
||||||
|
this.setName(name);
|
||||||
|
this.set(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof config.load === 'function') {
|
||||||
|
try {
|
||||||
|
config.load.call(this);
|
||||||
|
}
|
||||||
|
catch (err) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
catch (err) {
|
||||||
// json
|
this._onError(err);
|
||||||
name = this.getName();
|
|
||||||
data = this.get();
|
|
||||||
|
|
||||||
this._delete();
|
|
||||||
util.clear(this);
|
|
||||||
util.extend(this, config.editor.prototype);
|
|
||||||
this._create(container, options);
|
|
||||||
|
|
||||||
this.setName(name);
|
|
||||||
this.set(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof config.load === 'function') {
|
|
||||||
config.load.call(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -209,6 +217,28 @@ JSONEditor.prototype.setMode = function (mode) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw an error. If an error callback is configured in options.error, this
|
||||||
|
* callback will be invoked. Else, a regular error is thrown.
|
||||||
|
* @param {Error} err
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
JSONEditor.prototype._onError = function(err) {
|
||||||
|
// TODO: onError is deprecated since version 2.2.0. cleanup some day
|
||||||
|
if (typeof this.onError === 'function') {
|
||||||
|
util.log('WARNING: JSONEditor.onError is deprecated. ' +
|
||||||
|
'Use options.error instead.');
|
||||||
|
this.onError(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof this.options.error === 'function') {
|
||||||
|
this.options.error(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor TreeEditor
|
* @constructor TreeEditor
|
||||||
* @param {Element} container Container element
|
* @param {Element} container Container element
|
||||||
|
@ -303,22 +333,22 @@ TreeEditor.prototype._setOptions = function (options) {
|
||||||
if (options['enableSearch']) {
|
if (options['enableSearch']) {
|
||||||
// deprecated since version 1.6.0, 2012-11-03
|
// deprecated since version 1.6.0, 2012-11-03
|
||||||
this.options.search = options['enableSearch'];
|
this.options.search = options['enableSearch'];
|
||||||
console.log('WARNING: Option "enableSearch" is deprecated. Use "search" instead.');
|
util.log('WARNING: Option "enableSearch" is deprecated. Use "search" instead.');
|
||||||
}
|
}
|
||||||
if (options['enableHistory']) {
|
if (options['enableHistory']) {
|
||||||
// deprecated since version 1.6.0, 2012-11-03
|
// deprecated since version 1.6.0, 2012-11-03
|
||||||
this.options.history = options['enableHistory'];
|
this.options.history = options['enableHistory'];
|
||||||
console.log('WARNING: Option "enableHistory" is deprecated. Use "history" instead.');
|
util.log('WARNING: Option "enableHistory" is deprecated. Use "history" instead.');
|
||||||
}
|
}
|
||||||
if (options['mode'] == 'editor') {
|
if (options['mode'] == 'editor') {
|
||||||
// deprecated since version 2.2.0, 2013-04-30
|
// deprecated since version 2.2.0, 2013-04-30
|
||||||
this.options.mode = 'tree';
|
this.options.mode = 'tree';
|
||||||
console.log('WARNING: Mode "editor" is deprecated. Use "tree" instead.');
|
util.log('WARNING: Mode "editor" is deprecated. Use "tree" instead.');
|
||||||
}
|
}
|
||||||
if (options['mode'] == 'viewer') {
|
if (options['mode'] == 'viewer') {
|
||||||
// deprecated since version 2.2.0, 2013-04-30
|
// deprecated since version 2.2.0, 2013-04-30
|
||||||
this.options.mode = 'view';
|
this.options.mode = 'view';
|
||||||
console.log('WARNING: Mode "viewer" is deprecated. Use "view" instead.');
|
util.log('WARNING: Mode "viewer" is deprecated. Use "view" instead.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +373,7 @@ TreeEditor.prototype.set = function (json, name) {
|
||||||
// adjust field name for root node
|
// adjust field name for root node
|
||||||
if (name) {
|
if (name) {
|
||||||
// TODO: deprecated since version 2.2.0. Cleanup some day.
|
// TODO: deprecated since version 2.2.0. Cleanup some day.
|
||||||
console.log('Warning: second parameter "name" is deprecated. ' +
|
util.log('Warning: second parameter "name" is deprecated. ' +
|
||||||
'Use setName(name) instead.');
|
'Use setName(name) instead.');
|
||||||
this.options.name = name;
|
this.options.name = name;
|
||||||
}
|
}
|
||||||
|
@ -528,7 +558,7 @@ TreeEditor.prototype._onAction = function (action, params) {
|
||||||
this.options.change();
|
this.options.change();
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.log('Error in change callback: ', err);
|
util.log('Error in change callback: ', err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1023,17 +1053,18 @@ TextEditor.prototype._create = function (container, options, json) {
|
||||||
if (options.indentation) {
|
if (options.indentation) {
|
||||||
this.indentation = Number(options.indentation);
|
this.indentation = Number(options.indentation);
|
||||||
}
|
}
|
||||||
|
this.options = options;
|
||||||
this.mode = (options.mode == 'code') ? 'code' : 'text';
|
this.mode = (options.mode == 'code') ? 'code' : 'text';
|
||||||
if (this.mode == 'code') {
|
if (this.mode == 'code') {
|
||||||
// verify whether Ace editor is available and supported
|
// verify whether Ace editor is available and supported
|
||||||
if (typeof ace === 'undefined') {
|
if (typeof ace === 'undefined') {
|
||||||
this.mode = 'text';
|
this.mode = 'text';
|
||||||
console.log('WARNING: Cannot load code editor, Ace library not loaded. ' +
|
util.log('WARNING: Cannot load code editor, Ace library not loaded. ' +
|
||||||
'Falling back to plain text editor');
|
'Falling back to plain text editor');
|
||||||
}
|
}
|
||||||
if (util.getInternetExplorerVersion() == 8) {
|
if (util.getInternetExplorerVersion() == 8) {
|
||||||
this.mode = 'text';
|
this.mode = 'text';
|
||||||
console.log('WARNING: Cannot load code editor, Ace is not supported on IE8. ' +
|
util.log('WARNING: Cannot load code editor, Ace is not supported on IE8. ' +
|
||||||
'Falling back to plain text editor');
|
'Falling back to plain text editor');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1067,7 +1098,12 @@ TextEditor.prototype._create = function (container, options, json) {
|
||||||
//buttonFormat.className = 'jsoneditor-button';
|
//buttonFormat.className = 'jsoneditor-button';
|
||||||
this.menu.appendChild(buttonFormat);
|
this.menu.appendChild(buttonFormat);
|
||||||
buttonFormat.onclick = function () {
|
buttonFormat.onclick = function () {
|
||||||
me.format();
|
try {
|
||||||
|
me.format();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
me._onError(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// create compact button
|
// create compact button
|
||||||
|
@ -1078,7 +1114,13 @@ TextEditor.prototype._create = function (container, options, json) {
|
||||||
//buttonCompact.className = 'jsoneditor-button';
|
//buttonCompact.className = 'jsoneditor-button';
|
||||||
this.menu.appendChild(buttonCompact);
|
this.menu.appendChild(buttonCompact);
|
||||||
buttonCompact.onclick = function () {
|
buttonCompact.onclick = function () {
|
||||||
me.compact();
|
try {
|
||||||
|
me.compact();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
me._onError(err);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.content = document.createElement('div');
|
this.content = document.createElement('div');
|
||||||
|
@ -1166,39 +1208,41 @@ TextEditor.prototype._delete = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is executed on error.
|
* Throw an error. If an error callback is configured in options.error, this
|
||||||
* It can be overwritten for each instance of the TextEditor
|
* callback will be invoked. Else, a regular error is thrown.
|
||||||
* @param {String} err
|
* @param {Error} err
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
// TODO: replace with an options.error
|
TextEditor.prototype._onError = function(err) {
|
||||||
TextEditor.prototype.onError = function(err) {
|
// TODO: onError is deprecated since version 2.2.0. cleanup some day
|
||||||
// action should be implemented for the instance
|
if (typeof this.onError === 'function') {
|
||||||
|
util.log('WARNING: JSONEditor.onError is deprecated. ' +
|
||||||
|
'Use options.error instead.');
|
||||||
|
this.onError(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof this.options.error === 'function') {
|
||||||
|
this.options.error(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compact the code in the formatter
|
* Compact the code in the formatter
|
||||||
*/
|
*/
|
||||||
TextEditor.prototype.compact = function () {
|
TextEditor.prototype.compact = function () {
|
||||||
try {
|
var json = util.parse(this.getText());
|
||||||
var json = util.parse(this.getText());
|
this.setText(JSON.stringify(json));
|
||||||
this.setText(JSON.stringify(json));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
this.onError(err);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format the code in the formatter
|
* Format the code in the formatter
|
||||||
*/
|
*/
|
||||||
TextEditor.prototype.format = function () {
|
TextEditor.prototype.format = function () {
|
||||||
try {
|
var json = util.parse(this.getText());
|
||||||
var json = util.parse(this.getText());
|
this.setText(JSON.stringify(json, null, this.indentation));
|
||||||
this.setText(JSON.stringify(json, null, this.indentation));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
this.onError(err);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1409,7 +1453,7 @@ Node.prototype.setValue = function(value, type) {
|
||||||
if (typeof(value) == 'string') {
|
if (typeof(value) == 'string') {
|
||||||
var escValue = JSON.stringify(value);
|
var escValue = JSON.stringify(value);
|
||||||
this.value = escValue.substring(1, escValue.length - 1);
|
this.value = escValue.substring(1, escValue.length - 1);
|
||||||
console.log('check', value, this.value);
|
util.log('check', value, this.value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
@ -3179,7 +3223,7 @@ Node.prototype.onKeyDown = function (event) {
|
||||||
var handled = false;
|
var handled = false;
|
||||||
var prevNode, nextNode, nextDom, nextDom2;
|
var prevNode, nextNode, nextDom, nextDom2;
|
||||||
|
|
||||||
// console.log(ctrlKey, keynum, event.charCode); // TODO: cleanup
|
// util.log(ctrlKey, keynum, event.charCode); // TODO: cleanup
|
||||||
if (keynum == 13) { // Enter
|
if (keynum == 13) { // Enter
|
||||||
if (target == this.dom.value) {
|
if (target == this.dom.value) {
|
||||||
if (!this.editor.mode.edit || event.ctrlKey) {
|
if (!this.editor.mode.edit || event.ctrlKey) {
|
||||||
|
@ -4979,7 +5023,7 @@ History.prototype.undo = function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log('Error: unknown action "' + obj.action + '"');
|
util.log('Error: unknown action "' + obj.action + '"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.index--;
|
this.index--;
|
||||||
|
@ -5006,7 +5050,7 @@ History.prototype.redo = function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log('Error: unknown action "' + obj.action + '"');
|
util.log('Error: unknown action "' + obj.action + '"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5415,13 +5459,6 @@ if (!Array.prototype.forEach) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Old browsers do not have a console, so create a fake one in that case.
|
|
||||||
if (typeof console === 'undefined') {
|
|
||||||
console = {
|
|
||||||
log: function () {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse JSON using the parser built-in in the browser.
|
* Parse JSON using the parser built-in in the browser.
|
||||||
* On exception, the jsonString is validated and a detailed error is thrown.
|
* On exception, the jsonString is validated and a detailed error is thrown.
|
||||||
|
@ -5432,9 +5469,9 @@ util.parse = function (jsonString) {
|
||||||
return JSON.parse(jsonString);
|
return JSON.parse(jsonString);
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
// get a detailed error message using validate
|
// try to throw a more detailed error message using validate
|
||||||
var message = util.validate(jsonString) || err;
|
util.validate(jsonString);
|
||||||
throw new Error(message);
|
throw err;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5443,33 +5480,15 @@ util.parse = function (jsonString) {
|
||||||
* This method uses JSONLint to validate the String. If JSONLint is not
|
* This method uses JSONLint to validate the String. If JSONLint is not
|
||||||
* available, the built-in JSON parser of the browser is used.
|
* available, the built-in JSON parser of the browser is used.
|
||||||
* @param {String} jsonString String with an (invalid) JSON object
|
* @param {String} jsonString String with an (invalid) JSON object
|
||||||
* @return {String | undefined} Returns undefined when the string is valid JSON,
|
* @throws Error
|
||||||
* returns a string with an error message when
|
|
||||||
* the data is invalid. This message is HTML
|
|
||||||
* formatted.
|
|
||||||
*/
|
*/
|
||||||
util.validate = function (jsonString) {
|
util.validate = function (jsonString) {
|
||||||
var message = undefined;
|
if (typeof(jsonlint) != 'undefined') {
|
||||||
|
jsonlint.parse(jsonString);
|
||||||
try {
|
|
||||||
if (typeof(jsonlint) != 'undefined') {
|
|
||||||
jsonlint.parse(jsonString);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
JSON.parse(jsonString);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (err) {
|
else {
|
||||||
message = '<pre class="error">' + err.toString() + '</pre>';
|
JSON.parse(jsonString);
|
||||||
if (typeof(jsonlint) != 'undefined') {
|
|
||||||
message +=
|
|
||||||
'<a class="error" href="http://zaach.github.com/jsonlint/" target="_blank">' +
|
|
||||||
'validated by jsonlint' +
|
|
||||||
'</a>';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return message;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5501,6 +5520,16 @@ util.clear = function (a) {
|
||||||
return a;
|
return a;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output text to the console, if console is available
|
||||||
|
* @param {...*} args
|
||||||
|
*/
|
||||||
|
util.log = function(args) {
|
||||||
|
if (console && typeof console.log === 'function') {
|
||||||
|
console.log.apply(console, arguments);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether a text contains a url (matches when a string starts
|
* Test whether a text contains a url (matches when a string starts
|
||||||
* with 'http://*' or 'https://*' and has no whitespace characters)
|
* with 'http://*' or 'https://*' and has no whitespace characters)
|
||||||
|
|
|
@ -181,7 +181,7 @@ History.prototype.undo = function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log('Error: unknown action "' + obj.action + '"');
|
util.log('Error: unknown action "' + obj.action + '"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.index--;
|
this.index--;
|
||||||
|
@ -208,7 +208,7 @@ History.prototype.redo = function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log('Error: unknown action "' + obj.action + '"');
|
util.log('Error: unknown action "' + obj.action + '"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,38 +139,68 @@ JSONEditor.prototype.setMode = function (mode) {
|
||||||
options.mode = mode;
|
options.mode = mode;
|
||||||
var config = JSONEditor.modes[mode];
|
var config = JSONEditor.modes[mode];
|
||||||
if (config) {
|
if (config) {
|
||||||
if (config.data == 'text') {
|
try {
|
||||||
// text
|
if (config.data == 'text') {
|
||||||
name = this.getName();
|
// text
|
||||||
data = this.getText();
|
name = this.getName();
|
||||||
|
data = this.getText();
|
||||||
|
|
||||||
this._delete();
|
this._delete();
|
||||||
util.clear(this);
|
util.clear(this);
|
||||||
util.extend(this, config.editor.prototype);
|
util.extend(this, config.editor.prototype);
|
||||||
this._create(container, options);
|
this._create(container, options);
|
||||||
|
|
||||||
this.setName(name);
|
this.setName(name);
|
||||||
this.setText(data);
|
this.setText(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// json
|
||||||
|
name = this.getName();
|
||||||
|
data = this.get();
|
||||||
|
|
||||||
|
this._delete();
|
||||||
|
util.clear(this);
|
||||||
|
util.extend(this, config.editor.prototype);
|
||||||
|
this._create(container, options);
|
||||||
|
|
||||||
|
this.setName(name);
|
||||||
|
this.set(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof config.load === 'function') {
|
||||||
|
try {
|
||||||
|
config.load.call(this);
|
||||||
|
}
|
||||||
|
catch (err) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
catch (err) {
|
||||||
// json
|
this._onError(err);
|
||||||
name = this.getName();
|
|
||||||
data = this.get();
|
|
||||||
|
|
||||||
this._delete();
|
|
||||||
util.clear(this);
|
|
||||||
util.extend(this, config.editor.prototype);
|
|
||||||
this._create(container, options);
|
|
||||||
|
|
||||||
this.setName(name);
|
|
||||||
this.set(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof config.load === 'function') {
|
|
||||||
config.load.call(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new Error('Unknown mode "' + options.mode + '"');
|
throw new Error('Unknown mode "' + options.mode + '"');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw an error. If an error callback is configured in options.error, this
|
||||||
|
* callback will be invoked. Else, a regular error is thrown.
|
||||||
|
* @param {Error} err
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
JSONEditor.prototype._onError = function(err) {
|
||||||
|
// TODO: onError is deprecated since version 2.2.0. cleanup some day
|
||||||
|
if (typeof this.onError === 'function') {
|
||||||
|
util.log('WARNING: JSONEditor.onError is deprecated. ' +
|
||||||
|
'Use options.error instead.');
|
||||||
|
this.onError(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof this.options.error === 'function') {
|
||||||
|
this.options.error(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -129,7 +129,7 @@ Node.prototype.setValue = function(value, type) {
|
||||||
if (typeof(value) == 'string') {
|
if (typeof(value) == 'string') {
|
||||||
var escValue = JSON.stringify(value);
|
var escValue = JSON.stringify(value);
|
||||||
this.value = escValue.substring(1, escValue.length - 1);
|
this.value = escValue.substring(1, escValue.length - 1);
|
||||||
console.log('check', value, this.value);
|
util.log('check', value, this.value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
@ -1899,7 +1899,7 @@ Node.prototype.onKeyDown = function (event) {
|
||||||
var handled = false;
|
var handled = false;
|
||||||
var prevNode, nextNode, nextDom, nextDom2;
|
var prevNode, nextNode, nextDom, nextDom2;
|
||||||
|
|
||||||
// console.log(ctrlKey, keynum, event.charCode); // TODO: cleanup
|
// util.log(ctrlKey, keynum, event.charCode); // TODO: cleanup
|
||||||
if (keynum == 13) { // Enter
|
if (keynum == 13) { // Enter
|
||||||
if (target == this.dom.value) {
|
if (target == this.dom.value) {
|
||||||
if (!this.editor.mode.edit || event.ctrlKey) {
|
if (!this.editor.mode.edit || event.ctrlKey) {
|
||||||
|
|
|
@ -41,17 +41,18 @@ TextEditor.prototype._create = function (container, options, json) {
|
||||||
if (options.indentation) {
|
if (options.indentation) {
|
||||||
this.indentation = Number(options.indentation);
|
this.indentation = Number(options.indentation);
|
||||||
}
|
}
|
||||||
|
this.options = options;
|
||||||
this.mode = (options.mode == 'code') ? 'code' : 'text';
|
this.mode = (options.mode == 'code') ? 'code' : 'text';
|
||||||
if (this.mode == 'code') {
|
if (this.mode == 'code') {
|
||||||
// verify whether Ace editor is available and supported
|
// verify whether Ace editor is available and supported
|
||||||
if (typeof ace === 'undefined') {
|
if (typeof ace === 'undefined') {
|
||||||
this.mode = 'text';
|
this.mode = 'text';
|
||||||
console.log('WARNING: Cannot load code editor, Ace library not loaded. ' +
|
util.log('WARNING: Cannot load code editor, Ace library not loaded. ' +
|
||||||
'Falling back to plain text editor');
|
'Falling back to plain text editor');
|
||||||
}
|
}
|
||||||
if (util.getInternetExplorerVersion() == 8) {
|
if (util.getInternetExplorerVersion() == 8) {
|
||||||
this.mode = 'text';
|
this.mode = 'text';
|
||||||
console.log('WARNING: Cannot load code editor, Ace is not supported on IE8. ' +
|
util.log('WARNING: Cannot load code editor, Ace is not supported on IE8. ' +
|
||||||
'Falling back to plain text editor');
|
'Falling back to plain text editor');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +86,12 @@ TextEditor.prototype._create = function (container, options, json) {
|
||||||
//buttonFormat.className = 'jsoneditor-button';
|
//buttonFormat.className = 'jsoneditor-button';
|
||||||
this.menu.appendChild(buttonFormat);
|
this.menu.appendChild(buttonFormat);
|
||||||
buttonFormat.onclick = function () {
|
buttonFormat.onclick = function () {
|
||||||
me.format();
|
try {
|
||||||
|
me.format();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
me._onError(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// create compact button
|
// create compact button
|
||||||
|
@ -96,7 +102,13 @@ TextEditor.prototype._create = function (container, options, json) {
|
||||||
//buttonCompact.className = 'jsoneditor-button';
|
//buttonCompact.className = 'jsoneditor-button';
|
||||||
this.menu.appendChild(buttonCompact);
|
this.menu.appendChild(buttonCompact);
|
||||||
buttonCompact.onclick = function () {
|
buttonCompact.onclick = function () {
|
||||||
me.compact();
|
try {
|
||||||
|
me.compact();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
me._onError(err);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.content = document.createElement('div');
|
this.content = document.createElement('div');
|
||||||
|
@ -184,39 +196,41 @@ TextEditor.prototype._delete = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is executed on error.
|
* Throw an error. If an error callback is configured in options.error, this
|
||||||
* It can be overwritten for each instance of the TextEditor
|
* callback will be invoked. Else, a regular error is thrown.
|
||||||
* @param {String} err
|
* @param {Error} err
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
// TODO: replace with an options.error
|
TextEditor.prototype._onError = function(err) {
|
||||||
TextEditor.prototype.onError = function(err) {
|
// TODO: onError is deprecated since version 2.2.0. cleanup some day
|
||||||
// action should be implemented for the instance
|
if (typeof this.onError === 'function') {
|
||||||
|
util.log('WARNING: JSONEditor.onError is deprecated. ' +
|
||||||
|
'Use options.error instead.');
|
||||||
|
this.onError(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof this.options.error === 'function') {
|
||||||
|
this.options.error(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compact the code in the formatter
|
* Compact the code in the formatter
|
||||||
*/
|
*/
|
||||||
TextEditor.prototype.compact = function () {
|
TextEditor.prototype.compact = function () {
|
||||||
try {
|
var json = util.parse(this.getText());
|
||||||
var json = util.parse(this.getText());
|
this.setText(JSON.stringify(json));
|
||||||
this.setText(JSON.stringify(json));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
this.onError(err);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format the code in the formatter
|
* Format the code in the formatter
|
||||||
*/
|
*/
|
||||||
TextEditor.prototype.format = function () {
|
TextEditor.prototype.format = function () {
|
||||||
try {
|
var json = util.parse(this.getText());
|
||||||
var json = util.parse(this.getText());
|
this.setText(JSON.stringify(json, null, this.indentation));
|
||||||
this.setText(JSON.stringify(json, null, this.indentation));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
this.onError(err);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -92,22 +92,22 @@ TreeEditor.prototype._setOptions = function (options) {
|
||||||
if (options['enableSearch']) {
|
if (options['enableSearch']) {
|
||||||
// deprecated since version 1.6.0, 2012-11-03
|
// deprecated since version 1.6.0, 2012-11-03
|
||||||
this.options.search = options['enableSearch'];
|
this.options.search = options['enableSearch'];
|
||||||
console.log('WARNING: Option "enableSearch" is deprecated. Use "search" instead.');
|
util.log('WARNING: Option "enableSearch" is deprecated. Use "search" instead.');
|
||||||
}
|
}
|
||||||
if (options['enableHistory']) {
|
if (options['enableHistory']) {
|
||||||
// deprecated since version 1.6.0, 2012-11-03
|
// deprecated since version 1.6.0, 2012-11-03
|
||||||
this.options.history = options['enableHistory'];
|
this.options.history = options['enableHistory'];
|
||||||
console.log('WARNING: Option "enableHistory" is deprecated. Use "history" instead.');
|
util.log('WARNING: Option "enableHistory" is deprecated. Use "history" instead.');
|
||||||
}
|
}
|
||||||
if (options['mode'] == 'editor') {
|
if (options['mode'] == 'editor') {
|
||||||
// deprecated since version 2.2.0, 2013-04-30
|
// deprecated since version 2.2.0, 2013-04-30
|
||||||
this.options.mode = 'tree';
|
this.options.mode = 'tree';
|
||||||
console.log('WARNING: Mode "editor" is deprecated. Use "tree" instead.');
|
util.log('WARNING: Mode "editor" is deprecated. Use "tree" instead.');
|
||||||
}
|
}
|
||||||
if (options['mode'] == 'viewer') {
|
if (options['mode'] == 'viewer') {
|
||||||
// deprecated since version 2.2.0, 2013-04-30
|
// deprecated since version 2.2.0, 2013-04-30
|
||||||
this.options.mode = 'view';
|
this.options.mode = 'view';
|
||||||
console.log('WARNING: Mode "viewer" is deprecated. Use "view" instead.');
|
util.log('WARNING: Mode "viewer" is deprecated. Use "view" instead.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ TreeEditor.prototype.set = function (json, name) {
|
||||||
// adjust field name for root node
|
// adjust field name for root node
|
||||||
if (name) {
|
if (name) {
|
||||||
// TODO: deprecated since version 2.2.0. Cleanup some day.
|
// TODO: deprecated since version 2.2.0. Cleanup some day.
|
||||||
console.log('Warning: second parameter "name" is deprecated. ' +
|
util.log('Warning: second parameter "name" is deprecated. ' +
|
||||||
'Use setName(name) instead.');
|
'Use setName(name) instead.');
|
||||||
this.options.name = name;
|
this.options.name = name;
|
||||||
}
|
}
|
||||||
|
@ -317,7 +317,7 @@ TreeEditor.prototype._onAction = function (action, params) {
|
||||||
this.options.change();
|
this.options.change();
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.log('Error in change callback: ', err);
|
util.log('Error in change callback: ', err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,13 +26,6 @@ if (!Array.prototype.forEach) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Old browsers do not have a console, so create a fake one in that case.
|
|
||||||
if (typeof console === 'undefined') {
|
|
||||||
console = {
|
|
||||||
log: function () {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse JSON using the parser built-in in the browser.
|
* Parse JSON using the parser built-in in the browser.
|
||||||
* On exception, the jsonString is validated and a detailed error is thrown.
|
* On exception, the jsonString is validated and a detailed error is thrown.
|
||||||
|
@ -43,9 +36,9 @@ util.parse = function (jsonString) {
|
||||||
return JSON.parse(jsonString);
|
return JSON.parse(jsonString);
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
// get a detailed error message using validate
|
// try to throw a more detailed error message using validate
|
||||||
var message = util.validate(jsonString) || err;
|
util.validate(jsonString);
|
||||||
throw new Error(message);
|
throw err;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,33 +47,15 @@ util.parse = function (jsonString) {
|
||||||
* This method uses JSONLint to validate the String. If JSONLint is not
|
* This method uses JSONLint to validate the String. If JSONLint is not
|
||||||
* available, the built-in JSON parser of the browser is used.
|
* available, the built-in JSON parser of the browser is used.
|
||||||
* @param {String} jsonString String with an (invalid) JSON object
|
* @param {String} jsonString String with an (invalid) JSON object
|
||||||
* @return {String | undefined} Returns undefined when the string is valid JSON,
|
* @throws Error
|
||||||
* returns a string with an error message when
|
|
||||||
* the data is invalid. This message is HTML
|
|
||||||
* formatted.
|
|
||||||
*/
|
*/
|
||||||
util.validate = function (jsonString) {
|
util.validate = function (jsonString) {
|
||||||
var message = undefined;
|
if (typeof(jsonlint) != 'undefined') {
|
||||||
|
jsonlint.parse(jsonString);
|
||||||
try {
|
|
||||||
if (typeof(jsonlint) != 'undefined') {
|
|
||||||
jsonlint.parse(jsonString);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
JSON.parse(jsonString);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (err) {
|
else {
|
||||||
message = '<pre class="error">' + err.toString() + '</pre>';
|
JSON.parse(jsonString);
|
||||||
if (typeof(jsonlint) != 'undefined') {
|
|
||||||
message +=
|
|
||||||
'<a class="error" href="http://zaach.github.com/jsonlint/" target="_blank">' +
|
|
||||||
'validated by jsonlint' +
|
|
||||||
'</a>';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return message;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -112,6 +87,16 @@ util.clear = function (a) {
|
||||||
return a;
|
return a;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output text to the console, if console is available
|
||||||
|
* @param {...*} args
|
||||||
|
*/
|
||||||
|
util.log = function(args) {
|
||||||
|
if (console && typeof console.log === 'function') {
|
||||||
|
console.log.apply(console, arguments);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether a text contains a url (matches when a string starts
|
* Test whether a text contains a url (matches when a string starts
|
||||||
* with 'http://*' or 'https://*' and has no whitespace characters)
|
* with 'http://*' or 'https://*' and has no whitespace characters)
|
||||||
|
|
Loading…
Reference in New Issue