commit
e2192df650
10
HISTORY.md
10
HISTORY.md
|
@ -3,6 +3,16 @@
|
|||
https://github.com/josdejong/jsoneditor
|
||||
|
||||
|
||||
## 2014-07-28, version 3.1.0
|
||||
|
||||
- JSONEditor now accepts JavaScript objects as input, and can turn them into
|
||||
valid JSON. For example `{a:2,b:'str'}` can be turned into `{"a":2,"b":"str"}`.
|
||||
- Implemented an option `editable`, a callback function, which allows to set
|
||||
individual nodes (their field and/or value) editable or read-only.
|
||||
- Fixed: shortcut keys to manipulate the nodes are now disabled when mode
|
||||
is `form` or `view`.
|
||||
|
||||
|
||||
## 2014-05-31, version 3.0.0
|
||||
|
||||
- Large code reorganization.
|
||||
|
|
15
README.md
15
README.md
|
@ -1,9 +1,10 @@
|
|||
# JSON Editor
|
||||
|
||||
https://github.com/josdejong/jsoneditor
|
||||
|
||||
http://jsoneditoronline.org/
|
||||
|
||||
Website: http://jsoneditoronline.org/
|
||||
Github: https://github.com/josdejong/jsoneditor
|
||||
|
||||
|
||||
### Description
|
||||
|
||||
|
@ -36,20 +37,12 @@ Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 9+.
|
|||
- Format and compact JSON.
|
||||
|
||||
|
||||
### Screenshots
|
||||
|
||||
#### Tree editor
|
||||
<img alt="json editor" src="https://raw.github.com/josdejong/jsoneditor/master/misc/jsoneditor.png">
|
||||
|
||||
#### Code editor
|
||||
<img alt="code editor" src="https://raw.github.com/josdejong/jsoneditor/master/misc/codeeditor.png">
|
||||
|
||||
|
||||
### Documentation
|
||||
|
||||
- Documentation:
|
||||
- [API](https://github.com/josdejong/jsoneditor/tree/master/docs/api.md)
|
||||
- [Usage](https://github.com/josdejong/jsoneditor/tree/master/docs/usage.md)
|
||||
- [Shortcut keys](https://github.com/josdejong/jsoneditor/tree/master/docs/shortcut_keys.md)
|
||||
- [Examples](https://github.com/josdejong/jsoneditor/tree/master/examples)
|
||||
- [Source](https://github.com/josdejong/jsoneditor)
|
||||
- [History](https://github.com/josdejong/jsoneditor/blob/master/HISTORY.md)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "jsoneditor",
|
||||
"version": "3.0.0",
|
||||
"version": "3.1.0",
|
||||
"description": "A web-based tool to view, edit and format JSON",
|
||||
"tags": [
|
||||
"json",
|
||||
|
|
65
docs/api.md
65
docs/api.md
|
@ -11,41 +11,29 @@ Constructs a new JSONEditor.
|
|||
*Parameters:*
|
||||
|
||||
- `{Element} container`
|
||||
An HTML DIV element. The JSONEditor will be created inside this container
|
||||
element.
|
||||
An HTML DIV element. The JSONEditor will be created inside this container element.
|
||||
- `{Object} options`
|
||||
Optional object with options. Available options:
|
||||
|
||||
- `{function} change`.
|
||||
Set a callback method triggered when the contents of the JSONEditor change.
|
||||
Called without parameters.
|
||||
- `{function} error`.
|
||||
Set a callback method triggered when an error occurs.
|
||||
Invoked with the error as first argument. The callback is only invoked
|
||||
- `{function} change`
|
||||
Set a callback method triggered when the contents of the JSONEditor change. Called without parameters.
|
||||
- `{function} editable`
|
||||
Set a callback method to determine whether individual nodes are editable or read-only. Only applicable when option `mode` is `tree`. The callback is invoked as `editable(node)`, where `node` is an object `{field: string, value: string, path: string[]}`. The function must either return a boolean value to set both the nodes field and value editable or read-only, or return an object `{field: boolean, value: boolean}`.
|
||||
- `{function} error`
|
||||
Set a callback method triggered when an error occurs. Invoked with the error as first argument. The callback is only invoked
|
||||
for errors triggered by a users action.
|
||||
- `{boolean} history`.
|
||||
Enables history, adds a button Undo and Redo to the menu of the JSONEditor.
|
||||
True by default. Only applicable when `mode` is 'tree' or 'form'.
|
||||
- `{String} mode`.
|
||||
Set the editor mode. Available values: 'tree' (default), 'view', 'form',
|
||||
'code', 'text'. In 'view' mode, the data and datastructure is read-only.
|
||||
In 'form' mode, only the value can be changed, the datastructure is read-only.
|
||||
Mode 'code' requires the Ace editor to be loaded on the page.
|
||||
Mode 'text' shows the data as plain text.
|
||||
- `{String[]} modes`.
|
||||
Create a box in the editor menu where the user can switch between the specified
|
||||
modes. Available values: see option `mode`.
|
||||
- `{String} name`.
|
||||
Initial field name for the root node, is undefined by default.
|
||||
Can also be set using `JSONEditor.setName(name)`.
|
||||
Only applicable when `mode` is 'tree', 'view', or 'form'.
|
||||
- `{boolean} search`.
|
||||
Enables a search box in the upper right corner of the JSONEditor.
|
||||
True by default.
|
||||
Only applicable when `mode` is 'tree', 'view', or 'form'.
|
||||
- `{Number} indentation`.
|
||||
Number of indentation spaces. 2 by default.
|
||||
Only applicable when `mode` is 'code' or 'text'.
|
||||
- `{boolean} history`
|
||||
Enables history, adds a button Undo and Redo to the menu of the JSONEditor. True by default. Only applicable when `mode` is 'tree' or 'form'.
|
||||
- `{String} mode`
|
||||
Set the editor mode. Available values: 'tree' (default), 'view', 'form', 'code', 'text'. In 'view' mode, the data and datastructure is read-only. In 'form' mode, only the value can be changed, the datastructure is read-only. Mode 'code' requires the Ace editor to be loaded on the page. Mode 'text' shows the data as plain text.
|
||||
- `{String[]} modes`
|
||||
Create a box in the editor menu where the user can switch between the specified modes. Available values: see option `mode`.
|
||||
- `{String} name`
|
||||
Initial field name for the root node, is undefined by default. Can also be set using `JSONEditor.setName(name)`. Only applicable when `mode` is 'tree', 'view', or 'form'.
|
||||
- `{boolean} search`
|
||||
Enables a search box in the upper right corner of the JSONEditor. True by default. Only applicable when `mode` is 'tree', 'view', or 'form'.
|
||||
- `{Number} indentation`
|
||||
Number of indentation spaces. 2 by default. Only applicable when `mode` is 'code' or 'text'.
|
||||
|
||||
- `{JSON} json`
|
||||
Initial JSON data to be loaded into the JSONEditor. Alternatively, the method `JSONEditor.set(json)` can be used to load JSON data into the editor.
|
||||
|
@ -98,14 +86,18 @@ Set a field name for the root node.
|
|||
Set text data in the formatter.
|
||||
|
||||
*Parameters:*
|
||||
- `{String} jsonString` Contents of the JSONformatter as string.
|
||||
|
||||
- `{String} jsonString`
|
||||
Contents of the JSONformatter as string.
|
||||
|
||||
#### `JSONEditor.get()`
|
||||
|
||||
Get JSON data.
|
||||
|
||||
*Returns:*
|
||||
- `{JSON} json` JSON data from the JSONEditor.
|
||||
|
||||
- `{JSON} json`
|
||||
JSON data from the JSONEditor.
|
||||
|
||||
#### `JSONEditor.getName()`
|
||||
|
||||
|
@ -121,7 +113,9 @@ Retrieve the current field name of the root node.
|
|||
Get JSON data as string.
|
||||
|
||||
*Returns:*
|
||||
- `{String} jsonString` Contents of the JSONformatter as string.
|
||||
|
||||
- `{String} jsonString`
|
||||
Contents of the JSONformatter as string.
|
||||
|
||||
|
||||
### Examples
|
||||
|
@ -171,8 +165,7 @@ var json = editor.get(json);
|
|||
|
||||
## JSON parsing and stringification
|
||||
|
||||
In general to parse or stringify JSON data, the browsers built in JSON parser can be used.
|
||||
To create a formatted string from a JSON object, use:
|
||||
In general to parse or stringify JSON data, the browsers built in JSON parser can be used. To create a formatted string from a JSON object, use:
|
||||
|
||||
```js
|
||||
var formattedString = JSON.stringify(json, null, 2);
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Shortcut keys
|
||||
|
||||
Key | Description
|
||||
----------------------- | ------------------------------------------------
|
||||
Alt+Arrows | Move the caret up/down/left/right between fields
|
||||
Shift+Alt+Arrows | Move field up/down/left/right
|
||||
Ctrl+D | Duplicate field
|
||||
Ctrl+Del | Remove field
|
||||
Ctrl+Enter | Open link when on a field containing an url
|
||||
Ctrl+Ins | Insert a new field with type auto
|
||||
Ctrl+Shift+Ins | Append a new field with type auto
|
||||
Ctrl+E | Expand or collapse field
|
||||
Alt+End | Move the caret to the last field
|
||||
Ctrl+F | Find
|
||||
F3, Ctrl+G | Find next
|
||||
Shift+F3, Ctrl+Shift+G | Find previous
|
||||
Alt+Home | Move the caret to the first field
|
||||
Ctrl+M | Show actions menu
|
||||
Ctrl+Z | Undo last action
|
||||
Ctrl+Shift+Z | Redo
|
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>JSONEditor | Load and save</title>
|
||||
<link rel="stylesheet" type="text/css" href="../jsoneditor.css">
|
||||
<script src="../jsoneditor.js"></script>
|
||||
|
||||
<script src="http://bgrins.github.io/filereader.js/filereader.js"></script>
|
||||
<script src="http://eligrey.com/demos/FileSaver.js/FileSaver.js"></script>
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
font: 11pt sans-serif;
|
||||
}
|
||||
#jsoneditor {
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Load and save JSON documents</h1>
|
||||
<p>
|
||||
This examples uses HTML5 to load/save local files.
|
||||
Powered by <a href="http://bgrins.github.io/filereader.js/">FileReader.js</a> and
|
||||
<a href="https://github.com/eligrey/FileSaver.js">FileSaver.js</a>.<br>
|
||||
Only supported on modern browsers (Chrome, FireFox, IE10+, Safari 6.1+, Opera 15+).
|
||||
</p>
|
||||
<p>
|
||||
Load a JSON document: <input type="file" id="loadDocument" value="Load"/>
|
||||
</p>
|
||||
<p>
|
||||
Save a JSON document: <input type="button" id="saveDocument" value="Save" />
|
||||
</p>
|
||||
|
||||
<div id="jsoneditor"></div>
|
||||
|
||||
<script type="text/javascript" >
|
||||
// create the editor
|
||||
var editor = new JSONEditor(document.getElementById('jsoneditor'));
|
||||
|
||||
// Load a JSON document
|
||||
FileReaderJS.setupInput(document.getElementById('loadDocument'), {
|
||||
readAsDefault: 'Text',
|
||||
on: {
|
||||
load: function (event, file) {
|
||||
editor.setText(event.target.result);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Save a JSON document
|
||||
document.getElementById('saveDocument').onclick = function () {
|
||||
var blob = new Blob([editor.getText()], {type: 'application/json;charset=utf-8'});
|
||||
saveAs(blob, 'document.json');
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>JSONEditor | Basic usage</title>
|
||||
<link rel="stylesheet" type="text/css" href="../jsoneditor.css">
|
||||
<script type="text/javascript" src="../jsoneditor.js"></script>
|
||||
<style type="text/css">
|
||||
#jsoneditor {
|
||||
width: 500px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
In this example:
|
||||
</p>
|
||||
<ul>
|
||||
<li>the field <code>_id</code> and its value are read-only</li>
|
||||
<li>the field <code>name</code> is read-only but has an editable value</li>
|
||||
<li>the field <code>age</code> and its value are editable</li>
|
||||
</ul>
|
||||
|
||||
<div id="jsoneditor"></div>
|
||||
|
||||
<script type="text/javascript" >
|
||||
var container = document.getElementById('jsoneditor');
|
||||
|
||||
var options = {
|
||||
editable: function (node) {
|
||||
// node is an object like:
|
||||
// {
|
||||
// field: 'FIELD',
|
||||
// value: 'VALUE',
|
||||
// path: ['PATH', 'TO', 'NODE']
|
||||
// }
|
||||
switch (node.field) {
|
||||
case '_id':
|
||||
return false;
|
||||
|
||||
case 'name':
|
||||
return {
|
||||
field: false,
|
||||
value: true
|
||||
};
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var json = {
|
||||
_id: 123456,
|
||||
name: 'John',
|
||||
age: 32
|
||||
};
|
||||
|
||||
var editor = new JSONEditor(container, options, json);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
389
jsoneditor.js
389
jsoneditor.js
|
@ -23,8 +23,8 @@
|
|||
* Copyright (c) 2011-2014 Jos de Jong, http://jsoneditoronline.org
|
||||
*
|
||||
* @author Jos de Jong, <wjosdejong@gmail.com>
|
||||
* @version 3.0.0
|
||||
* @date 2014-05-31
|
||||
* @version 3.1.0
|
||||
* @date 2014-07-28
|
||||
*/
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
|
@ -37,12 +37,12 @@
|
|||
root["JSONEditor"] = factory();
|
||||
})(this, function() {
|
||||
return /******/ (function(modules) { // webpackBootstrap
|
||||
/******/
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
@ -74,7 +74,6 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
|
@ -381,7 +380,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
|
||||
this._setOptions(options);
|
||||
|
||||
if (this.options.history && !this.mode.view) {
|
||||
if (this.options.history && this.options.mode !== 'view') {
|
||||
this.history = new History(this);
|
||||
}
|
||||
|
||||
|
@ -420,13 +419,6 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// interpret the mode options
|
||||
this.mode = {
|
||||
edit: (this.options.mode != 'view' && this.options.mode != 'form'),
|
||||
view: (this.options.mode == 'view'),
|
||||
form: (this.options.mode == 'form')
|
||||
};
|
||||
};
|
||||
|
||||
// node currently being edited
|
||||
|
@ -1032,7 +1024,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
// width, and the edit columns do have a fixed width
|
||||
var col;
|
||||
this.colgroupContent = document.createElement('colgroup');
|
||||
if (this.mode.edit) {
|
||||
if (this.options.mode === 'tree') {
|
||||
col = document.createElement('col');
|
||||
col.width = "24px";
|
||||
this.colgroupContent.appendChild(col);
|
||||
|
@ -1386,10 +1378,20 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
return JSON.parse(jsonString);
|
||||
}
|
||||
catch (err) {
|
||||
// try to load as JavaScript instead of JSON (like "{a: 2}" instead of "{"a": 2}"
|
||||
try {
|
||||
return eval('(' + jsonString + ')');
|
||||
}
|
||||
catch(err2) {
|
||||
// ok no luck loading as JavaScript
|
||||
|
||||
// try to throw a more detailed error message using validate
|
||||
util.validate(jsonString);
|
||||
|
||||
// rethrow the original error
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2513,6 +2515,56 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the field and/or value of this node are editable
|
||||
* @private
|
||||
*/
|
||||
Node.prototype._updateEditability = function () {
|
||||
this.editable = {
|
||||
field: true,
|
||||
value: true
|
||||
};
|
||||
|
||||
if (this.editor) {
|
||||
this.editable.field = this.editor.options.mode === 'tree';
|
||||
this.editable.value = this.editor.options.mode !== 'view';
|
||||
|
||||
if (this.editor.options.mode === 'tree' && (typeof this.editor.options.editable === 'function')) {
|
||||
var editable = this.editor.options.editable({
|
||||
field: this.field,
|
||||
value: this.value,
|
||||
path: this.path()
|
||||
});
|
||||
|
||||
if (typeof editable === 'boolean') {
|
||||
this.editable.field = editable;
|
||||
this.editable.value = editable;
|
||||
}
|
||||
else {
|
||||
if (typeof editable.field === 'boolean') this.editable.field = editable.field;
|
||||
if (typeof editable.value === 'boolean') this.editable.value = editable.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the path of this node
|
||||
* @return {String[]} Array containing the path to this node
|
||||
*/
|
||||
Node.prototype.path = function () {
|
||||
var node = this;
|
||||
var path = [];
|
||||
while (node) {
|
||||
var field = node.field || node.index;
|
||||
if (field !== undefined) {
|
||||
path.unshift(field);
|
||||
}
|
||||
node = node.parent;
|
||||
}
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set parent node
|
||||
* @param {Node} parent
|
||||
|
@ -2584,7 +2636,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
if (childValue !== undefined && !(childValue instanceof Function)) {
|
||||
// ignore undefined and functions
|
||||
child = new Node(this.editor, {
|
||||
'value': childValue
|
||||
value: childValue
|
||||
});
|
||||
this.appendChild(child);
|
||||
}
|
||||
|
@ -2600,8 +2652,8 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
if (childValue !== undefined && !(childValue instanceof Function)) {
|
||||
// ignore undefined and functions
|
||||
child = new Node(this.editor, {
|
||||
'field': childField,
|
||||
'value': childValue
|
||||
field: childField,
|
||||
value: childValue
|
||||
});
|
||||
this.appendChild(child);
|
||||
}
|
||||
|
@ -3463,7 +3515,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
var t = (this.type == 'auto') ? util.type(v) : this.type;
|
||||
var isUrl = (t == 'string' && util.isUrl(v));
|
||||
var color = '';
|
||||
if (isUrl && !this.editor.mode.edit) {
|
||||
if (isUrl && !this.editable.value) { // TODO: when to apply this?
|
||||
color = '';
|
||||
}
|
||||
else if (t == 'string') {
|
||||
|
@ -3510,7 +3562,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
domValue.title = this.type + ' containing ' + count + ' items';
|
||||
}
|
||||
else if (t == 'string' && util.isUrl(v)) {
|
||||
if (this.editor.mode.edit) {
|
||||
if (this.editable.value) {
|
||||
domValue.title = 'Ctrl+Click or Ctrl+Enter to open url in new window';
|
||||
}
|
||||
}
|
||||
|
@ -3634,13 +3686,16 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
return dom.tr;
|
||||
}
|
||||
|
||||
this._updateEditability();
|
||||
|
||||
// create row
|
||||
dom.tr = document.createElement('tr');
|
||||
dom.tr.node = this;
|
||||
|
||||
if (this.editor.mode.edit) {
|
||||
// create draggable area
|
||||
if (this.editor.options.mode === 'tree') { // note: we take here the global setting
|
||||
var tdDrag = document.createElement('td');
|
||||
if (this.editable.field) {
|
||||
// create draggable area
|
||||
if (this.parent) {
|
||||
var domDrag = document.createElement('button');
|
||||
dom.drag = domDrag;
|
||||
|
@ -3648,6 +3703,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
domDrag.title = 'Drag to move this field (Alt+Shift+Arrows)';
|
||||
tdDrag.appendChild(domDrag);
|
||||
}
|
||||
}
|
||||
dom.tr.appendChild(tdDrag);
|
||||
|
||||
// create context menu
|
||||
|
@ -3971,9 +4027,9 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
// update field
|
||||
var domField = this.dom.field;
|
||||
if (domField) {
|
||||
if (this.fieldEditable == true) {
|
||||
if (this.fieldEditable) {
|
||||
// parent is an object
|
||||
domField.contentEditable = this.editor.mode.edit;
|
||||
domField.contentEditable = this.editable.field;
|
||||
domField.spellcheck = false;
|
||||
domField.className = 'field';
|
||||
}
|
||||
|
@ -4089,7 +4145,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
domValue.innerHTML = '{...}';
|
||||
}
|
||||
else {
|
||||
if (!this.editor.mode.edit && util.isUrl(this.value)) {
|
||||
if (!this.editable.value && util.isUrl(this.value)) {
|
||||
// create a link in case of read-only editor and value containing an url
|
||||
domValue = document.createElement('a');
|
||||
domValue.className = 'value';
|
||||
|
@ -4098,9 +4154,9 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
domValue.innerHTML = this._escapeHTML(this.value);
|
||||
}
|
||||
else {
|
||||
// create and editable or read-only div
|
||||
// create an editable or read-only div
|
||||
domValue = document.createElement('div');
|
||||
domValue.contentEditable = !this.editor.mode.view;
|
||||
domValue.contentEditable = this.editable.value;
|
||||
domValue.spellcheck = false;
|
||||
domValue.className = 'value';
|
||||
domValue.innerHTML = this._escapeHTML(this.value);
|
||||
|
@ -4263,7 +4319,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
break;
|
||||
|
||||
case 'click':
|
||||
if (event.ctrlKey && this.editor.mode.edit) {
|
||||
if (event.ctrlKey || !this.editable.value) {
|
||||
if (util.isUrl(this.value)) {
|
||||
window.open(this.value, '_blank');
|
||||
}
|
||||
|
@ -4381,11 +4437,12 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
var altKey = event.altKey;
|
||||
var handled = false;
|
||||
var prevNode, nextNode, nextDom, nextDom2;
|
||||
var editable = this.editor.options.mode === 'tree';
|
||||
|
||||
// util.log(ctrlKey, keynum, event.charCode); // TODO: cleanup
|
||||
if (keynum == 13) { // Enter
|
||||
if (target == this.dom.value) {
|
||||
if (!this.editor.mode.edit || event.ctrlKey) {
|
||||
if (!this.editable.value || event.ctrlKey) {
|
||||
if (util.isUrl(this.value)) {
|
||||
window.open(this.value, '_blank');
|
||||
handled = true;
|
||||
|
@ -4403,7 +4460,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
}
|
||||
}
|
||||
else if (keynum == 68) { // D
|
||||
if (ctrlKey) { // Ctrl+D
|
||||
if (ctrlKey && editable) { // Ctrl+D
|
||||
this._onDuplicate();
|
||||
handled = true;
|
||||
}
|
||||
|
@ -4415,19 +4472,19 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
handled = true;
|
||||
}
|
||||
}
|
||||
else if (keynum == 77) { // M
|
||||
else if (keynum == 77 && editable) { // M
|
||||
if (ctrlKey) { // Ctrl+M
|
||||
this.showContextMenu(target);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
else if (keynum == 46) { // Del
|
||||
else if (keynum == 46 && editable) { // Del
|
||||
if (ctrlKey) { // Ctrl+Del
|
||||
this._onRemove();
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
else if (keynum == 45) { // Ins
|
||||
else if (keynum == 45 && editable) { // Ins
|
||||
if (ctrlKey && !shiftKey) { // Ctrl+Ins
|
||||
this._onInsertBefore();
|
||||
handled = true;
|
||||
|
@ -4466,7 +4523,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
}
|
||||
handled = true;
|
||||
}
|
||||
else if (altKey && shiftKey) { // Alt + Shift Arrow left
|
||||
else if (altKey && shiftKey && editable) { // Alt + Shift Arrow left
|
||||
if (this.expanded) {
|
||||
var appendDom = this.getAppend();
|
||||
nextDom = appendDom ? appendDom.nextSibling : undefined;
|
||||
|
@ -4539,7 +4596,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
}
|
||||
handled = true;
|
||||
}
|
||||
else if (altKey && shiftKey) { // Alt + Shift + Arrow Down
|
||||
else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Down
|
||||
// find the 2nd next node and move before that one
|
||||
if (this.expanded) {
|
||||
nextNode = this.append ? this.append._nextNode() : undefined;
|
||||
|
@ -4624,11 +4681,11 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
|
||||
// store history action
|
||||
this.editor._onAction('removeNode', {
|
||||
'node': this,
|
||||
'parent': this.parent,
|
||||
'index': index,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
node: this,
|
||||
parent: this.parent,
|
||||
index: index,
|
||||
oldSelection: oldSelection,
|
||||
newSelection: newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -4643,11 +4700,11 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor._onAction('duplicateNode', {
|
||||
'node': this,
|
||||
'clone': clone,
|
||||
'parent': this.parent,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
node: this,
|
||||
clone: clone,
|
||||
parent: this.parent,
|
||||
oldSelection: oldSelection,
|
||||
newSelection: newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -4662,9 +4719,9 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
var oldSelection = this.editor.getSelection();
|
||||
|
||||
var newNode = new Node(this.editor, {
|
||||
'field': (field != undefined) ? field : '',
|
||||
'value': (value != undefined) ? value : '',
|
||||
'type': type
|
||||
field: (field != undefined) ? field : '',
|
||||
value: (value != undefined) ? value : '',
|
||||
type: type
|
||||
});
|
||||
newNode.expand(true);
|
||||
this.parent.insertBefore(newNode, this);
|
||||
|
@ -4673,11 +4730,11 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor._onAction('insertBeforeNode', {
|
||||
'node': newNode,
|
||||
'beforeNode': this,
|
||||
'parent': this.parent,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
node: newNode,
|
||||
beforeNode: this,
|
||||
parent: this.parent,
|
||||
oldSelection: oldSelection,
|
||||
newSelection: newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -4692,9 +4749,9 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
var oldSelection = this.editor.getSelection();
|
||||
|
||||
var newNode = new Node(this.editor, {
|
||||
'field': (field != undefined) ? field : '',
|
||||
'value': (value != undefined) ? value : '',
|
||||
'type': type
|
||||
field: (field != undefined) ? field : '',
|
||||
value: (value != undefined) ? value : '',
|
||||
type: type
|
||||
});
|
||||
newNode.expand(true);
|
||||
this.parent.insertAfter(newNode, this);
|
||||
|
@ -4703,11 +4760,11 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor._onAction('insertAfterNode', {
|
||||
'node': newNode,
|
||||
'afterNode': this,
|
||||
'parent': this.parent,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
node: newNode,
|
||||
afterNode: this,
|
||||
parent: this.parent,
|
||||
oldSelection: oldSelection,
|
||||
newSelection: newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -4722,9 +4779,9 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
var oldSelection = this.editor.getSelection();
|
||||
|
||||
var newNode = new Node(this.editor, {
|
||||
'field': (field != undefined) ? field : '',
|
||||
'value': (value != undefined) ? value : '',
|
||||
'type': type
|
||||
field: (field != undefined) ? field : '',
|
||||
value: (value != undefined) ? value : '',
|
||||
type: type
|
||||
});
|
||||
newNode.expand(true);
|
||||
this.parent.appendChild(newNode);
|
||||
|
@ -4733,10 +4790,10 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor._onAction('appendNode', {
|
||||
'node': newNode,
|
||||
'parent': this.parent,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
node: newNode,
|
||||
parent: this.parent,
|
||||
oldSelection: oldSelection,
|
||||
newSelection: newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -4753,11 +4810,11 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor._onAction('changeType', {
|
||||
'node': this,
|
||||
'oldType': oldType,
|
||||
'newType': newType,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
node: this,
|
||||
oldType: oldType,
|
||||
newType: newType,
|
||||
oldSelection: oldSelection,
|
||||
newSelection: newSelection
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -4789,11 +4846,11 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
this.sort = (order == 1) ? 'asc' : 'desc';
|
||||
|
||||
this.editor._onAction('sort', {
|
||||
'node': this,
|
||||
'oldChilds': oldChilds,
|
||||
'oldSort': oldSort,
|
||||
'newChilds': this.childs,
|
||||
'newSort': this.sort
|
||||
node: this,
|
||||
oldChilds: oldChilds,
|
||||
oldSort: oldSort,
|
||||
newChilds: this.childs,
|
||||
newSort: this.sort
|
||||
});
|
||||
|
||||
this.showChilds();
|
||||
|
@ -5023,73 +5080,75 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
var titles = Node.TYPE_TITLES;
|
||||
var items = [];
|
||||
|
||||
if (this.editable.value) {
|
||||
items.push({
|
||||
'text': 'Type',
|
||||
'title': 'Change the type of this field',
|
||||
'className': 'type-' + this.type,
|
||||
'submenu': [
|
||||
text: 'Type',
|
||||
title: 'Change the type of this field',
|
||||
className: 'type-' + this.type,
|
||||
submenu: [
|
||||
{
|
||||
'text': 'Auto',
|
||||
'className': 'type-auto' +
|
||||
text: 'Auto',
|
||||
className: 'type-auto' +
|
||||
(this.type == 'auto' ? ' selected' : ''),
|
||||
'title': titles.auto,
|
||||
'click': function () {
|
||||
title: titles.auto,
|
||||
click: function () {
|
||||
node._onChangeType('auto');
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Array',
|
||||
'className': 'type-array' +
|
||||
text: 'Array',
|
||||
className: 'type-array' +
|
||||
(this.type == 'array' ? ' selected' : ''),
|
||||
'title': titles.array,
|
||||
'click': function () {
|
||||
title: titles.array,
|
||||
click: function () {
|
||||
node._onChangeType('array');
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Object',
|
||||
'className': 'type-object' +
|
||||
text: 'Object',
|
||||
className: 'type-object' +
|
||||
(this.type == 'object' ? ' selected' : ''),
|
||||
'title': titles.object,
|
||||
'click': function () {
|
||||
title: titles.object,
|
||||
click: function () {
|
||||
node._onChangeType('object');
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'String',
|
||||
'className': 'type-string' +
|
||||
text: 'String',
|
||||
className: 'type-string' +
|
||||
(this.type == 'string' ? ' selected' : ''),
|
||||
'title': titles.string,
|
||||
'click': function () {
|
||||
title: titles.string,
|
||||
click: function () {
|
||||
node._onChangeType('string');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
if (this._hasChilds()) {
|
||||
var direction = ((this.sort == 'asc') ? 'desc': 'asc');
|
||||
items.push({
|
||||
'text': 'Sort',
|
||||
'title': 'Sort the childs of this ' + this.type,
|
||||
'className': 'sort-' + direction,
|
||||
'click': function () {
|
||||
text: 'Sort',
|
||||
title: 'Sort the childs of this ' + this.type,
|
||||
className: 'sort-' + direction,
|
||||
click: function () {
|
||||
node._onSort(direction);
|
||||
},
|
||||
'submenu': [
|
||||
submenu: [
|
||||
{
|
||||
'text': 'Ascending',
|
||||
'className': 'sort-asc',
|
||||
'title': 'Sort the childs of this ' + this.type + ' in ascending order',
|
||||
'click': function () {
|
||||
text: 'Ascending',
|
||||
className: 'sort-asc',
|
||||
title: 'Sort the childs of this ' + this.type + ' in ascending order',
|
||||
click: function () {
|
||||
node._onSort('asc');
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Descending',
|
||||
'className': 'sort-desc',
|
||||
'title': 'Sort the childs of this ' + this.type +' in descending order',
|
||||
'click': function () {
|
||||
text: 'Descending',
|
||||
className: 'sort-desc',
|
||||
title: 'Sort the childs of this ' + this.type +' in descending order',
|
||||
click: function () {
|
||||
node._onSort('desc');
|
||||
}
|
||||
}
|
||||
|
@ -5098,52 +5157,54 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
}
|
||||
|
||||
if (this.parent && this.parent._hasChilds()) {
|
||||
if (items.length) {
|
||||
// create a separator
|
||||
items.push({
|
||||
'type': 'separator'
|
||||
});
|
||||
}
|
||||
|
||||
// create append button (for last child node only)
|
||||
var childs = node.parent.childs;
|
||||
if (node == childs[childs.length - 1]) {
|
||||
items.push({
|
||||
'text': 'Append',
|
||||
'title': 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)',
|
||||
'submenuTitle': 'Select the type of the field to be appended',
|
||||
'className': 'append',
|
||||
'click': function () {
|
||||
text: 'Append',
|
||||
title: 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)',
|
||||
submenuTitle: 'Select the type of the field to be appended',
|
||||
className: 'append',
|
||||
click: function () {
|
||||
node._onAppend('', '', 'auto');
|
||||
},
|
||||
'submenu': [
|
||||
submenu: [
|
||||
{
|
||||
'text': 'Auto',
|
||||
'className': 'type-auto',
|
||||
'title': titles.auto,
|
||||
'click': function () {
|
||||
text: 'Auto',
|
||||
className: 'type-auto',
|
||||
title: titles.auto,
|
||||
click: function () {
|
||||
node._onAppend('', '', 'auto');
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Array',
|
||||
'className': 'type-array',
|
||||
'title': titles.array,
|
||||
'click': function () {
|
||||
text: 'Array',
|
||||
className: 'type-array',
|
||||
title: titles.array,
|
||||
click: function () {
|
||||
node._onAppend('', []);
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Object',
|
||||
'className': 'type-object',
|
||||
'title': titles.object,
|
||||
'click': function () {
|
||||
text: 'Object',
|
||||
className: 'type-object',
|
||||
title: titles.object,
|
||||
click: function () {
|
||||
node._onAppend('', {});
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'String',
|
||||
'className': 'type-string',
|
||||
'title': titles.string,
|
||||
'click': function () {
|
||||
text: 'String',
|
||||
className: 'type-string',
|
||||
title: titles.string,
|
||||
click: function () {
|
||||
node._onAppend('', '', 'string');
|
||||
}
|
||||
}
|
||||
|
@ -5153,69 +5214,71 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
|
||||
// create insert button
|
||||
items.push({
|
||||
'text': 'Insert',
|
||||
'title': 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)',
|
||||
'submenuTitle': 'Select the type of the field to be inserted',
|
||||
'className': 'insert',
|
||||
'click': function () {
|
||||
text: 'Insert',
|
||||
title: 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)',
|
||||
submenuTitle: 'Select the type of the field to be inserted',
|
||||
className: 'insert',
|
||||
click: function () {
|
||||
node._onInsertBefore('', '', 'auto');
|
||||
},
|
||||
'submenu': [
|
||||
submenu: [
|
||||
{
|
||||
'text': 'Auto',
|
||||
'className': 'type-auto',
|
||||
'title': titles.auto,
|
||||
'click': function () {
|
||||
text: 'Auto',
|
||||
className: 'type-auto',
|
||||
title: titles.auto,
|
||||
click: function () {
|
||||
node._onInsertBefore('', '', 'auto');
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Array',
|
||||
'className': 'type-array',
|
||||
'title': titles.array,
|
||||
'click': function () {
|
||||
text: 'Array',
|
||||
className: 'type-array',
|
||||
title: titles.array,
|
||||
click: function () {
|
||||
node._onInsertBefore('', []);
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Object',
|
||||
'className': 'type-object',
|
||||
'title': titles.object,
|
||||
'click': function () {
|
||||
text: 'Object',
|
||||
className: 'type-object',
|
||||
title: titles.object,
|
||||
click: function () {
|
||||
node._onInsertBefore('', {});
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'String',
|
||||
'className': 'type-string',
|
||||
'title': titles.string,
|
||||
'click': function () {
|
||||
text: 'String',
|
||||
className: 'type-string',
|
||||
title: titles.string,
|
||||
click: function () {
|
||||
node._onInsertBefore('', '', 'string');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
if (this.editable.field) {
|
||||
// create duplicate button
|
||||
items.push({
|
||||
'text': 'Duplicate',
|
||||
'title': 'Duplicate this field (Ctrl+D)',
|
||||
'className': 'duplicate',
|
||||
'click': function () {
|
||||
text: 'Duplicate',
|
||||
title: 'Duplicate this field (Ctrl+D)',
|
||||
className: 'duplicate',
|
||||
click: function () {
|
||||
node._onDuplicate();
|
||||
}
|
||||
});
|
||||
|
||||
// create remove button
|
||||
items.push({
|
||||
'text': 'Remove',
|
||||
'title': 'Remove this field (Ctrl+Del)',
|
||||
'className': 'remove',
|
||||
'click': function () {
|
||||
text: 'Remove',
|
||||
title: 'Remove this field (Ctrl+Del)',
|
||||
className: 'remove',
|
||||
click: function () {
|
||||
node._onRemove();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var menu = new ContextMenu(items, {close: onClose});
|
||||
menu.show(anchor);
|
||||
|
@ -5949,6 +6012,8 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
return dom.tr;
|
||||
}
|
||||
|
||||
this._updateEditability();
|
||||
|
||||
// a row for the append button
|
||||
var trAppend = document.createElement('tr');
|
||||
trAppend.node = this;
|
||||
|
@ -5956,7 +6021,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
|
||||
// TODO: consistent naming
|
||||
|
||||
if (this.editor.mode.edit) {
|
||||
if (this.editable.field) {
|
||||
// a cell for the dragarea column
|
||||
dom.tdDrag = document.createElement('td');
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -29,7 +29,7 @@ correct date and version number in the header.
|
|||
Test whether the npm library is ok by installing it locally:
|
||||
|
||||
cd ../tmp-folder
|
||||
npm install ../mathjs
|
||||
npm install ./path/to/jsoneditor
|
||||
|
||||
Check whether the examples in the library work ok, and whether the necessary
|
||||
files are included.
|
||||
|
@ -57,13 +57,13 @@ Publish at cdnjs: test after 30 to 60 minutes whether the new version is
|
|||
published at cdnjs (should auto update).
|
||||
|
||||
|
||||
## Test published libraries
|
||||
## Test published library
|
||||
|
||||
Install the libraries locally and test whether they work correctly:
|
||||
|
||||
cd tmp-folder
|
||||
npm install mathjs
|
||||
bower install mathjs
|
||||
npm install jsoneditor
|
||||
bower install jsoneditor
|
||||
|
||||
|
||||
## Put zip file to website
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "jsoneditor",
|
||||
"version": "3.0.0",
|
||||
"version": "3.1.0",
|
||||
"main": "jsoneditor.js",
|
||||
"description": "A web-based tool to view, edit and format JSON",
|
||||
"tags": [
|
||||
|
|
357
src/js/Node.js
357
src/js/Node.js
|
@ -27,6 +27,56 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the field and/or value of this node are editable
|
||||
* @private
|
||||
*/
|
||||
Node.prototype._updateEditability = function () {
|
||||
this.editable = {
|
||||
field: true,
|
||||
value: true
|
||||
};
|
||||
|
||||
if (this.editor) {
|
||||
this.editable.field = this.editor.options.mode === 'tree';
|
||||
this.editable.value = this.editor.options.mode !== 'view';
|
||||
|
||||
if (this.editor.options.mode === 'tree' && (typeof this.editor.options.editable === 'function')) {
|
||||
var editable = this.editor.options.editable({
|
||||
field: this.field,
|
||||
value: this.value,
|
||||
path: this.path()
|
||||
});
|
||||
|
||||
if (typeof editable === 'boolean') {
|
||||
this.editable.field = editable;
|
||||
this.editable.value = editable;
|
||||
}
|
||||
else {
|
||||
if (typeof editable.field === 'boolean') this.editable.field = editable.field;
|
||||
if (typeof editable.value === 'boolean') this.editable.value = editable.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the path of this node
|
||||
* @return {String[]} Array containing the path to this node
|
||||
*/
|
||||
Node.prototype.path = function () {
|
||||
var node = this;
|
||||
var path = [];
|
||||
while (node) {
|
||||
var field = node.field || node.index;
|
||||
if (field !== undefined) {
|
||||
path.unshift(field);
|
||||
}
|
||||
node = node.parent;
|
||||
}
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set parent node
|
||||
* @param {Node} parent
|
||||
|
@ -98,7 +148,7 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
if (childValue !== undefined && !(childValue instanceof Function)) {
|
||||
// ignore undefined and functions
|
||||
child = new Node(this.editor, {
|
||||
'value': childValue
|
||||
value: childValue
|
||||
});
|
||||
this.appendChild(child);
|
||||
}
|
||||
|
@ -114,8 +164,8 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
if (childValue !== undefined && !(childValue instanceof Function)) {
|
||||
// ignore undefined and functions
|
||||
child = new Node(this.editor, {
|
||||
'field': childField,
|
||||
'value': childValue
|
||||
field: childField,
|
||||
value: childValue
|
||||
});
|
||||
this.appendChild(child);
|
||||
}
|
||||
|
@ -977,7 +1027,7 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
var t = (this.type == 'auto') ? util.type(v) : this.type;
|
||||
var isUrl = (t == 'string' && util.isUrl(v));
|
||||
var color = '';
|
||||
if (isUrl && !this.editor.mode.edit) {
|
||||
if (isUrl && !this.editable.value) { // TODO: when to apply this?
|
||||
color = '';
|
||||
}
|
||||
else if (t == 'string') {
|
||||
|
@ -1024,7 +1074,7 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
domValue.title = this.type + ' containing ' + count + ' items';
|
||||
}
|
||||
else if (t == 'string' && util.isUrl(v)) {
|
||||
if (this.editor.mode.edit) {
|
||||
if (this.editable.value) {
|
||||
domValue.title = 'Ctrl+Click or Ctrl+Enter to open url in new window';
|
||||
}
|
||||
}
|
||||
|
@ -1148,13 +1198,16 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
return dom.tr;
|
||||
}
|
||||
|
||||
this._updateEditability();
|
||||
|
||||
// create row
|
||||
dom.tr = document.createElement('tr');
|
||||
dom.tr.node = this;
|
||||
|
||||
if (this.editor.mode.edit) {
|
||||
// create draggable area
|
||||
if (this.editor.options.mode === 'tree') { // note: we take here the global setting
|
||||
var tdDrag = document.createElement('td');
|
||||
if (this.editable.field) {
|
||||
// create draggable area
|
||||
if (this.parent) {
|
||||
var domDrag = document.createElement('button');
|
||||
dom.drag = domDrag;
|
||||
|
@ -1162,6 +1215,7 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
domDrag.title = 'Drag to move this field (Alt+Shift+Arrows)';
|
||||
tdDrag.appendChild(domDrag);
|
||||
}
|
||||
}
|
||||
dom.tr.appendChild(tdDrag);
|
||||
|
||||
// create context menu
|
||||
|
@ -1485,9 +1539,9 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
// update field
|
||||
var domField = this.dom.field;
|
||||
if (domField) {
|
||||
if (this.fieldEditable == true) {
|
||||
if (this.fieldEditable) {
|
||||
// parent is an object
|
||||
domField.contentEditable = this.editor.mode.edit;
|
||||
domField.contentEditable = this.editable.field;
|
||||
domField.spellcheck = false;
|
||||
domField.className = 'field';
|
||||
}
|
||||
|
@ -1603,7 +1657,7 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
domValue.innerHTML = '{...}';
|
||||
}
|
||||
else {
|
||||
if (!this.editor.mode.edit && util.isUrl(this.value)) {
|
||||
if (!this.editable.value && util.isUrl(this.value)) {
|
||||
// create a link in case of read-only editor and value containing an url
|
||||
domValue = document.createElement('a');
|
||||
domValue.className = 'value';
|
||||
|
@ -1612,9 +1666,9 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
domValue.innerHTML = this._escapeHTML(this.value);
|
||||
}
|
||||
else {
|
||||
// create and editable or read-only div
|
||||
// create an editable or read-only div
|
||||
domValue = document.createElement('div');
|
||||
domValue.contentEditable = !this.editor.mode.view;
|
||||
domValue.contentEditable = this.editable.value;
|
||||
domValue.spellcheck = false;
|
||||
domValue.className = 'value';
|
||||
domValue.innerHTML = this._escapeHTML(this.value);
|
||||
|
@ -1777,7 +1831,7 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
break;
|
||||
|
||||
case 'click':
|
||||
if (event.ctrlKey && this.editor.mode.edit) {
|
||||
if (event.ctrlKey || !this.editable.value) {
|
||||
if (util.isUrl(this.value)) {
|
||||
window.open(this.value, '_blank');
|
||||
}
|
||||
|
@ -1895,11 +1949,12 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
var altKey = event.altKey;
|
||||
var handled = false;
|
||||
var prevNode, nextNode, nextDom, nextDom2;
|
||||
var editable = this.editor.options.mode === 'tree';
|
||||
|
||||
// util.log(ctrlKey, keynum, event.charCode); // TODO: cleanup
|
||||
if (keynum == 13) { // Enter
|
||||
if (target == this.dom.value) {
|
||||
if (!this.editor.mode.edit || event.ctrlKey) {
|
||||
if (!this.editable.value || event.ctrlKey) {
|
||||
if (util.isUrl(this.value)) {
|
||||
window.open(this.value, '_blank');
|
||||
handled = true;
|
||||
|
@ -1917,7 +1972,7 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
}
|
||||
}
|
||||
else if (keynum == 68) { // D
|
||||
if (ctrlKey) { // Ctrl+D
|
||||
if (ctrlKey && editable) { // Ctrl+D
|
||||
this._onDuplicate();
|
||||
handled = true;
|
||||
}
|
||||
|
@ -1929,19 +1984,19 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
handled = true;
|
||||
}
|
||||
}
|
||||
else if (keynum == 77) { // M
|
||||
else if (keynum == 77 && editable) { // M
|
||||
if (ctrlKey) { // Ctrl+M
|
||||
this.showContextMenu(target);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
else if (keynum == 46) { // Del
|
||||
else if (keynum == 46 && editable) { // Del
|
||||
if (ctrlKey) { // Ctrl+Del
|
||||
this._onRemove();
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
else if (keynum == 45) { // Ins
|
||||
else if (keynum == 45 && editable) { // Ins
|
||||
if (ctrlKey && !shiftKey) { // Ctrl+Ins
|
||||
this._onInsertBefore();
|
||||
handled = true;
|
||||
|
@ -1980,7 +2035,7 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
}
|
||||
handled = true;
|
||||
}
|
||||
else if (altKey && shiftKey) { // Alt + Shift Arrow left
|
||||
else if (altKey && shiftKey && editable) { // Alt + Shift Arrow left
|
||||
if (this.expanded) {
|
||||
var appendDom = this.getAppend();
|
||||
nextDom = appendDom ? appendDom.nextSibling : undefined;
|
||||
|
@ -2053,7 +2108,7 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
}
|
||||
handled = true;
|
||||
}
|
||||
else if (altKey && shiftKey) { // Alt + Shift + Arrow Down
|
||||
else if (altKey && shiftKey && editable) { // Alt + Shift + Arrow Down
|
||||
// find the 2nd next node and move before that one
|
||||
if (this.expanded) {
|
||||
nextNode = this.append ? this.append._nextNode() : undefined;
|
||||
|
@ -2138,11 +2193,11 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
|
||||
// store history action
|
||||
this.editor._onAction('removeNode', {
|
||||
'node': this,
|
||||
'parent': this.parent,
|
||||
'index': index,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
node: this,
|
||||
parent: this.parent,
|
||||
index: index,
|
||||
oldSelection: oldSelection,
|
||||
newSelection: newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -2157,11 +2212,11 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor._onAction('duplicateNode', {
|
||||
'node': this,
|
||||
'clone': clone,
|
||||
'parent': this.parent,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
node: this,
|
||||
clone: clone,
|
||||
parent: this.parent,
|
||||
oldSelection: oldSelection,
|
||||
newSelection: newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -2176,9 +2231,9 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
var oldSelection = this.editor.getSelection();
|
||||
|
||||
var newNode = new Node(this.editor, {
|
||||
'field': (field != undefined) ? field : '',
|
||||
'value': (value != undefined) ? value : '',
|
||||
'type': type
|
||||
field: (field != undefined) ? field : '',
|
||||
value: (value != undefined) ? value : '',
|
||||
type: type
|
||||
});
|
||||
newNode.expand(true);
|
||||
this.parent.insertBefore(newNode, this);
|
||||
|
@ -2187,11 +2242,11 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor._onAction('insertBeforeNode', {
|
||||
'node': newNode,
|
||||
'beforeNode': this,
|
||||
'parent': this.parent,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
node: newNode,
|
||||
beforeNode: this,
|
||||
parent: this.parent,
|
||||
oldSelection: oldSelection,
|
||||
newSelection: newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -2206,9 +2261,9 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
var oldSelection = this.editor.getSelection();
|
||||
|
||||
var newNode = new Node(this.editor, {
|
||||
'field': (field != undefined) ? field : '',
|
||||
'value': (value != undefined) ? value : '',
|
||||
'type': type
|
||||
field: (field != undefined) ? field : '',
|
||||
value: (value != undefined) ? value : '',
|
||||
type: type
|
||||
});
|
||||
newNode.expand(true);
|
||||
this.parent.insertAfter(newNode, this);
|
||||
|
@ -2217,11 +2272,11 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor._onAction('insertAfterNode', {
|
||||
'node': newNode,
|
||||
'afterNode': this,
|
||||
'parent': this.parent,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
node: newNode,
|
||||
afterNode: this,
|
||||
parent: this.parent,
|
||||
oldSelection: oldSelection,
|
||||
newSelection: newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -2236,9 +2291,9 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
var oldSelection = this.editor.getSelection();
|
||||
|
||||
var newNode = new Node(this.editor, {
|
||||
'field': (field != undefined) ? field : '',
|
||||
'value': (value != undefined) ? value : '',
|
||||
'type': type
|
||||
field: (field != undefined) ? field : '',
|
||||
value: (value != undefined) ? value : '',
|
||||
type: type
|
||||
});
|
||||
newNode.expand(true);
|
||||
this.parent.appendChild(newNode);
|
||||
|
@ -2247,10 +2302,10 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor._onAction('appendNode', {
|
||||
'node': newNode,
|
||||
'parent': this.parent,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
node: newNode,
|
||||
parent: this.parent,
|
||||
oldSelection: oldSelection,
|
||||
newSelection: newSelection
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -2267,11 +2322,11 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
var newSelection = this.editor.getSelection();
|
||||
|
||||
this.editor._onAction('changeType', {
|
||||
'node': this,
|
||||
'oldType': oldType,
|
||||
'newType': newType,
|
||||
'oldSelection': oldSelection,
|
||||
'newSelection': newSelection
|
||||
node: this,
|
||||
oldType: oldType,
|
||||
newType: newType,
|
||||
oldSelection: oldSelection,
|
||||
newSelection: newSelection
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -2303,11 +2358,11 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
this.sort = (order == 1) ? 'asc' : 'desc';
|
||||
|
||||
this.editor._onAction('sort', {
|
||||
'node': this,
|
||||
'oldChilds': oldChilds,
|
||||
'oldSort': oldSort,
|
||||
'newChilds': this.childs,
|
||||
'newSort': this.sort
|
||||
node: this,
|
||||
oldChilds: oldChilds,
|
||||
oldSort: oldSort,
|
||||
newChilds: this.childs,
|
||||
newSort: this.sort
|
||||
});
|
||||
|
||||
this.showChilds();
|
||||
|
@ -2537,73 +2592,75 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
var titles = Node.TYPE_TITLES;
|
||||
var items = [];
|
||||
|
||||
if (this.editable.value) {
|
||||
items.push({
|
||||
'text': 'Type',
|
||||
'title': 'Change the type of this field',
|
||||
'className': 'type-' + this.type,
|
||||
'submenu': [
|
||||
text: 'Type',
|
||||
title: 'Change the type of this field',
|
||||
className: 'type-' + this.type,
|
||||
submenu: [
|
||||
{
|
||||
'text': 'Auto',
|
||||
'className': 'type-auto' +
|
||||
text: 'Auto',
|
||||
className: 'type-auto' +
|
||||
(this.type == 'auto' ? ' selected' : ''),
|
||||
'title': titles.auto,
|
||||
'click': function () {
|
||||
title: titles.auto,
|
||||
click: function () {
|
||||
node._onChangeType('auto');
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Array',
|
||||
'className': 'type-array' +
|
||||
text: 'Array',
|
||||
className: 'type-array' +
|
||||
(this.type == 'array' ? ' selected' : ''),
|
||||
'title': titles.array,
|
||||
'click': function () {
|
||||
title: titles.array,
|
||||
click: function () {
|
||||
node._onChangeType('array');
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Object',
|
||||
'className': 'type-object' +
|
||||
text: 'Object',
|
||||
className: 'type-object' +
|
||||
(this.type == 'object' ? ' selected' : ''),
|
||||
'title': titles.object,
|
||||
'click': function () {
|
||||
title: titles.object,
|
||||
click: function () {
|
||||
node._onChangeType('object');
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'String',
|
||||
'className': 'type-string' +
|
||||
text: 'String',
|
||||
className: 'type-string' +
|
||||
(this.type == 'string' ? ' selected' : ''),
|
||||
'title': titles.string,
|
||||
'click': function () {
|
||||
title: titles.string,
|
||||
click: function () {
|
||||
node._onChangeType('string');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
if (this._hasChilds()) {
|
||||
var direction = ((this.sort == 'asc') ? 'desc': 'asc');
|
||||
items.push({
|
||||
'text': 'Sort',
|
||||
'title': 'Sort the childs of this ' + this.type,
|
||||
'className': 'sort-' + direction,
|
||||
'click': function () {
|
||||
text: 'Sort',
|
||||
title: 'Sort the childs of this ' + this.type,
|
||||
className: 'sort-' + direction,
|
||||
click: function () {
|
||||
node._onSort(direction);
|
||||
},
|
||||
'submenu': [
|
||||
submenu: [
|
||||
{
|
||||
'text': 'Ascending',
|
||||
'className': 'sort-asc',
|
||||
'title': 'Sort the childs of this ' + this.type + ' in ascending order',
|
||||
'click': function () {
|
||||
text: 'Ascending',
|
||||
className: 'sort-asc',
|
||||
title: 'Sort the childs of this ' + this.type + ' in ascending order',
|
||||
click: function () {
|
||||
node._onSort('asc');
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Descending',
|
||||
'className': 'sort-desc',
|
||||
'title': 'Sort the childs of this ' + this.type +' in descending order',
|
||||
'click': function () {
|
||||
text: 'Descending',
|
||||
className: 'sort-desc',
|
||||
title: 'Sort the childs of this ' + this.type +' in descending order',
|
||||
click: function () {
|
||||
node._onSort('desc');
|
||||
}
|
||||
}
|
||||
|
@ -2612,52 +2669,54 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
}
|
||||
|
||||
if (this.parent && this.parent._hasChilds()) {
|
||||
if (items.length) {
|
||||
// create a separator
|
||||
items.push({
|
||||
'type': 'separator'
|
||||
});
|
||||
}
|
||||
|
||||
// create append button (for last child node only)
|
||||
var childs = node.parent.childs;
|
||||
if (node == childs[childs.length - 1]) {
|
||||
items.push({
|
||||
'text': 'Append',
|
||||
'title': 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)',
|
||||
'submenuTitle': 'Select the type of the field to be appended',
|
||||
'className': 'append',
|
||||
'click': function () {
|
||||
text: 'Append',
|
||||
title: 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)',
|
||||
submenuTitle: 'Select the type of the field to be appended',
|
||||
className: 'append',
|
||||
click: function () {
|
||||
node._onAppend('', '', 'auto');
|
||||
},
|
||||
'submenu': [
|
||||
submenu: [
|
||||
{
|
||||
'text': 'Auto',
|
||||
'className': 'type-auto',
|
||||
'title': titles.auto,
|
||||
'click': function () {
|
||||
text: 'Auto',
|
||||
className: 'type-auto',
|
||||
title: titles.auto,
|
||||
click: function () {
|
||||
node._onAppend('', '', 'auto');
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Array',
|
||||
'className': 'type-array',
|
||||
'title': titles.array,
|
||||
'click': function () {
|
||||
text: 'Array',
|
||||
className: 'type-array',
|
||||
title: titles.array,
|
||||
click: function () {
|
||||
node._onAppend('', []);
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Object',
|
||||
'className': 'type-object',
|
||||
'title': titles.object,
|
||||
'click': function () {
|
||||
text: 'Object',
|
||||
className: 'type-object',
|
||||
title: titles.object,
|
||||
click: function () {
|
||||
node._onAppend('', {});
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'String',
|
||||
'className': 'type-string',
|
||||
'title': titles.string,
|
||||
'click': function () {
|
||||
text: 'String',
|
||||
className: 'type-string',
|
||||
title: titles.string,
|
||||
click: function () {
|
||||
node._onAppend('', '', 'string');
|
||||
}
|
||||
}
|
||||
|
@ -2667,69 +2726,71 @@ define(['./ContextMenu', './appendNodeFactory', './util'], function (ContextMenu
|
|||
|
||||
// create insert button
|
||||
items.push({
|
||||
'text': 'Insert',
|
||||
'title': 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)',
|
||||
'submenuTitle': 'Select the type of the field to be inserted',
|
||||
'className': 'insert',
|
||||
'click': function () {
|
||||
text: 'Insert',
|
||||
title: 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)',
|
||||
submenuTitle: 'Select the type of the field to be inserted',
|
||||
className: 'insert',
|
||||
click: function () {
|
||||
node._onInsertBefore('', '', 'auto');
|
||||
},
|
||||
'submenu': [
|
||||
submenu: [
|
||||
{
|
||||
'text': 'Auto',
|
||||
'className': 'type-auto',
|
||||
'title': titles.auto,
|
||||
'click': function () {
|
||||
text: 'Auto',
|
||||
className: 'type-auto',
|
||||
title: titles.auto,
|
||||
click: function () {
|
||||
node._onInsertBefore('', '', 'auto');
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Array',
|
||||
'className': 'type-array',
|
||||
'title': titles.array,
|
||||
'click': function () {
|
||||
text: 'Array',
|
||||
className: 'type-array',
|
||||
title: titles.array,
|
||||
click: function () {
|
||||
node._onInsertBefore('', []);
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'Object',
|
||||
'className': 'type-object',
|
||||
'title': titles.object,
|
||||
'click': function () {
|
||||
text: 'Object',
|
||||
className: 'type-object',
|
||||
title: titles.object,
|
||||
click: function () {
|
||||
node._onInsertBefore('', {});
|
||||
}
|
||||
},
|
||||
{
|
||||
'text': 'String',
|
||||
'className': 'type-string',
|
||||
'title': titles.string,
|
||||
'click': function () {
|
||||
text: 'String',
|
||||
className: 'type-string',
|
||||
title: titles.string,
|
||||
click: function () {
|
||||
node._onInsertBefore('', '', 'string');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
if (this.editable.field) {
|
||||
// create duplicate button
|
||||
items.push({
|
||||
'text': 'Duplicate',
|
||||
'title': 'Duplicate this field (Ctrl+D)',
|
||||
'className': 'duplicate',
|
||||
'click': function () {
|
||||
text: 'Duplicate',
|
||||
title: 'Duplicate this field (Ctrl+D)',
|
||||
className: 'duplicate',
|
||||
click: function () {
|
||||
node._onDuplicate();
|
||||
}
|
||||
});
|
||||
|
||||
// create remove button
|
||||
items.push({
|
||||
'text': 'Remove',
|
||||
'title': 'Remove this field (Ctrl+Del)',
|
||||
'className': 'remove',
|
||||
'click': function () {
|
||||
text: 'Remove',
|
||||
title: 'Remove this field (Ctrl+Del)',
|
||||
className: 'remove',
|
||||
click: function () {
|
||||
node._onRemove();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var menu = new ContextMenu(items, {close: onClose});
|
||||
menu.show(anchor);
|
||||
|
|
|
@ -32,6 +32,8 @@ define(['./ContextMenu', './util'], function (ContextMenu, util) {
|
|||
return dom.tr;
|
||||
}
|
||||
|
||||
this._updateEditability();
|
||||
|
||||
// a row for the append button
|
||||
var trAppend = document.createElement('tr');
|
||||
trAppend.node = this;
|
||||
|
@ -39,7 +41,7 @@ define(['./ContextMenu', './util'], function (ContextMenu, util) {
|
|||
|
||||
// TODO: consistent naming
|
||||
|
||||
if (this.editor.mode.edit) {
|
||||
if (this.editable.field) {
|
||||
// a cell for the dragarea column
|
||||
dom.tdDrag = document.createElement('td');
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ define(['./Highlighter', './History', './SearchBox', './Node', './modeswitcher',
|
|||
|
||||
this._setOptions(options);
|
||||
|
||||
if (this.options.history && !this.mode.view) {
|
||||
if (this.options.history && this.options.mode !== 'view') {
|
||||
this.history = new History(this);
|
||||
}
|
||||
|
||||
|
@ -70,13 +70,6 @@ define(['./Highlighter', './History', './SearchBox', './Node', './modeswitcher',
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// interpret the mode options
|
||||
this.mode = {
|
||||
edit: (this.options.mode != 'view' && this.options.mode != 'form'),
|
||||
view: (this.options.mode == 'view'),
|
||||
form: (this.options.mode == 'form')
|
||||
};
|
||||
};
|
||||
|
||||
// node currently being edited
|
||||
|
@ -682,7 +675,7 @@ define(['./Highlighter', './History', './SearchBox', './Node', './modeswitcher',
|
|||
// width, and the edit columns do have a fixed width
|
||||
var col;
|
||||
this.colgroupContent = document.createElement('colgroup');
|
||||
if (this.mode.edit) {
|
||||
if (this.options.mode === 'tree') {
|
||||
col = document.createElement('col');
|
||||
col.width = "24px";
|
||||
this.colgroupContent.appendChild(col);
|
||||
|
|
|
@ -13,10 +13,20 @@ define(function () {
|
|||
return JSON.parse(jsonString);
|
||||
}
|
||||
catch (err) {
|
||||
// try to load as JavaScript instead of JSON (like "{a: 2}" instead of "{"a": 2}"
|
||||
try {
|
||||
return eval('(' + jsonString + ')');
|
||||
}
|
||||
catch(err2) {
|
||||
// ok no luck loading as JavaScript
|
||||
|
||||
// try to throw a more detailed error message using validate
|
||||
util.validate(jsonString);
|
||||
|
||||
// rethrow the original error
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -67,17 +67,37 @@
|
|||
mode: 'tree',
|
||||
modes: ['code', 'form', 'text', 'tree', 'view'], // allowed modes
|
||||
error: function (err) {
|
||||
console.trace();
|
||||
alert(err.toString());
|
||||
},
|
||||
editable: function (node) {
|
||||
console.log(node);
|
||||
switch(node.field) {
|
||||
case '_id':
|
||||
return false;
|
||||
|
||||
case '_field':
|
||||
return {
|
||||
field: false,
|
||||
value: true
|
||||
};
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
json = {
|
||||
"_id": "1234",
|
||||
"_field": "ABCD",
|
||||
"array": [1, 2, 3],
|
||||
"boolean": true,
|
||||
"null": null,
|
||||
"number": 123,
|
||||
"object": {"a": "b", "c": "d"},
|
||||
"string": "Hello World"
|
||||
"object": {"a": "b", "c": {"d": "e", "f": "g"}},
|
||||
"string": "Hello World",
|
||||
"url": "http://jsoneditoronline.org"
|
||||
};
|
||||
|
||||
editor = new JSONEditor(container, options, json);
|
||||
|
|
Loading…
Reference in New Issue