Merge branch 'develop' of https://github.com/josdejong/jsoneditor into get_caret_position
# Conflicts: # docs/api.md # src/js/Node.js # src/js/treemode.js
This commit is contained in:
commit
3b186633e7
27
HISTORY.md
27
HISTORY.md
|
@ -3,13 +3,36 @@
|
|||
https://github.com/josdejong/jsoneditor
|
||||
|
||||
|
||||
## not yet released, version 5.13.2
|
||||
## 2018-03-21, version 5.14.1
|
||||
|
||||
- Fixed absolute path of css image `jsoneditor-icons.svg`, which could.
|
||||
give issues with webpack plugin "file-loader". Thanks @landru29.
|
||||
|
||||
|
||||
## 2018-02-25, version 5.14.0
|
||||
|
||||
- Implemented support for translations. Thanks @mariohmol.
|
||||
- Fixed a bug sometimes occurring when dragging items from array to
|
||||
object, see #509. Thanks @43081j.
|
||||
- Fixed autocomplete not accepting returned `null` values, see #512.
|
||||
Thanks @43081j.
|
||||
- Fixed memory inefficiency when working with large JSON Schema's
|
||||
generating many errors. Thanks @43081j.
|
||||
|
||||
|
||||
## 2018-02-07, version 5.13.3
|
||||
|
||||
- Fixed a positioning issue with JSON Schema errors in text/code mode.
|
||||
|
||||
|
||||
## 2018-01-18, version 5.13.2
|
||||
|
||||
- Fixed view mode opening links in a new tab instead of current tab
|
||||
when Ctrl key is not down. Thanks @LEW21.
|
||||
- Fixed #502: code editor not showing a monospaced font some cases.
|
||||
|
||||
|
||||
## 2018-12-28, version 5.13.1
|
||||
## 2017-12-28, version 5.13.1
|
||||
|
||||
- Fixed another occurrence of #494: properties not escaped in the
|
||||
navigation bar.
|
||||
|
|
|
@ -67,10 +67,15 @@ with bower:
|
|||
|
||||
#### More
|
||||
|
||||
There is a directive available for using JSONEditor in Angular.js:
|
||||
|
||||
There is a directive available for using JSONEditor in AngularJS:
|
||||
|
||||
[https://github.com/isonet/angular-jsoneditor](https://github.com/isonet/angular-jsoneditor)
|
||||
|
||||
Directive for Angular 5.x as well:
|
||||
|
||||
[https://github.com/mariohmol/ang-jsoneditor](https://github.com/mariohmol/ang-jsoneditor)
|
||||
|
||||
|
||||
## Use
|
||||
|
||||
|
|
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
|
@ -310,7 +310,7 @@ div.jsoneditor td,
|
|||
div.jsoneditor th,
|
||||
div.jsoneditor textarea,
|
||||
.jsoneditor-schema-error {
|
||||
font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif;
|
||||
font-family: "dejavu sans mono", "droid sans mono", consolas, monaco, "lucida console", "courier new", courier, monospace, sans-serif;
|
||||
font-size: 10pt;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
@ -974,7 +974,7 @@ div.jsoneditor div.autocomplete.dropdown {
|
|||
padding-right: 5pt;
|
||||
text-align: left;
|
||||
outline: 0;
|
||||
font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif;
|
||||
font-family: "dejavu sans mono", "droid sans mono", consolas, monaco, "lucida console", "courier new", courier, monospace, sans-serif;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
|
@ -1021,7 +1021,7 @@ div.jsoneditor-treepath span.jsoneditor-treepath-seperator:hover {
|
|||
div.jsoneditor-statusbar {
|
||||
line-height: 26px;
|
||||
height: 26px;
|
||||
margin-top: -26px;
|
||||
margin-top: -1px;
|
||||
color: #808080;
|
||||
background-color: #ebebeb;
|
||||
border-top: 1px solid #d3d3d3;
|
||||
|
|
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
File diff suppressed because one or more lines are too long
25
docs/api.md
25
docs/api.md
|
@ -125,7 +125,7 @@ Constructs a new JSONEditor.
|
|||
|
||||
The following example allow you can create a "Person" node and a "Address" node, each one will appear in your context menu, once you selected the whole json object will be created.
|
||||
|
||||
```js
|
||||
```js
|
||||
var options = {
|
||||
templates: [
|
||||
{
|
||||
|
@ -226,6 +226,29 @@ Constructs a new JSONEditor.
|
|||
}
|
||||
```
|
||||
Only applicable when `mode` is 'tree'.
|
||||
|
||||
- `{string} language`
|
||||
|
||||
The default language comes from the browser navigator, but you can force a specific language. So use here string as 'en' or 'pt-BR'. Built-in languages: `en`, `pt-BR`. Other translations can be specified via the option `languages`.
|
||||
|
||||
|
||||
- `{Object} languages`
|
||||
|
||||
You can override existing translations or provide a new translation for a specific language. To do it provide an object at languages with language and the keys/values to be inserted. For example:
|
||||
|
||||
```
|
||||
'languages': {
|
||||
'pt-BR': {
|
||||
'auto': 'Automático testing'
|
||||
},
|
||||
'en': {
|
||||
'auto': 'Auto testing'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
All available fields for translation can be found in the source file `src/js/i18n.js`.
|
||||
|
||||
|
||||
### Methods
|
||||
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>JSONEditor | Translate</title>
|
||||
|
||||
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
|
||||
<script src="../dist/jsoneditor.js"></script>
|
||||
|
||||
<style type="text/css">
|
||||
#jsoneditor {
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>
|
||||
JSONEditor has support for multiple languages (i18n), in this case uses <code>pt-BR</code>.
|
||||
</p>
|
||||
<div id="jsoneditor"></div>
|
||||
|
||||
<script>
|
||||
// create the editor
|
||||
var container = document.getElementById('jsoneditor');
|
||||
var options = {
|
||||
// switch between pt-BR or en for testing forcing a language
|
||||
// leave blank to get language
|
||||
'language': 'pt-BR',
|
||||
'languages': {
|
||||
'pt-BR': {
|
||||
'auto': 'Automático testing'
|
||||
},
|
||||
'en': {
|
||||
'auto': 'Auto testing'
|
||||
},
|
||||
'newlang': {
|
||||
'auto': 'Auto new lang'
|
||||
}
|
||||
}
|
||||
};
|
||||
var editor = new JSONEditor(container, options);
|
||||
|
||||
var json = {
|
||||
'array': [1, 2, 3],
|
||||
'boolean': true,
|
||||
'null': null,
|
||||
'number': 123,
|
||||
'object': { 'a': 'b', 'c': 'd' },
|
||||
'string': 'Hello World'
|
||||
};
|
||||
editor.set(json);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "jsoneditor",
|
||||
"version": "5.13.1",
|
||||
"version": "5.14.1",
|
||||
"main": "./index",
|
||||
"description": "A web-based tool to view, edit, format, and validate JSON",
|
||||
"tags": [
|
||||
|
|
|
@ -13,7 +13,7 @@ div.jsoneditor div.autocomplete.dropdown {
|
|||
padding-right: 5pt;
|
||||
text-align: left;
|
||||
outline: 0;
|
||||
font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif;
|
||||
font-family: "dejavu sans mono", "droid sans mono", consolas, monaco, "lucida console", "courier new", courier, monospace, sans-serif;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ div.jsoneditor-contextmenu div.jsoneditor-icon {
|
|||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-image: url('img/jsoneditor-icons.svg');
|
||||
background-image: url('./img/jsoneditor-icons.svg');
|
||||
}
|
||||
|
||||
div.jsoneditor-contextmenu ul li ul div.jsoneditor-icon {
|
||||
|
@ -110,7 +110,7 @@ div.jsoneditor-contextmenu ul li button div.jsoneditor-expand {
|
|||
height: 24px;
|
||||
padding: 0;
|
||||
margin: 0 4px 0 0;
|
||||
background: url('img/jsoneditor-icons.svg') 0 -72px;
|
||||
background: url('./img/jsoneditor-icons.svg') 0 -72px;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ div.jsoneditor-tree button {
|
|||
margin: 0;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
background: transparent url('img/jsoneditor-icons.svg');
|
||||
background: transparent url('./img/jsoneditor-icons.svg');
|
||||
}
|
||||
|
||||
div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree,
|
||||
|
@ -263,7 +263,7 @@ tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu {
|
|||
}
|
||||
|
||||
div.jsoneditor-tree button.jsoneditor-dragarea {
|
||||
background: url('img/jsoneditor-icons.svg') -72px -72px;
|
||||
background: url('./img/jsoneditor-icons.svg') -72px -72px;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
|
@ -294,7 +294,7 @@ div.jsoneditor td,
|
|||
div.jsoneditor th,
|
||||
div.jsoneditor textarea,
|
||||
.jsoneditor-schema-error {
|
||||
font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif;
|
||||
font-family: "dejavu sans mono", "droid sans mono", consolas, monaco, "lucida console", "courier new", courier, monospace, sans-serif;
|
||||
font-size: 10pt;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ div.jsoneditor-tree .jsoneditor-schema-error {
|
|||
height: 24px;
|
||||
padding: 0;
|
||||
margin: 0 4px 0 0;
|
||||
background: url('img/jsoneditor-icons.svg') -168px -48px;
|
||||
background: url('./img/jsoneditor-icons.svg') -168px -48px;
|
||||
}
|
||||
|
||||
.jsoneditor-schema-error .jsoneditor-popover {
|
||||
|
@ -454,6 +454,6 @@ div.jsoneditor-tree .jsoneditor-schema-error {
|
|||
height: 24px;
|
||||
padding: 0;
|
||||
margin: 0 4px 0 0;
|
||||
background: url('img/jsoneditor-icons.svg') -168px -48px;
|
||||
background: url('./img/jsoneditor-icons.svg') -168px -48px;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ div.jsoneditor-menu > div.jsoneditor-modes > button {
|
|||
padding: 0;
|
||||
border-radius: 2px;
|
||||
border: 1px solid transparent;
|
||||
background: transparent url('img/jsoneditor-icons.svg');
|
||||
background: transparent url('./img/jsoneditor-icons.svg');
|
||||
color: white;
|
||||
opacity: 0.8;
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ table.jsoneditor-search button {
|
|||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
background: url('img/jsoneditor-icons.svg');
|
||||
background: url('./img/jsoneditor-icons.svg');
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
div.jsoneditor-statusbar {
|
||||
line-height: 26px;
|
||||
height: 26px;
|
||||
margin-top: -26px;
|
||||
margin-top: -1px;
|
||||
color: #808080;
|
||||
background-color: #ebebeb;
|
||||
border-top: 1px solid #d3d3d3;
|
||||
|
@ -9,7 +9,6 @@ div.jsoneditor-statusbar {
|
|||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
font-size: 10pt;
|
||||
|
||||
}
|
||||
|
||||
div.jsoneditor-statusbar > .jsoneditor-curserinfo-label {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
var util = require('./util');
|
||||
var translate = require('./i18n').translate;
|
||||
|
||||
/**
|
||||
* Node.getRootNode shim
|
||||
|
@ -151,7 +152,7 @@ function ContextMenu (items, options) {
|
|||
else {
|
||||
// no submenu, just a button with clickhandler
|
||||
button.innerHTML = '<div class="jsoneditor-icon"></div>' +
|
||||
'<div class="jsoneditor-text">' + item.text + '</div>';
|
||||
'<div class="jsoneditor-text">' + translate(item.text) + '</div>';
|
||||
}
|
||||
|
||||
domItems.push(domItem);
|
||||
|
|
|
@ -91,7 +91,7 @@ function JSONEditor (container, options, json) {
|
|||
'ace', 'theme','autocomplete',
|
||||
'onChange', 'onEditable', 'onError', 'onModeChange', 'onSelectionChange', 'onTextSelectionChange',
|
||||
'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation',
|
||||
'sortObjectKeys', 'navigationBar', 'statusBar'
|
||||
'sortObjectKeys', 'navigationBar', 'statusBar', 'languages', 'language'
|
||||
];
|
||||
|
||||
Object.keys(options).forEach(function (option) {
|
||||
|
|
|
@ -4,6 +4,7 @@ var naturalSort = require('javascript-natural-sort');
|
|||
var ContextMenu = require('./ContextMenu');
|
||||
var appendNodeFactory = require('./appendNodeFactory');
|
||||
var util = require('./util');
|
||||
var translate = require('./i18n').translate;
|
||||
|
||||
/**
|
||||
* @constructor Node
|
||||
|
@ -995,7 +996,7 @@ Node.prototype._move = function(node, beforeNode) {
|
|||
|
||||
// check if this node is not a child of the node to be moved here
|
||||
if (node.containsNode(this)) {
|
||||
throw new Error('Cannot move a field into a child of itself');
|
||||
throw new Error(translate('validationCannotMove'));
|
||||
}
|
||||
|
||||
// remove the original node
|
||||
|
@ -1239,14 +1240,15 @@ Node.prototype._onChangeField = function () {
|
|||
// get current selection, then override the range such that we can select
|
||||
// the added/removed text on undo/redo
|
||||
var oldSelection = this.editor.getDomSelection();
|
||||
var previous = this.previousField || '';
|
||||
if (oldSelection.range) {
|
||||
var undoDiff = util.textDiff(this.field, this.previousField);
|
||||
var undoDiff = util.textDiff(this.field, previous);
|
||||
oldSelection.range.startOffset = undoDiff.start;
|
||||
oldSelection.range.endOffset = undoDiff.end;
|
||||
}
|
||||
var newSelection = this.editor.getDomSelection();
|
||||
if (newSelection.range) {
|
||||
var redoDiff = util.textDiff(this.previousField, this.field);
|
||||
var redoDiff = util.textDiff(previous, this.field);
|
||||
newSelection.range.startOffset = redoDiff.start;
|
||||
newSelection.range.endOffset = redoDiff.end;
|
||||
}
|
||||
|
@ -1306,7 +1308,7 @@ Node.prototype._updateDomValue = function () {
|
|||
domValue.title = this.type + ' containing ' + count + ' items';
|
||||
}
|
||||
else if (isUrl && this.editable.value) {
|
||||
domValue.title = 'Ctrl+Click or Ctrl+Enter to open url in new window';
|
||||
domValue.title = translate('openUrl');
|
||||
}
|
||||
else {
|
||||
domValue.title = '';
|
||||
|
@ -1493,7 +1495,7 @@ Node.prototype.validate = function () {
|
|||
return {
|
||||
node: node,
|
||||
error: {
|
||||
message: 'duplicate key "' + node.field + '"'
|
||||
message: translate('duplicateKey') + ' "' + node.field + '"'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1550,7 +1552,7 @@ Node.prototype.getDom = function() {
|
|||
domDrag.type = 'button';
|
||||
dom.drag = domDrag;
|
||||
domDrag.className = 'jsoneditor-dragarea';
|
||||
domDrag.title = 'Drag to move this field (Alt+Shift+Arrows)';
|
||||
domDrag.title = translate('drag');
|
||||
tdDrag.appendChild(domDrag);
|
||||
}
|
||||
}
|
||||
|
@ -1562,7 +1564,7 @@ Node.prototype.getDom = function() {
|
|||
menu.type = 'button';
|
||||
dom.menu = menu;
|
||||
menu.className = 'jsoneditor-contextmenu';
|
||||
menu.title = 'Click to open the actions menu (Ctrl+M)';
|
||||
menu.title = translate('actionsMenu');
|
||||
tdMenu.appendChild(dom.menu);
|
||||
dom.tr.appendChild(tdMenu);
|
||||
}
|
||||
|
@ -2219,9 +2221,7 @@ Node.prototype._createDomExpandButton = function () {
|
|||
expand.type = 'button';
|
||||
if (this._hasChilds()) {
|
||||
expand.className = this.expanded ? 'jsoneditor-expanded' : 'jsoneditor-collapsed';
|
||||
expand.title =
|
||||
'Click to expand/collapse this field (Ctrl+E). \n' +
|
||||
'Ctrl+Click to expand/collapse including all childs.';
|
||||
expand.title = translate('expandTitle');
|
||||
}
|
||||
else {
|
||||
expand.className = 'jsoneditor-invisible';
|
||||
|
@ -3249,16 +3249,10 @@ Node.prototype._hasChilds = function () {
|
|||
|
||||
// titles with explanation for the different types
|
||||
Node.TYPE_TITLES = {
|
||||
'auto': 'Field type "auto". ' +
|
||||
'The field type is automatically determined from the value ' +
|
||||
'and can be a string, number, boolean, or null.',
|
||||
'object': 'Field type "object". ' +
|
||||
'An object contains an unordered set of key/value pairs.',
|
||||
'array': 'Field type "array". ' +
|
||||
'An array contains an ordered collection of values.',
|
||||
'string': 'Field type "string". ' +
|
||||
'Field type is not determined from the value, ' +
|
||||
'but always returned as string.'
|
||||
'auto': translate('autoType'),
|
||||
'object': translate('objectType'),
|
||||
'array': translate('arrayType'),
|
||||
'string': translate('stringType')
|
||||
};
|
||||
|
||||
Node.prototype.addTemplates = function (menu, append) {
|
||||
|
@ -3301,12 +3295,12 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
|
||||
if (this.editable.value) {
|
||||
items.push({
|
||||
text: 'Type',
|
||||
title: 'Change the type of this field',
|
||||
text: translate('type'),
|
||||
title: translate('typeTitle'),
|
||||
className: 'jsoneditor-type-' + this.type,
|
||||
submenu: [
|
||||
{
|
||||
text: 'Auto',
|
||||
text: translate('auto'),
|
||||
className: 'jsoneditor-type-auto' +
|
||||
(this.type == 'auto' ? ' jsoneditor-selected' : ''),
|
||||
title: titles.auto,
|
||||
|
@ -3315,7 +3309,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
}
|
||||
},
|
||||
{
|
||||
text: 'Array',
|
||||
text: translate('array'),
|
||||
className: 'jsoneditor-type-array' +
|
||||
(this.type == 'array' ? ' jsoneditor-selected' : ''),
|
||||
title: titles.array,
|
||||
|
@ -3324,7 +3318,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
}
|
||||
},
|
||||
{
|
||||
text: 'Object',
|
||||
text: translate('object'),
|
||||
className: 'jsoneditor-type-object' +
|
||||
(this.type == 'object' ? ' jsoneditor-selected' : ''),
|
||||
title: titles.object,
|
||||
|
@ -3333,7 +3327,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
}
|
||||
},
|
||||
{
|
||||
text: 'String',
|
||||
text: translate('string'),
|
||||
className: 'jsoneditor-type-string' +
|
||||
(this.type == 'string' ? ' jsoneditor-selected' : ''),
|
||||
title: titles.string,
|
||||
|
@ -3348,25 +3342,25 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
if (this._hasChilds()) {
|
||||
var direction = ((this.sortOrder == 'asc') ? 'desc': 'asc');
|
||||
items.push({
|
||||
text: 'Sort',
|
||||
title: 'Sort the childs of this ' + this.type,
|
||||
text: translate('sort'),
|
||||
title: translate('sortTitle') + this.type,
|
||||
className: 'jsoneditor-sort-' + direction,
|
||||
click: function () {
|
||||
node.sort(direction);
|
||||
},
|
||||
submenu: [
|
||||
{
|
||||
text: 'Ascending',
|
||||
text: translate('ascending'),
|
||||
className: 'jsoneditor-sort-asc',
|
||||
title: 'Sort the childs of this ' + this.type + ' in ascending order',
|
||||
title: translate('ascendingTitle' , {type: this.type}),
|
||||
click: function () {
|
||||
node.sort('asc');
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'Descending',
|
||||
text: translate('descending'),
|
||||
className: 'jsoneditor-sort-desc',
|
||||
title: 'Sort the childs of this ' + this.type +' in descending order',
|
||||
title: translate('descendingTitle' , {type: this.type}),
|
||||
click: function () {
|
||||
node.sort('desc');
|
||||
}
|
||||
|
@ -3388,7 +3382,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
if (node == childs[childs.length - 1]) {
|
||||
var appendSubmenu = [
|
||||
{
|
||||
text: 'Auto',
|
||||
text: translate('auto'),
|
||||
className: 'jsoneditor-type-auto',
|
||||
title: titles.auto,
|
||||
click: function () {
|
||||
|
@ -3396,7 +3390,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
}
|
||||
},
|
||||
{
|
||||
text: 'Array',
|
||||
text: translate('array'),
|
||||
className: 'jsoneditor-type-array',
|
||||
title: titles.array,
|
||||
click: function () {
|
||||
|
@ -3404,7 +3398,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
}
|
||||
},
|
||||
{
|
||||
text: 'Object',
|
||||
text: translate('object'),
|
||||
className: 'jsoneditor-type-object',
|
||||
title: titles.object,
|
||||
click: function () {
|
||||
|
@ -3412,7 +3406,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
}
|
||||
},
|
||||
{
|
||||
text: 'String',
|
||||
text: translate('string'),
|
||||
className: 'jsoneditor-type-string',
|
||||
title: titles.string,
|
||||
click: function () {
|
||||
|
@ -3422,9 +3416,9 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
];
|
||||
node.addTemplates(appendSubmenu, true);
|
||||
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',
|
||||
text: translate('appendText'),
|
||||
title: translate('appendTitle'),
|
||||
submenuTitle: translate('appendSubmenuTitle'),
|
||||
className: 'jsoneditor-append',
|
||||
click: function () {
|
||||
node._onAppend('', '', 'auto');
|
||||
|
@ -3438,7 +3432,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
// create insert button
|
||||
var insertSubmenu = [
|
||||
{
|
||||
text: 'Auto',
|
||||
text: translate('auto'),
|
||||
className: 'jsoneditor-type-auto',
|
||||
title: titles.auto,
|
||||
click: function () {
|
||||
|
@ -3446,7 +3440,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
}
|
||||
},
|
||||
{
|
||||
text: 'Array',
|
||||
text: translate('array'),
|
||||
className: 'jsoneditor-type-array',
|
||||
title: titles.array,
|
||||
click: function () {
|
||||
|
@ -3454,7 +3448,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
}
|
||||
},
|
||||
{
|
||||
text: 'Object',
|
||||
text: translate('object'),
|
||||
className: 'jsoneditor-type-object',
|
||||
title: titles.object,
|
||||
click: function () {
|
||||
|
@ -3462,7 +3456,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
}
|
||||
},
|
||||
{
|
||||
text: 'String',
|
||||
text: translate('string'),
|
||||
className: 'jsoneditor-type-string',
|
||||
title: titles.string,
|
||||
click: function () {
|
||||
|
@ -3472,9 +3466,9 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
];
|
||||
node.addTemplates(insertSubmenu, false);
|
||||
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',
|
||||
text: translate('insert'),
|
||||
title: translate('insertTitle'),
|
||||
submenuTitle: translate('insertSub'),
|
||||
className: 'jsoneditor-insert',
|
||||
click: function () {
|
||||
node._onInsertBefore('', '', 'auto');
|
||||
|
@ -3485,8 +3479,8 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
if (this.editable.field) {
|
||||
// create duplicate button
|
||||
items.push({
|
||||
text: 'Duplicate',
|
||||
title: 'Duplicate this field (Ctrl+D)',
|
||||
text: translate('duplicateText'),
|
||||
title: translate('duplicateField'),
|
||||
className: 'jsoneditor-duplicate',
|
||||
click: function () {
|
||||
Node.onDuplicate(node);
|
||||
|
@ -3495,8 +3489,8 @@ Node.prototype.showContextMenu = function (anchor, onClose) {
|
|||
|
||||
// create remove button
|
||||
items.push({
|
||||
text: 'Remove',
|
||||
title: 'Remove this field (Ctrl+Del)',
|
||||
text: translate('removeText'),
|
||||
title: translate('removeField'),
|
||||
className: 'jsoneditor-remove',
|
||||
click: function () {
|
||||
Node.onRemove(node);
|
||||
|
|
|
@ -38,7 +38,7 @@ color: #333\
|
|||
}\
|
||||
\
|
||||
.ace-jsoneditor.ace_editor {\
|
||||
font-family: droid sans mono, consolas, monospace, courier new, courier, sans-serif;\
|
||||
font-family: \"dejavu sans mono\", \"droid sans mono\", consolas, monaco, \"lucida console\", \"courier new\", courier, monospace, sans-serif;\
|
||||
line-height: 1.3;\
|
||||
background-color: #fff;\
|
||||
}\
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
var util = require('./util');
|
||||
var ContextMenu = require('./ContextMenu');
|
||||
var translate = require('./i18n').translate;
|
||||
|
||||
/**
|
||||
* A factory function to create an AppendNode, which depends on a Node
|
||||
|
@ -62,7 +63,7 @@ function appendNodeFactory(Node) {
|
|||
// a cell for the contents (showing text 'empty')
|
||||
var tdAppend = document.createElement('td');
|
||||
var domText = document.createElement('div');
|
||||
domText.innerHTML = '(empty)';
|
||||
domText.innerHTML = '(' + translate('empty') + ')';
|
||||
domText.className = 'jsoneditor-readonly';
|
||||
tdAppend.appendChild(domText);
|
||||
dom.td = tdAppend;
|
||||
|
@ -86,7 +87,7 @@ function appendNodeFactory(Node) {
|
|||
|
||||
var domText = dom.text;
|
||||
if (domText) {
|
||||
domText.innerHTML = '(empty ' + this.parent.type + ')';
|
||||
domText.innerHTML = '(' + translate('empty') + ' ' + this.parent.type + ')';
|
||||
}
|
||||
|
||||
// attach or detach the contents of the append node:
|
||||
|
@ -136,7 +137,7 @@ function appendNodeFactory(Node) {
|
|||
var titles = Node.TYPE_TITLES;
|
||||
var appendSubmenu = [
|
||||
{
|
||||
text: 'Auto',
|
||||
text: translate('auto'),
|
||||
className: 'jsoneditor-type-auto',
|
||||
title: titles.auto,
|
||||
click: function () {
|
||||
|
@ -144,7 +145,7 @@ function appendNodeFactory(Node) {
|
|||
}
|
||||
},
|
||||
{
|
||||
text: 'Array',
|
||||
text: translate('array'),
|
||||
className: 'jsoneditor-type-array',
|
||||
title: titles.array,
|
||||
click: function () {
|
||||
|
@ -152,7 +153,7 @@ function appendNodeFactory(Node) {
|
|||
}
|
||||
},
|
||||
{
|
||||
text: 'Object',
|
||||
text: translate('object'),
|
||||
className: 'jsoneditor-type-object',
|
||||
title: titles.object,
|
||||
click: function () {
|
||||
|
@ -160,7 +161,7 @@ function appendNodeFactory(Node) {
|
|||
}
|
||||
},
|
||||
{
|
||||
text: 'String',
|
||||
text: translate('string'),
|
||||
className: 'jsoneditor-type-string',
|
||||
title: titles.string,
|
||||
click: function () {
|
||||
|
@ -172,9 +173,9 @@ function appendNodeFactory(Node) {
|
|||
var items = [
|
||||
// create append button
|
||||
{
|
||||
'text': 'Append',
|
||||
'title': 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)',
|
||||
'submenuTitle': 'Select the type of the field to be appended',
|
||||
'text': translate('appendText'),
|
||||
'title': translate('appendTitleAuto'),
|
||||
'submenuTitle': translate('appendSubmenuTitle'),
|
||||
'className': 'jsoneditor-insert',
|
||||
'click': function () {
|
||||
node._onAppend('', '', 'auto');
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
'use strict';
|
||||
|
||||
var _locales = ['en', 'pt-BR'];
|
||||
var _defs = {
|
||||
en: {
|
||||
'array': 'Array',
|
||||
'auto': 'Auto',
|
||||
'appendText': 'Append',
|
||||
'appendTitle': 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)',
|
||||
'appendSubmenuTitle': 'Select the type of the field to be appended',
|
||||
'appendTitleAuto': 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)',
|
||||
'ascending': 'Ascending',
|
||||
'ascendingTitle': 'Sort the childs of this ${type} in ascending order',
|
||||
'actionsMenu': 'Click to open the actions menu (Ctrl+M)',
|
||||
'collapseAll': 'Collapse all fields',
|
||||
'descending': 'Descending',
|
||||
'descendingTitle': 'Sort the childs of this ${type} in descending order',
|
||||
'drag': 'Drag to move this field (Alt+Shift+Arrows)',
|
||||
'duplicateKey': 'duplicate key',
|
||||
'duplicateText': 'Duplicate',
|
||||
'duplicateTitle': 'Duplicate selected fields (Ctrl+D)',
|
||||
'duplicateField': 'Duplicate this field (Ctrl+D)',
|
||||
'empty': 'empty',
|
||||
'expandAll': 'Expand all fields',
|
||||
'expandTitle': 'Click to expand/collapse this field (Ctrl+E). \n' +
|
||||
'Ctrl+Click to expand/collapse including all childs.',
|
||||
'insert': 'Insert',
|
||||
'insertTitle': 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)',
|
||||
'insertSub': 'Select the type of the field to be inserted',
|
||||
'object': 'Object',
|
||||
'redo': 'Redo (Ctrl+Shift+Z)',
|
||||
'removeText': 'Remove',
|
||||
'removeTitle': 'Remove selected fields (Ctrl+Del)',
|
||||
'removeField': 'Remove this field (Ctrl+Del)',
|
||||
'sort': 'Sort',
|
||||
'sortTitle': 'Sort the childs of this ',
|
||||
'string': 'String',
|
||||
'type': 'Type',
|
||||
'typeTitle': 'Change the type of this field',
|
||||
'openUrl': 'Ctrl+Click or Ctrl+Enter to open url in new window',
|
||||
'undo': 'Undo last action (Ctrl+Z)',
|
||||
'validationCannotMove': 'Cannot move a field into a child of itself',
|
||||
'autoType': 'Field type "auto". ' +
|
||||
'The field type is automatically determined from the value ' +
|
||||
'and can be a string, number, boolean, or null.',
|
||||
'objectType': 'Field type "object". ' +
|
||||
'An object contains an unordered set of key/value pairs.',
|
||||
'arrayType': 'Field type "array". ' +
|
||||
'An array contains an ordered collection of values.',
|
||||
'stringType': 'Field type "string". ' +
|
||||
'Field type is not determined from the value, ' +
|
||||
'but always returned as string.'
|
||||
},
|
||||
'pt-BR': {
|
||||
'array': 'Lista',
|
||||
'auto': 'Automatico',
|
||||
'appendText': 'Adicionar',
|
||||
'appendTitle': 'Adicionar novo campo com tipo \'auto\' depois deste campo (Ctrl+Shift+Ins)',
|
||||
'appendSubmenuTitle': 'Selecione o tipo do campo a ser adicionado',
|
||||
'appendTitleAuto': 'Adicionar novo campo com tipo \'auto\' (Ctrl+Shift+Ins)',
|
||||
'ascending': 'Ascendente',
|
||||
'ascendingTitle': 'Organizar filhor do tipo ${type} em crescente',
|
||||
'actionsMenu': 'Clique para abrir o menu de ações (Ctrl+M)',
|
||||
'collapseAll': 'Fechar todos campos',
|
||||
'descending': 'Descendente',
|
||||
'descendingTitle': 'Organizar o filhos do tipo ${type} em decrescente',
|
||||
'duplicateKey': 'chave duplicada',
|
||||
'drag': 'Arraste para mover este campo (Alt+Shift+Arrows)',
|
||||
'duplicateText': 'Duplicar',
|
||||
'duplicateTitle': 'Duplicar campos selecionados (Ctrl+D)',
|
||||
'duplicateField': 'Duplicar este campo (Ctrl+D)',
|
||||
'empty': 'vazio',
|
||||
'expandAll': 'Expandir todos campos',
|
||||
'expandTitle': 'Clique para expandir/encolher este campo (Ctrl+E). \n' +
|
||||
'Ctrl+Click para expandir/encolher incluindo todos os filhos.',
|
||||
'insert': 'Inserir',
|
||||
'insertTitle': 'Inserir um novo campo do tipo \'auto\' antes deste campo (Ctrl+Ins)',
|
||||
'insertSub': 'Selecionar o tipo de campo a ser inserido',
|
||||
'object': 'Objeto',
|
||||
'redo': 'Refazer (Ctrl+Shift+Z)',
|
||||
'removeText': 'Remover',
|
||||
'removeTitle': 'Remover campos selecionados (Ctrl+Del)',
|
||||
'removeField': 'Remover este campo (Ctrl+Del)',
|
||||
'sort': 'Organizar',
|
||||
'sortTitle': 'Organizar os filhos deste ',
|
||||
'string': 'Texto',
|
||||
'type': 'Tipo',
|
||||
'typeTitle': 'Mudar o tipo deste campo',
|
||||
'openUrl': 'Ctrl+Click ou Ctrl+Enter para abrir link em nova janela',
|
||||
'undo': 'Desfazer último ação (Ctrl+Z)',
|
||||
'validationCannotMove': 'Não pode mover um campo como filho dele mesmo',
|
||||
'autoType': 'Campo do tipo "auto". ' +
|
||||
'O tipo do campo é determinao automaticamente a partir do seu valor ' +
|
||||
'e pode ser texto, número, verdade/falso ou nulo.',
|
||||
'objectType': 'Campo do tipo "objeto". ' +
|
||||
'Um objeto contém uma lista de pares com chave e valor.',
|
||||
'arrayType': 'Campo do tipo "lista". ' +
|
||||
'Uma lista contem uma coleção de valores ordenados.',
|
||||
'stringType': 'Campo do tipo "string". ' +
|
||||
'Campo do tipo nao é determinado através do seu valor, ' +
|
||||
'mas sempre retornara um texto.'
|
||||
}
|
||||
};
|
||||
|
||||
var _defaultLang = 'en';
|
||||
var _lang;
|
||||
var userLang = navigator.language || navigator.userLanguage;
|
||||
_lang = _locales.find(function (l) {
|
||||
return l === userLang;
|
||||
});
|
||||
if (!_lang) {
|
||||
_lang = _defaultLang;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
// supported locales
|
||||
_locales: _locales,
|
||||
_defs: _defs,
|
||||
_lang: _lang,
|
||||
setLanguage: function (lang) {
|
||||
if (!lang) {
|
||||
return;
|
||||
}
|
||||
var langFound = _locales.find(function (l) {
|
||||
return l === lang;
|
||||
});
|
||||
if (langFound) {
|
||||
_lang = langFound;
|
||||
} else {
|
||||
console.error('Language not found');
|
||||
}
|
||||
},
|
||||
setLanguages: function (languages) {
|
||||
if (!languages) {
|
||||
return;
|
||||
}
|
||||
for (var key in languages) {
|
||||
var langFound = _locales.find(function (l) {
|
||||
return l === key;
|
||||
});
|
||||
if (!langFound) {
|
||||
_locales.push(key);
|
||||
}
|
||||
_defs[key] = Object.assign({}, _defs[_defaultLang], _defs[key], languages[key]);
|
||||
}
|
||||
},
|
||||
translate: function (key, data, lang) {
|
||||
if (!lang) {
|
||||
lang = _lang;
|
||||
}
|
||||
var text = _defs[lang][key];
|
||||
if (data) {
|
||||
for (key in data) {
|
||||
text = text.replace('${' + key + '}', data[key]);
|
||||
}
|
||||
}
|
||||
return text || key;
|
||||
}
|
||||
};
|
|
@ -252,11 +252,17 @@ textmode.create = function (container, options) {
|
|||
textarea.onblur = this._onBlur.bind(this);
|
||||
}
|
||||
|
||||
var validationErrorsContainer = document.createElement('div');
|
||||
validationErrorsContainer.className = 'validation-errors-container';
|
||||
this.dom.validationErrorsContainer = validationErrorsContainer;
|
||||
this.frame.appendChild(validationErrorsContainer);
|
||||
|
||||
if (options.statusBar) {
|
||||
util.addClassName(this.content, 'has-status-bar');
|
||||
|
||||
this.curserInfoElements = {};
|
||||
var statusBar = document.createElement('div');
|
||||
this.dom.statusBar = statusBar;
|
||||
statusBar.className = 'jsoneditor-statusbar';
|
||||
this.frame.appendChild(statusBar);
|
||||
|
||||
|
@ -651,9 +657,10 @@ textmode.validate = function () {
|
|||
'</table>';
|
||||
|
||||
this.dom.validationErrors = validationErrors;
|
||||
this.frame.appendChild(validationErrors);
|
||||
this.dom.validationErrorsContainer.appendChild(validationErrors);
|
||||
|
||||
var height = validationErrors.clientHeight;
|
||||
var height = validationErrors.clientHeight +
|
||||
(this.dom.statusBar ? this.dom.statusBar.clientHeight : 0);
|
||||
this.content.style.marginBottom = (-height) + 'px';
|
||||
this.content.style.paddingBottom = height + 'px';
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@ var Node = require('./Node');
|
|||
var ModeSwitcher = require('./ModeSwitcher');
|
||||
var util = require('./util');
|
||||
var autocomplete = require('./autocomplete');
|
||||
var translate = require('./i18n').translate;
|
||||
var setLanguages = require('./i18n').setLanguages;
|
||||
var setLanguage = require('./i18n').setLanguage;
|
||||
|
||||
// create a mixin with the functions for tree mode
|
||||
var treemode = {};
|
||||
|
@ -137,6 +140,9 @@ treemode._setOptions = function (options) {
|
|||
if (options.onSelectionChange) {
|
||||
this.onSelectionChange(options.onSelectionChange);
|
||||
}
|
||||
|
||||
setLanguages(this.options.languages);
|
||||
setLanguage(this.options.language)
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -440,28 +446,35 @@ treemode.validate = function () {
|
|||
}
|
||||
}
|
||||
|
||||
// display the error in the nodes with a problem
|
||||
this.errorNodes = duplicateErrors
|
||||
.concat(schemaErrors)
|
||||
.reduce(function expandParents (all, entry) {
|
||||
// expand parents, then merge such that parents come first and
|
||||
// original entries last
|
||||
return entry.node
|
||||
.findParents()
|
||||
.map(function (parent) {
|
||||
return {
|
||||
node: parent,
|
||||
child: entry.node,
|
||||
error: {
|
||||
message: parent.type === 'object'
|
||||
? 'Contains invalid properties' // object
|
||||
: 'Contains invalid items' // array
|
||||
}
|
||||
};
|
||||
})
|
||||
.concat(all, [entry]);
|
||||
}, [])
|
||||
// TODO: dedupe the parent nodes
|
||||
var errorNodes = duplicateErrors.concat(schemaErrors);
|
||||
var parentPairs = errorNodes
|
||||
.reduce(function (all, entry) {
|
||||
return entry.node
|
||||
.findParents()
|
||||
.filter(function (parent) {
|
||||
return !all.some(function (pair) {
|
||||
return pair[0] === parent;
|
||||
});
|
||||
})
|
||||
.map(function (parent) {
|
||||
return [parent, entry.node];
|
||||
})
|
||||
.concat(all);
|
||||
}, []);
|
||||
|
||||
this.errorNodes = parentPairs
|
||||
.map(function (pair) {
|
||||
return {
|
||||
node: pair[0],
|
||||
child: pair[1],
|
||||
error: {
|
||||
message: pair[0].type === 'object'
|
||||
? 'Contains invalid properties' // object
|
||||
: 'Contains invalid items' // array
|
||||
}
|
||||
};
|
||||
})
|
||||
.concat(errorNodes)
|
||||
.map(function setError (entry) {
|
||||
entry.node.setError(entry.error, entry.child);
|
||||
return entry.node;
|
||||
|
@ -700,7 +713,7 @@ treemode._createFrame = function () {
|
|||
var expandAll = document.createElement('button');
|
||||
expandAll.type = 'button';
|
||||
expandAll.className = 'jsoneditor-expand-all';
|
||||
expandAll.title = 'Expand all fields';
|
||||
expandAll.title = translate('expandAll');
|
||||
expandAll.onclick = function () {
|
||||
editor.expandAll();
|
||||
};
|
||||
|
@ -709,7 +722,7 @@ treemode._createFrame = function () {
|
|||
// create collapse all button
|
||||
var collapseAll = document.createElement('button');
|
||||
collapseAll.type = 'button';
|
||||
collapseAll.title = 'Collapse all fields';
|
||||
collapseAll.title = translate('collapseAll');
|
||||
collapseAll.className = 'jsoneditor-collapse-all';
|
||||
collapseAll.onclick = function () {
|
||||
editor.collapseAll();
|
||||
|
@ -722,7 +735,7 @@ treemode._createFrame = function () {
|
|||
var undo = document.createElement('button');
|
||||
undo.type = 'button';
|
||||
undo.className = 'jsoneditor-undo jsoneditor-separator';
|
||||
undo.title = 'Undo last action (Ctrl+Z)';
|
||||
undo.title = translate('undo');
|
||||
undo.onclick = function () {
|
||||
editor._onUndo();
|
||||
};
|
||||
|
@ -733,7 +746,7 @@ treemode._createFrame = function () {
|
|||
var redo = document.createElement('button');
|
||||
redo.type = 'button';
|
||||
redo.className = 'jsoneditor-redo';
|
||||
redo.title = 'Redo (Ctrl+Shift+Z)';
|
||||
redo.title = translate('redo');
|
||||
redo.onclick = function () {
|
||||
editor._onRedo();
|
||||
};
|
||||
|
@ -1233,13 +1246,18 @@ treemode._onKeyDown = function (event) {
|
|||
setTimeout(function (hnode, element) {
|
||||
if (element.innerText.length > 0) {
|
||||
var result = this.options.autocomplete.getOptions(element.innerText, hnode.getPath(), jsonElementType, hnode.editor);
|
||||
if (typeof result.then === 'function') {
|
||||
if (result === null) {
|
||||
this.autocomplete.hideDropDown();
|
||||
} else if (typeof result.then === 'function') {
|
||||
// probably a promise
|
||||
if (result.then(function (obj) {
|
||||
if (obj.options)
|
||||
if (obj === null) {
|
||||
this.autocomplete.hideDropDown();
|
||||
} else if (obj.options) {
|
||||
this.autocomplete.show(element, obj.startFrom, obj.options);
|
||||
else
|
||||
} else {
|
||||
this.autocomplete.show(element, 0, obj);
|
||||
}
|
||||
}.bind(this)));
|
||||
} else {
|
||||
// definitely not a promise
|
||||
|
@ -1317,8 +1335,8 @@ treemode.showContextMenu = function (anchor, onClose) {
|
|||
|
||||
// create duplicate button
|
||||
items.push({
|
||||
text: 'Duplicate',
|
||||
title: 'Duplicate selected fields (Ctrl+D)',
|
||||
text: translate('duplicateText'),
|
||||
title: translate('duplicateTitle'),
|
||||
className: 'jsoneditor-duplicate',
|
||||
click: function () {
|
||||
Node.onDuplicate(editor.multiselection.nodes);
|
||||
|
@ -1327,8 +1345,8 @@ treemode.showContextMenu = function (anchor, onClose) {
|
|||
|
||||
// create remove button
|
||||
items.push({
|
||||
text: 'Remove',
|
||||
title: 'Remove selected fields (Ctrl+Del)',
|
||||
text: translate('remove'),
|
||||
title: translate('removeTitle'),
|
||||
className: 'jsoneditor-remove',
|
||||
click: function () {
|
||||
Node.onRemove(editor.multiselection.nodes);
|
||||
|
|
Loading…
Reference in New Issue