Compare commits

...

955 Commits

Author SHA1 Message Date
ZaneYork ecebf360b3 Add text-plain mode 2020-10-16 15:32:07 +08:00
dependabot-preview[bot] b64e012da8
Bump uglify-js from 3.10.4 to 3.11.1 (#1123)
Bumps [uglify-js](https://github.com/mishoo/UglifyJS) from 3.10.4 to 3.11.1.
- [Release notes](https://github.com/mishoo/UglifyJS/releases)
- [Commits](https://github.com/mishoo/UglifyJS/compare/v3.10.4...v3.11.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-07 09:56:16 +02:00
Jos de Jong 8eb4819d0e Fix lint error 2020-09-23 15:49:44 +02:00
Jos de Jong e35e39ff2f Merge remote-tracking branch 'origin/develop' into develop 2020-09-23 15:44:11 +02:00
Jos de Jong 58f460a383 Log a clear error in the console when the returned value of `onEditable` is invalid. See #1112 2020-09-23 15:44:04 +02:00
dependabot-preview[bot] 1492f22eea
Bump webpack from 4.44.1 to 4.44.2 (#1114)
Bumps [webpack](https://github.com/webpack/webpack) from 4.44.1 to 4.44.2.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v4.44.1...v4.44.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-09-23 11:40:05 +02:00
Jos de Jong 223b78542e Publish v9.1.1 2020-09-23 10:33:34 +02:00
Jos de Jong e1a8077dc1 Fix quick-key `Ctrl+D` (duplicate) not working 2020-09-23 10:27:47 +02:00
Jos de Jong 745a1597dd Fix linter issue 2020-09-23 10:25:26 +02:00
Jos de Jong 2a861a2868 Defined charset="utf-8" and lang="en" in all examples 2020-09-23 10:23:38 +02:00
Josh Kelley 69fbe63f0e
Multi-select mouse events now honor the event's window (#1098)
* Multi-select mouse events now honor the event's window

This prevents errors from opening JSONEditor in a child window (such as `window.open` or third-party libraries like react-new-window).

* Add a demo of showing a JSONEditor in a child window

* Minor spelling fixes

* Further improvements to new window support

Use `event.view` instead of the global `window`. Copy VanillaPicker styles in the example so that the color picker is correctly styled.

* Add 'noopener'

This helps security; otherwise, JavaScript running in the context of the new window can access the original window object via the `window.opener` property, even if it's a different origin.

* Update modal handling for new windows

There are two approaches we could take; we could use the existing modalAnchor property and make callers responsible for setting it, or we could modify the default handling to default to the node's container body. For now, I chose to make callers responsible.

Rename showTransformModal's `anchor` parameter to `container`; as far as I can tell, `anchor` didn't work properly.
2020-09-23 10:06:12 +02:00
Jos de Jong f3694c3126 Update history 2020-09-23 09:45:37 +02:00
Žiga Miklič 6cf627a61a
Fix for issue #1111 (#1116)
Fixes enum dropdown not showing when using patternProperties for schema.

The issue happens as `_findSchema` is recursively called one more than than it should. Instead of returning the nested schema object (eg. `{ enum: [1, 2, 3] }`), it returns the parent object, eg.:

```javascript
{
  type: 'object',
  properties: {
    testrigId: {
      enum: [1, 2, 3]
    },
  },
  required: [
    'testrigId'
  ]
}
```

The fix adds an if check to ignore the additional recursive call and return the correct object.

The unit tests pass and I've also tested a complex schema inside `patternProperties` that uses the special types (boolean, color, enum).
2020-09-23 09:43:44 +02:00
Jos de Jong 41fbf6973f Publish v9.1.0 2020-09-15 20:51:01 +02:00
Jos de Jong 07e4221fad Fix quick-keys `Ctrl-\` (format) and `Ctrl-Shift-\` (compact) not working in `code` mode (see #1107) 2020-09-15 20:47:28 +02:00
Jos de Jong 8855944bae Update history and docs with new translation `de` 2020-09-14 20:05:34 +02:00
Stephan Ahlf 09b8ed8af6
Add German language support to i18n.js (#1105)
* Add German language support to i18n.js

* add `de` to `_locales` variable

* fix code format to fit JavaScript Standard Style

* fix variable typo in "de" dictionary

* add new containsInvalidProperties and containsInvalidItems translation keys to german i18n dictionary

Co-authored-by: s-a <stephan.ahlf@gmail.com>
2020-09-14 19:59:29 +02:00
Jos de Jong 2aee4a6008 Add translation for the texts "Contains invalid properties" and "Contains invalid items" (see #1105) 2020-09-12 17:33:37 +02:00
Jos de Jong 2314aa74e5 Publish v9.0.5 2020-09-09 09:36:06 +02:00
Jos de Jong 12fd998cc1 Update `uglify-js` to the latest version 2020-09-09 09:34:03 +02:00
Jos de Jong 60b84bb6bd Fix #1090: autocomplete firing on dragging or clicking a node 2020-09-09 09:29:45 +02:00
Jos de Jong 2cbac6fd5c Default to tree mode in custom styling example 2020-09-09 09:05:04 +02:00
Jos de Jong 70c9b0b454 Update devDependencies 2020-09-06 10:18:06 +02:00
Jos de Jong 59dd16a538 Update dependencies and devDependencies 2020-08-26 21:56:45 +02:00
Jos de Jong b214915b34 Fix #1096: editor crashing when passing an empty string as `name` 2020-08-26 21:35:30 +02:00
Jos de Jong b48ec89953 Publish v9.0.4 2020-08-15 10:27:18 +02:00
Jos de Jong 295e771ec4 Merge remote-tracking branch 'origin/develop' into develop 2020-08-15 10:17:49 +02:00
Jos de Jong df81d1098d Fix #1077: change the `main` field in `package.json` to point to the actual bundled and minified file instead of a node.js index file 2020-08-15 10:17:41 +02:00
dependabot-preview[bot] 475902593e
Bump jsdom from 16.3.0 to 16.4.0 (#1074)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 16.3.0 to 16.4.0.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Changelog](https://github.com/jsdom/jsdom/blob/master/Changelog.md)
- [Commits](https://github.com/jsdom/jsdom/compare/16.3.0...16.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-08-10 21:35:25 +02:00
Jos de Jong e92bdf407f Update devDependencies 2020-08-07 15:14:48 +02:00
jos f9649d1155 Update devDependencies 2020-07-25 15:06:29 +02:00
Jos de Jong e89632d9ce Update dependencies 2020-07-11 13:01:26 +02:00
Jos de Jong 09f2a398ca Make React examples maintenance friendly 2020-07-04 15:06:15 +02:00
josdejong 162756ef69 Publish v9.0.3 2020-07-02 20:10:21 +02:00
josdejong 025c0649fa Fix regression introduced in `v9.0.2` in the select boxes in the Transform model not lighlighting the matches correctly 2020-07-02 20:07:27 +02:00
josdejong fb994728fd Publish v9.0.2 2020-07-01 11:05:00 +02:00
josdejong 400b1eea37 Small styling fix 2020-07-01 10:58:29 +02:00
josdejong 87bc7b2561 Fix #1029: XSS vulnerabilities 2020-07-01 10:45:09 +02:00
josdejong 8826c6f2b6 Fix #1017: unable to style the color of a value containing a color. See also #1028 2020-06-27 17:15:58 +02:00
josdejong 394432d3a6 Publish v9.0.1 2020-06-24 08:42:33 +02:00
josdejong 3a5ddb2ae7 Update devDependencies 2020-06-24 08:41:34 +02:00
josdejong b6235a8d23 Fix #1027: create IE11 Array polyfills `find` and `findIndex` in such a way that they are not iterable 2020-06-23 21:22:21 +02:00
josdejong 70a2f94693 Update history 2020-06-21 16:34:01 +02:00
patrikx3 d71c7b4ca0
FIXE: powered by ace link is updated to https://ace.c9.io/ (#1018) 2020-06-21 16:32:20 +02:00
dependabot[bot] 3048e710c9
Bump websocket-extensions in /examples/react_advanced_demo (#1007)
Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/faye/websocket-extensions-node/releases)
- [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/faye/websocket-extensions-node/compare/0.1.3...0.1.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-06-06 16:49:11 +02:00
dependabot[bot] 2d38d0bbc9
Bump websocket-extensions from 0.1.3 to 0.1.4 in /examples/react_demo (#1006)
Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/faye/websocket-extensions-node/releases)
- [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/faye/websocket-extensions-node/compare/0.1.3...0.1.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-06-06 14:08:16 +02:00
josdejong ae84c74996 Update devDependencies 2020-06-06 14:04:01 +02:00
josdejong f94589c1e9 Update devDependencies 2020-05-30 13:40:52 +02:00
josdejong 901b8aa8dd Describe `onFocus` and `onBlur` in the docs (see #612) 2020-05-27 09:03:46 +02:00
josdejong 1b259e7e47 Publish v9.0.0 2020-05-24 16:08:09 +02:00
josdejong 62025c490d Implemented option `limitDragging`, see #962 2020-05-24 16:02:04 +02:00
josdejong c2fa821a31 Update example 20 to also show how to customize font color (See #990) 2020-05-23 14:26:29 +02:00
josdejong bd69cf9ebd Remove greenkeeper badge 2020-05-13 12:42:12 +02:00
josdejong 71e209528d Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	package.json
2020-05-13 08:57:22 +02:00
josdejong 27eb02a410 Publish v8.6.8 2020-05-13 08:56:56 +02:00
josdejong 9fbd352c12 Update devDependencies 2020-05-13 08:20:40 +02:00
josdejong ad021ec7af Fix #936: too many return characters inserted when pasting formatted text from OpenOffice 2020-05-13 08:17:54 +02:00
dependabot-preview[bot] 81513d0f4a
Bump uglify-js from 3.9.1 to 3.9.2 (#980)
Bumps [uglify-js](https://github.com/mishoo/UglifyJS2) from 3.9.1 to 3.9.2.
- [Release notes](https://github.com/mishoo/UglifyJS2/releases)
- [Commits](https://github.com/mishoo/UglifyJS2/compare/v3.9.1...v3.9.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-05-10 19:22:28 +02:00
josdejong 79beb26d66 Publish v8.6.7 2020-05-10 17:22:14 +02:00
josdejong ea7893a2f6 Update history 2020-05-10 12:07:42 +02:00
josdejong d3231570ab Fix #978: in some special cases the caret was jumping to the beginning of the line whilst typing 2020-05-10 12:06:50 +02:00
josdejong 561e582de8 Fix #858: the `dist/jsoneditor.js` bundle containing a link to a non-existing source map 2020-05-10 11:46:11 +02:00
josdejong 7dafdf8d9a Update dependencies of React examples 2020-05-03 10:13:57 +02:00
josdejong fe800bada7 Update devDependencies 2020-05-03 10:10:08 +02:00
josdejong cfa5575884 Update dependencies 2020-04-22 09:46:39 +02:00
josdejong 990f481f5f Publish `v8.6.6` 2020-04-22 09:30:47 +02:00
josdejong 2db9e70ac4 Fix #969: adding a new property to an empty object or array is broken 2020-04-22 09:00:18 +02:00
josdejong a68ecf5297 Fix #969: adding a new property to an empty object or array is broken 2020-04-22 08:56:02 +02:00
josdejong a292b82792 Fix linting 2020-04-19 10:05:19 +02:00
josdejong 830be6c3df Update dependencies and devDependencies. Publish v8.6.5 2020-04-19 10:00:26 +02:00
josdejong 2519c0fee5 Merge remote-tracking branch 'origin/develop' into develop 2020-04-19 09:48:29 +02:00
josdejong 894af51861 Fix #964: translation of titles of some context menu items not working 2020-04-19 09:47:59 +02:00
dependabot-preview[bot] b05e6059de
Bump ace-builds from 1.4.9 to 1.4.10 (#958)
Bumps [ace-builds](https://github.com/ajaxorg/ace-builds) from 1.4.9 to 1.4.10.
- [Release notes](https://github.com/ajaxorg/ace-builds/releases)
- [Changelog](https://github.com/ajaxorg/ace-builds/blob/master/ChangeLog.txt)
- [Commits](https://github.com/ajaxorg/ace-builds/compare/v1.4.9...v1.4.10)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-04-15 20:29:46 +02:00
dependabot-preview[bot] c42ddd4f65
Bump uglify-js from 3.8.1 to 3.9.0 (#957)
Bumps [uglify-js](https://github.com/mishoo/UglifyJS2) from 3.8.1 to 3.9.0.
- [Release notes](https://github.com/mishoo/UglifyJS2/releases)
- [Commits](https://github.com/mishoo/UglifyJS2/compare/v3.8.1...v3.9.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-04-14 18:21:58 +02:00
Tim Gates fc4927bcf6
docs: Fix simple typo, vaidation -> validation (#956)
There is a small typo in src/js/JSONEditor.js.

Should read `validation` rather than `vaidation`.
2020-04-14 18:14:59 +02:00
dependabot-preview[bot] 981dd220a0
Bump @babel/preset-env from 7.9.0 to 7.9.5 (#955)
Bumps [@babel/preset-env](https://github.com/babel/babel) from 7.9.0 to 7.9.5.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.9.0...v7.9.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-04-08 10:50:36 +02:00
jos c32f667396 Update dependencies and devDependencies 2020-04-04 11:33:18 +02:00
jos 5508d421e8 Publish v8.6.4 2020-03-29 14:48:01 +02:00
jos 78ac97c001 Revert reckoning with the order of object properties when updating an object. See #917 2020-03-29 12:15:36 +02:00
jos d62d2e14db Fix #946: `language` not working in modes `text`, `code`, and `preview` 2020-03-29 11:57:06 +02:00
jos 4f433cb6a9 A fix in repairing line-separated json 2020-03-25 12:18:41 +01:00
jos fd0db5dc73 Implement support for repairing line separate JSON 2020-03-25 12:11:33 +01:00
jos 0ba8321eb3 Fix linting issue 2020-03-25 10:37:33 +01:00
jos 253c02c684 Merge remote-tracking branch 'origin/develop' into develop 2020-03-25 10:31:16 +01:00
jos 87d320efc3 Fix #921: `sortObjectKeys` emits `onChange` events 2020-03-25 10:30:45 +01:00
Snyk bot 16a46885fe
fix: upgrade react-scripts from 3.4.0 to 3.4.1 (#943)
Snyk has created this PR to upgrade react-scripts from 3.4.0 to 3.4.1.

See this package in NPM:
https://www.npmjs.com/package/react-scripts

See this project in Snyk:
https://app.snyk.io/org/josdejong/project/913c7924-24ae-4f86-8a9b-91da27c3e8f1?utm_source=github&utm_medium=upgrade-pr
2020-03-24 20:10:00 +01:00
jos c76f552e47 Update devDependencies 2020-03-23 21:57:40 +01:00
greenkeeper[bot] ac5a24ffce
Update react in group default to the latest version 🚀 (#933)
* fix(package): update react to version 16.13.1

* fix(package): update react to version 16.13.1

* fix(package): update react-dom to version 16.13.1

* fix(package): update react-dom to version 16.13.1

* chore(package): update lockfile examples/react_demo/package-lock.json

* chore(package): update lockfile examples/react_advanced_demo/package-lock.json

Co-authored-by: greenkeeper[bot] <23040076+greenkeeper[bot]@users.noreply.github.com>
2020-03-20 22:48:22 +01:00
jos ef88b8ef9a Publish v8.6.3 2020-03-18 16:48:40 +01:00
jos f356c875a1 Fix #932: `JSONEditor.update` broken, did not always recognize when the input changed 2020-03-18 16:47:41 +01:00
jos f954a81c05 Publish v8.6.2 2020-03-18 10:53:34 +01:00
jos a33aa14cc2 Update test_build.html 2020-03-18 10:47:34 +01:00
jos b09dbca3fd Fix #917, #926: update ordering of object keys 2020-03-18 10:44:25 +01:00
jos 3363c2df8a Fix a regression in `setValue` 2020-03-18 10:37:44 +01:00
jos 2316c87a46 Fix #926: Keep order of properties when updating an object 2020-03-18 09:37:44 +01:00
dependabot[bot] 341cc2ca8e
Bump acorn from 5.7.3 to 5.7.4 in /examples/react_demo (#930)
Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.3 to 5.7.4.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/5.7.3...5.7.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-03-14 15:37:29 +01:00
dependabot[bot] 98e9fb222c
Bump acorn from 5.7.3 to 5.7.4 in /examples/react_advanced_demo (#929)
Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.3 to 5.7.4.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/5.7.3...5.7.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-03-14 15:36:48 +01:00
jos b81a6d06f4 Update `ajv` and devDependencies 2020-03-12 21:46:13 +01:00
jos 0229ba328c Merge remote-tracking branch 'origin/develop' into develop 2020-03-12 21:44:47 +01:00
jos 854a407da1 Fixed #928: Custom root name not reflected in path of navigation bar 2020-03-12 21:44:20 +01:00
greenkeeper[bot] d0a2644485
Update react in group default to the latest version 🚀 (#919)
* fix(package): update react to version 16.13.0

* fix(package): update react to version 16.13.0

* fix(package): update react-dom to version 16.13.0

* fix(package): update react-dom to version 16.13.0

* chore(package): update lockfile examples/react_demo/package-lock.json

* chore(package): update lockfile examples/react_advanced_demo/package-lock.json
2020-02-29 13:13:38 +01:00
jos f6152c2103 Publish v8.6.1 2020-02-17 20:10:23 +01:00
jos 3ad5c9f9c1 Fix #908: editor throwing an exception when switching from `'preview'` to `'code'` mode 2020-02-17 20:08:16 +01:00
jos 582645df70 Fix replacing Python constants in arrays 2020-02-16 10:11:12 +01:00
jos 30fcdf5ce8 Publish v8.6.0 2020-02-16 10:00:24 +01:00
jos dcc66d5d81 Fixed #906: Implemented turning Python objects containing `True`, `False` and `None` into valid JSON using repair 2020-02-15 20:21:38 +01:00
jos 21aa049588 Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	examples/react_advanced_demo/package-lock.json
#	examples/react_demo/package-lock.json
2020-02-15 11:04:51 +01:00
jos bdd90847eb Update dependencies in react examples 2020-02-15 11:04:33 +01:00
greenkeeper[bot] b8ca5f5f16
Update react-scripts in group default to the latest version 🚀 (#905)
* fix(package): update react-scripts to version 3.4.0

* fix(package): update react-scripts to version 3.4.0

* chore(package): update lockfile examples/react_demo/package-lock.json

* chore(package): update lockfile examples/react_advanced_demo/package-lock.json
2020-02-15 09:13:24 +01:00
jos ba770f25f8 Publish v8.5.3 2020-02-06 21:42:54 +01:00
jos 5e467ad968 Fix #892: the undo/redo buttons in mode `code` being broken when custom loading an old version of Ace Editor 2020-02-06 21:41:41 +01:00
petermanders89 11b8a04ff3
Creating and optimized scss imports (#885)
* Optimized scss imports

* Moved selectr to the jsoneditor scss

* Added new line at end of file jsoneditor
2020-02-06 21:23:50 +01:00
jos 825156dfce Publish v8.5.2 2020-02-05 11:49:53 +01:00
jos 9fd1c0f932 Fix undo/redo buttons in mode `code` not always updating 2020-02-05 11:46:23 +01:00
jos 98fb5114b7 Publish v8.5.1, fix broken import 2020-02-05 10:57:22 +01:00
jos ae372441c2 Publish v8.5.0 2020-02-05 10:46:59 +01:00
jos 4293afe451 Expose `showTransformModal` and `showSortModal` 2020-02-05 10:43:19 +01:00
jos df46f721e9 Implement undo/redo buttons in mode `code` 2020-02-05 10:37:28 +01:00
jos 42672eeef5 Fix history (undo/redo) being cleared in mode `code` and `text` after transforming or sorting 2020-02-05 10:11:37 +01:00
jos 9e9fd72edd Merge remote-tracking branch 'origin/develop' into develop 2020-02-05 08:50:19 +01:00
jos c5c64bcde3 Merge branch 'feature/custom_query_language' into develop
# Conflicts:
#	HISTORY.md
2020-02-05 08:50:12 +01:00
greenkeeper[bot] a20c9f1f9f
Update react-scripts in group default to the latest version 🚀 (#890)
* fix(package): update react-scripts to version 3.3.1

* fix(package): update react-scripts to version 3.3.1

* chore(package): update lockfile examples/react_demo/package-lock.json

* chore(package): update lockfile examples/react_advanced_demo/package-lock.json
2020-02-02 17:57:09 +01:00
jos 7e2fb82b2f Updated devDependencies 2020-02-01 19:43:32 +01:00
jos 385d22de27 Publish v8.4.1 2020-01-25 13:24:01 +01:00
jos e22829e2af Publish v8.4.0 2020-01-25 11:04:29 +01:00
jos d257c50746 Merge branch 'develop' of github.com:josdejong/jsoneditor into develop 2020-01-25 10:59:33 +01:00
jos eea9c797ad Added CSS classes on array and object nodes reflecting there expanded/collapsed state 2020-01-25 10:59:22 +01:00
fls-indinf bed062dda8 missing ` in navigationBar-Area (#887) 2020-01-21 19:40:09 +01:00
jos aa08a204f4 Publish v8.3.0 2020-01-18 14:30:01 +01:00
jos 7d4b72fb38 Publish v8.3.0 2020-01-18 14:26:28 +01:00
jos b3c0eedc08 Fix #790: editor breaking when missing some translations 2020-01-18 14:19:06 +01:00
jos 259b32d441 Publish v8.2.0 2020-01-16 19:43:55 +01:00
petermanders89 dab47eef75 Changing sass variables #881 (#882)
* Added !default to SASS color variables

* Added variable for icon path

* Small styling change in the icon variable

* Added default to the jse-icons variable
2020-01-16 19:38:18 +01:00
jos 0f031dc6cd Publish `v8.1.2` 2020-01-06 20:01:54 +01:00
Jos de Jong 090d41f8d9 Fix #877: Some CSS styling issues when used in combination with Materialize 2020-01-04 16:05:25 +01:00
Jos de Jong 0c061b33e3 Intent with 2 spaces 2020-01-04 15:09:15 +01:00
Jos de Jong 924ca1afc3 Fix #873: buttons Format, Compact, and Repair not supporting internationalization 2020-01-04 15:05:42 +01:00
jos 09827482bc Update history 2020-01-04 12:29:27 +01:00
jos d12a5e7cf2 Improve projection in example to flatten picking a single field 2020-01-04 12:24:12 +01:00
jos ad430a3173 Improve example with a `projection` which flattens the selected fields 2020-01-04 12:21:01 +01:00
jos 540566f0cd Write docs for `createQuery`, `executeQuery`, and `queryDescription` 2020-01-04 12:06:35 +01:00
jos 9ed5d5c5ae Work out handling of `'@'` field in example 2020-01-04 11:41:11 +01:00
jos 32871f85fd Work out error handling 2020-01-04 11:11:09 +01:00
jos 40d312b987 Work out fixme in the example 2020-01-04 10:46:21 +01:00
jos e09fde628b Change `showTransformModal` to pass an object with properties. Fix transform not working in `text` and `preview` mode. 2020-01-04 10:39:34 +01:00
jos aba0a58383 Change `showTransformModal` to pass an object with properties. Fix transform not working in `text` and `preview` mode. 2020-01-04 10:16:32 +01:00
jos 6ece0f9acb Merge branch 'develop' into feature/custom_query_language
# Conflicts:
#	src/js/JSONEditor.js
2020-01-04 09:59:22 +01:00
jos 3615b841c5 Change maintenance badge to 2020 2020-01-04 09:53:35 +01:00
jos 042cd1be79 Publish v8.1.1 2019-12-28 17:59:12 +01:00
jos 10a48ca7b2 Fix lint issues 2019-12-28 17:17:27 +01:00
jos 275fcc8fee Changed the file size reported in `preview` mode to `KB` and `MB` 2019-12-28 17:12:56 +01:00
jos 7729e8b38e Update devDependencies 2019-12-27 22:31:52 +01:00
jos c059fdb543 Have the preview test file actually load `preview` mode 2019-12-27 22:31:01 +01:00
jos 4937337147 Publish v8.1.0 2019-12-18 17:42:00 +01:00
jos d973464545 Rename test file 2019-12-18 17:39:32 +01:00
jos 582e0b1fc1 Fix color picker positioning when `popupAnchor` is defined 2019-12-18 17:37:25 +01:00
jos f86f3d4e1c Implemented `popupAnchor` allowing to select a custom anchor element. See #869 and #870. 2019-12-18 17:26:16 +01:00
jos 036c9e1914 Merge remote-tracking branch 'origin/develop' into develop 2019-12-16 20:29:06 +01:00
jos 7c3695df4a Fixed #502: CSS rule `* { font-family: ... }` resulting in Ace editor (`code` mode) not having a mono-space font anymore 2019-12-16 20:28:46 +01:00
greenkeeper[bot] 1f02eda866 Update jsoneditor in group default to the latest version 🚀 (#868)
* fix(package): update jsoneditor to version 8.0.0

* fix(package): update jsoneditor to version 8.0.0

* chore(package): update lockfile examples/react_demo/package-lock.json

* chore(package): update lockfile examples/react_advanced_demo/package-lock.json
2019-12-11 17:37:48 +01:00
jos c766290bf7 Fix linting issues 2019-12-11 17:12:37 +01:00
jos d2332dc308 Implement proof of concept for `createQuery` and `executeQuery`, see #857 2019-12-11 17:09:47 +01:00
jos 4eb55bffde Publish v8.0.0 2019-12-11 12:09:54 +01:00
jos 3aba2c243b Oops 2019-12-11 12:09:03 +01:00
jos 5c7e1e6fe9 Changed the behavior of `timestampTag` to fallback on the built-in rules when the function does not return a boolean. See #856. 2019-12-11 12:08:31 +01:00
jos 00c02b9bcf Publish v7.6.0 2019-12-11 11:56:50 +01:00
jos 03fa90bd71 Revert using field names to determine whether a value is a timestamp (see #847, #856) 2019-12-11 11:51:48 +01:00
jos a55977830f Update history 2019-12-11 11:39:05 +01:00
jos fd21b1c525 Add title for timestamp tag again (see #863) 2019-12-11 11:37:39 +01:00
Small ce15bb4b37 add timestampFormat (#863)
* add timestampFormat

* use createTextNode instead innerHTML
2019-12-11 11:34:24 +01:00
jos 90423573ab Publish v7.5.0 2019-12-08 21:53:55 +01:00
jos b73a7495fe Update history 2019-12-08 10:46:21 +01:00
Meir Rotstein 84950ac69a onValidationError to report any kind of error (#861)
* onValidationError to report any kind of error

* lint fixes
2019-12-08 10:35:22 +01:00
jos 7888dcf660 Update dependencies 2019-12-08 10:21:58 +01:00
jos 45ade363f4 Update dependencies of example projects 2019-12-08 10:19:21 +01:00
jos 7f053eab8d Publish `v7.4.0` 2019-12-01 16:33:29 +01:00
Meir Rotstein 266eeec21a onValidationError option (#854)
* provide onValidationError callback

* linter fixes

* docu fixes

* textmode - invoke callback also when no errors
This to cover situation of changes that fixes validations

* fixed cautom validation example
2019-12-01 16:21:16 +01:00
jos 87691e6693 Remove test options from example again (see #850) 2019-12-01 11:56:22 +01:00
jos 0d4525d3d2 Fixed #850: make autocomplete options robust against non-string inputs 2019-12-01 11:54:56 +01:00
jos eb9fb32038 Reduce length of line, make code better readable 2019-12-01 11:53:09 +01:00
jos 9d2067f281 Publish `v7.3.1` 2019-12-01 10:26:42 +01:00
jos 4e68c54988 Update devDependencies 2019-12-01 10:24:29 +01:00
jos 323ee3ddf8 Clarify #855 fix in history 2019-12-01 10:20:10 +01:00
jos 1026d9102c Fixed #855: focus tracker not created when creating an editor without main menu bar 2019-12-01 10:19:07 +01:00
jos c1d2f124c2 Publish v7.3.0 2019-11-27 16:48:36 +01:00
jos 51410c363f More improvements in the built-in `isTimestamp` function (see #847) 2019-11-27 15:45:48 +01:00
jos 7be97ceffb Cleanup unused constant 2019-11-27 15:29:59 +01:00
jos 39dfc41100 Improve `timestampTag` API (see #847) 2019-11-27 15:28:50 +01:00
jos 42dd2aeb93 Update history 2019-11-24 19:43:22 +01:00
Survesh Jones 8894420263 Fix #727 (#809)
* Fix #727: exposing Focus and Blur events through JSONEditor options

* Comments for onFocus and onBlur exposed events

* Fixing lint issues

* Fix for #727: Updated code for emitting onFocus and onBlur events

* Seperating FocusTarget out as a seperate class

* Fixing an issue that kept on setting the focus to the last element in the editor instead of passing it out

* Moving the add() method of FocusTracker into its constructor and renaming its remove() to destroy()

* removing a flag not needed anymore and making FocusTracker.target a required input

* updating focus tracker's focus checking condition

* Emitting onBlur callback when FocusTracker is being destroyed

* fixing lint issues
2019-11-24 19:41:08 +01:00
jos a615f7ab91 Fixed #847: allow customizing the rules determining whether a value is a timestamp or not 2019-11-20 10:47:49 +01:00
Jos de Jong 728c10c137 Update devDependencies 2019-11-16 14:59:45 +01:00
Jos de Jong 792e4fa3b9 Merge branch 'master' into develop 2019-11-16 14:57:50 +01:00
Jos de Jong ebc7756b5b Add Funding.yml to project 2019-11-16 14:56:04 +01:00
Jos de Jong 6b6c6cb2c3 Fix missing date in history 2019-11-16 14:55:36 +01:00
greenkeeper[bot] 58c6379e32 Update react in group default to the latest version 🚀 (#846)
* fix(package): update react to version 16.12.0

* fix(package): update react to version 16.12.0

* fix(package): update react-dom to version 16.12.0

* fix(package): update react-dom to version 16.12.0

* chore(package): update lockfile examples/react_demo/package-lock.json

* chore(package): update lockfile examples/react_advanced_demo/package-lock.json
2019-11-15 19:42:08 +01:00
jos c25118bceb Update devDependencies 2019-11-02 14:06:32 +01:00
jos f3baeb6ffd Publish `v7.2.1` 2019-10-27 11:35:20 +01:00
jos 009d896c30 Fix #829: z-index issue of context-menu button and conflicting css names 2019-10-26 11:18:06 +02:00
jos 43e0c129ec Fixed #826: editor not allowing indentation `0` 2019-10-26 10:51:40 +02:00
jos 8e15be0f12 Fixed #828: do not expand/collapse when clicking the text of a node in modes `view` or `form` 2019-10-26 10:45:37 +02:00
jos da235536bc Update dependencies of react example projects 2019-10-23 14:41:06 +02:00
jos 55300ce7ef Update history 2019-10-23 14:30:56 +02:00
jos b0fc57ccef Publish v7.2.0 2019-10-23 14:24:09 +02:00
jos 626d3959c9 Fixed #824: Parse errors not displayed with bottom right error icon in modes `code` and `text` 2019-10-23 14:19:43 +02:00
jos 73214b6985 Change all dependencies to inexact version numbers with `^` 2019-10-22 20:30:20 +02:00
jos 75f16348b9 Update devDependencies 2019-10-22 20:25:36 +02:00
jos d3e1aef2d3 Update history 2019-10-20 23:02:30 +02:00
yannickyvin 88b03ae4f2 fr-FR translation + i18n ModeSwitcher title & Search title (#823)
* fr-FR translation + i18n ModeSwitcher title & Search title

* standardJS fix

* update api.md with fr-FR
2019-10-20 23:00:32 +02:00
jos a9ad446954 Update history 2019-10-17 19:51:12 +02:00
Yuta Kiyama c60f1f65de Added Japanese language support (#818)
* i18n support japanese

* Add japanese in the docs
2019-10-17 19:49:02 +02:00
jos 9a46d29ab7 Update devDependencies 2019-10-15 22:21:03 +02:00
greenkeeper[bot] 42a2f89bae Update jsdom to the latest version 🚀 (#815)
* chore(package): update jsdom to version 15.2.0

* chore(package): update lockfile package-lock.json
2019-10-14 19:56:08 +02:00
jos abbf866e08 Publish v7.1.0 2019-10-13 09:11:03 +02:00
jos 9202890844 Replace `brace` (using Ace v1.2.9) with `ace-builds@1.4.6` 2019-10-13 08:58:33 +02:00
jos 37f7bff262 Update devDependencies 2019-10-12 11:17:14 +02:00
jos 38c6da4bad Update history 2019-10-12 11:12:21 +02:00
Victor b7c8e3a713 some portuguese translations added (#813) 2019-10-12 11:11:21 +02:00
jos 31e1e08dc4 Publish v7.0.5 2019-10-06 10:52:33 +02:00
jos ecb1674f09 Update dependencies 2019-10-05 22:10:48 +02:00
greenkeeper[bot] 42821e2c53 Update react in group default to the latest version 🚀 (#807)
* fix(package): update react to version 16.10.2

* fix(package): update react to version 16.10.2

* fix(package): update react-dom to version 16.10.2

* fix(package): update react-dom to version 16.10.2

* chore(package): update lockfile examples/react_demo/package-lock.json

* chore(package): update lockfile examples/react_advanced_demo/package-lock.json
2019-10-05 21:54:58 +02:00
Jos de Jong 8c7b6f2b31
Update history 2019-10-05 21:46:56 +02:00
Arun 4c82f5cb3f [Docs] Minor documentation improvements (#808)
* Minor documentation improvements

* Add few more missed corrections
2019-10-05 21:43:03 +02:00
greenkeeper[bot] 3997062911 Update react in group default to the latest version 🚀 (#803)
* fix(package): update react to version 16.10.0

* fix(package): update react to version 16.10.0

* fix(package): update react-dom to version 16.10.0

* fix(package): update react-dom to version 16.10.0

* chore(package): update lockfile examples/react_demo/package-lock.json

* chore(package): update lockfile examples/react_advanced_demo/package-lock.json
2019-09-29 16:29:05 +02:00
jos 8bce7b4758 Update dependencies and history.md 2019-09-29 16:11:07 +02:00
jos 94520c44c8 Merge branch 'develop' of github.com:josdejong/jsoneditor into develop 2019-09-29 16:04:06 +02:00
greenkeeper[bot] 3f355ecd63 Update babel7 to the latest version 🚀 (#800)
* chore(package): update @babel/core to version 7.6.2

* chore(package): update @babel/preset-env to version 7.6.2

* chore(package): update @babel/register to version 7.6.2

* chore(package): update lockfile package-lock.json
2019-09-29 16:03:26 +02:00
greenkeeper[bot] a548ad30fc Update webpack to the latest version 🚀 (#802)
* chore(package): update webpack to version 4.41.0

* chore(package): update lockfile package-lock.json
2019-09-29 12:43:13 +02:00
greenkeeper[bot] 8633f33420 Update react-scripts in group default to the latest version 🚀 (#797)
* fix(package): update react-scripts to version 3.1.2

* fix(package): update react-scripts to version 3.1.2

* chore(package): update lockfile examples/react_demo/package-lock.json

* chore(package): update lockfile examples/react_advanced_demo/package-lock.json
2019-09-19 22:36:31 +02:00
greenkeeper[bot] 6cb47746f5 Update standard to the latest version 🚀 (#796)
* chore(package): update standard to version 14.3.1

* chore(package): update lockfile package-lock.json
2019-09-18 21:49:37 +02:00
jos 22f691e4fd Minor styling fix in modals 2019-09-17 21:19:26 +02:00
jos fc780bbb10 Minor styling fix in modals 2019-09-17 21:16:39 +02:00
jos a60a1125ea Reverted solution for #794 due to undesirable side effects 2019-09-17 20:20:40 +02:00
jos 587db80d21 Fix linting issue 2019-09-15 11:58:20 +02:00
jos 21b0cd12e9 Merge remote-tracking branch 'origin/develop' into develop 2019-09-15 11:55:24 +02:00
jos 8554789aa7 Fix #794: fix discrepancy between valid JSON numbers and valid JavaScript numbers 2019-09-15 11:55:15 +02:00
greenkeeper[bot] c605d79f3c Update standard to the latest version 🚀 (#795)
* chore(package): update standard to version 14.3.0

* chore(package): update lockfile package-lock.json
2019-09-15 08:42:35 +02:00
greenkeeper[bot] fc9d5e9af5 Update webpack to the latest version 🚀 (#793)
* chore(package): update webpack to version 4.40.0

* chore(package): update lockfile package-lock.json
2019-09-14 14:26:14 +02:00
greenkeeper[bot] 1107bdbbf3 Update standard to the latest version 🚀 (#792)
* chore(package): update standard to version 14.2.0

* chore(package): update lockfile package-lock.json
2019-09-11 22:00:03 +02:00
jos 97cda1457a Publish v7.0.4 2019-09-11 16:22:10 +02:00
jos 18f08d3400 Fix lint errors 2019-09-11 16:16:05 +02:00
jos fe14ab5b79 Render color picker on top when there is not enough space below (see #723) 2019-09-11 16:14:24 +02:00
jos 83e9e0655c Fixed #723: schema error popup not always fully visible 2019-09-11 15:59:19 +02:00
jos e23eb8f191 Update history 2019-09-11 10:19:51 +02:00
jos 8c1f932dc2 Update history 2019-09-11 10:16:29 +02:00
Dmitry Kulikov 9d69a699db Set color for text in search box (#791) 2019-09-11 10:15:13 +02:00
greenkeeper[bot] 017800cea4 Update babel7 to the latest version 🚀 (#789)
* chore(package): update @babel/core to version 7.6.0

* chore(package): update @babel/preset-env to version 7.6.0

* chore(package): update @babel/register to version 7.6.0

* chore(package): update lockfile package-lock.json
2019-09-07 14:00:48 +02:00
Vishwas Navada K f100c4f403 change jsoneditor dependency property value. (#787)
* change jsoneditor dependency property value. 

Adding the jsoneditor version into package.json npm install did not install jsoneditor with "file:../..".

* update jsoneditor version to have version.
2019-09-07 11:29:36 +02:00
jos 2876d49a59 Publish v7.0.3 2019-09-04 09:47:04 +02:00
jos f064dcf965 Fixed `index.js` pointing to non-transpiled code. See #783 2019-09-04 09:42:40 +02:00
jos 60f0470a3c Update history 2019-09-03 19:45:08 +02:00
qiuweiwei 8a1af034c9 fix:Modify the file address reference method (#782) 2019-09-03 19:43:39 +02:00
jos 05e0733c24 Publish v7.0.2 2019-09-02 22:03:08 +02:00
jos ccd87d9edd Changed let in const 2019-09-02 22:01:18 +02:00
jos 671cad86fb Fix #781: race condition when destroying the editor right after setting data 2019-09-02 22:00:41 +02:00
jos a78adf6676 Defined files to be included in the npm package 2019-09-01 20:49:26 +02:00
jos 862c3f6822 Add `prepublishOnly` script running test and build before publish 2019-09-01 17:39:40 +02:00
jos 2d129f2df5 Publish v7.0.1 2019-09-01 17:37:16 +02:00
jos 299aa3da18 Publish v7.0.0 2019-09-01 16:42:03 +02:00
jos ceb08fe13d Some fixes and updates in examples 2019-09-01 16:37:57 +02:00
jos 9d018c408a Fix results undefined initially in `SearchBox` 2019-09-01 16:37:29 +02:00
jos b354ddbe8d Fix broken unit tests 2019-08-31 17:38:57 +02:00
jos 88b785d1d9 Oops. Fix lint issues 2019-08-31 17:36:09 +02:00
jos 6e5309665b Refactored some prototypes into ES6 classes 2019-08-31 17:34:09 +02:00
jos b79885471e A few more files refactored to ES modules 2019-08-31 11:21:29 +02:00
jos f321eb54ee A few more files refactored to ES modules 2019-08-29 18:31:33 +02:00
jos 9ef44bda6b Fix linting issues 2019-08-29 17:03:39 +02:00
jos be61222225 Partial refactor to ES modules 2019-08-29 17:03:09 +02:00
jos a7d501fe3c Rewrite unclear docs. Fixes #772 2019-08-29 15:52:17 +02:00
jos 6bfede956b Rewrite code styling of browser examples 2019-08-29 15:45:32 +02:00
jos 004d1100cd Fix linting issues 2019-08-29 14:41:42 +02:00
jos 21d0d532fd Merge remote-tracking branch 'origin/develop' into develop 2019-08-29 14:36:05 +02:00
jos d293cbcfc0 Fixed #586: caret position lost when switching browser tabs 2019-08-29 14:35:57 +02:00
greenkeeper[bot] 0e648f4333 Update standard to the latest version 🚀 (#780)
* chore(package): update standard to version 14.1.0

* chore(package): update lockfile package-lock.json
2019-08-29 10:05:58 +02:00
jos 3397b97f98 Describe how to test, lint, watch in readme 2019-08-28 14:56:07 +02:00
jos ecd65c3ad2 Fix merge conflicts 2019-08-28 14:53:07 +02:00
jos ecaa8d141c Publish v6.4.1 2019-08-28 14:49:25 +02:00
jos 1976a8e2e8 Fix styling of autocompletion dropdown broken. Regression since `v6.4.0` 2019-08-28 14:47:48 +02:00
jos 812b4227b6 Update history 2019-08-28 13:43:56 +02:00
jos e67fa19375 Run lebab on test folder: convert let/const and arrow functions 2019-08-28 13:43:06 +02:00
jos 531ddc5c74 Run lebab: convert let/const and arrow functions 2019-08-28 13:37:27 +02:00
jos d1a858548d Fix travis config (test + lint) 2019-08-28 13:23:33 +02:00
jos a5d6b8a65b Set up code style linting with standardjs 2019-08-28 13:21:14 +02:00
jos 8e2a7de17c Set up Babel transpilation 2019-08-28 11:54:14 +02:00
jos f11b070a1d Drop bower support, remove `dist` folder from repo 2019-08-28 11:34:41 +02:00
jos 6d5d9965c3 Publish v6.4.0 2019-08-28 11:12:44 +02:00
jos c404c1bc1f Fixed #777: option `sortObjectKeys` broken 2019-08-28 11:04:10 +02:00
jos 09e24ce238 remove arrow function 2019-08-28 10:55:07 +02:00
ppetkow 0d0cf17121 Search Box improvements (#773)
* update contextmenu, menu, searchbox remove necessary div. before each class name

* move from css to scss compilation for project and set colors and font to variables

* remove override from css

* update move color and clean styles

* #760 update base on last RP review

* refactor searchbox with div only and css box model

* clear code
2019-08-28 10:42:26 +02:00
greenkeeper[bot] 0bce4232a2 Update webpack to the latest version 🚀 (#778)
* chore(package): update webpack to version 4.39.3

* chore(package): update lockfile package-lock.json
2019-08-28 10:39:03 +02:00
dependabot[bot] 06618fcbd5 Bump eslint-utils from 1.4.0 to 1.4.2 in /examples/react_advanced_demo (#775)
Bumps [eslint-utils](https://github.com/mysticatea/eslint-utils) from 1.4.0 to 1.4.2.
- [Release notes](https://github.com/mysticatea/eslint-utils/releases)
- [Commits](https://github.com/mysticatea/eslint-utils/compare/v1.4.0...v1.4.2)

Signed-off-by: dependabot[bot] <support@github.com>
2019-08-28 10:38:38 +02:00
dependabot[bot] e9f301c901 Bump eslint-utils from 1.4.0 to 1.4.2 in /examples/react_demo (#776)
Bumps [eslint-utils](https://github.com/mysticatea/eslint-utils) from 1.4.0 to 1.4.2.
- [Release notes](https://github.com/mysticatea/eslint-utils/releases)
- [Commits](https://github.com/mysticatea/eslint-utils/compare/v1.4.0...v1.4.2)

Signed-off-by: dependabot[bot] <support@github.com>
2019-08-28 10:38:17 +02:00
jos 964fe3e06d Fixed #761: JSON schema errors not rendered in the gutter for mode `code` when the path contained a property with a forward slash 2019-08-25 20:43:21 +02:00
jos 9749a517b1 Update history 2019-08-22 15:59:19 +02:00
ppetkow 97893d40b5 Replace css with sass #760 (#765)
* update contextmenu, menu, searchbox remove necessary div. before each class name

* move from css to scss compilation for project and set colors and font to variables

* remove override from css

* update move color and clean styles

* #760 update base on last RP review

* remove some selectors from status bar
2019-08-22 15:56:38 +02:00
jos ee64c1fbb3 Update dependencies of react examples 2019-08-15 11:45:18 +02:00
jos dcd060f1b7 Publish v6.3.0 2019-08-15 10:50:29 +02:00
jos e4385c030f Do not invoke `_showAutoComplete` when there is no node found (see #763) 2019-08-15 10:37:25 +02:00
jos b05af3dd44 Fix `promise.then` inside `if` 2019-08-15 10:29:49 +02:00
jos 16e46878ba Fixed #763: `autocomplete.trigger: 'focus'` throws an error when opening the context menu 2019-08-15 10:29:15 +02:00
jos 2b76640611 Fix indentation 2019-08-15 10:22:36 +02:00
jos 174918f4eb Fixed #769: option `name` not working anymore 2019-08-15 10:04:57 +02:00
jos ca6e384e8d When duplicating an object property, move focus to the field and do not immediately add the ` (copy)` suffix. See #766 2019-08-08 20:57:42 +02:00
jos 9892249e49 Fixed #755: JSONEditor throwing an exception in mode `code`, `text`, and
`preview` when `statusBar: false`
2019-08-03 11:08:00 +02:00
jos f0097afcc0 Publish v6.2.1 2019-08-01 19:47:55 +02:00
jos 79e54a1d3a Update history 2019-07-31 09:42:53 +02:00
Sargeras.Wang dba54806df completion Chinese i18n (#753) 2019-07-31 09:40:42 +02:00
jos ce7433fd46 Publish v6.2.0 2019-07-28 16:12:46 +02:00
jos 14cdd0e61b Fix using arrow function and const 2019-07-28 11:45:43 +02:00
jos eff2fe85a0 Update dependencies 2019-07-28 11:30:15 +02:00
jos ea02a5be68 Fix format/compact/repair clearing history in mode code 2019-07-27 14:31:53 +02:00
jos 3f182a1f04 Repair button is now capable of turning MongoDB documents into valid JSON 2019-07-27 14:16:59 +02:00
jos cec16b9de1 Rename `util.sanitize` to `util.repair` 2019-07-27 13:13:02 +02:00
jos df952ac61d Replace deprecated `assert.equal` with `assert.strictEqual` 2019-07-27 13:08:02 +02:00
jos e5169018c5 cleanup unused import 2019-07-24 15:55:23 +02:00
jos 89bb66fe42 Repair only when json is undefined 2019-07-24 15:37:16 +02:00
jos e90ca1c422 Cleanup redundant code for Array info 2019-07-24 15:28:41 +02:00
jos fb30ded5fa Fix showing parse error in mode `text` and `preview` 2019-07-24 15:26:01 +02:00
jos 2b6caba3df Parse directly after setText 2019-07-24 15:19:45 +02:00
jos 72455e3302 Describe new mode `preview` in docs 2019-07-24 14:00:39 +02:00
jos 6bef66aaba Merge branch 'develop' into feature/preview
# Conflicts:
#	HISTORY.md
2019-07-24 13:48:20 +02:00
jos 745a4f3665 Implement validation in mode `"preview"` 2019-07-24 13:30:44 +02:00
jos 3ed0318624 Extract function `validateCustom` 2019-07-24 11:56:47 +02:00
jos 21b3cca592 Move parse error icon to `ErrorTable` too 2019-07-24 11:20:01 +02:00
jos e82ef3ed31 Move rendering of errors in separate component `ErrorTable` 2019-07-24 11:00:49 +02:00
jos 8c06c41f02 Merge remote-tracking branch 'origin/develop' into develop 2019-07-20 11:11:12 +02:00
jos 6f6f58bb33 Update package-lock.json files of react examples 2019-07-20 11:11:01 +02:00
greenkeeper[bot] a077e660e3 Update lodash in group default to the latest version 🚀 (#747)
* fix(package): update lodash to version 4.17.15

* chore(package): update lockfile examples/react_advanced_demo/package-lock.json
2019-07-20 11:03:00 +02:00
jos e490d7a512 Upgraded dependencies and devDependencies 2019-07-20 10:58:23 +02:00
jos bec0e71fc8 Implement `focus` 2019-07-17 18:01:12 +02:00
jos 939826d41f Update dependencies 2019-07-17 12:17:34 +02:00
jos e3e3886da8 Implemented history in preview mode 2019-07-17 12:17:08 +02:00
jos 92bf65f4d4 Update `mobius1-selectr@2.4.13` 2019-07-13 11:14:41 +02:00
dependabot[bot] 23463740df Bump lodash.template in /examples/react_advanced_demo (#733)
Bumps [lodash.template](https://github.com/lodash/lodash) from 4.4.0 to 4.5.0.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.4.0...4.5.0)

Signed-off-by: dependabot[bot] <support@github.com>
2019-07-13 11:08:39 +02:00
dependabot[bot] f6e2ec0461 Bump lodash from 4.17.11 to 4.17.14 (#734)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.14.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.14)

Signed-off-by: dependabot[bot] <support@github.com>
2019-07-13 11:08:20 +02:00
dependabot[bot] fe7b0eaa2a Bump lodash from 4.17.11 to 4.17.13 in /examples/react_advanced_demo (#736)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.13.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.13)

Signed-off-by: dependabot[bot] <support@github.com>
2019-07-13 11:07:55 +02:00
dependabot[bot] 47630710af Bump lodash from 4.17.11 to 4.17.14 in /examples/react_demo (#737)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.14.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.14)

Signed-off-by: dependabot[bot] <support@github.com>
2019-07-13 11:07:20 +02:00
jos bc0e99ab4a Fixed #730: in `code` mode, there was an initial undo action which clears the content 2019-07-10 14:27:46 +02:00
jos 477037dc46 Update history 2019-07-08 20:04:17 +02:00
greenkeeper[bot] 59c2846f02 Update dependencies for default 🌴 (#729)
* chore(package): update dependencies

* chore(package): update lockfile package-lock.json
2019-07-08 20:03:15 +02:00
jos df386b6f1b Add `'preview'` to the list with allowed modes in all examples 2019-07-08 20:00:34 +02:00
greenkeeper[bot] ec474a0328 Update webpack to the latest version 🚀 (#731)
* chore(package): update webpack to version 4.35.3

* chore(package): update lockfile package-lock.json
2019-07-08 19:45:55 +02:00
jos 95cef491a9 Fix merge conflicts 2019-07-07 10:24:06 +02:00
greenkeeper[bot] 7d1306f0a3 Update ajv to the latest version 🚀 (#728)
* fix(package): update ajv to version 6.10.1

* chore(package): update lockfile package-lock.json
2019-07-07 10:12:48 +02:00
dependabot[bot] 05753a00ef Bump handlebars from 4.0.11 to 4.1.2 in /examples/react_advanced_demo (#726)
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.0.11 to 4.1.2.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/wycats/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.0.11...v4.1.2)

Signed-off-by: dependabot[bot] <support@github.com>
2019-07-04 19:38:00 +02:00
dependabot[bot] 4d12b1d000 Bump handlebars from 4.0.11 to 4.1.2 in /examples/react_demo (#725)
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.0.11 to 4.1.2.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/wycats/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.0.11...v4.1.2)

Signed-off-by: dependabot[bot] <support@github.com>
2019-07-04 19:37:39 +02:00
jos 102b6d2b0c Implement `onChange`, `onChangeText` and `onChangeJSON` in preview mode 2019-07-03 16:16:39 +02:00
jos abc242c873 Implement array size in status bar 2019-07-03 13:10:00 +02:00
jos 9ed18da7b6 Create util function `limitCharacters`, tweak limiting of preview texts 2019-07-03 11:54:00 +02:00
greenkeeper[bot] e0b86551e7 Update webpack to the latest version 🚀 (#721)
* chore(package): update webpack to version 4.35.2

* chore(package): update lockfile package-lock.json
2019-07-01 19:30:32 +02:00
jos 726f829541 Show "busy" message when working on a heavy action 2019-06-30 20:08:52 +02:00
greenkeeper[bot] a8b083dfe3 Update vanilla-picker to the latest version 🚀 (#720)
* fix(package): update vanilla-picker to version 2.8.2

* chore(package): update lockfile package-lock.json
2019-06-29 16:35:09 +02:00
jos 14f7dcdf28 Fix overflowing contents 2019-06-26 22:03:14 +02:00
jos 3920215f73 Check existence of `sizeInfo` before updating it's contents 2019-06-26 21:58:41 +02:00
jos cda54f95fc Implemented `stringifyPartial` and use it in Transform modal 2019-06-26 21:57:22 +02:00
jos 1e1ee3463c Implemented `preview` mode (WIP) 2019-06-26 17:24:09 +02:00
greenkeeper[bot] 7f5e0c6870 Update dependencies to enable Greenkeeper 🌴 (#718)
* chore: add Greenkeeper config file

* chore(package): update dependencies

* docs(readme): add Greenkeeper badge

* chore(package): update lockfile package-lock.json
2019-06-22 20:37:09 +02:00
jos d509d4e542 Publish v6.1.0 2019-06-22 16:31:42 +02:00
jos 8a95b5b640 Make displaying of paths in Sort modal consistent with Transform modal 2019-06-22 16:27:12 +02:00
jos f83bb3e5cd Implemented function to extract a nested array/object 2019-06-19 17:29:28 +02:00
jos 797541cd6b Make `getChildPaths` json pointer compliant 2019-06-19 12:46:50 +02:00
jos d712e642cc Refactoring in showSortModal internal API 2019-06-19 12:09:06 +02:00
jos 7311e78b53 Implemented `transform` modal for modes `code` and `text` 2019-06-19 11:57:28 +02:00
jos 74b816a554 Implemented sort button in code/text mode 2019-06-19 11:16:30 +02:00
jos 12dc0408e8 Update dependencies of react examples 2019-06-12 22:01:56 +02:00
jos 436c56dd20 Publish v6.0.0 2019-06-12 20:53:48 +02:00
jos 7da4cd09f8 Fix broken unit test 2019-06-12 15:58:13 +02:00
jos 10daf40b56 Use JSON schema title as name for the root object if defined (see #635) 2019-06-12 15:43:16 +02:00
jos 4813cd79a1 Configure option `$data: true` for Ajv 2019-06-12 15:25:33 +02:00
jos 9dfc1aab39 Upgrade to `ajv@6` 2019-06-12 15:11:41 +02:00
jos b78ad35670 Upgrade to `webpack@4` and refactor gulp tasks 2019-06-12 14:14:15 +02:00
jos b1a4bce3d8 Upgrade to `uglify-js@3` 2019-06-12 13:23:36 +02:00
jos ab4a6a2f5e Upgrade to latest `mocha` and `jsdom` 2019-06-12 13:19:25 +02:00
jos a8d246778f Upgdate gulp dependencies. Cleanup unused zip task 2019-06-12 13:17:46 +02:00
jos 7bf25b3129 Publish v5.34.0 2019-06-08 12:13:53 +02:00
Gcaufy 85e0710097 Feat: Added filter and trigger options for autocomplete (#713)
* Feat: Added filter options for autocomplete

* Feat: added trigger option for autocomplete

* Fix: const/let => var
2019-06-08 11:37:52 +02:00
jos 59290dd6c2 Merge remote-tracking branch 'origin/develop' into develop 2019-06-08 10:29:50 +02:00
jos 041243b117 Update history 2019-06-08 10:29:13 +02:00
Gcaufy 73e05a6604 fix(css): remove :hover style on disabled button. (#712)
Should not have :hover style on disabled buttons.
2019-06-08 10:23:53 +02:00
jos 5ba71998bb Update build file, publish v5.33.0 for real now :) 2019-05-29 17:26:10 +02:00
jos d2ef76abb5 fix merge conflict 2019-05-29 17:25:28 +02:00
jos 006ff56fc0 Publish v5.33.0 2019-05-29 17:22:58 +02:00
jos aee1d2dcde Publish v5.33.0 2019-05-29 17:22:03 +02:00
jos a9abad2cd4 Fix #698 `node.path` sometimes null in `onCreateMenu` 2019-05-29 16:29:29 +02:00
jos f1b5e2a692 Add travis configuration file 2019-05-29 15:54:07 +02:00
Jos de Jong 3ccdeeec40
Fix #697 JSON Schema enum dropdown not working inside an array (#707)
* Fix #697 JSON Schema enum dropdown not working inside an array

* Make schema in unit test valid by adding `type: 'object'`
2019-05-29 15:51:42 +02:00
jos f005c437db Publish v5.32.5 2019-04-27 17:38:12 +02:00
jos a773d5cf8f Fixed JMESPath query wizard not correctly handling selection of multiple fields 2019-04-26 21:34:17 +02:00
jos b781a47702 Publish v5.32.4 2019-04-10 12:28:52 +02:00
jos 70b7e7914b Fixed #663 and #682: JSONEditor not being able to handle JSON schema validation errors when the root of the document is an Array 2019-04-10 12:23:13 +02:00
jos d51090b7c9 Publish `v5.32.3` 2019-04-04 19:51:40 +02:00
jos c685813538 Fix #684: `const` used in bundled library 2019-04-04 19:49:39 +02:00
jos 965584efe6 Publish v5.32.2 2019-04-03 15:08:29 +02:00
jos 271cb2b512 Update history 2019-04-03 14:58:36 +02:00
jos b38816a88b Merge branch 'duplicate_key_errors_take2' into develop
# Conflicts:
#	src/js/util.js
2019-04-03 14:56:39 +02:00
jos 35ff268759 Fix links in transform modal not working 2019-04-02 21:30:34 +02:00
jos 8cc4bf7efa Fix error in transform modal in case of an empty object 2019-04-02 21:27:50 +02:00
jos b279ed3069 Fix CSS class for default/non-default schema values not applied to enums, see (#666) 2019-04-02 21:09:17 +02:00
jos ff8be9635a Remove redundant 300px bottom padding (see #416) 2019-04-02 20:49:53 +02:00
jos 7624919a6c Fix broken build (remove usage of ` characters) 2019-04-02 20:47:29 +02:00
jos ebe7bafe51 Fix JMESPath query not working anymore for arrays with numbers 2019-03-31 20:03:56 +02:00
jos 801921867d Improve detection of value type in transform modal 2019-03-31 19:51:12 +02:00
jos 4818c4bb27 Styling improvements in the transform modal 2019-03-31 17:17:47 +02:00
jos 144be4a16d Fix duplicate warning icon not aways showing up 2019-03-31 16:29:09 +02:00
jos 2a551117b2 Merge branch 'develop' into duplicate_key_errors_take2 2019-03-30 21:19:41 +01:00
jos 9e3b6fb196 Fixed #416: Clipped action menu for append nodes 2019-03-30 21:00:26 +01:00
jos 12d908d08a Show warning icon when value or field is invalid or duplicate 2019-03-30 20:58:43 +01:00
jos 19a625fa6e Fix duplicate not working for arrays anymore 2019-03-30 14:15:24 +01:00
jos 6ccf5c651d Fix redo duplicate not checking for duplicate property names 2019-03-30 14:13:25 +01:00
jos d31917390c Revert to previous valid value on blur 2019-03-30 13:47:40 +01:00
jos 00baaacacc Disable having duplicate nodes (except whilst typing) 2019-03-30 13:35:51 +01:00
jos 55c4c91370 Publish v5.32.1 2019-03-28 20:17:11 +01:00
jos 4c5b19e7fa Update history 2019-03-28 19:51:42 +01:00
Adam Vigneaux 09ab92017c Fix JSON path parsing for array indices (#679)
* Switch JSON path tests to strict equality

The tests for `stringifyPath` and `parsePath` were using
[`assert.deepEqual`](https://nodejs.org/api/assert.html#assert_assert_deepequal_actual_expected_message),
which was causing the tests to pass when they should not have. Beyond
that, the `deepEqual` method is deprecated. The suggested replacement is
[`assert.deepStrictEqual`](https://nodejs.org/api/assert.html#assert_assert_deepstrictequal_actual_expected_message),
which causes the tests to fail where they should.

The difference between the two methods is the different between `==` and
`===`. `deepEqual` would coerce the input `"2"` to `2`, so the test was
passing even though the output was of the wrong type (string instead of
number).

* Coerce numeric indices to numbers in parsePath

This fixes a regression introduced in
3e7e1cebfd.
2019-03-28 19:49:36 +01:00
jos 560dd033ad Updated history 2019-03-21 21:29:38 +01:00
tobiasfriden 4763bdf293 Fixed using hyphens in the path of custom validation errors (#665)
* Fixed a bug where using hyphens in the path for custom validatons error didn't work

* Added closing bracket check and unit tests

* Automatically add brackets when path component contains hyphens

* use regexp to check if dot notation is safe
2019-03-21 21:27:17 +01:00
jos 0fbe7eee9a Publish v5.32.0 2019-03-20 17:46:49 +01:00
jos 3e7e1cebfd Fixed #676: JSON Paths containing array properties with a `]` not parsed correctly 2019-03-20 17:34:39 +01:00
jos 7c398aeef7 Update history. Fix JSON schema default value styling not working for `false` and `null`, and fixed the styling not updating when clicking a boolean checkbox (See #666) 2019-03-17 15:56:29 +01:00
Adam Vigneaux c79bea4eb8 Display schema defaults inline next to Nodes (#666)
* Display schema defaults inline next to Nodes

* Improve usability of schema default display

- When value is default, make it bold and set a tooltip
- When value is not default, display the default next to the value
- When value is default and is a select, show "Default" next to it
- Lighten the color of green used for values
  This increases the contrast between normal values and default values.

* Remove styling when value is the same as the schema default

This styling may have been confusing for some users and may not have
been applicable to all situations.

* Apply is-default and is-not-default classes to values

This allows the user to supply custom styling for these states.

To set styles for values that match the default value in the schema, use
the class `.jsoneditor-is-default`.

To set styles for values that _do not_ match the default value in the
schema, use the class `.jsoneditor-is-not-default`.

* Remove extra newline after schema examples in tooltip

* Move schema default display from inline to tooltip

This presents less opportunity for user confusion and is likely to be
more widely applicable.

* Add examples of schema metadata display

* Add documentation on styling
2019-03-17 15:39:00 +01:00
jos 7a2e89c329 Update history 2019-03-17 15:35:03 +01:00
jos 1d0870af36 Merge branch 'fix/schema-ref-examples' of https://github.com/AdamVig/jsoneditor into AdamVig-fix/schema-ref-examples 2019-03-17 15:31:23 +01:00
Adam Vigneaux 4f4a733fd6
Fix Node._findSchema bug when path is not present in schema
Previously, the function would return the wrong schema when it was
unable to find a path in the given schema.
2019-03-15 15:29:08 -04:00
jos 88972a62fc Publish v5.31.1 2019-03-14 21:22:07 +01:00
jos a01ff4a892 Fix missing polyfill on IE11 2019-03-14 21:21:19 +01:00
Adam Vigneaux f36cecdfde
Fix Node._findSchema schema reference support 2019-03-14 16:14:14 -04:00
Adam Vigneaux c0915548de
Add failing Node._findSchema schema reference test 2019-03-14 16:12:03 -04:00
DappWind 92fbe410a3 fix(i18b): fix Chinese translation error (#670) 2019-03-14 20:42:07 +01:00
Adam Vigneaux c93b8f1305
Add reproduction for schema ref examples bug 2019-03-14 11:27:28 -04:00
jos 1acd2d6116 Describe `onClassName` in the docs 2019-03-11 20:14:55 +01:00
jos 868dc38ceb Update history 2019-03-11 19:53:55 +01:00
adf0001 390afbdae0 Fix Chinese translation error (#668) 2019-03-11 19:52:46 +01:00
jos afead89e3b Publish `v5.31.0` 2019-03-10 17:56:47 +01:00
jos 829225849e Update history 2019-03-07 20:51:01 +01:00
jos 2dfde82197 Add examples to test_schema.html 2019-03-07 20:50:05 +01:00
Adam Vigneaux c8aeb1134d
Merge remote-tracking branch 'upstream/develop' into tooltip-examples 2019-03-04 16:15:14 -05:00
Adam Vigneaux 803563003c
Show examples from schema in field tooltip 2019-03-04 16:10:30 -05:00
Adam Vigneaux 03d019a554
Provide Navigator and allow locale override in test environment setup 2019-03-04 16:09:52 -05:00
jos a4d704f792 Publish `v5.30.0` 2019-03-02 10:51:50 +01:00
jos 03c833bad6 Update history 2019-03-02 10:31:01 +01:00
jos b5e9cfb34b Fix custom menu item in example 21 broken 2019-03-02 10:28:50 +01:00
jos 83b6c9a892 Update example 21 so it can run in IE11 2019-03-02 10:26:39 +01:00
jos 1857e80fcb Merge branch 'master' of https://github.com/RobAley/jsoneditor into RobAley-master 2019-03-02 10:18:49 +01:00
RobAley b83090d412
change path parameter to object 2019-02-25 16:14:49 +00:00
RobAley edca7a7a62
update oncreatemenu to change path to object 2019-02-25 16:05:54 +00:00
RobAley 74272397b4
change oncreatemenu path to object 2019-02-25 16:03:25 +00:00
RobAley b48f084cf5
Change oncreatemenu path to object 2019-02-25 16:02:35 +00:00
RobAley 43ac83520d
changed onCreateMenu path to object 2019-02-25 16:00:40 +00:00
RobAley b801affd9c
added onCreateMenu docs 2019-02-21 14:48:34 +00:00
RobAley 1c743bed1d
Add example for onCreateMenu 2019-02-21 14:32:20 +00:00
RobAley aec7308c78
Add call to onCreateMenu 2019-02-21 14:31:14 +00:00
RobAley aa577d2437
Add call to onCreateMenu 2019-02-21 14:26:37 +00:00
RobAley 981ce535d1
Change onCreateMenu to pass path rather than node 2019-02-21 14:23:40 +00:00
jos 8fc8e50bf1 Publish `v5.29.1` 2019-02-20 20:56:14 +01:00
jos 704a50d415 Fixed #661: JSONEditor broken on IE11 caused by duplicate JSON entries in a translation 2019-02-20 20:38:21 +01:00
RobAley 5d833d2131
Add call to options.onCreateMenu
to allow customisation of context menu items
2019-02-17 11:16:14 +00:00
RobAley 2bd4ca67af
Add onCreateMenu as valid option 2019-02-17 11:12:07 +00:00
jos df4673146f Publish `v5.29.0` 2019-02-16 14:12:53 +01:00
Adam Vigneaux f8279537d0 Fix Node._findSchema() (#651)
* Add test setup function for simulating browser globals

* Add tests for Node._findSchema

Some of the tests currently fail, which will be helpful in fixing the
incorrect behavior of the `_findSchema` function. The current failures
are:
- the last schema in the pattern properties object is always returned
- when pattern properties are present, wrong object schemas are returned

* Add schema-based tooltip to field names

Using the `title` and `description` properties from the schema, create
and set a tooltip on each field name. When the user hovers over a field
name, it will show the applicable information: title, description, both,
or neither, depending on what data is present in the schema.

* Remove redundant setting of field name title

* Remove accidental .only() from Node tests

* Fix Node._findSchema for pattern properties

The method now checks the key against the RegExp specified by the
pattern properties instead of always returning the last pattern property
in the object.

* Fix path used for recursive calls in Node._findSchema

* Add failing Node._findSchema tests for multi-level pattern properties

* Fix Node._findSchema for schemas with properties and patternProperties
2019-02-16 14:01:30 +01:00
jos 53a4f57dda Fix #657: `onClassName` throwing an error when a node is removed 2019-02-14 20:42:23 +01:00
jos c28cef0a9a Update history 2019-02-13 11:53:07 +01:00
jos 7c17ef9001 Merge branch 'add-schema-description-tooltips' of https://github.com/AdamVig/jsoneditor into AdamVig-add-schema-description-tooltips 2019-02-13 11:50:40 +01:00
Adam Vigneaux 9377ee825d
Remove redundant setting of field name title 2019-02-11 11:24:05 -05:00
jos 5098095e86 Update docs 2019-02-09 13:05:53 +01:00
jos a0ad953c4c Update history 2019-02-09 13:02:18 +01:00
jos dc55c11015 Fix merge conflicts 2019-02-09 12:57:09 +01:00
Berat Postalcioglu ae2e8018c5 tr json is updated 2019-02-09 02:52:47 +03:00
Berat Postalcioglu 07f7e0fcb4 turkish language support is added by adding tr json to i18n.js 2019-02-09 02:19:27 +03:00
Adam Vigneaux dc357061a7
Add schema-based tooltip to field names
Using the `title` and `description` properties from the schema, create
and set a tooltip on each field name. When the user hovers over a field
name, it will show the applicable information: title, description, both,
or neither, depending on what data is present in the schema.
2019-02-08 09:31:28 -05:00
jos 53a8803e06 Update history 2019-02-05 20:50:10 +01:00
long2ice 10bcf425f7 i18n support zh_CN (#640)
* i18n support chinese

* fix _locales

* rename zh_CN to zh-CN
change the indentation to 2 space
2019-02-05 20:48:56 +01:00
jos 4c6f2cdd4f Publish `v5.28.2` 2019-01-23 14:29:13 +01:00
jos cb2f343d1d Fix #639: Occurrence of non-ES5 `const` declaration in published code 2019-01-23 14:27:19 +01:00
jos 21ae2180e7 Publish `v5.28.1` 2019-01-22 20:48:08 +01:00
jos 3f9ea75f20 Minor code cleanup 2019-01-22 20:44:52 +01:00
jos 7d9db67d69 Fix #637: vertical white border left/right from the main menu in some specific circumstances 2019-01-22 20:44:10 +01:00
jos 958463a9cd Fix #638: cannot expand after collapse 2019-01-22 20:27:23 +01:00
jos 3334241ab9 Publish v5.28.0 2019-01-21 21:06:23 +01:00
jos db9f5480c7 Define `onClassName` once and use it twice 2019-01-21 21:04:32 +01:00
jos 20e42ab8b0 Fix example 20 always highlighting objects and arrays (see #604) 2019-01-21 21:01:38 +01:00
jos c7d054406c Make the method `refresh()` public 2019-01-21 20:56:50 +01:00
jos a7cc8527bd Updated history, some minor tweaks in example 20 (see #604) 2019-01-21 20:53:02 +01:00
Pawel Raszewski 1c5d7d71ac added an ability to set custom css classes for Node's field and value (#604)
* update for gulp 4.0.0

* added an ability to set custom css classes for Node's field and value

* v5.9.8-beta

* wip

* wip

* wip

* wip

* wip

* wip

* cleanup

* reverted ./dist/ files

* cleanup

* reverted package-lock.json

* updated onClassName signature

* recursive node class name update on change

* add/remove css classes on node

* example fix

* merged remote

* removed yarn.lock

* changes get reflected on both sides of the diff view in example 20

* refactored and cleaned up example 20
2019-01-21 20:42:43 +01:00
jos 160c82f378 Updated history 2019-01-16 17:48:29 +01:00
Ben Chadwick a20908f462 Configurable max visible childs (#630)
* repair branch; undo childs->children change; make getMaxVisibleChilds a fn

* address PR comment
2019-01-16 17:47:08 +01:00
jos 4e62cf5ba5 Publish v5.27.1 2019-01-16 15:59:11 +01:00
jos 182150ea30 Updated history 2019-01-16 14:20:54 +01:00
Tyler Chen 4f9fc926f8 Update Node.js (#624)
* Update Node.js

add both:
1. fix childSchema with $ref, and not display the select element on the child schema because of not found enum
2. add title from schema description to show the tips for user input

* Update Node.js

fix this.editor.options.schema could be nullable.

* Update Node.js

improve the Node._findSchema to Node._findSchema = function (schema, schemaRefs, path) { ... } by tylerchen

* update Node._findSchema to Node._findSchema = function (schema, schemaRefs, path)
2019-01-16 14:18:02 +01:00
jos 5a93d3df6d Update history 2019-01-12 11:27:52 +01:00
Meir Rotstein 02d7d0fc71 Add option for show all path on the navigation bar (tree mode) (#628)
* navigation bar - allow to see all path when there is no space

* fix: ellipsis was not presented on some cases

* some code cleaning
2019-01-12 11:25:02 +01:00
jos e9f6a299f7 Publish v5.27.0 2019-01-05 15:21:54 +01:00
jos b59da1a5c9 Describe `onNodeName` in docs (see #617) 2019-01-05 15:15:33 +01:00
jos 8c74bc7ef9 Put try/catch directly around `this.editor.options.onNodeName(...)` (see #617) 2019-01-05 15:00:13 +01:00
jos 1e29d2a94a Check whether `onNodeName` is defined before calling the function (see #617) 2019-01-04 21:11:27 +01:00
jos 535a47c347 Updated history 2019-01-04 21:04:37 +01:00
jos b6e34ea476 Merge remote-tracking branch 'origin/develop' into develop 2019-01-04 21:03:58 +01:00
Bastian Nanchen 93232a09cc Customize object names 2 (#617)
* Customize object names

* Fix: the object's name updates when its properties change

* Creation of node.prototype.updateObjectName method

* Implementation of recursivelyUpdateObjectName method

* Callback arguments: path and size

* New callback argument - type: array | object

* Code improvement and callback function renaming: onNodeName
2019-01-04 21:03:45 +01:00
jos b202627f6e Update history 2019-01-04 21:00:21 +01:00
Meir Rotstein 78194051b0 Hide show error table (#620)
* allow to hide adn show the error table

* code mode: scroll to line on text selection

* validation icon - pointer cursor

* (1) toggle validation errors table by clicking validation count
(2) preserve show/hide state after fixing parse errors

* remove arrow function (no ES6 support)
2019-01-04 20:57:19 +01:00
jos bc5c133b52 Updated history 2018-12-20 21:18:07 +01:00
Anthony Fu ea119df821 i18n for ModeSwitcher (#616)
* unquote keys

* i18n for ModeSwitcher
2018-12-20 21:14:04 +01:00
jos 72ab51002c Publish v5.26.3 2018-12-06 21:44:37 +01:00
jos 6551701153 Fixed #610: JSON Repair now removes trailing commas 2018-12-06 20:15:14 +01:00
jos 550e0a2c4e Updated history 2018-12-05 09:38:51 +01:00
Pawel Raszewski 404fa036f9 Gulp4 (#608)
* update for gulp 4.0.0

* added gulp 4.0.0
2018-12-05 09:35:52 +01:00
jos 9ac82e24d2 Publish v5.26.2 2018-11-13 20:39:02 +01:00
jos db8652baa6 Publish v5.26.1 2018-11-13 20:29:22 +01:00
jos 2cd9cc168a Fixed #598: Search field can't be focused in object view 2018-11-13 20:27:54 +01:00
Jacob Page 3065dad0f5 Fix deepEqual for null values (#600)
When doing a `.update` on an editor that was showing an object and
replacing it with `null`, a runtime exception occurs. This is because
the `deepEqual` check doesn't account for the fact that `typeof null ===
'object'`, so it tries to access properties of a null value.
2018-11-13 20:04:54 +01:00
jos bd8bac03bd Publish v5.26.0 2018-11-12 20:14:03 +01:00
Tanmay Rajani d7551da7e6 Create option to hide the blue main menu bar on top (#596)
* ability to hide main menu bar; minor fixes for typos, JSDoc etc.

* fix CSS issue when mainMenuBar is hidden in all modes; other minor refactoring
2018-11-12 20:11:09 +01:00
jos 4e24601823 Publish v5.25.0 2018-10-29 20:31:10 +01:00
jos d0b49fbf12 Fixed #589 for undo/redo and duplicate actions too 2018-10-29 20:28:27 +01:00
jos 67ef58bef3 Fixed #595: navigation bar path link not working 2018-10-24 21:58:56 +02:00
jos 07b341546e Updated history 2018-10-18 20:43:23 +02:00
Tanmay Rajani 6403c0bd17 Adds ability to hide sort and transform options (#588)
* adds ability to hide sort and transform buttons

* adds new options to API doc

* cover context-menu sort, transform options; remove negations

* update readme wordings
2018-10-18 20:42:02 +02:00
jos 9c23ca9791 Fixed not preventing default selection of text when selecting nodes 2018-10-17 15:31:42 +02:00
jos e08250c3cb Fixed duplicate and remove of the action menu of multiple selected nodes not working 2018-10-17 15:26:05 +02:00
jos 7d2d669191 Fixed #590: validation failing in code and text mode when status bar is disabled 2018-10-17 14:50:47 +02:00
jos 37e609d4d8 Fixed #589: when deleting or moving a node, the navigation bar is not updated with the correct path 2018-10-17 13:40:48 +02:00
jos b45993ccd5 Release v5.24.7 2018-10-08 20:07:21 +02:00
Meir Rotstein 4d7bb3c6e3 refresh annotations with error type only (#587)
* Fix #582: parse error annotations not always up to date in code editor

* refresh annotations with error type only
2018-10-08 19:52:47 +02:00
Mark Herhold 68aba366ad Don't package CONTRIBUTING.md or examples folder (#579)
* Don't package CONTRIBUTING.md or examples folder

If you don't want this, please just close.

Thanks for the awesome module!

* Update .npmignore

don't ignore examples/
2018-09-18 19:53:57 +02:00
jos ef764df37d Release v5.24.6 2018-09-12 09:44:23 +02:00
jos 655990c2a7 Fix #548: `import JSONEditor from 'jsoneditor'` not working in TypeScript projects 2018-09-12 09:41:07 +02:00
jos f27bd97d9d Release `v5.24.5` 2018-09-06 20:44:14 +02:00
jos 70140b0712 Release `v5.24.4` 2018-09-06 20:33:04 +02:00
jos c680a1ca4c Fixed #576: Visualization in mode `view` when an array with more than 100 items is rendered 2018-09-06 20:24:18 +02:00
jos 36f79de242 Throw console errors when Promise is missing (on IE 11) 2018-09-06 20:18:31 +02:00
jos 1736b11b41 Fixed `onClose` of color picker not always being fired 2018-08-29 21:10:13 +02:00
jos 1f1a92354d Merge remote-tracking branch 'origin/master' 2018-08-29 11:32:19 +02:00
jos 384859b132 Release `v5.24.3` for real (exclude vanilla-picker from minimalist bundle again) 2018-08-29 11:32:07 +02:00
jos 53da7fb8df Release `v5.24.3` 2018-08-29 11:27:29 +02:00
jos 321f947e72 Fixed color picker closing immediately after the first `onChange` event, and `onChange` events are now debounced 2018-08-29 11:06:11 +02:00
jos ed9a6d48f3 Fixed color picker not working in ES6 projects 2018-08-29 10:53:33 +02:00
Jos de Jong 9ae7c22286
Fixed #574: removed outdated ways to install `jsoneditor` 2018-08-28 20:14:41 +02:00
jos d528c37909 Release `v5.24.2` 2018-08-27 19:56:01 +02:00
Meir Rotstein d720a94d45 Improvements for errors panel (#567)
* util.getPositionForPath

* utils.getPositionForPath - allow multiple paths

* code mode - show validation errors on gutter

* show all validation errors with scroll indication on text mode

* import json-source-map in favor of getting validation errors location

* revert dist change

* add statusbar indication for validation errors

* reset valodation errors indication  + code clean

* change display indication for validationErrorIndication

* extend schema validatin example with additional errors to demonstrate recent changes

* minor css change

* text mode: navigation from error to code

* bugfix: validation errors scroll indication remains on json error

* show parse errors on the editor bottom and add a status bar indication

* give more helpful tooltip for parse error

* errors container - set onscroll only when needed

* (1) Json parse erros: replace jsonLint errors newline with breakdown
(2) scroll to line on text selection
(3) bugfix: 'show more errors' indication stays when there are no errors
2018-08-27 19:47:22 +02:00
jos ed28e91b9f Release `v5.24.1` for real 2018-08-26 17:47:41 +02:00
jos 2644cb9d1c Release `v5.24.1` 2018-08-26 17:47:02 +02:00
jos d3192e9fbe Fixed `transform` not creating/removing expand button when the type of a node changed 2018-08-26 17:35:45 +02:00
jos 00f2ab0b76 Revert small test editors 2018-08-25 15:31:58 +02:00
jos 4c364dc404 Update history 2018-08-25 15:27:53 +02:00
jos 2b938a27f9 Cleanup anchor when color picker closes 2018-08-25 15:26:27 +02:00
jos fe4144f5f2 Absolutely positioned color picker 2018-08-25 15:22:37 +02:00
jos 181140f733 Absolute instead of relatively positioned context menu: can overflow the editor if it doesn't fit 2018-08-25 14:29:12 +02:00
jos 5ca264d037 Fixed #568: mode switcher disappearing when selecting the current mode again 2018-08-24 20:24:12 +02:00
jos 1a99acd36d Release `v5.24.0` 2018-08-22 21:19:11 +02:00
jos f913d4e08a Implemented `timestampTag` 2018-08-22 18:00:56 +02:00
jos 61039c665e Show picker on left side if it doesn't fit at the bottom 2018-08-22 17:43:13 +02:00
jos 30d7a7b2a6 Revert an unnecessary change in textmode classes 2018-08-22 12:53:23 +02:00
jos 38a54ab9de Fixed styling of validation error buttons 2018-08-22 12:39:34 +02:00
jos 9833c2dd9c Black text color for values holding a color 2018-08-22 12:18:42 +02:00
jos b853ec3f64 Implement color picker. Expose `VanillaPicker`, `ace`, and `Ajv`. 2018-08-22 12:10:15 +02:00
jos 4f72c5e113 Display a colored square left from values containing a color 2018-08-22 09:20:19 +02:00
jos 72bcb6802d Released v5.23.1 2018-08-17 20:22:52 +02:00
jos ffe727849e Fixed #566: transform function broken, regression since `v5.20.0` 2018-08-17 20:20:36 +02:00
jos eb56fc38b4 Released v5.23.0 2018-08-15 12:29:56 +02:00
jos f11f763171 Implemented support for async custom validation 2018-08-15 12:21:27 +02:00
jos 620c5e0b89 Add className `jsoneditor-validation-error` to nodes with a validation error 2018-08-15 11:02:54 +02:00
jos d57beb9f47 Minor refactoring 2018-08-15 10:55:34 +02:00
jos 8bb2962505 Implemented support for custom validation 2018-08-15 10:48:51 +02:00
jos ed81af02ec Release v5.22.0 2018-08-13 20:57:11 +02:00
jos 9dec9617b1 Updated history 2018-08-13 20:54:47 +02:00
jos 482b9a74a2 Cleanup comments and update number of example 2018-08-13 20:53:32 +02:00
jos 13bb4d7bb1 Merge branch 'extendEvent' of https://github.com/cristinabarrantes/jsoneditor into cristinabarrantes-extendEvent
# Conflicts:
#	package.json
#	src/js/JSONEditor.js
2018-08-13 20:53:03 +02:00
jos c7a29d74c5 Release v5.21.0 2018-08-12 13:10:20 +02:00
jos 260a428249 Fix #562: allow `$` character in property names of of a JSON schema 2018-08-12 13:06:31 +02:00
jos ae3fb78486 Update history 2018-08-12 12:43:35 +02:00
Meir Rotstein d387de366a Show validation errors inline in code mode (#560)
* util.getPositionForPath

* utils.getPositionForPath - allow multiple paths

* code mode - show validation errors on gutter

* show all validation errors with scroll indication on text mode

* import json-source-map in favor of getting validation errors location

* revert dist change

* add statusbar indication for validation errors

* reset valodation errors indication  + code clean

* change display indication for validationErrorIndication

* extend schema validatin example with additional errors to demonstrate recent changes

* minor css change
2018-08-12 12:41:02 +02:00
jos 6a6c34fd00 Release `v5.20.0` 2018-08-10 13:27:32 +02:00
jos 03543883b8 Fixed transform undo/redo losing order of properties 2018-08-10 13:15:45 +02:00
Cristina bb699e1473 Update documentation 2018-08-10 12:29:25 +02:00
jos ea4b064ab7 Initialize field when moving item from array to object 2018-08-10 08:52:34 +02:00
jos 5f749e1f6e Fix navigation path not correct when a node in an Array still has a value 2018-08-09 18:28:05 +02:00
jos eb9f250725 Fixed `clone` not copying `previousField` and `previousValue` 2018-08-09 18:18:23 +02:00
jos 672b6491cd Fixed restoring DOM selection and another bug in `moveNodes` 2018-08-09 18:13:49 +02:00
jos d81e2b8dab Fixed another bug in `moveNodes` 2018-08-09 18:05:13 +02:00
jos 2ee39cbca8 More fixes in `moveNodes` 2018-08-09 17:54:54 +02:00
jos 5686e2003a More fixes for moveNodes 2018-08-09 15:11:38 +02:00
jos 751c3b5b32 Don't focus on node when there are multiple selected 2018-08-09 13:53:02 +02:00
jos 07f04be182 Fixes in undo/redo of `moveNodes` action 2018-08-09 13:02:12 +02:00
jos 872bd2d186 Fix restoring selection (store serializable path instead of DOM element) 2018-08-09 11:52:12 +02:00
jos 476d44d11c Store internal path in history to prevent issues with duplicates 2018-08-09 11:26:47 +02:00
jos 3a632cf6f9 Revert clone method, gives issues with duplicate 2018-08-09 10:27:18 +02:00
jos b93ba1106c Fixed losing field names on undo/redo moved nodes 2018-08-09 10:16:56 +02:00
jos f47d17e377 Fixed inserting new Array/Object broken 2018-08-09 10:07:09 +02:00
jos 48b73cafcf Fixed a bug in undo/redo moving nodes 2018-08-09 09:47:14 +02:00
jos 0cebd8f618 Fixes in history 2018-08-08 15:00:43 +02:00
jos 3e518e4742 Merge branch 'update_json' into update_json_fix_history
# Conflicts:
#	src/js/Node.js
2018-08-08 11:00:27 +02:00
jos d89eaee231 Add missing attach/detach methods 2018-08-08 10:58:40 +02:00
jos d85419b2c7 Create helper functions to detach/attach a node to DOM 2018-08-08 10:54:35 +02:00
jos b0acd3f1cd Fixed menu buttons "Sort" and "Transform" being available in modes `view` and `form` 2018-08-07 13:52:23 +02:00
jos 73bec80df5 Fixed validation not being executed after `update` in tree mode 2018-08-07 13:46:18 +02:00
jos e794943e20 Fixed `onChange` events being fired during `update` and `updateText` 2018-08-07 13:43:36 +02:00
jos 393dc3f809 Implemented advanced react example and some minor improvements 2018-08-07 13:32:41 +02:00
jos 983fafdf9c Implemented options `onChangeJSON(json)` and `onChangeText(jsonString)` 2018-08-07 11:03:27 +02:00
jos d1ac1cb694 Fixed bug in deepEqual not handling duplicate fields of an object 2018-08-07 10:22:55 +02:00
jos 54cae20630 Implement a simple React demo 2018-08-06 17:10:07 +02:00
jos 235410c59f Implemented an example synchronizing two editors 2018-08-06 14:48:40 +02:00
jos d49518a9ba Describe new methods `update` and `updateText` in the docs 2018-08-06 14:39:21 +02:00
jos a7da2349e5 Order methods in docs alphabetically 2018-08-06 14:30:44 +02:00
jos 3a439ba795 Some refactoring 2018-08-06 14:24:24 +02:00
jos 338df99410 Fix undo/redo (WIP) 2018-08-06 13:36:35 +02:00
jos ab8e6322d2 Handle undo/redo when contents is updated 2018-08-06 12:03:13 +02:00
jos 9ae30ea63d Update only when there are changes in the JSON 2018-08-06 11:14:27 +02:00
jos e16a8fb429 Implemented `update` and `updateText` for text/code mode (currently has no effect) 2018-08-06 10:46:19 +02:00
jos 80e5da9728 Impelemented `updateText` 2018-08-06 10:27:57 +02:00
jos 3d433741d2 Update selection when updating JSON document 2018-08-06 10:01:44 +02:00
jos e8e684a516 Update search results after updating JSON 2018-08-06 09:23:15 +02:00
jos 94871dd2d8 Merge branch 'develop' into update_json 2018-08-06 09:05:33 +02:00
jos ca86cb54bc Publish `v5.19.2` 2018-08-02 10:45:11 +02:00
jos 46593c24c5 Some more fixes around #558 2018-08-02 10:43:12 +02:00
jos 21199eb9e0 Fixed #558: scrolling to search results broken 2018-08-02 10:27:02 +02:00
Cristina 5adf77a193 Use getPath in onEvent 2018-07-30 13:09:27 +02:00
jos 0ea0059696 Fixed switching from object/array to auto/string and vice versa 2018-07-29 22:00:15 +02:00
jos ebcfa301ad Merge remote-tracking branch 'origin/develop' into update_json 2018-07-29 21:46:15 +02:00
jos 53b42184a3 Publish `v5.19.1` 2018-07-28 15:34:18 +02:00
jos 91241c6684 Fixed #557: inner contents of the scrollable area being displayed outside of the editor (on Chrome only) 2018-07-28 15:29:34 +02:00
jos 69e88537c3 Implement `update` method (WIP) 2018-07-28 14:21:12 +02:00
Cristina ef74ede75e Use extended path with type for onEvent 2018-07-26 01:48:03 +02:00
Cristina 9de11c04cd Changes due to PR. 2018-07-16 16:52:41 +02:00
jos d05231977c Fix clear button being activated when clicking the modal header 2018-07-11 13:31:07 +02:00
jos 6edfac4ef1 Released `v5.19.0` 2018-07-11 13:11:41 +02:00
jos 28215132f7 Fixed showing child fields as options when sorting an object 2018-07-11 13:09:01 +02:00
jos 6288139aa7 No more grayed out icons of the context menu, see #532 2018-07-11 12:40:51 +02:00
jos 9244f4719e Created sort and transform buttons in the main menu 2018-07-11 12:23:36 +02:00
jos 77e9303ace Fix select box getting cleared when clicking on an empty area in the modal 2018-07-11 11:44:55 +02:00
jos 7f9fdac9d1 Styling fixes 2018-07-11 11:24:38 +02:00
jos e0d4ab27a3 Add spacing at the bottom to display the dropdown on the bottom item 2018-07-11 11:08:18 +02:00
jos 7662874036 Integrated `mobius1-selectr` 2018-07-11 10:54:08 +02:00
jos 228a9e9f12 Change query input into a textarea 2018-07-07 14:58:16 +02:00
jos 0e674a6b02 Debounce updating preview 2018-07-07 14:41:11 +02:00
jos fdbfa8a951 Enclose string values in double quotes 2018-07-02 22:09:40 +02:00
jos 066f5d37e6 Fixes in extracting all child paths 2018-07-02 21:40:47 +02:00
Cristina ecd9bf021f Add API functionality to extend event behaviour. 2018-07-02 13:13:02 +02:00
jos 8e619dea2f Release v5.18.0 2018-06-27 12:30:46 +02:00
jos b53317e431 Styling tweaks 2018-06-27 12:27:57 +02:00
jos 12ba61f935 Implemented JMESPath wizard 2018-06-27 11:47:59 +02:00
jos fbf20b5031 Fixed #544: JSON Schema errors sometimes not being displayed in the editor 2018-06-24 15:41:25 +02:00
jos cab3211e05 Make code robust against missing `navigator` 2018-06-24 14:37:56 +02:00
jos 463276a3d9 Implemented `modalAnchor` 2018-06-20 20:27:36 +02:00
jos 86d2c60fb4 Some fixes in undo/redo a transform action (WIP) 2018-06-20 15:18:48 +02:00
jos 866c520a71 Remove unused method `_move` 2018-06-20 14:02:14 +02:00
jos df477ed199 Implemented JMESPath preview 2018-06-20 14:01:36 +02:00
jos bcca373931 Change `i18n.js` to 2 space indentation 2018-06-20 13:04:22 +02:00
jos a5a43bbc7b Integrated JMESPath 2018-06-20 12:25:58 +02:00
jos d85a151243 Moved `showSortModal` into a separate file 2018-06-20 09:32:18 +02:00
jos 05c259dfb4 Released `v5.17.1` 2018-06-03 15:26:16 +02:00
jos daee0d05c3 Released `v5.17.0` 2018-06-03 15:21:18 +02:00
jos a2e0b22349 Make "Select a node..." text translatable 2018-06-03 15:17:28 +02:00
jos 0f0ec480f4 Fixed styling issues with select on IE11 and Edge 2018-06-03 14:58:31 +02:00
jos 3b23ef88a2 Fixed sort modal not working when JSONEditor is created inside a form 2018-06-03 13:45:52 +02:00
jos 185a81e03a Translate the text in the sort modal 2018-06-02 20:21:27 +02:00
jos b28f73ee13 Implemented modal header 2018-06-02 16:37:40 +02:00
jos 41aa876b08 Implemented button group for asc/desc 2018-06-02 16:19:21 +02:00
jos 95d5d33f56 Remember sorting 2018-06-02 15:02:24 +02:00
jos bd87ac83d5 Neat styling of modal popup contents 2018-06-02 14:53:57 +02:00
jos 2e207196df Make sure the paths in the sort modal are sorted 2018-05-30 22:33:58 +02:00
jos 1106404822 Sorting robust against missing nested childs, and collect nested properties from all childs instead of just the first. 2018-05-30 22:32:37 +02:00
jos 8b77111393 Implemented advanced sorting modal (WIP) 2018-05-30 21:54:25 +02:00
jos 9eb9c4fe0b Implemented `getSortablePaths` 2018-05-30 09:48:51 +02:00
jos f00c837388 Released v5.16.0 2018-05-23 09:50:53 +02:00
jos d9babab497 Limit search results to max 1000 matches 2018-05-21 20:35:49 +02:00
jos 916c657e28 Set back correct `MAX_VISIBLE_CHILDS` 2018-05-16 21:17:56 +02:00
jos 02ae08173b Renamed `maxVisibleChilds` to `visibleChilds` 2018-05-16 21:11:52 +02:00
jos 8eaa488318 Fixed updating `maxVisibleChilds` in `appendChild` 2018-05-16 21:05:56 +02:00
jos 0fd1cbabb4 Highlight showMore when selected 2018-05-16 17:26:56 +02:00
jos abe274869c Some more fixes 2018-05-16 17:12:48 +02:00
jos 2c806bd105 Change default max visible childs to 100 2018-05-12 20:14:12 +02:00
jos c0a5774005 Render errors only for visible nodes 2018-05-12 17:51:24 +02:00
jos 53a49107d0 Handle expanding maxVisibleChilds if needed with undo/redo 2018-05-12 17:23:21 +02:00
jos 8dff972dce Implemented translate (`pt-BR` still has to be checked for correctness) 2018-05-12 16:53:18 +02:00
jos 3d8ca6df33 Cleanup commented code 2018-05-12 16:36:41 +02:00
jos 402afe92e2 Fixed changing type of object to array and vice versa 2018-05-12 16:27:33 +02:00
jos 6a15c04053 Fixed quickkeys alt+arrows moving over "show more" tag 2018-05-12 16:14:19 +02:00
jos 92a431e37d Fixed being able to drag an item after the "show more" area 2018-05-07 20:55:39 +02:00
jos 10a2447caa Fixed dragging not working with "show more" 2018-05-06 21:20:53 +02:00
jos 497c20019d No more expanding of all search results. Search working with large arrays 2018-05-06 21:03:53 +02:00
jos 904110d141 Implementing "show more" for large arrays (WIP) 2018-05-06 19:42:19 +02:00
jos 358ef3086c Fixed index of Array items not being updated after sorting 2018-05-03 11:22:58 +02:00
jos 9a77045e78 Released v5.15.0 2018-05-02 10:42:47 +02:00
jos a3c79d0270 Updated history 2018-04-26 22:44:55 +02:00
Jos de Jong 63d8280e85
Merge pull request #504 from meirotstein/get_caret_position
API for caret selection
2018-04-26 22:40:57 +02:00
Meir Rotstein bbff682533 remove comment 2018-04-26 22:22:53 +03:00
Meir Rotstein 1a66dbcedd (1) onTextSelectionChange: change params order (2) getSelection: empty selection 2018-04-26 22:19:35 +03:00
Meir Rotstein e80a840a33 additional fixes + docu 2018-04-22 10:02:17 +03:00
Meir Rotstein ea939591fe change treemode.getNodesByRange to return a list of SerializableNode 2018-04-22 10:01:57 +03:00
Meir Rotstein 1579e787bf CR Fix: remove `field` from SerializedNode 2018-04-19 09:24:07 +03:00
Meir Rotstein dfc03fa4b5 selection API - return selection accrding to direction for both tree and text modes 2018-04-17 23:54:58 +03:00
Meir Rotstein be0e781359 change # of example after merge 2018-04-17 23:48:16 +03:00
Jos de Jong 924b6a708f
Merge pull request #522 from dmitry-kulikov/fix/typos
Fixed typos
2018-04-11 21:08:00 +02:00
Dmitry Kulikov b826ee398b Fixed typos. 2018-04-11 21:54:04 +06:00
Jos de Jong c7fd2ba180
Update maintenance badge 2018-04-11 10:51:55 +02:00
Meir Rotstein e1f91cb1ac some minor fixes & docu 2018-04-02 11:18:32 +03:00
Meir Rotstein 3b186633e7 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
2018-04-02 02:07:53 +03:00
Meir Rotstein e57c292f30 Add treenode.getNodesByRange 2018-04-02 02:01:22 +03:00
Meir Rotstein 39e8d36f72 CR Fix: tree selection - use serializable node as parameters 2018-04-02 01:40:10 +03:00
jos fed496881a Released version 5.14.1 2018-03-21 19:04:45 +01:00
jos e72b1fe839 Updated history 2018-03-05 19:24:36 +01:00
Jos de Jong fa7af9b3da
Merge pull request #515 from landru29/master
jsoneditor-icons.svg is explicitly in a relative path to be compliant…
2018-03-05 19:23:14 +01:00
Meir Rotstein 7e90161057 CR fix: setSelection signature and doc change 2018-03-01 23:05:27 +02:00
Meir Rotstein fb85ffdd5b CR fix - remove 'Node' from node selection function signatures 2018-03-01 22:49:08 +02:00
Cyrille Meichel 04cff49f89 jsoneditor-icons.svg is explicitly in a relative path to be compliant with webpack plugin "file-loader" 2018-02-28 08:40:30 +01:00
jos 1c596ee84d Released version 5.14.0 2018-02-25 19:59:49 +01:00
jos 36e83445ef Simplify example 14 a bit 2018-02-25 19:59:20 +01:00
jos 9fb29a644d Refactor to ES5 code. Some updates in the docs 2018-02-25 19:54:59 +01:00
Jos de Jong 6f4729885b
Merge pull request #514 from mariohmol/master
Basic translate
2018-02-25 19:43:56 +01:00
jos 4b17f56169 Updated history 2018-02-25 17:32:42 +01:00
Jos de Jong 4e6f43412c
Merge pull request #510 from crispthinking/parent-error-cache
cache parent errors
2018-02-25 17:31:23 +01:00
Mario Mol 5305030337 Including link for angular 5.x directive in main docs 2018-02-21 14:21:14 -03:00
Mario Mol 2f13f7fa54 Example incuding a new language and new language created based on english, that means that, if a key is missing in translations that will be english 2018-02-21 14:17:01 -03:00
Mario Mol 466c2c548b Support for overriding translations and for setting one language 2018-02-21 13:58:50 -03:00
James Garbutt e75043e51d use first node as context for parent errors 2018-02-21 15:06:32 +00:00
Mario Mol 40d577732d better performance when getting locale 2018-02-20 09:24:29 -03:00
Mario Mol c42bf9dd4c Basic translate starting up with en and pt-br 2018-02-20 00:00:25 -03:00
43081j 106a75c46a refactor error node computation 2018-02-13 19:38:26 +00:00
Meir Rotstein 8cbe15aa1f move selection_api.html to examples 2018-02-13 20:08:09 +02:00
jos 97cc0f39f4 Updated history 2018-02-12 21:19:52 +01:00
Jos de Jong d40d470c2a
Merge pull request #512 from crispthinking/null-autocomplete
allow null autocomplete results
2018-02-12 21:17:37 +01:00
James Garbutt 00e99a791a cache parent errors 2018-02-12 19:48:01 +00:00
43081j bfbd334b71 allow null autocomplete results 2018-02-12 19:43:04 +00:00
Jos de Jong 5e7f81050e
Merge pull request #509 from crispthinking/missing-previous
pass empty string when no previous field value
2018-02-12 20:23:13 +01:00
James Garbutt 803daf4253 pass empty string when no previous field value 2018-02-09 10:21:10 +00:00
jos c6c592c399 Released v5.13.3 2018-02-07 12:17:32 +01:00
jos 4c8c4d4a02 Fixed a positioning issue with JSON Schema errors in text/code mode 2018-02-07 12:16:00 +01:00
Meir Rotstein 242f3fc3a4 Selection API - docu 2018-01-26 01:25:17 +02:00
Meir Rotstein ad15c8a85f some minor changes 2018-01-25 17:57:01 +02:00
Meir Rotstein 84c015ee93 setNodeSelection - input test 2018-01-25 16:43:47 +02:00
Meir Rotstein 803ce34ed4 test file for selection apis 2018-01-24 23:55:12 +02:00
Meir Rotstein 55674f5b0f add on{Text/Node}SelectionChange configurations to editor options 2018-01-24 22:33:10 +02:00
Meir Rotstein f04eff7b4e unit test for getIndexForPosition() 2018-01-24 21:41:36 +02:00
Meir Rotstein 6bb7f734cf treemode: getNodeSelection() & onNodeSelectionChanged() 2018-01-23 20:47:08 +02:00
Meir Rotstein 47ba66a5a9 textmode: setTextSelection() 2018-01-23 00:00:18 +02:00
Meir Rotstein 3c31476377 textmode: onTextSelectionChanged() 2018-01-20 16:03:46 -05:00
jos c5f3723b9c Released v5.13.2 2018-01-18 20:48:31 +01:00
jos f03b64ffec Consistently use the same font everywhere (see #502) 2018-01-18 20:16:44 +01:00
jos f4dbd1938b Fixed #502: code editor not showing a monospaced font some cases 2018-01-18 20:13:21 +01:00
Meir Rotstein d66d2d6e38 textmode: getTextSelection() 2018-01-18 14:39:34 +02:00
jos f5da46d2cc Updated history 2018-01-08 20:42:31 +01:00
Jos de Jong fbe65d122c
Merge pull request #499 from LEW21/patch-1
In the View mode, open links in the same tab by default
2018-01-08 20:39:39 +01:00
Linus Lewandowski 11cc2929bb
In the View mode, open links in the same tab by default
They'll still get opened in a new tab when the user presses Ctrl (like in the other modes).
2018-01-08 18:20:15 +01:00
jos 24d9920e0d Released v5.13.1 2017-12-28 16:20:32 +01:00
jos 50c6a3ac9f Updated history 2017-12-28 16:18:46 +01:00
jos 43832dd532 Fix another case of #494 2017-12-28 16:16:41 +01:00
jos 3f1c4c682a Released v5.13.0 2017-12-28 15:53:24 +01:00
jos a4cceef13e Update navigation bar with last entered character (instead of all but last) 2017-12-28 15:52:33 +01:00
jos 8aef543fa6 Set initial cursor location at (1, 1) instead of (0, 0) 2017-12-28 15:51:50 +01:00
Jos de Jong ddf6e1f16a
Merge pull request #497 from meirotstein/readme_fix
Update api.md for cursor position in text mode
2017-12-28 15:36:59 +01:00
Meir Rotstein 0a2d113e56 Update api.md for cursor position in text mode 2017-12-27 14:02:00 +02:00
jos 509ab7e275 Updated history 2017-12-24 16:53:06 +01:00
Jos de Jong 2a9107db79
Merge pull request #492 from meirotstein/master
Add caret position to text mode status bar
2017-12-24 16:52:14 +01:00
Meir Rotstein a5f549a289 revert jsoneditor.js 2017-12-24 17:18:17 +02:00
Meir Rotstein 5468c35a79 sync jsoneditor.js 2017-12-24 17:14:13 +02:00
Meir Rotstein 1dde8b2ac9 a bit simplification of cursot info implementation 2017-12-24 17:00:59 +02:00
jos 679a966d15 Updated history 2017-12-24 13:33:13 +01:00
Jos de Jong 14f0956d7a
Merge pull request #495 from meirotstein/textnode_newline_bug
use escaped field text for tree node
2017-12-24 13:30:42 +01:00
Meir Rotstein 95affe7186 use escaped field text for tree node 2017-12-24 10:50:23 +02:00
Meir Rotstein 91f763b9b9 type+ 2017-12-21 13:50:33 +02:00
Meir Rotstein ed030c0518 (1) add status bar to text mode
(2)add caret position to text mode status bar
2017-12-21 13:48:25 +02:00
jos 22e99aa801 Released v5.12.0 2017-12-18 20:42:48 +01:00
jos da26baec0c Update history 2017-12-10 15:05:58 +01:00
Jos de Jong 8d0b0c5b89
Merge pull request #490 from israelito3000/develop
Include caseSensitive option for autocomplete.
2017-12-10 15:04:15 +01:00
Israel 017cd22fd6 Dropdown items casing issue 2017-12-04 03:05:07 -05:00
Israel f2492e32dc caseSensitive option added to autocomplete 2017-12-02 13:30:44 -05:00
Israel 168a65cda4 Revert "caseSensitive option added to autocomplete"
This reverts commit 89601c3115.
2017-12-02 13:23:03 -05:00
Israel 89601c3115 caseSensitive option added to autocomplete 2017-12-02 04:44:25 -05:00
Israel 371a7b2d14 Merge branch 'develop' of https://github.com/josdejong/jsoneditor into develop 2017-12-02 03:00:30 -05:00
jos 179d80a26f Added badges 2017-11-29 09:01:32 +01:00
jos a8253afb35 Released v5.11.0 2017-11-22 16:20:51 +01:00
jos 9d93b3b808 Updated dependencies 2017-11-22 16:19:08 +01:00
jos ae50af0877 Updated history 2017-11-22 16:04:38 +01:00
Jos de Jong 129ad5594a
Merge pull request #487 from alshakero/master
Fix autocomplete.js encoding
2017-11-22 16:04:01 +01:00
jos b5d4e4500d Updated history 2017-11-22 15:54:40 +01:00
Jos de Jong 5dac87c424
Merge pull request #486 from alquist/master
Display a dropdown for enums inside pattern properties
2017-11-22 15:53:11 +01:00
Omar Alshaker dd11f6ec8c Fix autocomplete.js encoding 2017-11-22 12:48:58 +01:00
plany 723f9f5b3f Display a dropdown for enums inside pattern properties 2017-11-20 17:35:11 +01:00
plany c029f716da Display a dropdown for enums inside pattern properties 2017-11-20 17:32:58 +01:00
jos c4cff2e1a0 Released version `5.10.1` 2017-11-15 11:52:35 +01:00
jos 9e105276d9 Don't display statusbar for text mode, some CSS tweaks. 2017-11-15 11:51:05 +01:00
jos b28677d6d1 Released version `5.10.0` 2017-11-15 11:00:02 +01:00
jos 40e4ac9302 Fixed #481: A polyfill required `DocumentType` which is not defined in all environments 2017-11-15 10:52:45 +01:00
jos 42ede262d1 Minor tweak in the repair icon 2017-11-14 22:17:01 +01:00
jos 4875288cb7 Implemented repairing JSON objects containing special white space characters like non-breaking space 2017-11-14 21:59:23 +01:00
jos bf4e977427 Updated title of repair button 2017-11-14 21:41:54 +01:00
jos a958e229f9 Created repair button in text mode 2017-11-14 21:40:08 +01:00
jos cba5659e78 Implemented repairing JSON objects containing left and right single and double quotes 2017-11-14 21:18:49 +01:00
jos a733533af1 Updated history 2017-09-30 14:12:45 +02:00
Jos de Jong ea939d48cc Merge pull request #457 from meirotstein/path_and_count
Add selection count, cursor location and tree path
2017-09-30 13:54:00 +02:00
Jos de Jong ac4716a309 Merge branch 'develop' into path_and_count 2017-09-30 13:53:33 +02:00
Meir Rotstein 83fe0c86f4 color changes for nav and status bars 2017-09-24 00:20:32 +03:00
Meir Rotstein 9c78ea7959 update doc 2017-09-18 18:49:54 +03:00
Meir Rotstein 05dda45265 menu2 -> navBar 2017-09-18 18:25:09 +03:00
Meir Rotstein 5d2b5e5202 nav bar style changes: new colors, replace the arrows with triangle 2017-09-17 01:31:13 +03:00
Meir Rotstein 7899724810 set nav bar height fixed and scroll to selection 2017-09-17 00:13:48 +03:00
jos 5d5b6473b6 Released v5.9.6 2017-09-16 16:50:07 +02:00
jos 968e90edd0 Fixed #461: Urls opening twice on Firefox and Safari 2017-09-16 16:19:19 +02:00
jos de71499269 Fixed JSONEditor not working without having a schema defined 2017-09-16 16:17:31 +02:00
Jos de Jong 6a0ac9549a Merge pull request #463 from hachichaud/fix/findschema-with-nested-composite
Fix FindSchema for nested composites
2017-09-13 22:24:09 +02:00
Meir Rotstein b4e053030b rename option: treePath -> navigationBar 2017-09-13 22:31:26 +03:00
hachichaud b0266d90ab use recursive call to Node._findSchema to handle nested cases 2017-09-13 17:34:39 +02:00
jos 8bc9e8d596 Updated history 2017-09-12 21:59:46 +02:00
Jos de Jong b6ce1c0653 Merge pull request #459 from hachichaud/fix/enum-dropdown-with-composite
Display a dropdown for enums inside composite schemas
2017-09-12 21:52:04 +02:00
hachichaud fc1a81a6f5 loop through composite schemas in _findSchema method 2017-09-07 17:04:46 +02:00
Meir Rotstein 422284cf0d tree path - expand to selection 2017-09-03 14:26:56 +03:00
Meir Rotstein b36df94cfe document treePath in api.md 2017-09-03 13:54:55 +03:00
Meir Rotstein 7ae0c690ef add treePath option 2017-09-03 12:14:41 +03:00
Meir Rotstein 1f57894a4a Support breadcrumbs navigation in treepath 2017-09-03 11:16:22 +03:00
Meir Rotstein 1238d47bff tree path focus node when related section is clicked 2017-09-01 01:19:34 +03:00
Meir Rotstein 11e425e2ff add new treepath.css into gulp build 2017-09-01 00:03:10 +03:00
Meir Rotstein b643eeffb4 Basic path component for tree editor (wip) 2017-09-01 00:02:14 +03:00
Meir Rotstein 6d4aa7d082 Merge branch 'master' into path_and_count
# Conflicts:
#	HISTORY.md
#	dist/jsoneditor-minimalist.js
#	dist/jsoneditor-minimalist.map
#	dist/jsoneditor-minimalist.min.js
#	dist/jsoneditor.js
#	dist/jsoneditor.map
#	dist/jsoneditor.min.js
#	package.json
2017-08-31 01:23:06 +03:00
Meir Rotstein d06c5c3eca Add line and column indication for code editor menu 2017-08-31 00:47:51 +03:00
Meir Rotstein aff04b9cd0 Add count of selected characters on text/code menu 2017-08-31 00:16:25 +03:00
jos a418fbab01 Released v5.9.5 2017-08-26 13:17:50 +02:00
jos d5ba548902 Fixed a regression introduced in #448: after using the context menu once, it was not possible to set focus to an other input field anymore 2017-08-26 13:15:19 +02:00
jos d9746e3a84 Released version 5.9.3 2017-08-20 22:06:34 +03:00
jos 916fa174be Neatly wrap long text of context menu 2017-08-20 22:06:34 +03:00
jos 1504cfc216 Fixed broken multi-selection 2017-08-20 22:06:34 +03:00
Dave Hughes 1ae040243b Fix minor typo in comment 2017-08-20 22:06:34 +03:00
Dave Hughes 66578f4add Fix minor typo in comment 2017-08-20 22:06:34 +03:00
jos 262b65fc6c Released v5.9.2 2017-08-20 22:06:34 +03:00
jos a9e2f73089 Fixed a bug in the sanitizer 2017-08-20 22:06:34 +03:00
jos b92ec827f5 Released v5.9.1 2017-08-20 22:06:34 +03:00
Jos de Jong 7c7ca44313 Reordered browserstack info 2017-08-20 22:06:34 +03:00
jos f2b2756634 Released v5.9.0 2017-08-20 22:06:34 +03:00
jos 2457932400 Fixed JSONEditor picking the first entry of `modes` as initial mode instead of option `mode` 2017-08-20 22:06:34 +03:00
Thiago Bovi de Mendonca 6689759793 Add extra verification when creating JSON editor to avoid to look for an element in an empty array 2017-08-20 22:06:34 +03:00
jos 308f3b2bde Released v5.8.2 2017-08-20 22:06:34 +03:00
jos ea6b71986c Cleanup some unused code. Minor update in the readme and examples 2017-08-20 22:06:34 +03:00
Israel Garcia 3654e46f08 - move 'editor' parameter to the last position
- send standard array path instead of jsonpath in getOptions
2017-08-20 22:06:34 +03:00
Israel Garcia 97891621e3 return jsonpath in getOptions and editor instance. 2017-08-20 22:06:34 +03:00
jos 694e766fbf Drop package-lock for now, revert to using npm v4 2017-08-20 22:06:34 +03:00
jos 84ab5107dd Updated history 2017-08-20 22:06:34 +03:00
Owen Garland a9584e015f Enabled the default mode to be set when using a list of available modes. 2017-08-20 22:06:34 +03:00
jos a0f317d1d6 Released v5.9.4 2017-08-20 20:40:08 +02:00
Jos de Jong 9ee8700661 Merge pull request #448 from tomalec/issues/447-modes-in-shadow-dom
Add listeners to list (shadow) root instead of window,
2017-08-20 20:37:22 +02:00
Tomek Wytrebowicz 63c0689a61 Remove event listeners from (shadow) root instead of window,
make context menus work in Shadow DOM.

Fixes https://github.com/josdejong/jsoneditor/issues/447
2017-08-20 15:26:44 +02:00
Tomek Wytrebowicz b1a939d680 Add listeners to list (shadow) root instead of window,
make context menus work in Shadow DOM.

Fixes https://github.com/josdejong/jsoneditor/issues/447
2017-08-17 20:51:20 +02:00
Israel Garcia 1651c50c01 Merge pull request #2 from josdejong/develop
Merge Develop to Develop
2017-08-17 13:03:45 -04:00
jos c51db94f88 Released version 5.9.3 2017-07-24 11:56:21 +02:00
jos 06bbf2d1a5 Neatly wrap long text of context menu 2017-07-24 11:37:43 +02:00
jos 6ad7552c3e Merge remote-tracking branch 'origin/develop' into develop 2017-07-24 10:07:13 +02:00
jos 2110d251bb Fixed broken multi-selection 2017-07-24 10:07:00 +02:00
Jos de Jong b69d52a46b Merge pull request #439 from dhughes-xumak/defect/minor-treemode-comment-typo
Fix minor typo in comment
2017-07-18 21:18:23 +02:00
Dave Hughes 6b1546f803 Fix minor typo in comment 2017-07-18 12:15:46 -07:00
Jos de Jong 595c4f48df Merge pull request #436 from dhughes-xumak/defect/minor-treemode-comment-typo
Fix minor typo in comment in treemode.js
2017-07-18 21:11:18 +02:00
Dave Hughes 475dbc04b2 Fix minor typo in comment 2017-07-17 12:59:08 -07:00
jos f6e699e4cc Released v5.9.2 2017-07-13 21:02:38 +02:00
jos 524d00e15e Fixed a bug in the sanitizer 2017-07-13 21:01:52 +02:00
jos 3e4c975b70 Merge remote-tracking branch 'origin/master' 2017-07-13 20:19:27 +02:00
jos 2046d98936 Released v5.9.1 2017-07-13 20:19:01 +02:00
Jos de Jong 860aa31ddb Reordered browserstack info 2017-07-12 10:09:55 +02:00
jos a00ec59241 Released v5.9.0 2017-07-10 20:05:13 +02:00
jos 22fb4ca501 Merge remote-tracking branch 'origin/develop' into develop 2017-07-10 19:58:41 +02:00
jos 7ac3f5aee6 Fixed JSONEditor picking the first entry of `modes` as initial mode instead of option `mode` 2017-07-10 19:58:34 +02:00
Jos de Jong ccb9ea6d94 Merge pull request #423 from meirotstein/master
add support for json schema references ($ref)
2017-07-10 19:57:59 +02:00
Jos de Jong 15ed4da608 Merge pull request #428 from trystan2k/bugfix/incorrectConditionOnModesArray
Add extra verification when creating JSON editor to avoid to look for…
2017-07-10 19:47:15 +02:00
Thiago Bovi de Mendonca e8684d7d42 Add extra verification when creating JSON editor to avoid to look for an element in an empty array 2017-07-10 10:21:33 +02:00
Meir Rotstein 0b9c1f8d34 Set schemaRefs as optional parameter of setSchema() and remove setSchemaRefs() 2017-07-10 10:32:13 +03:00
jos b84621d054 Released v5.8.2 2017-07-08 11:51:48 +02:00
jos ee85fb099d Cleanup some unused code. Minor update in the readme and examples 2017-07-08 11:48:32 +02:00
Jos de Jong ea06b877b8 Merge pull request #426 from israelito3000/improvements/autocomplete
Improvements/autocomplete
2017-07-08 11:43:34 +02:00
Israel Garcia 495ed38063 - move 'editor' parameter to the last position
- send standard array path instead of jsonpath in getOptions
2017-07-07 13:43:15 -04:00
Israel Garcia d423a70a5d return jsonpath in getOptions and editor instance. 2017-07-06 22:26:25 -04:00
jos fec677883b Drop package-lock for now, revert to using npm v4 2017-07-05 22:12:58 +02:00
jos 3e7a7c08f0 Updated history 2017-07-05 22:12:37 +02:00
Jos de Jong 6d56b1ba76 Merge pull request #424 from bag-man/feature/default-mode-from-list
Enabled the default mode to be set when using a list of available modes.
2017-07-05 22:10:08 +02:00
Israel Garcia f9d8a039e2 merge from upstream 2017-07-05 12:10:59 -04:00
Owen Garland f6f2fce422 Enabled the default mode to be set when using a list of available modes. 2017-07-05 16:32:04 +02:00
Meir Rotstein b77deb969c add support for json schema references ($ref) 2017-07-05 00:28:28 +03:00
jos 3a8aa1755c Released v5.8.1 2017-07-03 19:23:32 +02:00
jos a6bd4646ca Released v5.8.0 2017-07-02 14:32:00 +02:00
jos 5559b0d417 Updated history 2017-07-02 13:45:06 +02:00
jos 0aed6e481e Some updates in the examples (indentation, link to jsonpath library instead of including it) 2017-07-02 13:44:08 +02:00
jos 02555b8510 Some updates in the docs 2017-07-02 13:43:10 +02:00
Jos de Jong 1f29f5912a Merge pull request #407 from israelito3000/feature/autocomplete2
Feature/autocomplete2
2017-07-02 13:23:55 +02:00
Israel Garcia 088d7d6c90 - Change signature of getOptions function to (text, path, input)
- Remove node object from exposure.
- Improve startFrom option by returning the start position.
2017-06-29 01:57:54 -04:00
Jos de Jong 3e431bc745 Released v5.7.2 2017-06-27 09:17:28 +02:00
Jos de Jong 294dfbe60e Fixed #419: minified bundles in dist folder are empty 2017-06-27 09:15:51 +02:00
jos 9e5dd53e8d Released v5.7.1 2017-06-25 14:53:28 +02:00
Israel Garcia f71aa6c5b9 Restore code for showing asyc the autocomplete. 2017-06-19 12:39:15 -04:00
Israel Garcia 4036f5cd28 Remove activationChar, update documentation. 2017-06-19 12:03:15 -04:00
jos a1780c7cdf Upgraded dependencies, added package-lock.json (npm v5) 2017-06-18 14:19:36 +02:00
Jos de Jong f0904b92f2 Merge pull request #412 from andreykaipov/update-ajv
Update Ajv version to prevent spurious warnings
2017-06-18 14:10:18 +02:00
Israel Garcia 00ba443acf - polyfills moved to utils.js
- lowercase "Show" function
- refine autocomplete examples.
- style improvements to match context menu.
- set auto to scrollbar in autocomplete dropdownbox
- Added docs for Templates and Autocomplete
- Promisify getOptions function
- Add elementType to getOptions function to return which element "field" or "value" is being edited.
- applyTo option now accept ['field', 'value'] instead of ['name', 'value']
- optimize confirmKeys to be part of the autocomplete option instead of autocomplete.config
2017-06-16 20:19:56 -04:00
Andrey Kaipov f0897d534b Update Ajv version to prevent spurious warnings 2017-06-13 11:41:55 -04:00
Israel Garcia fc4562fea1 restore onblur event for hide the dropdownbox 2017-05-31 19:44:51 -04:00
Israel Garcia df4cb21146 stylize as CSS classes, remove config inline styles. 2017-05-31 19:41:50 -04:00
Israel Garcia 0391ad11b4 adjust public methods to camelCase and refine examples. 2017-05-31 17:53:24 -04:00
jos 5f8b90f35e Released v5.7.0 2017-05-26 16:17:34 +02:00
Israel Garcia 5411ad19ac autocomplete integrated. 2017-05-26 03:58:16 -04:00
Israel Garcia 8707432837 adjust documentation in each example 2017-05-26 03:45:20 -04:00
Israel Garcia 2a0d9ec2bf remove horsey autocomplete 2017-05-26 03:34:36 -04:00
Israel Garcia ae287d48e9 Autocomplete integrated and 3 samples. 2017-05-26 03:32:01 -04:00
Israel Garcia c6121dfe5c Merge branch 'develop' of https://github.com/josdejong/jsoneditor into develop 2017-05-25 15:40:34 -04:00
Jos de Jong c20e24366e Merge pull request #405 from israelito3000/feature/template_properties
Feature/rename template properties.
2017-05-25 16:17:48 +02:00
Israel Garcia a4c4948934 ignore vs files 2017-05-23 20:29:41 -04:00
Israel Garcia 75ecd91593 Renaming properties templates 2017-05-23 20:21:30 -04:00
Israel Garcia 8a96f06df4 Renaming properties templates 2017-05-23 20:18:39 -04:00
Israel Garcia 1b998c5b1a Renaming properties templates 2017-05-23 20:06:07 -04:00
Israel Garcia 715343b028 merge from main origin:
https://github.com/josdejong/jsoneditor/tree/develop
2017-05-23 20:00:25 -04:00
Israel Garcia 26a1a84602 Add Horsey autocomplete example 2017-05-17 01:15:13 -04:00
Israel Garcia 1393b148db Autocomplete final refactory 2017-05-16 02:20:30 -04:00
Israel Garcia 131e8f106d custom autocomplete working 2017-05-15 00:31:20 -04:00
jos 0ddc9407b0 Updated history and example. Fixed bottom margin of submenu 2017-05-07 15:32:31 +02:00
Jos de Jong 913af51aab Merge pull request #396 from israelito3000/feature/templateItems
Feature/template items
2017-05-07 15:21:15 +02:00
Israel Garcia a5f91f8f99 Revert "Support for Template items"
This reverts commit 38ce7760dd.
2017-05-05 04:36:20 -04:00
Israel Garcia 3a9e55b3ae Support for Template Items 2017-05-05 04:36:13 -04:00
Israel Garcia 38ce7760dd Support for Template items 2017-05-05 04:33:38 -04:00
jos 56c450bf0f Released v5.6.0 2017-04-15 12:28:46 +02:00
jos 09c1375c84 Fixed not being able to move focus to a enum select box when clicking a JSON Schema warning 2017-04-15 12:21:41 +02:00
jos 0adf824f5b Merge remote-tracking branch 'origin/develop' into develop 2017-04-15 11:51:56 +02:00
jos fd91632904 Merge branch 'master' into develop 2017-04-15 11:51:49 +02:00
jos 3d2bf6bd48 Updated text 2017-04-14 14:34:31 +02:00
jos fcecb3fc2a Updated text 2017-04-14 14:32:03 +02:00
jos 77b7e10220 Updated text 2017-04-14 14:21:10 +02:00
jos 66dced1dd3 Fixed image? 2017-04-14 14:17:15 +02:00
jos 0007ee8de4 Added images again 2017-04-14 14:16:01 +02:00
jos fe3dffacf3 Drop broken images 2017-04-14 14:13:58 +02:00
jos d258167837 Renamed images 2017-04-14 14:11:35 +02:00
jos ac7ec05d1d Switched to png image instead of svg 2017-04-14 14:10:07 +02:00
jos d152aea2ad Switched to png image instead of svg 2017-04-14 14:09:47 +02:00
jos 23b5b301c6 Fixed broken link 2017-04-14 14:08:22 +02:00
jos b26024b6e3 Merge remote-tracking branch 'origin/master' 2017-04-14 14:06:47 +02:00
jos e497f54f6d Added link to BrowserStack 2017-04-14 14:06:25 +02:00
Jos de Jong eadf5c6403 Merge pull request #383 from walkerrandolphsmith/develop
#382 Read only text mode.
2017-04-12 21:08:57 +02:00
Walker Randolph Smith c0b7139fd2 #382 Rename example file. 2017-04-12 11:51:50 -04:00
Walker Randolph Smith 3539f40dc5 #382 Support read only code mode. 2017-04-12 11:51:50 -04:00
Walker Randolph Smith c29bcba5ff #382 typo on typeof function check 2017-04-12 11:51:50 -04:00
Walker Randolph Smith 2c72173366 #382 Read only text mode. 2017-04-12 11:51:50 -04:00
Jos de Jong cfc5a805e7 Merge pull request #381 from chinesedfan/fix_bkgcolor
Optimize the input experience of Chinese IME
2017-04-04 22:00:14 +02:00
Jos de Jong 1265ed78a9 Merge pull request #380 from chinesedfan/upgrade_ace
Fixed #253: upgrade ace to 1.2.6
2017-04-04 21:57:39 +02:00
Xianming Zhong a768784643 Optimize the input experience of Chinese IME 2017-03-30 16:38:53 +08:00
Xianming Zhong f5edad2d31 Fixed #253: upgrade ace to 1.2.6 2017-03-30 14:23:16 +08:00
jos e1f686b8e5 Fixed #368: Mode selection drop down not fully visible on small screen 2017-02-26 20:40:12 +01:00
Jos de Jong 6b5b54052c Merge pull request #355 from isonet/master
Suggesting a different directive for Angular.js.
2017-01-21 21:12:35 +01:00
Paul Biester 4bde72f7cf Suggesting a different directive for Angular.js. 2017-01-18 09:13:37 +01:00
jos 717ed48474 Fixed #309: already loaded version of Ace being overwritten by the embedded version of JSONEditor 2017-01-06 21:46:23 +01:00
jos 3117789ed7 Released v5.5.11 2017-01-06 20:58:19 +01:00
jos 2f4f221c9a Better fix for #347 (earlier fix introduced other CSS issues) 2017-01-06 20:56:03 +01:00
jos 74b9aaf5fa Fixed #347: CSS more robust against global settings of div position 2017-01-03 20:43:43 +01:00
jos 1c8ea64c2a Fixed #54: CSS more robust against global settings of div position 2017-01-03 20:43:10 +01:00
jos 94ca26e457 Fixed a styling issue with Ace search box 2017-01-03 20:36:08 +01:00
jos 8dc4752872 Fixed embedded version of jsoneditor ace theme not being loaded in minimalist version. Added docs and example on loading a custom Ace editor (see #55) 2017-01-03 20:23:03 +01:00
jos 4bc339f6fe Released v5.5.10 2016-11-02 21:03:18 +01:00
jos df12832a6b Fixed #85: pressing enter in an input in a form containing a JSONEditor too breaks submitting the form 2016-11-01 21:00:21 +01:00
jos d73665acf3 Released v5.5.9 2016-10-17 21:16:01 +02:00
jos 8913ce1f6f Fixed #329: Editor showing duplicate key warnings for keys defined on the Object prototype, like `toString` and `watch` 2016-10-15 10:49:44 +02:00
jos cee259f2a5 Released v5.5.8 2016-09-27 21:07:31 +02:00
jos 4aa9e7db7f Updated history 2016-09-24 19:23:31 +02:00
Jos de Jong b4c9417b7a Merge pull request #326 from nprdm/master
Fix https://github.com/josdejong/jsoneditor/issues/314
2016-09-24 19:20:51 +02:00
Stephen Thompson fe459e64c3 Update built artifacts with fix from 48408f4ded 2016-09-22 18:25:27 -04:00
Stephen Thompson 48408f4ded Fix https://github.com/josdejong/jsoneditor/issues/314
The JSON path parsing code assumes that string keys within square brackets in JSON paths will be valid, parseable JSON.

However, the ajv library on which this project depends emits string keys in single quotes.

For example, ajv can emit .foo['bar'], which will ultimately end up with a call to JSON.parse("'bar'"). This causes the "Unexpected token ' in JSON at position 0" error thrown from JSON.parse.

 Since ajv shouldn't need to change and since this utility is gone in the next branch, this fix checks for ajv-formatted string keys and patches them to double-quoted strings before calling JSON.parse. This is the narrowest fix for the problem.
2016-09-22 18:06:22 -04:00
jos 02f81ea8de Released v5.5.7 2016-08-17 21:29:14 +02:00
159 changed files with 47246 additions and 68389 deletions

5
.babelrc Normal file
View File

@ -0,0 +1,5 @@
{
"presets": [
["@babel/preset-env"]
]
}

1
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1 @@
github: josdejong

4
.gitignore vendored
View File

@ -1,6 +1,10 @@
.idea
*.iml
.vscode
build
dist
downloads
node_modules
*.zip
npm-debug.log
/.vs

View File

@ -1,4 +1,5 @@
bower.json
CONTRIBUTING.md
downloads
misc
node_modules

5
.travis.yml Normal file
View File

@ -0,0 +1,5 @@
language: node_js
node_js:
- "lts/*"
script: npm test && npm run lint

View File

@ -6,10 +6,18 @@ up with ideas and suggestions, and contribute to the code.
There are a few preferences regarding code contributions:
- `jsoneditor` follows the node.js code style as described
[here](http://nodeguide.com/style.html).
- Send pull requests to the `develop` branch, not the `master` branch.
- Only commit changes done in the source files under `./src`, not to the builds
which are located under the `./dist` folder.
- Send pull requests to the `develop` branch, not the `master` branch.
- You can use modern JavaScript features, the code is transpiled using Babel.
- `jsoneditor` follows the https://standardjs.com/ code style. To test:
```
npm run lint
```
- If possible, create a unit test for any new functionality. To run tests:
```
npm test
```
Thanks!

View File

@ -3,7 +3,916 @@
https://github.com/josdejong/jsoneditor
## not yet released, version 5.5.7
## not yet published, version 9.1.2
- Log a clear error in the console when the returned value of `onEditable` is
invalid. See #1112.
## 2020-09-23, version 9.1.1
- Fix #1111: Enum dropdown not showing when using patternProperties for schema.
Thanks @ziga-miklic.
- Fixed JSONEditor not working when opened in a new window, see #1098.
Thanks @joshkel.
- Fix quick-key `Ctrl+D` (duplicate) not working.
- Define "charset: utf-8" in all HTML examples.
## 2020-09-15, version 9.1.0
- Implemented German translation (`de`). Thanks @s-a.
- Fix quick-keys `Ctrl-\` (format) and `Ctrl-Shift-\` (compact) not working
in `code` mode.
- Updated dependencies to `ajv@6.12.5`.
## 2020-09-09, version 9.0.5
- Fix #1090: autocomplete firing on dragging or clicking a node.
- Fix #1096: editor crashing when passing an empty string as `name`.
- Updated dependencies to `ajv@6.12.4`.
## 2020-08-15, version 9.0.4
- Updated dependencies to `ace-builds@1.4.12`, `ajv@6.12.3`.
- Fix #1077: change the `main` field in `package.json` to point to the actual
bundled and minified file instead of a node.js index file.
## 2020-07-02, version 9.0.3
- Fix regression introduced in `v9.0.2` in the select boxes in the
Transform model not lighlighting the matches correctly.
## 2020-07-01, version 9.0.2
- Fix #1029: XSS vulnerabilities. Thanks @onemoreflag for reporting.
- Fix #1017: unable to style the color of a value containing a color.
Thanks @p3x-robot.
## 2020-06-24, version 9.0.1
- Fixed broken link to the Ace editor website (https://ace.c9.io/).
Thanks @p3x-robot.
- Fix #1027: create IE11 Array polyfills `find` and `findIndex` in such a way
that they are not iterable.
## 2020-05-24, version 9.0.0
- Implemented option `limitDragging`, see #962. This is a breaking change when
using a JSON schema: dragging is more restrictive by default in that case.
Set `limitDragging: false` to keep the old, non-restricted behavior.
## 2020-05-13, version 8.6.8
- Fix #936: too many return characters inserted when pasting formatted text
from OpenOffice.
## 2020-05-10, version 8.6.7
- Fix #858: the `dist/jsoneditor.js` bundle containing a link to a
non-existing source map.
- Fix #978: in some special cases the caret was jumping to the beginning of the
line whilst typing.
- Update dependencies to `ajv@6.12.2`.
## 2020-04-21, version 8.6.6
- Fix #969: adding a new property to an empty object or array is broken.
Regression introduced in `v8.6.5`.
## 2020-04-19, version 8.6.5
- Fix #964: translation of titles of some context menu items not working.
- Update dependencies to `ace-builds@1.4.11`, `ajv@6.12.1`.
## 2020-03-29, version 8.6.4
- Fix #921: `sortObjectKeys` emits `onChange` events.
- Fix #946: `language` not working in modes `text`, `code`, and `preview`.
- Revert reckoning with the order of object properties when updating an
object (introduced in `v8.6.2`). See #917.
- Implement support for repairing line separate JSON.
## 2020-03-18, version 8.6.3
- Fix #932: `JSONEditor.update` broken, did not always recognize when the
input changed. Regression introduced in `v8.6.2`.
## 2020-03-18, version 8.6.2
- Fixed #917, #926: Keep order of properties when updating an object.
- Fixed #928: Custom root name not reflected in path of navigation bar.
- Upgraded to `ajv@6.12.0`
## 2020-02-17, version 8.6.1
- Fixed #908: editor throwing an exception when switching from `'preview'`
to `'code'` mode.
## 2020-02-16, version 8.6.0
- Fixed #906: Implemented turning Python objects containing `True`, `False`
and `None` into valid JSON using repair.
## 2020-02-06, version 8.5.3
- Fix #892: the undo/redo buttons in mode `code` being broken when custom
loading an old version of Ace Editor.
## 2020-02-05, version 8.5.2
- Fix undo/redo buttons in mode `code` not always updating.
## 2020-02-05, version 8.5.1
- Fix broken build.
## 2020-02-05, version 8.5.0
- Implemented support for customizing the query language used in the
Transform modal. New options `createQuery`, `executeQuery`, and
`queryDescription` are available for this now. An example is available
in `examples/23_custom_query_language.html`. See #857, #871.
- Implement undo/redo buttons in `code` mode.
- Fix history (undo/redo) being cleared in mode `code` and `text` after
transforming or sorting.
## 2020-01-25, version 8.4.1
- Fix `console.log` in production code. Oopsie.
## 2020-01-25, version 8.4.0
- Added CSS classes `jsoneditor-expanded` and `jsoneditor-collapsed` on array
and object nodes reflecting there state.
## 2020-01-18, version 8.3.0
- Update dependency `ajv` to `v6.11.0`.
- Fix #790: editor breaking when missing a translation containing a
placeholder.
## 2020-01-16, version 8.2.0
- Make it easy to create custom styling by overriding default SASS variable
values, see #881. Thanks @petermanders89.
- Update `ace` to `v1.4.8`.
## 2020-01-06, version 8.1.2
- Fix #873: buttons Format, Compact, and Repair not supporting
internationalization.
- Fix #877: Some CSS styling issues when used in combination with Materialize.
- Updated dependency `vanilla-picker` to `v2.10.1`.
## 2019-12-28, version 8.1.1
- Fixed the file size reported in `preview` mode show `KB` and `MB` instead
of `KiB` and `MiB` in order to match the size reported by filesystems.
## 2019-12-18, version 8.1.0
- Implemented `popupAnchor` allowing to select a custom anchor element.
See #869 and #870.
- Fixed #502: CSS rule `* { font-family: ... }` resulting in Ace editor (`code`
mode) not having a mono-space font anymore.
## 2019-12-11, version 8.0.0
- Implemented option `timestampFormat` which allows customizing the formatting
of timestamp tags. See also option `timestampTag`. Thanks @smallp.
- Changed the behavior of `timestampTag` to fallback on the built-in rules when
the function does not return a boolean. See #856.
- Reverted the heuristics introduced in `v7.3.0` to check whether some field
contains a timestamp based on the field name, because they can give wrong
timestamps in case of values in seconds instead of the assumed milliseconds
(see #847, #856).
## 2019-12-08, version 7.5.0
- Extended the callback `onValidationError` to also report parse errors,
and distinguish between JSON schema validation errors and custom errors.
See #861 and #612. Thanks @meirotstein.
## 2019-12-01, version 7.4.0
- Implemented callback function `onValidationError`, see #612, #854.
Thanks @meirotstein.
- Fixed #850: make autocomplete options robust against non-string inputs
like `null`, `123`, `true`, `false`.
## 2019-12-01, version 7.3.1
- Fixed #855: `onFocus` and `onBlur` not working in modes `text` and `code`
when editor was created without main menu bar, and `editor.destroy()`
throwing an exception.
## 2019-11-27, version 7.3.0
- Implemented callbacks `onFocus` and `onBlur` (PR #809, issue #727).
Thanks @123survesh.
- Fixed #847: allow customizing the in rules determining whether a value
is a timestamp or not by passing a callback function to `timestampTag`.
## 2019-10-27, version 7.2.1
- Fixed #826: editor not allowing indentation `0`.
- Fixed #828: do not expand/collapse when clicking the text of a node
in modes `view` or `form`.
- Fixed #829: z-index issue of context-menu button and conflicting css names.
## 2019-10-23, version 7.2.0
- Implemented Japanese translation (`ja`). Thanks @yutakiyama.
- Implemented French translation (`fr-FR`), and some improvements in the
translation. Thanks @yannickyvin.
- Upgraded to the latest version of Ace editor, 1.4.7.
- Fixed #824: Parse errors not displayed with bottom right error icon in modes
`code` and `text`.
## 2019-10-13, version 7.1.0
- Upgraded to the latest version of Ace editor 1.4.6. Changed implementation
to use `ace-builds` directly instead of `brace` (still using Ace 1.2.9).
- Improved Portuguese translation. Thanks @victorananias.
## 2019-10-06, version 7.0.5
- Upgraded dependencies: `vanilla-picker@2.10.0`.
- Minor documentation improvements. Thanks @slash-arun.
- Minor styling fixes.
## 2019-09-11, version 7.0.4
- Fixed #723: schema error popup and color picker not always fully visible.
- Fixed wrong text color in search box when using JSONEditor in combination
with bootstrap. See #791. Thanks @dmitry-kulikov.
- Fixed react examples not working out of the box when cloning or downloading
the git repository of JSONEditor. See #787, #788. Thanks @vishwasnavadak.
## 2019-09-04, version 7.0.3
- Fixed `index.js` pointing to non-transpiled code. See #783.
- Fixed absolute url of images in SASS. Thanks @moonbreezee.
## 2019-09-02, version 7.0.2
- Fix #781: race condition when destroying the editor right after setting data.
## 2019-09-01, version 7.0.1
- Fix npm package missing `dist` folder.
## 2019-09-01, version 7.0.0
- Converted the code largely to ES6, put Babel transpiler in place.
- Dropped support for bower, removed the `dist` folder from the git repository.
- Fixed #586: caret position lost when switching browser tabs.
## 2019-08-28, version 6.4.1
- Fix styling of autocompletion dropdown broken. Regression since `v6.4.0`.
## 2019-08-28, version 6.4.0
- Replaces CSS with SASS internally, improvements in styling. Thanks @ppetkow.
- Fixed #761: JSON schema errors not rendered in the gutter for mode `code`
when the path contained a property with a forward slash, and errors not
clickable in the error table.
- Fixed #777: option `sortObjectKeys` broken.
## 2019-08-15, version 6.3.0
- Fixed #755: JSONEditor throwing an exception in mode `code`, `text`, and
`preview` when `statusBar: false`.
- When duplicating an object property, move focus to the field and do not
immediately add the ` (copy)` suffix. See #766.
- Fixed #769: option `name` not working anymore. Regression since `v6.1.0`.
- Fixed #763: `autocomplete.trigger: 'focus'` throws an error when opening the
context menu. Thanks @Thaina.
- Updated dependencies `json-source-map@0.6.1`
## 2019-08-01, version 6.2.1
- Updated Chinese translation. Thanks @SargerasWang.
## 2019-07-28, version 6.2.0
- Implemented new mode `preview`, capable of working with large JSON documents
up to 500 MiB.
- Repair button is now capable of turning MongoDB documents into valid JSON.
- Fixed #730: in `code` mode, there was an initial undo action which clears
the content.
- Upgraded dependencies `vanilla-picker@2.9.2`, `mobius1-selectr@2.4.13`,
`ajv@6.10.2`.
## 2019-06-22, version 6.1.0
- Implemented menu options `sort` and `transform` for modes `code` and `text`.
- Implemented new context menu item `extract`.
- Minor tweaks in the way paths are displayed in the sort and transform modals.
## 2019-06-12, version 6.0.0
- Breaking change: upgraded dependency `ajv@6.10.0`, supporting JSON schema
draft-07 alongside draft-06 and draft-04.
- Upgraded dependency `vanilla-picker@2.8.1`.
- Use JSON schema title as name for the root object if defined (see #635).
## 2019-06-08, version 5.34.0
- Extended the autocomplete feature with new options `filter` and `trigger`.
Thanks @Gcaufy.
- Removed :hover style on disabled buttons. Thanks @Gcaufy.
- Upgraded dependency `mobius1-selectr@2.4.12`.
## 2019-05-29, version 5.33.0
- Fixed #697: JSON Schema enum dropdown not working inside an array.
- Fixed #698: When using `onCreateMenu`, `node.path` is null when clicking
on an append node or when multiple nodes are selected.
- Upgraded dependencies to `mobius1-selectr@2.4.10`, `vanilla-picker@2.8.0`.
- Remove :hover style on disabled buttons. Thanks @Gcaufy.
## 2019-04-27, version 5.32.5
- Fixed a bug in the JMESPath query wizard which didn't correctly handle
selecting multiple fields.
- Fixed context menu not working when multiple nodes are selected.
## 2019-04-10, version 5.32.4
- Fixed #682 and #687: JSONEditor not being able to handle JSON schema
validation errors when the root of the document is an Array. Thanks @DusuWen.
## 2019-04-04, version 5.32.3
- Fixed #684: `const` used in bundled library.
## 2019-04-03, version 5.32.2
- Fixed #416: Clipped action menu for append nodes.
- Improve detection of value type in transform modal.
- Styling improvements in the transform modal.
- Fix CSS class for default/non-default schema values not applied to enums,
see (#666).
- Fixed #671: Improved handling of duplicate property names, which could cause
values to be cleared when used as a controlled component in for example React.
## 2019-03-28, version 5.32.1
- Fixed a regression in parsing JSON paths: numbers where parsed as strings
instead of a numeric value. See #679. Thanks @AdamVig.
- Fixed using hyphens in the path of custom validation errors (see #665).
Thanks @tobiasfriden.
## 2019-03-20, version 5.32.0
- Implemented support for reckoning with JSON schema default values: custom
styling can be applied for default and non-default values. Thanks @AdamVig.
- Fixed #667: resolving JSON Schema examples and descriptions did not always
work for referenced schemas. Thanks @AdamVig.
- Fixed #676: JSON Paths containing array properties with a `]` not parsed
correctly.
## 2019-03-14, version 5.31.1
- Fix IE11 issue.
- Some fixes in the Simplified Chinese translation.
Thanks @@adf0001 and @yuxizhe.
## 2019-03-10, version 5.31.0
- Display JSON schema examples in tooltip (#664). Thanks @AdamVig.
## 2019-03-02, version 5.30.0
- Implemented a new option `onCreateMenu` to customize the action menu.
Thanks @RobAley.
## 2019-02-20, version 5.29.1
- Fixed #661: JSONEditor broken on IE11 caused by duplicate JSON entries
in a translation.
## 2019-02-16, version 5.29.0
- Added Simplified Chinese localization. Thanks @long2ice.
- Added Turkish localization. Thanks @beratpostalci.
- Improved JSON schema titles on fields. Fixes #321. Thanks @AdamVig.
- Fixes in resolving JSON schemas, see #651. Thanks @AdamVig.
- Fix #657: `onClassName` throwing an error when a node is removed.
## 2019-01-23, version 5.28.2
- Fix #639: Occurrence of non-ES5 `const` declaration in published code.
Regression introduced in `v5.28.0`.
## 2019-01-22, version 5.28.1
- Fix #637: Vertical white border left/right from the main menu in some
specific circumstances.
- Fix #638: Cannot expand after collapse. Regression introduced in v5.28.0.
## 2019-01-21, version 5.28.0
- Implemented new option `maxVisibleChilds` to customize the maximum number
childs that is rendered by default. Thanks @20goto10.
- Implemented new option `onClassName`, allowing customized and dynamic
styling of nodes. See 20_custom_css_style_for_nodes.html for a demo.
Thanks @maestr0.
- Make the method `refresh()` public.
## 2019-01-16, version 5.27.1
- Improved navigating deeply nested paths via the navigation bar, see #619.
Thanks @meirotstein.
- Sdd title from schema description to show the tips for user input.
Thanks @tylerchen.
- Fix JSON Schema not resolving refs `$ref`, and not creating enum dropdowns.
Thanks @tylerchen.
## 2019-01-05, version 5.27.0
- Implemented customizing object and array names via a new option
`onNodeName`. Thanks @bnanchen.
- Visibility of schema validation errors at the bottom of mode code and text
are now toggleable. Thanks @meirotstein.
- Fixed text of the mode switcher not being translated. Thanks @antfu.
## 2018-12-06, version 5.26.3
- Fixed #610: JSON Repair now removes trailing commas.
- Upgraded devDependency `gulp` to v4. Thanks @maestr0.
## 2018-11-13, version 5.26.2
- Fixed dragging and selecting multiple nodes not working
(regression introduced in `v5.26.1`).
## 2018-11-13, version 5.26.1
- Fixed `.update()` throwing an exception when replacing a JSON object
with `null`. Thanks @DullReferenceException.
- Fixed #598: Search field can't be focused in object view.
## 2018-11-12, version 5.26.0
- Implemented option `mainMenuBar` to enable/disable the main menu bar.
Thanks @tanmayrajani.
## 2018-10-29, version 5.25.0
- Implemented options `enableSort` and `enableTransform` so you can turn off
these features. Thanks @tanmayrajani.
- Fixed #590: validation failing in code and text mode when status
bar is disabled.
- Fixed #589: the path in the navigation bar is not updated
when duplicating or removing a node, and neither after an undo/redo action.
- Fixed duplicate and remove of the action menu of multiple selected
nodes not working.
- Fixed not preventing default selection of text when selecting nodes.
- Fixed #595: navigation bar path link not working.
## 2018-10-08, version 5.24.7
- Fix #582: parse error annotations not always up to date in
code editor. Thanks @meirotstein.
## 2018-09-12, version 5.24.6
- Fix #548: `import JSONEditor from 'jsoneditor'` not working in
TypeScript projects (gave a constructor is undefined error).
## 2018-09-06, version 5.24.5
- Fixed a bug in textmode on IE 11, not loading the editor when
`Promise` is undefined.
## 2018-09-06, version 5.24.4
- Fixed #576: Visualization in mode `view` when an array
with more than 100 items is rendered.
- Fixed JSONEditor not working on IE11: continue and throw console
errors when `Promise` is undefined. Regression since `v5.23.0`.
- Fixed `onClose` of color picker not being fired when clicking outside
the picker to close it.
- Upgraded dependencies `brace`, `mobius1-selectr`, `vanilla-picker`.
- Upgraded devDependency `mocha`.
## 2018-08-29, version 5.24.3
- Fixed color picker not working in ES6 projects.
- Fixed color picker closing immediately after the first `onChange`
event, and `onChange` events are now debounced like all text inputs.
## 2018-08-27, version 5.24.2
- Improved error and validation messaging in `text` mode.
Thanks @meirotstein.
- Clicking a message now selects the line where the error occurs.
- Icon bottom right showing when there are warnings or errors.
- Fixed field still editable after moving a node from an object
to an array, changing the field from a property into an index.
## 2018-08-26, version 5.24.1
- Context menu and color picker are now absolutely positioned, and
can overflow the borders of the editor.
- Fixed #568: mode switcher disappearing when selecting the current
mode again.
- Fixed `transform` not creating/removing expand button when the type
of a node changed.
## 2018-08-22, version 5.24.0
- Implemented a color picker, and allow hooking in a custom color
picker. new options are `colorPicker` and `onColorPicker`.
- Implemented a timestamp tag displayed right from timestamps,
with corresponding option `timestampTag`.
## 2018-08-17, version 5.23.1
- Fixed #566: transform function broken, regression since `v5.20.0`.
## 2018-08-15, version 5.23.0
- Implemented support for custom validation using a new `onValidate` callback.
- In tree mode, nodes containing a validation error now have a className
`jsoneditor-validation-error` which can be used for custom styling.
## 2018-08-13, version 5.22.0
- Implemented `onEvent` callback triggered when an event occurs in a JSON
field or value. Thanks @cristinabarrantes.
## 2018-08-12, version 5.21.0
- Show validation errors inline instead of at the bottom when in code
mode. Thanks @meirotstein.
- Fix #562: allow `$` character in property names of of a JSON schema.
## 2018-08-10, version 5.20.0
_Good news: JSONEditor is finally framework friendly and can now be easily
integrated in React, Vue, and Angular!_
- Implemented new methods `update` and `updateText`, which maintain the state
of the editor (expanded nodes, search, selection). This makes it easy to
integrate in frameworks like React.
- Implemented options `onChangeJSON(json)` and `onChangeText(jsonString)`.
- Added two React examples to the `examples` folder.
- Fixed menu buttons "Sort" and "Transform" being available in modes `view`
and `form`.
## 2018-08-02, version 5.19.2
- Fixed #558: scrolling to search results and automatically scrolling up/down
when dragging an item broken (regression since v5.19.1).
## 2018-07-28, version 5.19.1
- Fixed #557: inner contents of the scrollable area being displayed outside of
the editor (on Chrome only).
## 2018-07-11, version 5.19.0
- No more grayed out icons of the context menu, see #532.
- Added Sort and Transform buttons to the main menu.
- Fixes and improvements in the Transform dialog.
## 2018-06-27, version 5.18.0
- Implemented JMESPath support for advanced filtering, sorting, and
transforming of JSON documents.
- Implemented a new option `modalAnchor` to control at which part of the
screen the modals are displayed.
- Fixed #544: JSON Schema errors sometimes not being displayed in the
editor.
## 2018-06-03, version 5.17.1
- Fixed a bug in a translation text.
## 2018-06-03, version 5.17.0
- Implemented advanced sorting for arrays.
## 2018-05-23, version 5.16.0
- Better handling of JSON documents containing large arrays:
- Only displays the first 100 items of large arrays,
with buttons "show more" and "show all" to render more items.
- Search results are now limited to max 1000 matches,
and search does no longer expand the paths to all matches
but only expands the path of the current search result.
- Fixed index numbers of Array items not being updated after sorting.
## 2018-05-02, version 5.15.0
- Implemented selection API: `onSelectionChanged`, `onTextSelectionChanged`,
`getSelection`, `getTextSelection`, `setSelection`, `setTextSelection`,
and `getNodesByRange`. Thanks @meirotstein.
## 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.
## 2017-12-28, version 5.13.1
- Fixed another occurrence of #494: properties not escaped in the
navigation bar.
## 2017-12-28, version 5.13.0
- Implemented cursor position in text mode. Thanks @meirotstein.
- Fixed #494: properties not escaped in the navigation bar.
Thanks @meirotstein.
## 2017-12-18, version 5.12.0
- Implemented #482: Include `caseSensitive` option for autocomplete.
Thanks @israelito3000.
- Upgraded dependencies
- `ajv@5.5.2`
## 2017-11-22, version 5.11.0
- Upgraded dependencies
- `ajv@5.4.0`
- `brace@0.11.0`
- Fixed dropdown for JSON Schema enums when defined inside pattern
properties. Thanks @alquist.
- Fixed code containing a non UTF-8 character. Thanks @alshakero.
## 2017-11-15, version 5.10.1
- Some styling tweaks in the navigation bar and status bar.
- Don't display status bar in `text` mode (which doesn't yet support
row and col counts).
## 2017-11-15, version 5.10.0
- Implemented a navigation bar showing the path. Thanks @meirotstein.
- Implemented a status bar showing cursor location.
Thanks @meirotstein.
- Implemented repairing JSON objects containing left and right single
and double quotes (which you get when typing a JSON object in Word)
in `text` and `code` mode.
- Implemented repairing JSON objects containing special white space
characters like non-breaking space.
- Upgraded dependency `ajv` to version `5.3.0`.
- Fixed #481: A polyfill required `DocumentType` which is not defined
in all environments.
## 2017-09-16, version 5.9.6
- Fixed displaying a dropdown for enums inside composite schemas.
Thanks @hachichaud.
- Fixed #461: Urls opening twice on Firefox and Safari.
## 2017-08-26, version 5.9.5
- Fixed a regression introduced in `v5.9.4`: after using the context
menu once, it was not possible to set focus to an other input field
anymore.
## 2017-08-20, version 5.9.4
- Fixed #447: context menus not working in Shadow DOM. Thanks @tomalec.
## 2017-07-24, version 5.9.3
- Fixed broken multi-selection (regression).
## 2017-07-13, version 5.9.2
- Fixed a bug in the JSON sanitizer.
## 2017-07-13, version 5.9.1
- `setText` method of tree mode now automatically sanitizes JSON input
when needed.
- Fixed #430: automatically fix unescaped control characters in
JSON input.
## 2017-07-10, version 5.9.0
- Implemented support for JSON schema references `$ref`, see #302.
Thanks @meirotstein.
- Fixed #429: JSONEditor no longer accepting an empty array for option
`modes`. Thanks @trystan2k.
- Fixed JSONEditor picking the first entry of `modes` as initial mode
instead of option `mode`.
## 2017-07-08, version 5.8.2
- Select first option from `modes` instead of `tree` when `mode` is not
configured. Thanks @bag-man.
- Some fixes and improvements in the API of autocompletion.
Thanks @israelito3000.
## 2017-07-03, version 5.8.1
- Fixed broken minified bundles in folder `dist` (again...).
## 2017-07-02, version 5.8.0
- Implemented support for autocompletion. Thanks @israelito3000.
## 2017-06-27, version 5.7.2
- Fixed broken minified bundles in folder `dist`
(reverted to `uglify-js@2.8.22` for now).
## 2017-06-25, version 5.7.1
- Upgraded dependency `ajv` to version `5.2.0`. Resolves warnings in
Webpack build processes.
## 2017-05-26, version 5.7.0
- Implemented support for template items. Thanks @israelito3000.
- Upgraded dependencies to the latest versions. Thanks @andreykaipov.
## 2017-04-15, version 5.6.0
- Implemented readonly option for modes `text` and `code.`
Thanks @walkerrandolphsmith.
- Upgraded dependencies (`brance` and `ajv`) to the latest versions.
- Fixed not being able to move focus to enum select box when clicking
a JSON Schema warning.
- Fixed #309: already loaded version of Ace being overwritten by the
embedded version of JSONEditor.
- Fixed #368: Mode selection drop down not fully visible on small screen.
- Fixed #253: Optimize the input experience of Chinese IME.
Thanks @chinesedfan.
## 2017-01-06, version 5.5.11
- Fixed embedded version of jsoneditor ace theme not being loaded in
minimalist version (see #55).
- Fixed a styling issue in the SearchBox of Ace editor (mode `code`).
- Fixed #347: CSS more robust against global settings of div position.
- Added docs and example on how to use a custom version of Ace editor.
## 2016-11-02, version 5.5.10
- Fixed #85: pressing enter in an input in a form containing a JSONEditor too
breaks submitting the form.
## 2016-10-17, version 5.5.9
- Fixed #329: Editor showing duplicate key warnings for keys defined on the
Object prototype, like `toString` and `watch`.
## 2016-09-27, version 5.5.8
- Fixed #314: JSON schema validation throwing an error "Unexpected token ' in
JSON at position 0" in specific cases. Thanks @apostrophest
## 2016-08-17, version 5.5.7
- Fixed #308: wrong positioning of label "empty array" when `onEditable`
returns false.
@ -455,7 +1364,7 @@ https://github.com/josdejong/jsoneditor
## 2012-08-12, version 1.2.0
- New: Added search functionality. Search results are expanded and highlighed.
- New: Added search functionality. Search results are expanded and highlighted.
Quickkeys in the search box: Enter (next), Shift+Enter (previous), Ctrl+Enter
(search again).
- New: The position of the vertical separator between left and right panel is
@ -502,7 +1411,7 @@ https://github.com/josdejong/jsoneditor
## 2012-03-01, version 0.9.10
- Nicer looking select box for the field types, with icons.
- Improved drag and drop: better visualized, and now working in all browers.
- Improved drag and drop: better visualized, and now working in all browsers.
- Previous values will be restored after changing the type of a field. When
changing the type back, the previous value or childs will be restored.
- When hovering buttons (fieldtype, duplicate, delete, add) or when dragging
@ -535,7 +1444,7 @@ https://github.com/josdejong/jsoneditor
## 2012-01-09, version 0.9.7
- Added functionallity to expand/collapse a node and all its childs. Click
- Added functionality to expand/collapse a node and all its childs. Click
the expand button of a node while holding Ctrl down.
- Small interface improvements

2
NOTICE
View File

@ -1,7 +1,7 @@
JSON Editor
https://github.com/josdejong/jsoneditor
Copyright (C) 2011-2015 Jos de Jong
Copyright (C) 2011-2020 Jos de Jong
Licensed under the Apache License, Version 2.0 (the "License");

View File

@ -1,5 +1,11 @@
# JSON Editor
[![Version](https://img.shields.io/npm/v/jsoneditor.svg)](https://www.npmjs.com/package/jsoneditor)
[![Downloads](https://img.shields.io/npm/dm/jsoneditor.svg)](https://www.npmjs.com/package/jsoneditor)
![Maintenance](https://img.shields.io/maintenance/yes/2020.svg)
[![License](https://img.shields.io/github/license/josdejong/jsoneditor.svg)](https://github.com/josdejong/jsoneditor/blob/master/LICENSE)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fjosdejong%2Fjsoneditor.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fjosdejong%2Fjsoneditor?ref=badge_shield)
JSON Editor is a web-based tool to view, edit, format, and validate JSON.
It has various modes such as a tree editor, a code editor, and a plain text
editor.
@ -7,32 +13,50 @@ editor.
The editor can be used as a component in your own web application. The library
can be loaded as CommonJS module, AMD module, or as a regular javascript file.
Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 9+.
Supported browsers: Chrome, Firefox, Safari, Opera, Edge, Internet Explorer 11.
<img alt="json editor" src="https://raw.github.com/josdejong/jsoneditor/master/misc/jsoneditor.png"> &nbsp; <img alt="code editor" src="https://raw.github.com/josdejong/jsoneditor/master/misc/codeeditor.png">
Cross browser testing for JSONEditor is generously provided by <a href="https://www.browserstack.com" target="_blank">BrowserStack</a>
<a href="https://www.browserstack.com" target="_blank"><img alt="BrowserStack" src="https://raw.github.com/josdejong/jsoneditor/master/misc/browserstack.png"></a>
## Features
### Tree editor
- Edit, add, move, remove, and duplicate fields and values.
- Change type of values.
JSONEditor has various modes, with the following features.
### Tree mode
- Change, add, move, remove, and duplicate fields and values.
- Sort arrays and objects.
- Transform JSON using [JMESPath](http://jmespath.org/) queries.
- Colorized code.
- Color picker.
- Search & highlight text in the tree view.
- Undo and redo all actions.
- JSON schema validation (powered by [ajv](https://github.com/epoberezkin/ajv)).
### Code editor
### Code mode
- Colorized code (powered by [Ace](https://ace.c9.io)).
- Inspect JSON (powered by [Ace](https://ace.c9.io)).
- Format and compact JSON.
- Repair JSON.
- JSON schema validation (powered by [ajv](https://github.com/epoberezkin/ajv)).
### Text editor
### Text mode
- Format and compact JSON.
- Repair JSON.
- JSON schema validation (powered by [ajv](https://github.com/epoberezkin/ajv)).
### Preview mode
- Handle large JSON documents up to 500 MiB.
- Transform JSON using [JMESPath](http://jmespath.org/) queries.
- Format and compact JSON.
- Repair JSON.
- JSON schema validation (powered by [ajv](https://github.com/epoberezkin/ajv)).
## Documentation
@ -51,26 +75,18 @@ with npm (recommended):
npm install jsoneditor
with bower:
bower install jsoneditor
#### More
There is a directive available for using JSONEditor in Angular.js:
[https://github.com/angular-tools/ng-jsoneditor](https://github.com/angular-tools/ng-jsoneditor)
> Note that to use JSONEditor in Internet Explorer 11, it is necessary
> to load a polyfill for `Promise` in your application.
## Use
```html
<!DOCTYPE HTML>
<html>
<html lang="en">
<head>
<!-- when using the mode "code", it's important to specify charset utf-8 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta charset="utf-8">
<link href="jsoneditor/dist/jsoneditor.min.css" rel="stylesheet" type="text/css">
<script src="jsoneditor/dist/jsoneditor.min.js"></script>
@ -80,23 +96,23 @@ There is a directive available for using JSONEditor in Angular.js:
<script>
// create the editor
var container = document.getElementById("jsoneditor");
var options = {};
var editor = new JSONEditor(container, options);
const container = document.getElementById("jsoneditor")
const options = {}
const editor = new JSONEditor(container, options)
// set json
var json = {
const initialJson = {
"Array": [1, 2, 3],
"Boolean": true,
"Null": null,
"Number": 123,
"Object": {"a": "b", "c": "d"},
"String": "Hello World"
};
editor.set(json);
}
editor.set(initialJson)
// get json
var json = editor.get();
const updatedJson = editor.get()
</script>
</body>
</html>
@ -126,7 +142,7 @@ jsoneditor:
- To automatically build when a source file has changed:
```
npm run watch
npm start
```
This will update `./jsoneditor.js` and `./jsoneditor.css` in the dist folder
@ -134,6 +150,21 @@ jsoneditor:
an expensive operation.
## Test
Run unit tests:
```
npm test
```
Run code linting ([JavaScript Standard Style](https://standardjs.com/)):
```
npm run lint
```
## Custom builds
The source code of JSONEditor consists of CommonJS modules. JSONEditor can be bundled in a customized way using a module bundler like [browserify](http://browserify.org/) or [webpack](http://webpack.github.io/). First, install all dependencies of jsoneditor:
@ -144,7 +175,7 @@ To create a custom bundle of the source code using browserify:
browserify ./index.js -o ./jsoneditor.custom.js -s JSONEditor
The Ace editor, used in mode `code`, accounts for about 75% of the total
The Ace editor, used in mode `code`, accounts for about one third of the total
size of the library. To exclude the Ace editor from the bundle:
browserify ./index.js -o ./jsoneditor.custom.js -s JSONEditor -x brace -x brace/mode/json -x brace/ext/searchbox

View File

@ -1,32 +0,0 @@
{
"name": "jsoneditor",
"description": "A web-based tool to view, edit and format JSON",
"tags": [
"json",
"editor",
"viewer",
"formatter"
],
"homepage": "http://jsoneditoronline.org/",
"repository": {
"type": "git",
"url": "https://github.com/josdejong/jsoneditor.git"
},
"main": [
"./dist/jsoneditor.min.js",
"./dist/jsoneditor.min.css"
],
"bugs": "https://github.com/josdejong/jsoneditor/issues",
"ignore": [
"misc",
"node_modules",
"test",
"tools",
"gulpfile.js",
"npm-debug.log",
".idea",
".npmignore",
".gitignore"
],
"dependencies": {}
}

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

929
dist/jsoneditor.css vendored
View File

@ -1,929 +0,0 @@
/* reset styling (prevent conflicts with bootstrap, materialize.css, etc.) */
div.jsoneditor input {
height: auto;
border: inherit;
}
div.jsoneditor input:focus {
border: none !important;
box-shadow: none !important;
}
div.jsoneditor table {
border-collapse: collapse;
width: auto;
}
div.jsoneditor td,
div.jsoneditor th {
padding: 0;
display: table-cell;
text-align: left;
vertical-align: inherit;
border-radius: inherit;
}
div.jsoneditor-field,
div.jsoneditor-value,
div.jsoneditor-readonly {
border: 1px solid transparent;
min-height: 16px;
min-width: 32px;
padding: 2px;
margin: 1px;
word-wrap: break-word;
float: left;
}
/* adjust margin of p elements inside editable divs, needed for Opera, IE */
div.jsoneditor-field p,
div.jsoneditor-value p {
margin: 0;
}
div.jsoneditor-value {
word-break: break-word;
}
div.jsoneditor-readonly {
min-width: 16px;
color: gray;
}
div.jsoneditor-empty {
border-color: lightgray;
border-style: dashed;
border-radius: 2px;
}
div.jsoneditor-field.jsoneditor-empty::after,
div.jsoneditor-value.jsoneditor-empty::after {
pointer-events: none;
color: lightgray;
font-size: 8pt;
}
div.jsoneditor-field.jsoneditor-empty::after {
content: "field";
}
div.jsoneditor-value.jsoneditor-empty::after {
content: "value";
}
div.jsoneditor-value.jsoneditor-url,
a.jsoneditor-value.jsoneditor-url {
color: green;
text-decoration: underline;
}
a.jsoneditor-value.jsoneditor-url {
display: inline-block;
padding: 2px;
margin: 2px;
}
a.jsoneditor-value.jsoneditor-url:hover,
a.jsoneditor-value.jsoneditor-url:focus {
color: #ee422e;
}
div.jsoneditor td.jsoneditor-separator {
padding: 3px 0;
vertical-align: top;
color: gray;
}
div.jsoneditor-field[contenteditable=true]:focus,
div.jsoneditor-field[contenteditable=true]:hover,
div.jsoneditor-value[contenteditable=true]:focus,
div.jsoneditor-value[contenteditable=true]:hover,
div.jsoneditor-field.jsoneditor-highlight,
div.jsoneditor-value.jsoneditor-highlight {
background-color: #FFFFAB;
border: 1px solid yellow;
border-radius: 2px;
}
div.jsoneditor-field.jsoneditor-highlight-active,
div.jsoneditor-field.jsoneditor-highlight-active:focus,
div.jsoneditor-field.jsoneditor-highlight-active:hover,
div.jsoneditor-value.jsoneditor-highlight-active,
div.jsoneditor-value.jsoneditor-highlight-active:focus,
div.jsoneditor-value.jsoneditor-highlight-active:hover {
background-color: #ffee00;
border: 1px solid #ffc700;
border-radius: 2px;
}
div.jsoneditor-value.jsoneditor-string {
color: #008000;
}
div.jsoneditor-value.jsoneditor-object,
div.jsoneditor-value.jsoneditor-array {
min-width: 16px;
color: #808080;
}
div.jsoneditor-value.jsoneditor-number {
color: #ee422e;
}
div.jsoneditor-value.jsoneditor-boolean {
color: #ff8c00;
}
div.jsoneditor-value.jsoneditor-null {
color: #004ED0;
}
div.jsoneditor-value.jsoneditor-invalid {
color: #000000;
}
div.jsoneditor-tree button {
width: 24px;
height: 24px;
padding: 0;
margin: 0;
border: none;
cursor: pointer;
background: transparent url("img/jsoneditor-icons.svg");
}
div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree,
div.jsoneditor-mode-form tr.jsoneditor-expandable td.jsoneditor-tree {
cursor: pointer;
}
div.jsoneditor-tree button.jsoneditor-collapsed {
background-position: 0 -48px;
}
div.jsoneditor-tree button.jsoneditor-expanded {
background-position: 0 -72px;
}
div.jsoneditor-tree button.jsoneditor-contextmenu {
background-position: -48px -72px;
}
div.jsoneditor-tree button.jsoneditor-contextmenu:hover,
div.jsoneditor-tree button.jsoneditor-contextmenu:focus,
div.jsoneditor-tree button.jsoneditor-contextmenu.jsoneditor-selected,
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu {
background-position: -48px -48px;
}
div.jsoneditor-tree *:focus {
outline: none;
}
div.jsoneditor-tree button:focus {
/* TODO: nice outline for buttons with focus
outline: #97B0F8 solid 2px;
box-shadow: 0 0 8px #97B0F8;
*/
background-color: #f5f5f5;
outline: #e5e5e5 solid 1px;
}
div.jsoneditor-tree button.jsoneditor-invisible {
visibility: hidden;
background: none;
}
div.jsoneditor {
color: #1A1A1A;
border: 1px solid #3883fa;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
padding: 0;
line-height: 100%;
}
div.jsoneditor-tree table.jsoneditor-tree {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
margin: 0;
}
div.jsoneditor-outer {
width: 100%;
height: 100%;
margin: -35px 0 0 0;
padding: 35px 0 0 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
textarea.jsoneditor-text,
.ace-jsoneditor {
min-height: 150px;
}
div.jsoneditor-tree {
width: 100%;
height: 100%;
position: relative;
overflow: auto;
}
textarea.jsoneditor-text {
width: 100%;
height: 100%;
margin: 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
outline-width: 0;
border: none;
background-color: white;
resize: none;
}
tr.jsoneditor-highlight,
tr.jsoneditor-selected {
background-color: #e6e6e6;
}
tr.jsoneditor-selected button.jsoneditor-dragarea,
tr.jsoneditor-selected button.jsoneditor-contextmenu {
visibility: hidden;
}
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea,
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu {
visibility: visible;
}
div.jsoneditor-tree button.jsoneditor-dragarea {
background: url("img/jsoneditor-icons.svg") -72px -72px;
cursor: move;
}
div.jsoneditor-tree button.jsoneditor-dragarea:hover,
div.jsoneditor-tree button.jsoneditor-dragarea:focus,
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea {
background-position: -72px -48px;
}
div.jsoneditor tr,
div.jsoneditor th,
div.jsoneditor td {
padding: 0;
margin: 0;
}
div.jsoneditor td {
vertical-align: top;
}
div.jsoneditor td.jsoneditor-tree {
vertical-align: top;
}
div.jsoneditor-field,
div.jsoneditor-value,
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-size: 10pt;
color: #1A1A1A;
}
/* popover */
.jsoneditor-schema-error {
cursor: default;
display: inline-block;
/*font-family: arial, sans-serif;*/
height: 24px;
line-height: 24px;
position: relative;
text-align: center;
width: 24px;
}
div.jsoneditor-tree .jsoneditor-schema-error {
width: 24px;
height: 24px;
padding: 0;
margin: 0 4px 0 0;
background: url("img/jsoneditor-icons.svg") -168px -48px;
}
.jsoneditor-schema-error .jsoneditor-popover {
background-color: #4c4c4c;
border-radius: 3px;
box-shadow: 0 0 5px rgba(0,0,0,0.4);
color: #fff;
display: none;
padding: 7px 10px;
position: absolute;
width: 200px;
z-index: 4;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above {
bottom: 32px;
left: -98px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below {
top: 32px;
left: -98px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left {
top: -7px;
right: 32px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right {
top: -7px;
left: 32px;
}
.jsoneditor-schema-error .jsoneditor-popover:before {
border-right: 7px solid transparent;
border-left: 7px solid transparent;
content: '';
display: block;
left: 50%;
margin-left: -7px;
position: absolute;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above:before {
border-top: 7px solid #4c4c4c;
bottom: -7px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below:before {
border-bottom: 7px solid #4c4c4c;
top: -7px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left:before {
border-left: 7px solid #4c4c4c;
border-top: 7px solid transparent;
border-bottom: 7px solid transparent;
content: '';
top: 19px;
right: -14px;
left: inherit;
margin-left: inherit;
margin-top: -7px;
position: absolute;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right:before {
border-right: 7px solid #4c4c4c;
border-top: 7px solid transparent;
border-bottom: 7px solid transparent;
content: '';
top: 19px;
left: -14px;
margin-left: inherit;
margin-top: -7px;
position: absolute;
}
.jsoneditor-schema-error:hover .jsoneditor-popover,
.jsoneditor-schema-error:focus .jsoneditor-popover {
display: block;
-webkit-animation: fade-in .3s linear 1, move-up .3s linear 1;
-moz-animation: fade-in .3s linear 1, move-up .3s linear 1;
-ms-animation: fade-in .3s linear 1, move-up .3s linear 1;
}
@-webkit-keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@-moz-keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@-ms-keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/*@-webkit-keyframes move-up {*/
/*from { bottom: 24px; }*/
/*to { bottom: 32px; }*/
/*}*/
/*@-moz-keyframes move-up {*/
/*from { bottom: 24px; }*/
/*to { bottom: 32px; }*/
/*}*/
/*@-ms-keyframes move-up {*/
/*from { bottom: 24px; }*/
/*to { bottom: 32px; }*/
/*}*/
/* JSON schema errors displayed at the bottom of the editor in mode text and code */
.jsoneditor .jsoneditor-text-errors {
width: 100%;
border-collapse: collapse;
background-color: #ffef8b;
border-top: 1px solid #ffd700;
}
.jsoneditor .jsoneditor-text-errors td {
padding: 3px 6px;
vertical-align: middle;
}
.jsoneditor-text-errors .jsoneditor-schema-error {
border: none;
width: 24px;
height: 24px;
padding: 0;
margin: 0 4px 0 0;
background: url("img/jsoneditor-icons.svg") -168px -48px;
}
/* ContextMenu - main menu */
div.jsoneditor-contextmenu-root {
position: relative;
width: 0;
height: 0;
}
div.jsoneditor-contextmenu {
position: absolute;
box-sizing: content-box;
z-index: 99999;
}
div.jsoneditor-contextmenu ul,
div.jsoneditor-contextmenu li {
box-sizing: content-box;
}
div.jsoneditor-contextmenu ul {
position: relative;
left: 0;
top: 0;
width: 124px;
background: white;
border: 1px solid #d3d3d3;
box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3);
list-style: none;
margin: 0;
padding: 0;
}
div.jsoneditor-contextmenu ul li button {
padding: 0;
margin: 0;
width: 124px;
height: 24px;
border: none;
cursor: pointer;
color: #4d4d4d;
background: transparent;
font-size: 10pt;
font-family: arial, sans-serif;
box-sizing: border-box;
line-height: 26px;
text-align: left;
}
/* Fix button padding in firefox */
div.jsoneditor-contextmenu ul li button::-moz-focus-inner {
padding: 0;
border: 0;
}
div.jsoneditor-contextmenu ul li button:hover,
div.jsoneditor-contextmenu ul li button:focus {
color: #1a1a1a;
background-color: #f5f5f5;
outline: none;
}
div.jsoneditor-contextmenu ul li button.jsoneditor-default {
width: 92px;
}
div.jsoneditor-contextmenu ul li button.jsoneditor-expand {
float: right;
width: 32px;
height: 24px;
border-left: 1px solid #e5e5e5;
}
div.jsoneditor-contextmenu div.jsoneditor-icon {
float: left;
width: 24px;
height: 24px;
border: none;
padding: 0;
margin: 0;
background-image: url("img/jsoneditor-icons.svg");
}
div.jsoneditor-contextmenu ul li button div.jsoneditor-expand {
float: right;
width: 24px;
height: 24px;
padding: 0;
margin: 0 4px 0 0;
background: url("img/jsoneditor-icons.svg") 0 -72px;
opacity: 0.4;
}
div.jsoneditor-contextmenu ul li button:hover div.jsoneditor-expand,
div.jsoneditor-contextmenu ul li button:focus div.jsoneditor-expand,
div.jsoneditor-contextmenu ul li.jsoneditor-selected div.jsoneditor-expand,
div.jsoneditor-contextmenu ul li button.jsoneditor-expand:hover div.jsoneditor-expand,
div.jsoneditor-contextmenu ul li button.jsoneditor-expand:focus div.jsoneditor-expand {
opacity: 1;
}
div.jsoneditor-contextmenu div.jsoneditor-separator {
height: 0;
border-top: 1px solid #e5e5e5;
padding-top: 5px;
margin-top: 5px;
}
div.jsoneditor-contextmenu button.jsoneditor-remove > div.jsoneditor-icon {
background-position: -24px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-remove:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-remove:focus > div.jsoneditor-icon {
background-position: -24px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-append > div.jsoneditor-icon {
background-position: 0 -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-append:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-append:focus > div.jsoneditor-icon {
background-position: 0 0;
}
div.jsoneditor-contextmenu button.jsoneditor-insert > div.jsoneditor-icon {
background-position: 0 -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-insert:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-insert:focus > div.jsoneditor-icon {
background-position: 0 0;
}
div.jsoneditor-contextmenu button.jsoneditor-duplicate > div.jsoneditor-icon {
background-position: -48px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-duplicate:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-duplicate:focus > div.jsoneditor-icon {
background-position: -48px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-sort-asc > div.jsoneditor-icon {
background-position: -168px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-sort-asc:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-sort-asc:focus > div.jsoneditor-icon {
background-position: -168px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-sort-desc > div.jsoneditor-icon {
background-position: -192px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-sort-desc:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-sort-desc:focus > div.jsoneditor-icon {
background-position: -192px 0;
}
/* ContextMenu - sub menu */
div.jsoneditor-contextmenu ul li button.jsoneditor-selected,
div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover,
div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus {
color: white;
background-color: #ee422e;
}
div.jsoneditor-contextmenu ul li {
overflow: hidden;
}
div.jsoneditor-contextmenu ul li ul {
display: none;
position: relative;
left: -10px;
top: 0;
border: none;
box-shadow: inset 0 0 10px rgba(128, 128, 128, 0.5);
padding: 0 10px;
/* TODO: transition is not supported on IE8-9 */
-webkit-transition: all 0.3s ease-out;
-moz-transition: all 0.3s ease-out;
-o-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
div.jsoneditor-contextmenu ul li ul li button {
padding-left: 24px;
animation: all ease-in-out 1s;
}
div.jsoneditor-contextmenu ul li ul li button:hover,
div.jsoneditor-contextmenu ul li ul li button:focus {
background-color: #f5f5f5;
}
div.jsoneditor-contextmenu button.jsoneditor-type-string > div.jsoneditor-icon {
background-position: -144px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-type-string:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-string:focus > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-string.jsoneditor-selected > div.jsoneditor-icon {
background-position: -144px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-type-auto > div.jsoneditor-icon {
background-position: -120px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-type-auto:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-auto:focus > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-auto.jsoneditor-selected > div.jsoneditor-icon {
background-position: -120px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-type-object > div.jsoneditor-icon {
background-position: -72px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-type-object:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-object:focus > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-object.jsoneditor-selected > div.jsoneditor-icon {
background-position: -72px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-type-array > div.jsoneditor-icon {
background-position: -96px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-type-array:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-array:focus > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-array.jsoneditor-selected > div.jsoneditor-icon {
background-position: -96px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon {
background-image: none;
width: 6px;
}
div.jsoneditor-menu {
width: 100%;
height: 35px;
padding: 2px;
margin: 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: white;
background-color: #3883fa;
border-bottom: 1px solid #3883fa;
}
div.jsoneditor-menu > button,
div.jsoneditor-menu > div.jsoneditor-modes > button {
width: 26px;
height: 26px;
margin: 2px;
padding: 0;
border-radius: 2px;
border: 1px solid transparent;
background: transparent url("img/jsoneditor-icons.svg");
color: white;
opacity: 0.8;
font-family: arial, sans-serif;
font-size: 10pt;
float: left;
}
div.jsoneditor-menu > button:hover,
div.jsoneditor-menu > div.jsoneditor-modes > button:hover {
background-color: rgba(255,255,255,0.2);
border: 1px solid rgba(255,255,255,0.4);
}
div.jsoneditor-menu > button:focus,
div.jsoneditor-menu > button:active,
div.jsoneditor-menu > div.jsoneditor-modes > button:focus,
div.jsoneditor-menu > div.jsoneditor-modes > button:active {
background-color: rgba(255,255,255,0.3);
}
div.jsoneditor-menu > button:disabled,
div.jsoneditor-menu > div.jsoneditor-modes > button:disabled {
opacity: 0.5;
}
div.jsoneditor-menu > button.jsoneditor-collapse-all {
background-position: 0 -96px;
}
div.jsoneditor-menu > button.jsoneditor-expand-all {
background-position: 0 -120px;
}
div.jsoneditor-menu > button.jsoneditor-undo {
background-position: -24px -96px;
}
div.jsoneditor-menu > button.jsoneditor-undo:disabled {
background-position: -24px -120px;
}
div.jsoneditor-menu > button.jsoneditor-redo {
background-position: -48px -96px;
}
div.jsoneditor-menu > button.jsoneditor-redo:disabled {
background-position: -48px -120px;
}
div.jsoneditor-menu > button.jsoneditor-compact {
background-position: -72px -96px;
}
div.jsoneditor-menu > button.jsoneditor-format {
background-position: -72px -120px;
}
div.jsoneditor-menu > div.jsoneditor-modes {
display: inline-block;
float: left;
}
div.jsoneditor-menu > div.jsoneditor-modes > button {
background-image: none;
width: auto;
padding-left: 6px;
padding-right: 6px;
}
div.jsoneditor-menu > button.jsoneditor-separator,
div.jsoneditor-menu > div.jsoneditor-modes > button.jsoneditor-separator {
margin-left: 10px;
}
div.jsoneditor-menu a {
font-family: arial, sans-serif;
font-size: 10pt;
color: white;
opacity: 0.8;
vertical-align: middle;
}
div.jsoneditor-menu a:hover {
opacity: 1;
}
div.jsoneditor-menu a.jsoneditor-poweredBy {
font-size: 8pt;
position: absolute;
right: 0;
top: 0;
padding: 10px;
}
table.jsoneditor-search input,
table.jsoneditor-search div.jsoneditor-results {
font-family: arial, sans-serif;
font-size: 10pt;
color: #1A1A1A;
background: transparent;
/* For Firefox */
}
table.jsoneditor-search div.jsoneditor-results {
color: white;
padding-right: 5px;
line-height: 24px;
}
table.jsoneditor-search {
position: absolute;
right: 4px;
top: 4px;
border-collapse: collapse;
border-spacing: 0;
}
table.jsoneditor-search div.jsoneditor-frame {
border: 1px solid transparent;
background-color: white;
padding: 0 2px;
margin: 0;
}
table.jsoneditor-search div.jsoneditor-frame table {
border-collapse: collapse;
}
table.jsoneditor-search input {
width: 120px;
border: none;
outline: none;
margin: 1px;
line-height: 20px;
}
table.jsoneditor-search button {
width: 16px;
height: 24px;
padding: 0;
margin: 0;
border: none;
background: url("img/jsoneditor-icons.svg");
vertical-align: top;
}
table.jsoneditor-search button:hover {
background-color: transparent;
}
table.jsoneditor-search button.jsoneditor-refresh {
width: 18px;
background-position: -99px -73px;
}
table.jsoneditor-search button.jsoneditor-next {
cursor: pointer;
background-position: -124px -73px;
}
table.jsoneditor-search button.jsoneditor-next:hover {
background-position: -124px -49px;
}
table.jsoneditor-search button.jsoneditor-previous {
cursor: pointer;
background-position: -148px -73px;
margin-right: 2px;
}
table.jsoneditor-search button.jsoneditor-previous:hover {
background-position: -148px -49px;
}

36348
dist/jsoneditor.js vendored

File diff suppressed because one or more lines are too long

1
dist/jsoneditor.map vendored

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

View File

@ -1,41 +0,0 @@
# Which files do I need?
Ehhh, that's quite some files in this dist folder. Which files do I need?
## Full version
If you're not sure which version to use, use the full version.
Which files are needed when using the full version?
- jsoneditor.min.js
- jsoneditor.map (optional, for debugging purposes only)
- jsoneditor.min.css
- img/jsoneditor-icons.svg
## Minimalist version
The minimalist version has excluded the following libraries:
- `ace` (via `brace`), used for the code editor.
- `ajv`, used for JSON schema validation.
This reduces the the size of the minified and gzipped JavaScript file from
about 160 kB to about 40 kB.
When to use the minimalist version?
- If you don't need the mode "code" and don't need JSON schema validation.
- Or if you want to provide `ace` and/or `ajv` yourself via the configuration
options, for example when you already use Ace in other parts of your
web application too and don't want to bundle the library twice.
Which files are needed when using the minimalist version?
- jsoneditor-minimalist.min.js
- jsoneditor-minimalist.map (optional, for debugging purposes only)
- jsoneditor.min.css
- img/jsoneditor-icons.svg

View File

@ -35,6 +35,8 @@ Constructs a new JSONEditor.
Provide a custom version of the [Ace editor](http://ace.c9.io/) and use this instead of the version that comes embedded with JSONEditor. Only applicable when `mode` is `code`.
Note that when using the minimalist version of JSONEditor (which has Ace excluded), JSONEditor will try to load the Ace plugins `ace/mode/json` and `ace/ext/searchbox`. These plugins must be loaded beforehand or be available in the folder of the Ace editor.
- `{Object} ajv`
Provide a custom instance of [ajv](https://github.com/epoberezkin/ajv), the
@ -46,15 +48,65 @@ Constructs a new JSONEditor.
}
```
- `{function} onChange`
- `{function} onChange()`
Set a callback function triggered when the contents of the JSONEditor change. Called without parameters. Will only be triggered on changes made by the user, not in case of programmatic changes via the functions `set` or `setText`.
Set a callback function triggered when the contents of the JSONEditor change.
This callback does not pass the changed contents, use `get()` or `getText()` for that.
Note that `get()` can throw an exception in mode `text`, `code`, or `preview`, when the editor contains invalid JSON.
Will only be triggered on changes made by the user, not in case of programmatic changes via the functions `set`, `setText`, `update`, or `updateText`.
See also callback functions `onChangeJSON(json)` and `onChangeText(jsonString)`.
- `{function} onEditable`
- `{function} onChangeJSON(json)`
Set a callback function 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}`.
Set a callback function triggered when the contents of the JSONEditor change.
Passes the changed JSON document.
Only applicable when option `mode` is `tree`, `form`, or `view`.
The callback will only be triggered on changes made by the user, not in case of programmatic changes via the functions `set`, `setText`, `update`, or `updateText`.
Also see the callback function `onChangeText(jsonString)`.
- `{function} onError`
- `{function} onChangeText(jsonString)`
Set a callback function triggered when the contents of the JSONEditor change.
Passes the changed JSON document inside a string (stringified).
The callback will only be triggered on changes made by the user, not in case of programmatic changes via the functions `set`, `setText`, `update`, or `updateText`.
Also see the callback function `onChangeJSON(json)`.
- `{function} onClassName({ path, field, value })`
Set a callback function to add custom CSS classes to the rendered nodes. Only applicable when option `mode` is `tree`, `form`, or `view`.
The callback is invoked with an object containing `path`, `field` and `value`:
```
{
path: string[],
field: string,
value: string
}
```
The function must either return a string containing CSS class names, or return `undefined` in order to do nothing for a specific node.
In order to update css classes when they depend on external state, you can call `editor.refresh()`.
- `{function} onEditable({ path, field, value })`
Set a callback function to determine whether individual nodes are editable or read-only. Only applicable when option `mode` is `tree`, `text`, or `code`.
In case of mode `tree`, the callback is invoked as `editable(node)`, where the first parameter 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}` to set set the read-only attribute for field and value individually.
In modes `text` and `code`, the callback is invoked as `editable(node)` where `node` is an empty object (no field, value, or path). In that case the function can return false to make the text or code editor completely read-only.
- `{function} onError(error)`
Set a callback function triggered when an error occurs. Invoked with the error as first argument. The callback is only invoked
for errors triggered by a users action, like switching from code mode to tree mode or clicking the Format button whilst the editor doesn't contain valid JSON.
@ -64,21 +116,131 @@ Constructs a new JSONEditor.
Set a callback function triggered right after the mode is changed by the user. Only applicable when
the mode can be changed by the user (i.e. when option `modes` is set).
- `{function} onNodeName({ path, type, size })`
Customize the name of object and array nodes. By default the names are brackets with the number of childs inside,
like `{5}` and `[32]`. The number inside can be customized. using `onNodeName`.
The first parameter is an object containing the following properties:
```
{
path: string[],
type: 'object' | 'array',
size: number
}
```
The `onNodeName` function should return a string containing the name for the node. If nothing is returned,
the size (number of childs) will be displayed.
- `{function} onValidate(json)`
Set a callback function for custom validation. Available in all modes.
On a change of the JSON, the callback function is invoked with the changed data. The function should return
an array with errors or null if there are no errors. The function can also return a `Promise` resolving with
the errors retrieved via an asynchronous validation (like sending a request to a server for validation).
The returned errors must have the following structure: `{path: Array.<string | number>, message: string}`.
Example:
```js
var options = {
onValidate: function (json) {
var errors = [];
if (json && json.customer && !json.customer.address) {
errors.push({
path: ['customer'],
message: 'Required property "address" missing.'
});
}
return errors;
}
}
```
Also see the option `schema` for JSON schema validation.
- `{function} onValidationError(errors)`
Set a callback function for validation and parse errors. Available in all modes.
On validation of the json, if errors of any kind were found this callback is invoked with the errors data.
On change, the callback will be invoked only if errors were changed.
Example:
```js
var options = {
/**
* @param {Array} errors validation errors
*/
onValidationError: function (errors) {
errors.forEach((error) => {
switch (error.type) {
case 'validation': // schema validation error
...
break;
case 'customValidation': // custom validation error
...
break;
case 'error': // json parse error
...
break;
...
}
});
...
}
}
```
- `{function} onCreateMenu(items, node)`
Customize context menus in tree mode.
Sets a callback function to customize the context menu in tree mode. Each time the user clicks on the context menu button, an array of menu items is created. If this callback is configured, the array with menu items is passed to this function. The menu items can be customized in this function in any aspect of these menu items, including deleting them and/or adding new items. The function should return the final array of menu items to be displayed to the user.
Each menu item is represented by an object, which may also contain a submenu array of items. See the source code of example 21 in the examples folder for more info on the format of the items and submenu objects.
The second argument `node` is an object containing the following properties:
```
{
type: 'single' | 'multiple' | 'append'
path: Array,
paths: Array with paths
}
```
The property `path` containing the path of the node, and `paths` contains the same path or in case there are multiple selected nodes it contains the paths of all selected nodes.
When the user opens the context menu of an append node (in an empty object or array), the `type` will be `'append'` and the `path` will contain the path of the parent node.
- `{boolean} escapeUnicode`
If true, unicode characters are escaped and displayed as their hexadecimal code (like `\u260E`) instead of of the character itself (like `☎`). False by default.
If `true`, unicode characters are escaped and displayed as their hexadecimal code (like `\u260E`) instead of of the character itself (like `☎`). `false` by default.
- `{boolean} sortObjectKeys`
If true, object keys in 'tree', 'view' or 'form' mode list be listed alphabetically instead by their insertion order. Sorting is performed using a natural sort algorithm, which makes it easier to see objects that have string numbers as keys. False by default.
If `true`, object keys in 'tree', 'view' or 'form' mode list be listed alphabetically instead by their insertion order. Sorting is performed using a natural sort algorithm, which makes it easier to see objects that have string numbers as keys. `false` by default.
- `{boolean} limitDragging`
If `false`, nodes can be dragged from any parent node to any other parent node. If `true`, nodes can only be dragged inside the same parent node, which effectively only allows reordering of nodes. By default, `limitDragging` is `true` when no JSON `schema` is defined, and `false` otherwise.
- `{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'.
Enables history, adds a button Undo and Redo to the menu of the JSONEditor. `true` by default. Only applicable when `mode` is `'tree'`, `'form'`, or `'preview'`.
- `{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.
Set the editor mode. Available values: 'tree' (default), 'view', 'form', 'code', 'text', 'preview'. In 'view' mode, the data and datastructure is read-only. In 'form' mode, only the value can be changed, the data structure is read-only. Mode 'code' requires the Ace editor to be loaded on the page. Mode 'text' shows the data as plain text.
The 'preview' mode can handle large JSON documents up to 500 MiB. It shows a preview of the data, and allows to
transform, sort, filter, format, or compact the data.
- `{String[]} modes`
@ -86,7 +248,7 @@ Constructs a new JSONEditor.
- `{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'.
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'.
- `{Object} schema`
@ -96,17 +258,397 @@ Constructs a new JSONEditor.
See [http://json-schema.org/](http://json-schema.org/) for more information.
Also see the option `onValidate` for custom validation.
- `{Object} schemaRefs`
Schemas that are referenced using the `$ref` property from the JSON schema that are set in the `schema` option,
the object structure in the form of `{reference_key: schemaObject}`
- `{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'.
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'.
Number of indentation spaces. `2` by default. Only applicable when `mode` is 'code', 'text', or 'preview'.
- `{String} theme`
Set the Ace editor theme, uses included 'ace/theme/jsoneditor' by default. Please note that only the default theme is included with jsoneditor, so if you specify another one you need to make sure it is loaded.
Set the Ace editor theme, uses included 'ace/theme/jsoneditor' by default. Please note that only the default theme is included with JSONEditor, so if you specify another one you need to make sure it is loaded.
- `{Object} templates`
Array of templates that will appear in the context menu, Each template is a json object precreated that can be added as a object value to any node in your document.
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
var options = {
templates: [
{
text: 'Person',
title: 'Insert a Person Node',
className: 'jsoneditor-type-object',
field: 'PersonTemplate',
value: {
'firstName': 'John',
'lastName': 'Do',
'age': 28
}
},
{
text: 'Address',
title: 'Insert a Address Node',
field: 'AddressTemplate',
value: {
'street': "",
'city': "",
'state': "",
'ZIP code': ""
}
}
]
}
```
- `{Object} autocomplete`
*autocomplete* will enable this feature in your editor in tree mode, the object have the following **subelements**:
- `{string} filter`
- `{Function} filter`
Indicate the filter method of the autocomplete. Default to `start`.
- `start` : Match your input from the start, e.g. `ap` match `apple` but `pl` does not.
- `contain` : Contain your input or not, e.g. `pl` match `apple` too.
- Custom Function : Define custom filter rule, return `true` will match you input.
- `{string} trigger`
Indicate the way to trigger autocomplete menu. Default to `keydown`
- `keydown` : When you type something in the field or value, it will trigger autocomplete.
- `focus` : When you focus in the field or value, it will trigger the autocomplete.
- `{number[]} confirmKeys`
Indicate the KeyCodes for trigger confirm completion, by default those keys are: `[39, 35, 9]` which are the code for [right, end, tab]
- `{boolean} caseSensitive`
Indicate if the autocomplete is going to be strict case-sensitive to match the options.
- `{Function} getOptions (text: string, path: string[], input: string, editor: JSONEditor)`
This function will return your possible options for create the autocomplete selection, you can control dynamically which options you want to display according to the current active editing node.
*Parameters:*
- `text` : The text in the current node part. (basically the text that the user is editing)
- `path` : The path of the node that is being edited as an array with strings.
- `input` : Can be "field" or "value" depending if the user is editing a field name or a value of a node.
- `editor` : The editor instance object that is being edited.
*Returns:*
- Can return an array with autocomplete options (strings), for example `['apple','cranberry','raspberry','pie']`
- Can return `null` when there are no autocomplete options.
- Can return an object `{startFrom: number, options: string[]}`. Here `startFrom` determines the start character from where the existing text will be replaced. `startFrom` is `0` by default, replacing the whole text.
- Can return a `Promise` resolving one of the return types above to support asynchronously retrieving a list with options.
- `{boolean} mainMenuBar`
Adds main menu bar - Contains format, sort, transform, search etc. functionality. `true` by default. Applicable in all types of `mode`.
- `{boolean} navigationBar`
Adds navigation bar to the menu - the navigation bar visualize the current position on the tree structure as well as allows breadcrumbs navigation. `true` by default. Only applicable when `mode` is 'tree', 'form' or 'view'.
- `{boolean} statusBar`
Adds status bar to the bottom of the editor - the status bar shows the cursor position and a count of the selected characters. `true` by default. Only applicable when `mode` is 'code', 'text', or 'preview'.
- `{function} onTextSelectionChange(start, end, text)`
Set a callback function triggered when a text is selected in the JSONEditor.
callback signature should be:
```js
/**
* @param {{row:Number, column:Number}} start Selection start position
* @param {{row:Number, column:Number}} end Selected end position
* @param {String} text selected text
*/
function onTextSelectionChange(start, end, text) {
...
}
```
Only applicable when `mode` is 'code' or 'text'.
- `{function} onSelectionChange(start, end)`
Set a callback function triggered when Nodes are selected in the JSONEditor.
callback signature should be:
```js
/**
* @typedef {{value: String|Object|Number|Boolean, path: Array.<String|Number>}} SerializableNode
*
* @param {SerializableNode=} start
* @param {SerializableNode=} end
*/
function onSelectionChange(start, end) {
...
}
```
Only applicable when `mode` is 'tree'.
- `{function} onEvent({ field, path, value? }, event)`
Set a callback function that will be triggered when an event will occur in
a JSON field or value.
In case of field event, node information will be
```
{
field: string,
path: {string|number}[]
}
```
In case of value event, node information will be
```
{
field: string,
path: {string|number}[],
value: string
}
```
signature should be:
```js
/**
* @param {Node} the Node where event has been triggered
identified by {field: string, path: {string|number}[] [, value: string]}`
* @param {event} the event fired
*/
function onEvent(node, event) {
...
}
```
Only applicable when `mode` is 'form', 'tree' or 'view'.
- `{function} onFocus({ type: 'focus', target })`
Callback method, triggered when the editor comes into focus,
passing an object `{type, target}`, Applicable for all modes.
- `{function} onBlur({ type: 'blur', target })`
Callback method, triggered when the editor goes out of focus,
passing an object `{type, target}`, Applicable for all modes.
- `{boolean} colorPicker`
If `true` (default), values containing a color name or color code will have a color picker rendered on their left side.
- `{function} onColorPicker(parent, color, onChange)`
Callback function triggered when the user clicks a color.
Can be used to implement a custom color picker.
The callback is invoked with three arguments:
`parent` is an HTML element where the color picker can be attached,
`color` is the current color,
`onChange(newColor)` is a callback which has to be invoked with the new color selected in the color picker.
JSONEditor comes with a built-in color picker, powered by [vanilla-picker](https://github.com/Sphinxxxx/vanilla-picker).
A simple example of `onColorPicker` using `vanilla-picker`:
```js
var options = {
onColorPicker: function (parent, color, onChange) {
new VanillaPicker({
parent: parent,
color: color,
onDone: function (color) {
onChange(color.hex)
}
}).show();
}
}
```
- `{boolean | function({field, value, path}) -> boolean} timestampTag`
If `true` (default), a tag with the date/time of a timestamp is displayed
right from values containing a timestamp. By default, a value is
considered a timestamp when it is an integer number with a value larger
than Jan 1th 2000, `946684800000`.
When `timestampTag` a is a function, a timestamp tag will be displayed when
this function returns `true`, and no timestamp is displayed when the function
returns `false`. When the function returns a non-boolean value like `null`
or `undefined`, JSONEditor will fallback on the built-in rules to determine
whether or not to show a timestamp.
The function is invoked with an object as first parameter:
```
{
field: string,
value: string,
path: string[]
}
```
Whether a value is a timestamp can be determined implicitly based on
the `value`, or explicitly based on `field` or `path`. You can for example
test whether a field name contains a string like: `'date'` or `'time'`.
Example:
```js
var options = {
timestampTag: function ({ field, value, path }) {
if (field === 'dateCreated') {
return true
}
return false
}
}
```
Only applicable for modes `tree`, `form`, and `view`.
- `{ function({field, value, path}) -> string|null } timestampFormat`
Customizing the way formating the timestamp. Called when a value is timestamp after `timestampTag`. If it returns null, the timestamp would be formatted with default setting (`new Date(value).toISOString()`).
parameter:
```
{
field: string,
value: string,
path: string[]
}
```
Example:
```js
var options = {
timestampFormat: function ({ field, value, path }) {
if (field === 'customTime') {
return new Date(value*1000).toString()
}
return null
}
}
```
Only applicable for modes `tree`, `form`, and `view`.
- `{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`, `zh-CN`, `pt-BR`, `tr`, `ja`, `fr-FR`, `de`. 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`.
- `{HTMLElement} modalAnchor`
The container element where modals (like for sorting and filtering) are attached: an overlay will be created on top
of this container, and the modal will be created in the center of this container.
- `{HTMLElement} popupAnchor`
The container element where popups (for example drop down menus, for JSON Schema error
tooltips, and color pickers) will be absolutely positioned.
By default, this is the root DIV element of the editor itself.
When the JSONEditor is inside a DIV element which hides overflowing contents
(CSS `overflow: auto` or `overflow: hidden`), tooltips will be visible only partly.
In this case, a `popupAnchor` outside of the element without hidden overflow will allow
the tooltips to be visible when overflowing the DIV element of the JSONEditor.
- `{boolean} enableSort`
Enable sorting of arrays and object properties. Only applicable for mode 'tree'. `true` by default.
- `{boolean} enableTransform`
Enable filtering, sorting, and transforming JSON using a [JMESPath](http://jmespath.org/) query. Only applicable for mode 'tree'. `true` by default.
- `{Number} maxVisibleChilds`
Number of children allowed for a given node before the "show more / show all" message appears (in 'tree', 'view', or 'form' modes). `100` by default.
- `{ function(json: JSON, queryOptions: QueryOptions) -> string } createQuery`
Create a query string based on query options filled in the Transform Wizard in the Transform modal.
Normally used in combination with `executeQuery`.
The input for the function are the entered query options and the current JSON, and the output
must be a string containing the query. This query will be executed using `executeQuery`.
The query options have the following structure:
```
interface QueryOptions {
filter?: {
field: string | '@'
relation: '==' | '!=' | '<' | '<=' | '>' | '>='
value: string
}
sort?: {
field: string | '@'
direction: 'asc' | 'desc'
}
projection?: {
fields: string[]
}
}
```
Note that there is a special case `'@'` for `filter.field` and `sort.field`.
It means that the field itself is selected, for example when having an array containing numbers.
A usage example can be found in `examples/23_custom_query_language.html`.
- `{ function(json: JSON, query: string) -> JSON } executeQuery`
Replace the build-in query language used in the Transform modal with a custom language.
Normally used in combination with `createQuery`.
The input for the function is the current JSON and a query string, and output must be the transformed JSON.
A usage example can be found in `examples/23_custom_query_language.html`.
- `{string} queryDescription`
A text description displayed on top of the Transform modal.
Can be used to explain a custom query language implemented via `createQuery` and `executeQuery`.
The text can contain HTML code like a link to a web page.
A usage example can be found in `examples/23_custom_query_language.html`.
### Methods
@ -127,66 +669,12 @@ Expand all fields. Only applicable for mode 'tree', 'view', and 'form'.
Set focus to the JSONEditor.
#### `JSONEditor.set(json)`
Set JSON data.
*Parameters:*
- `{JSON} json`
JSON data to be displayed in the JSONEditor.
#### `JSONEditor.setMode(mode)`
Switch mode. Mode `code` requires the [Ace editor](http://ace.ajax.org/).
*Parameters:*
- `{String} mode`
Available values: `tree`, `view`, `form`, `code`, `text`.
#### `JSONEditor.setName(name)`
Set a field name for the root node.
*Parameters:*
- `{String | undefined} name`
Field name of the root node. If undefined, the current name will be removed.
#### `JSONEditor.setSchema(schema)`
Set a JSON schema for validation of the JSON object. See also option `schema`.
See [http://json-schema.org/](http://json-schema.org/) for more information on the JSON schema definition.
*Parameters:*
- `{Object} schema`
A JSON schema.
#### `JSONEditor.setText(jsonString)`
Set text data in the editor.
This method throws an exception when the provided jsonString does not contain
valid JSON and the editor is in mode `tree`, `view`, or `form`.
*Parameters:*
- `{String} jsonString`
Contents of the editor as string.
#### `JSONEditor.get()`
Get JSON data.
This method throws an exception when the editor does not contain valid JSON,
which can be the case when the editor is in mode `code` or `text`.
which can be the case when the editor is in mode `code`, `text`, or `preview`.
*Returns:*
@ -202,7 +690,7 @@ Retrieve the current mode of the editor.
- `{String} mode`
Current mode of the editor for example `tree` or `code`.
Current mode of the editor, for example `tree` or `code`.
#### `JSONEditor.getName()`
@ -214,6 +702,30 @@ Retrieve the current field name of the root node.
Current field name of the root node, or undefined if not set.
#### `JSONEditor.getNodesByRange(start, end)`
A utility function for getting a list of `SerializableNode` under certain range.
This function can be used as complementary to `getSelection` and `onSelectionChange` if a list of __all__ the selected nodes is required.
*Parameters:*
- `{path: Array.<String>} start`
Path for the first node in range
- `{path: Array.<String>} end`
Path for the last node in range
#### `JSONEditor.getSelection()`
Get the current selected nodes, Only applicable for mode 'tree'.
*Returns:*
- `{start:SerializableNode, end: SerializableNode}`
#### `JSONEditor.getText()`
Get JSON data as string.
@ -222,11 +734,166 @@ Get JSON data as string.
- `{String} jsonString`
Contents of the editor as string. When the editor is in code `text` or `code`,
Contents of the editor as string. When the editor is in code `text`, `code` or `preview`,
the returned text is returned as-is. For the other modes, the returned text
is a compacted string. In order to get the JSON formatted with a certain
number of spaces, use `JSON.stringify(JSONEditor.get(), null, 2)`.
#### `JSONEditor.getTextSelection()`
Get the current selected text with the selection range, Only applicable for mode 'text' and 'code'.
*Returns:*
- `{start:{row:Number, column:Number},end:{row:Number, column:Number},text:String} selection`
#### `JSONEditor.refresh()`
Force the editor to refresh the user interface and update all rendered HTML. This can be useful for example when using `onClassName` and the returned class name depends on external factors.
#### `JSONEditor.set(json)`
Set JSON data.
Resets the state of the editor (expanded nodes, search, selection).
See also `JSONEditor.update(json)`.
*Parameters:*
- `{JSON} json`
JSON data to be displayed in the JSONEditor.
#### `JSONEditor.setMode(mode)`
Switch mode. Mode `code` requires the [Ace editor](https://ace.c9.io/).
*Parameters:*
- `{String} mode`
Available values: `tree`, `view`, `form`, `code`, `text`, `preview`.
#### `JSONEditor.setName(name)`
Set a field name for the root node.
*Parameters:*
- `{String | undefined} name`
Field name of the root node. If undefined, the current name will be removed.
#### `JSONEditor.setSchema(schema [,schemaRefs])`
Set a JSON schema for validation of the JSON object. See also option `schema`.
See [http://json-schema.org/](http://json-schema.org/) for more information on the JSON schema definition.
*Parameters:*
- `{Object} schema`
A JSON schema.
- `{Object} schemaRefs`
Optional, Schemas that are referenced using the `$ref` property from the JSON schema, the object structure in the form of `{reference_key: schemaObject}`
#### `JSONEditor.setSelection(start, end)`
Set selection for a range of nodes, Only applicable for mode 'tree'.
- If no parameters sent - the current selection will be removed, if exists.
- For single node selecion send only the `start` parameter.
- If the nodes are not from the same level the first common parent will be selected
*Parameters:*
- `{path: Array.<String>} start`
Path for the start node
- `{path: Array.<String>} end`
Path for the end node
#### `JSONEditor.setText(jsonString)`
Set text data in the editor.
This method throws an exception when the provided jsonString does not contain
valid JSON and the editor is in mode `tree`, `view`, or `form`.
*Parameters:*
- `{String} jsonString`
Contents of the editor as string.
#### `JSONEditor.setTextSelection(startPos, endPos)`
Set text selection for a range, Only applicable for mode 'text' and 'code'.
*Parameters:*
- `{row:Number, column:Number} startPos`
Position for selection start
- `{row:Number, column:Number} endPos`
Position for selection end
#### `JSONEditor.update(json)`
Replace JSON data when the new data contains changes.
In modes `tree`, `form`, and `view`, the state of the editor will be maintained (expanded nodes, search, selection).
See also `JSONEditor.set(json)`.
*Parameters:*
- `{JSON} json`
JSON data to be displayed in the JSONEditor.
#### `JSONEditor.updateText (json)`
Replace text data when the new data contains changes.
In modes `tree`, `form`, and `view`, the state of the editor will be maintained (expanded nodes, search, selection).
Also see `JSONEditor.setText(jsonString)`.
This method throws an exception when the provided jsonString does not contain
valid JSON and the editor is in mode `tree`, `view`, or `form`.
*Parameters:*
- `{String} jsonString`
Contents of the editor as string.
### Static properties
- `{string[]} JSONEditor.VALID_OPTIONS`
An array with the names of all known options.
- `{object} ace`
Access to the bundled Ace editor, via the [`brace` library](https://github.com/thlorenz/brace).
Ace is used in code mode.
Same as `var ace = require('brace');`.
- `{function} Ajv`
Access to the bundled [`ajv` library](https://github.com/epoberezkin/ajv), used for JSON schema validation.
Same as `var Ajv = require('ajv');`.
- `{function} VanillaPicker`
Access to the bundled [`vanilla-picker` library](https://github.com/Sphinxxxx/vanilla-picker), used as color picker.
Same as `var VanillaPicker = require('vanilla-picker');`.
### Examples
@ -275,7 +942,7 @@ var json = editor.get();
## 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);

25
docs/styling.md Normal file
View File

@ -0,0 +1,25 @@
# Styling Reference
Documentation for writing custom JSON Editor styles.
## Node
Node is the fundamental unit that makes up the hierarchical JSON display in the Form, Tree, and View modes. It can be
customized with several classes that reflect its type and state.
- `jsoneditor-field`: the property name
- `jsoneditor-value`: the value of the property
- The value element will have one of the following classes depending on its type:
- `jsoneditor-null`
- `jsoneditor-undefined`
- `jsoneditor-number`
- `jsoneditor-string`
- `jsoneditor-string jsoneditor-color-value`
- `jsoneditor-boolean`
- `jsoneditor-regexp`
- `jsoneditor-array`
- `jsoneditor-object`
- `jsoneditor-url`
- `jsoneditor-is-default`: applied to the value element when the value matches the default from the schema
- `jsoneditor-is-not-default`: applied to the value element when the value does not match the default from the schema
- `jsoneditor-schema-error`: the warning icon that appears when the Node has a schema validation error
- `jsoneditor-popover`: the popover that appears when hovering over the schema validation error warning icon

View File

@ -2,21 +2,10 @@
### Install
with npm:
Install via npm:
npm install jsoneditor
with bower:
bower install jsoneditor
download:
[http://jsoneditoronline.org/downloads/](http://jsoneditoronline.org/downloads/)
The library consists of three files: one javascript file, one css file and an
image. Both full and minified version are available.
## Load
To implement JSONEditor in a web application, load the javascript and css file
@ -29,7 +18,7 @@ in the head of the HTML page:
## Use
In the body, create an div element with an id and a size:
In the body, create a div element with an id and a size:
```html
<div id="jsoneditor" style="width: 400px; height: 400px;"></div>
@ -70,10 +59,10 @@ var json = editor.get();
```html
<!DOCTYPE HTML>
<html>
<html lang="en">
<head>
<!-- when using the mode "code", it's important to specify charset utf-8 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta charset="utf-8">
<link href="jsoneditor/dist/jsoneditor.min.css" rel="stylesheet" type="text/css">
<script src="jsoneditor/dist/jsoneditor.min.js"></script>

View File

@ -1,6 +1,8 @@
<!DOCTYPE HTML>
<html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | Basic usage</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
@ -22,28 +24,31 @@
<script>
// create the editor
var container = document.getElementById('jsoneditor');
var options = {};
var editor = new JSONEditor(container, options);
const container = document.getElementById('jsoneditor')
const options = {}
const editor = new JSONEditor(container, options)
// set json
document.getElementById('setJSON').onclick = function () {
var json = {
const json = {
'array': [1, 2, 3],
'boolean': true,
'color': '#82b92c',
'null': null,
'number': 123,
'object': {'a': 'b', 'c': 'd'},
'string': 'Hello World'
};
editor.set(json);
};
'time': 1575599819000,
'string': 'Hello World',
'onlineDemo': 'https://jsoneditoronline.org/'
}
editor.set(json)
}
// get json
document.getElementById('getJSON').onclick = function () {
var json = editor.get();
alert(JSON.stringify(json, null, 2));
};
const json = editor.get()
alert(JSON.stringify(json, null, 2))
}
</script>
</body>
</html>

View File

@ -1,6 +1,8 @@
<!DOCTYPE HTML>
<html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | Viewer</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
@ -23,22 +25,22 @@
<div id="jsoneditor"></div>
<script>
var container = document.getElementById('jsoneditor');
const container = document.getElementById('jsoneditor')
var options = {
const options = {
mode: 'view'
};
}
var json = {
const json = {
'array': [1, 2, 3],
'boolean': true,
'null': null,
'number': 123,
'object': {'a': 'b', 'c': 'd'},
'string': 'Hello World'
};
}
var editor = new JSONEditor(container, options, json);
const editor = new JSONEditor(container, options, json)
</script>
</body>
</html>

View File

@ -1,10 +1,10 @@
<!DOCTYPE HTML>
<html>
<html lang="en">
<head>
<title>JSONEditor | Switch mode</title>
<!-- when using the mode "code", it's important to specify charset utf-8 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta charset="utf-8">
<title>JSONEditor | Switch mode</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
@ -38,29 +38,29 @@
<div id="jsoneditor"></div>
<script>
var container = document.getElementById('jsoneditor');
const container = document.getElementById('jsoneditor')
var options = {
const options = {
mode: 'tree',
modes: ['code', 'form', 'text', 'tree', 'view'], // allowed modes
modes: ['code', 'form', 'text', 'tree', 'view', 'preview'], // allowed modes
onError: function (err) {
alert(err.toString());
alert(err.toString())
},
onModeChange: function (newMode, oldMode) {
console.log('Mode switched from', oldMode, 'to', newMode);
console.log('Mode switched from', oldMode, 'to', newMode)
}
};
}
var json = {
const json = {
"array": [1, 2, 3],
"boolean": true,
"null": null,
"number": 123,
"object": {"a": "b", "c": "d"},
"string": "Hello World"
};
}
var editor = new JSONEditor(container, options, json);
const editor = new JSONEditor(container, options, json)
</script>
</body>
</html>

View File

@ -1,6 +1,8 @@
<!DOCTYPE HTML>
<html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | Load and save</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
@ -38,36 +40,36 @@
<script>
// create the editor
var editor = new JSONEditor(document.getElementById('jsoneditor'));
const 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);
editor.setText(event.target.result)
}
}
});
})
// Save a JSON document
document.getElementById('saveDocument').onclick = function () {
// Save Dialog
fname = window.prompt("Save as...");
let fname = window.prompt("Save as...")
// Check json extension in file name
if(fname.indexOf(".")==-1){
fname = fname + ".json";
}else{
if(fname.split('.').pop().toLowerCase() == "json"){
if (fname.indexOf(".") === -1) {
fname = fname + ".json"
} else {
if (fname.split('.').pop().toLowerCase() === "json") {
// Nothing to do
}else{
fname = fname.split('.')[0] + ".json";
} else {
fname = fname.split('.')[0] + ".json"
}
}
var blob = new Blob([editor.getText()], {type: 'application/json;charset=utf-8'});
saveAs(blob, fname);
};
const blob = new Blob([editor.getText()], {type: 'application/json;charset=utf-8'})
saveAs(blob, fname)
}
</script>
</body>
</html>

View File

@ -1,6 +1,8 @@
<!DOCTYPE HTML>
<html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | Custom editable fields</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
@ -25,9 +27,9 @@
<div id="jsoneditor"></div>
<script>
var container = document.getElementById('jsoneditor');
const container = document.getElementById('jsoneditor')
var options = {
const options = {
onEditable: function (node) {
// node is an object like:
// {
@ -37,27 +39,27 @@
// }
switch (node.field) {
case '_id':
return false;
return false
case 'name':
return {
field: false,
value: true
};
}
default:
return true;
return true
}
}
};
}
var json = {
const json = {
_id: 123456,
name: 'John',
age: 32
};
}
var editor = new JSONEditor(container, options, json);
const editor = new JSONEditor(container, options, json)
</script>
</body>
</html>

View File

@ -1,51 +1,53 @@
<!DOCTYPE HTML>
<html>
<html lang="en">
<head>
<title>JSONEditor | Custom styling</title>
<meta charset="utf-8">
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<title>JSONEditor | Custom styling</title>
<style type="text/css">
#jsoneditor {
width: 500px;
height: 500px;
}
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
p {
width: 500px;
font-family: "DejaVu Sans", sans-serif;
}
</style>
<style type="text/css">
#jsoneditor {
width: 500px;
height: 500px;
}
<link href="./css/darktheme.css" rel="stylesheet" type="text/css">
p {
width: 500px;
font-family: "DejaVu Sans", sans-serif;
}
</style>
<link href="./css/darktheme.css" rel="stylesheet" type="text/css">
</head>
<body>
<p>
This example demonstrates how to customize the look of JSONEditor,
the editor below has a dark theme. Note that the example isn't worked
out for the mode <code>code</code>. To do that, you can load and configure
a custom theme for the Ace editor.
This example demonstrates how to customize the look of JSONEditor,
the editor below has a dark theme. Note that the example isn't worked
out for the mode <code>code</code>. To do that, you can load and configure
a custom theme for the Ace editor.
</p>
<div id="jsoneditor"></div>
<script>
// create the editor
var container = document.getElementById('jsoneditor');
var options = {
modes: ['text', 'tree']
};
var json = {
const container = document.getElementById('jsoneditor')
const options = {
modes: ['tree', 'text']
}
const json = {
'array': [1, 2, 3],
'boolean': true,
'null': null,
'number': 123,
'object': {'a': 'b', 'c': 'd'},
'string': 'Hello World'
};
var editor = new JSONEditor(container, options, json);
}
const editor = new JSONEditor(container, options, json)
</script>
</body>
</html>

View File

@ -1,6 +1,8 @@
<!DOCTYPE HTML>
<html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | JSON schema validation</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
@ -16,12 +18,16 @@
height: 500px;
}
/* custom bold styling for non-default JSON schema values */
.jsoneditor-is-not-default {
font-weight: bold;
}
</style>
</head>
<body>
<h1>JSON schema validation</h1>
<p>
This example demonstrates JSON schema validation. The JSON object in this example must contain properties <code>firstName</code> and <code>lastName</code>, can can optionally have a property <code>age</code> which must be a positive integer.
This example demonstrates JSON schema validation. The JSON object in this example must contain properties like <code>firstName</code> and <code>lastName</code>, can can optionally have a property <code>age</code> which must be a positive integer.
</p>
<p>
See <a href="http://json-schema.org/" target="_blank">http://json-schema.org/</a> for more information.
@ -30,42 +36,103 @@
<div id="jsoneditor"></div>
<script>
var schema = {
"title": "Example Schema",
const schema = {
"title": "Employee",
"description": "Object containing employee details",
"type": "object",
"properties": {
"firstName": {
"title": "First Name",
"description": "The given name.",
"examples": [
"John"
],
"type": "string"
},
"lastName": {
"title": "Last Name",
"description": "The family name.",
"examples": [
"Smith"
],
"type": "string"
},
"gender": {
"title": "Gender",
"enum": ["male", "female"]
},
"availableToHire": {
"type": "boolean",
"default": false
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
"minimum": 0,
"examples": [28, 32]
},
"job": {
"$ref": "job"
}
},
"required": ["firstName", "lastName"]
};
}
var json = {
const job = {
"title": "Job description",
"type": "object",
"required": ["address"],
"properties": {
"company": {
"type": "string",
"examples": [
"ACME",
"Dexter Industries"
]
},
"role": {
"description": "Job title.",
"type": "string",
"examples": [
"Human Resources Coordinator",
"Software Developer"
],
"default": "Software Developer"
},
"address": {
"type": "string"
},
"salary": {
"type": "number",
"minimum": 120,
"examples": [100, 110, 120]
}
}
}
const json = {
firstName: 'John',
lastName: 'Doe',
gender: null,
age: 28
};
age: "28",
availableToHire: true,
job: {
company: 'freelance',
role: 'developer',
salary: 100
}
}
var options = {
schema: schema
};
const options = {
schema: schema,
schemaRefs: {"job": job},
mode: 'tree',
modes: ['code', 'text', 'tree', 'preview']
}
// create the editor
var container = document.getElementById('jsoneditor');
var editor = new JSONEditor(container, options, json);
const container = document.getElementById('jsoneditor')
const editor = new JSONEditor(container, options, json)
</script>
</body>
</html>

View File

@ -0,0 +1,74 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | Custom Ace</title>
<!-- load a custom version of Ace editor -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ace.js"></script>
<!-- load the minimalist version of JSONEditor, which doesn't have Ace embedded -->
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor-minimalist.js"></script>
<style type="text/css">
#jsoneditor {
width: 500px;
height: 500px;
}
body, html {
font-family: "DejaVu Sans", sans-serif;
}
p, li {
width: 500px;
font-size: 10.5pt;
}
code {
background: #f5f5f5;
}
</style>
</head>
<body>
<h1>Custom Ace editor</h1>
<p>
This example demonstrates how to load a custom version of Ace editor into JSONEditor.
</p>
<p>
By default, JSONEditor <code>code</code> mode loads the following Ace plugins:
</p>
<ul>
<li>ace/mode/json</li>
<li>ace/ext/searchbox</li>
<li>ace/theme/jsoneditor</li>
</ul>
<p>
The jsoneditor theme comes embedded with JSONEditor. The other two plugins (json and searchbox) must be available in the folder of the custom Ace editor, or already be loaded via a script tag.
</p>
<div id="jsoneditor"></div>
<script>
// create the editor
const container = document.getElementById('jsoneditor')
const options = {
modes: ['text', 'code', 'tree', 'form', 'view'],
mode: 'code',
ace: ace
}
const json = {
'array': [1, 2, 3],
'boolean': true,
'null': null,
'number': 123,
'object': {'a': 'b', 'c': 'd'},
'string': 'Hello World'
}
const editor = new JSONEditor(container, options, json)
</script>
</body>
</html>

View File

@ -0,0 +1,73 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<!-- when using the mode "code", it's important to specify charset utf-8 -->
<meta charset="utf-8">
<title>JSONEditor | Switch mode</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<style type="text/css">
body {
font: 10.5pt arial;
color: #4d4d4d;
line-height: 150%;
width: 500px;
}
code {
background-color: #f5f5f5;
}
#jsoneditor {
width: 500px;
height: 500px;
}
</style>
</head>
<body>
<p>
Switch editor mode using the mode box.
Note that the mode can be changed programmatically as well using the method
<code>editor.setMode(mode)</code>, try it in the console of your browser.
</p>
<div id="jsoneditor"></div>
<script>
const container = document.getElementById('jsoneditor')
const options = {
mode: 'text',
modes: ['text', 'code'],
onEditable: function (node) {
if (!node.path) {
// In modes code and text, node is empty: no path, field, or value
// returning false makes the text area read-only
return false;
}
},
onError: function (err) {
alert(err.toString())
},
onModeChange: function (newMode, oldMode) {
console.log('Mode switched from', oldMode, 'to', newMode)
}
}
const json = {
"array": [1, 2, 3],
"boolean": true,
"null": null,
"number": 123,
"object": {"a": "b", "c": "d"},
"string": "Hello World"
}
const editor = new JSONEditor(container, options, json)
</script>
</body>
</html>

View File

@ -0,0 +1,73 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | Item templates</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<style type="text/css">
body {
width: 600px;
font: 11pt sans-serif;
}
#jsoneditor {
width: 100%;
height: 500px;
}
</style>
</head>
<body>
<h1>Item templates</h1>
<p>
Using item templates, the options in the context menu under "insert" and "append" can be extended with extra options, containing a domain specific template like a "Person", "Contact", "Order", "Address", etc.
</p>
<div id="jsoneditor"></div>
<script>
const json = [
{
firstName: 'John',
lastName: 'Doe',
age: 28
}
]
const options = {
templates: [
{
text: 'Person',
title: 'Insert a Person Node',
className: 'jsoneditor-type-object',
field: 'PersonTemplate',
value: {
'firstName': 'John',
'lastName': 'Do',
'age': 28
}
},
{
text: 'Address',
title: 'Insert a Address Node',
field: 'AddressTemplate',
value: {
'street': '',
'city': '',
'state': '',
'ZIP code': ''
}
}
]
}
// create the editor
const container = document.getElementById('jsoneditor')
const editor = new JSONEditor(container, options, json)
editor.expandAll()
</script>
</body>
</html>

View File

@ -0,0 +1,52 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | Auto Complete</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;
}
p {
width: 500px;
font-family: "DejaVu Sans", sans-serif;
}
</style>
</head>
<body>
<p>
This example demonstrates how to autocomplete works, options available are: 'apple','cranberry','raspberry','pie', 'mango', 'mandarine', 'melon', 'appleton'.
</p>
<div id="jsoneditor"></div>
<script>
// create the editor
const container = document.getElementById('jsoneditor')
const options = {
autocomplete: {
getOptions: function () {
return ['apple', 'cranberry', 'raspberry', 'pie', 'mango', 'mandarine', 'melon', 'appleton'];
}
}
}
const json = {
'array': [{'field1':'v1', 'field2':'v2'}, 2, 3],
'boolean': true,
'null': null,
'number': 123,
'object': {'a': 'b', 'c': 'd'},
'string': 'Hello World'
}
const editor = new JSONEditor(container, options, json)
</script>
</body>
</html>

View File

@ -0,0 +1,73 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | Dynamic Auto Complete</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<style type="text/css">
#jsoneditor {
width: 500px;
height: 500px;
}
p {
width: 500px;
font-family: "DejaVu Sans", sans-serif;
}
</style>
</head>
<body>
<p>
This example demonstrates how to autocomplete works, options available are dynamics and consist in all the strings found in the json
</p>
<div id="jsoneditor"></div>
<script>
// create the editor
const container = document.getElementById('jsoneditor')
const options = {
autocomplete: {
applyTo:['value'],
filter: 'contain',
trigger: 'focus',
getOptions: function (text, path, input, editor) {
return new Promise(function (resolve, reject) {
const options = extractUniqueWords(editor.get())
if (options.length > 0) {
resolve(options)
} else {
reject()
}
})
}
}
}
// helper function to extract all unique words in the keys and values of a JSON object
function extractUniqueWords (json) {
return _.uniq(_.flatMapDeep(json, function (value, key) {
return _.isObject(value)
? [key]
: [key, String(value)]
}))
}
const json = {
'array': [{'field1':'v1', 'field2':'v2'}, 2, 3],
'boolean': true,
'null': null,
'number': 123,
'object': {'a': 'b', 'c': 'd'},
'string': 'Hello World'
}
const editor = new JSONEditor(container, options, json)
</script>
</body>
</html>

View File

@ -0,0 +1,109 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | Advanced Auto Complete</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<script src="https://unpkg.com/jsonpath@0.2.11/jsonpath.min.js"></script>
<style type="text/css">
#jsoneditor {
width: 500px;
height: 500px;
}
p {
width: 500px;
font-family: "DejaVu Sans", sans-serif;
}
</style>
</head>
<body>
<p>
This example demonstrates how to autocomplete works with an ActivationChar option, press "*" in any value and continue with autocompletion.
The autocomplete returns the posible jsonpaths of the existing json document, for example <code>*object.a</code>.
</p>
<div id="jsoneditor"></div>
<script>
// create the editor
const container = document.getElementById('jsoneditor')
const activationChar = '*'
const options = {
autocomplete: {
confirmKeys: [39, 35, 9, 190], // Confirm Autocomplete Keys: [right, end, tab, '.'] // By default are only [right, end, tab]
caseSensitive: false,
getOptions: function (text, path, input, editor) {
if (!text.startsWith(activationChar) || input !== 'value') return []
let data = {}
let startFrom = 0
const lastPoint = text.lastIndexOf('.')
const jsonObj = editor.get()
if ((lastPoint > 0) && (text.length > 1)) {
data = jsonpath.query(jsonObj, '$.' + text.substring(activationChar.length, lastPoint))
if (data.length > 0) {
data = data[0]
} else {
data = {}
}
// Indicate that autocompletion should start after the . (ignoring the first part)
startFrom = text.lastIndexOf('.') + 1
} else {
data = jsonObj
}
const optionsStr = YaskON.stringify(data, null, activationChar)
const options = optionsStr.split('\n')
return { startFrom: startFrom, options: options }
}
}
}
// helper function to auto complete paths of a JSON object
const YaskON = {
// Return first level json paths by the node 'o'
stringify: function (o, prefix, activationChar) {
prefix = prefix || ''
switch (typeof o) {
case 'object':
let output = ''
if (Array.isArray(o)) {
o.forEach(function (e, index) {
output += activationChar + prefix + '[' + index + ']' + '\n'
}.bind(this))
return output
}
output = ''
for (let k in o) {
if (o.hasOwnProperty(k)) {
if (prefix === '') output += this.stringify(o[k], k, activationChar)
}
}
if (prefix !== '') output += activationChar + prefix + '\n'
return output
case 'function':
return ''
default:
return prefix + '\n'
}
}
}
const json = {
'array': [{ 'field1': 'v1', 'field2': 'v2' }, 2, 3],
'boolean': true,
'null': null,
'number': 123,
'object': { 'a': 'b', 'c': 'd' },
'string': 'Hello World'
}
const editor = new JSONEditor(container, options, json)
</script>
</body>
</html>

View File

@ -0,0 +1,57 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<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
const container = document.getElementById('jsoneditor')
const 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'
}
}
}
const editor = new JSONEditor(container, options)
const 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>

View File

@ -0,0 +1,124 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<style type="text/css">
body {
font: 10.5pt arial;
color: #4d4d4d;
line-height: 150%;
width: 500px;
padding-left: 40px;
}
code {
background-color: #f5f5f5;
}
code.multiline {
display: block;
white-space: pre-wrap
}
#jsoneditor {
width: 500px;
height: 500px;
}
</style>
</head>
<body>
<p>
Selection indication was done using the <code>on[Text]SelectionChange</code> listeners.<br/>
you can try the following calls in the console of your browser:<br/>
<code class="multiline">
// text and code modes:
editor.getTextSelection()
editor.setTextSelection(startPos, endPos)
// tree mode:
editor.getSelection()
editor.setSelection(startNode, endNode)
</code>
</p>
<form>
<div id="jsoneditor"></div>
<div id="textModeSelection" style="display:none;">
<b>Selection:</b><div id="textRange"></div>
<b>Text:</b><div id="selectedText"></div>
</div>
<div id="treeModeSelection">
<b>Selection:</b>
<div id="selectedNodes"></div>
</div>
</form>
<script>
const container = document.getElementById('jsoneditor')
const options = {
mode: 'tree',
modes: ['code', 'form', 'text', 'tree', 'view', 'preview'], // allowed modes
onError: function (err) {
alert(err.toString())
},
onChange: function () {
console.log('change')
},
onModeChange: function (mode) {
const treeMode = document.getElementById('treeModeSelection')
const textMode = document.getElementById('textModeSelection')
treeMode.style.display = textMode.style.display = 'none'
if (mode === 'code' || mode === 'text') {
textMode.style.display = 'inline'
} else {
treeMode.style.display = 'inline'
}
},
indentation: 4,
escapeUnicode: true,
onTextSelectionChange: function(start, end, text) {
const rangeEl = document.getElementById('textRange')
rangeEl.innerHTML = 'start: ' + JSON.stringify(start) + ', end: ' + JSON.stringify(end)
const textEl = document.getElementById('selectedText')
textEl.innerHTML = text
},
onSelectionChange: function(start, end) {
const nodesEl = document.getElementById('selectedNodes')
nodesEl.innerHTML = ''
if (start) {
nodesEl.innerHTML = ('start: ' + JSON.stringify(start))
if (end) {
nodesEl.innerHTML += ('<br/>end: ' + JSON.stringify(end))
}
}
}
}
const json = {
"array": [1, 2, [3,4,5]],
"boolean": true,
"htmlcode": '&quot;',
"escaped_unicode": '\\u20b9',
"unicode": '\u20b9,\uD83D\uDCA9',
"return": '\n',
"null": null,
"number": 123,
"object": {"a": "b", "c": "d"},
"string": "Hello World",
"url": "http://jsoneditoronline.org"
}
window.editor = new JSONEditor(container, options, json)
console.log('json', json)
console.log('string', JSON.stringify(json))
</script>
</body>
</html>

View File

@ -0,0 +1,66 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | Synchronize two editors</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<style type="text/css">
body {
font-family: sans-serif;
}
#jsoneditor1,
#jsoneditor2 {
width: 500px;
height: 500px;
margin-right: 10px;
display: inline-block;
}
</style>
</head>
<body>
<p>
Keep two editors synchronized using <code>onChangeText</code> and <code>updateText</code>.
</p>
<p>
This can be done too with <code>onChangeJSON</code> and <code>update</code>, which can only be used in
modes <code>tree</code>, <code>form</code> (and <code>view</code>).
</p>
<div id="jsoneditor1"></div>
<div id="jsoneditor2"></div>
<script>
// create editor 1
const editor1 = new JSONEditor(document.getElementById('jsoneditor1'), {
onChangeText: function (jsonString) {
editor2.updateText(jsonString)
}
})
// create editor 2
const editor2 = new JSONEditor(document.getElementById('jsoneditor2'), {
onChangeText: function (jsonString) {
editor1.updateText(jsonString)
}
})
// set initial data in both editors
const json = {
'array': [1, 2, 3],
'boolean': true,
'null': null,
'number': 123,
'object': {'a': 'b', 'c': 'd'},
'string': 'Hello World'
}
editor1.set(json)
editor2.set(json)
</script>
</body>
</html>

View File

@ -0,0 +1,96 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<style type="text/css">
body {
font: 10.5pt arial;
color: #4d4d4d;
line-height: 150%;
width: 500px;
padding-left: 40px;
}
code {
background-color: #f5f5f5;
}
#jsoneditor {
width: 500px;
height: 500px;
}
</style>
</head>
<body>
<p>
When clicking on a JSON field or value, a log message will be shown in
console.
</p>
<form>
<div id="jsoneditor"></div>
</form>
<script>
const container = document.getElementById('jsoneditor')
const options = {
mode: 'tree',
modes: ['code', 'form', 'text', 'tree', 'view', 'preview'], // allowed modes
name: "jsonContent",
onError: function (err) {
alert(err.toString())
},
onEvent: function(node, event) {
if (event.type === 'click') {
let message = 'click on <' + node.field +
'> under path <' + node.path +
'> with pretty path: <' + prettyPrintPath(node.path) + '>'
if (node.value) {
message += ' with value <' + node.value + '>'
}
console.log(message)
}
function prettyPrintPath(path) {
let str = ''
for (let i=0; i<path.length; i++) {
const element = path[i]
if (typeof element === 'number') {
str += '[' + element + ']'
} else {
if (str.length > 0) str += ','
str += element
}
}
return str
}
}
}
const json = {
"array": [1, 2, [3,4,5]],
"boolean": true,
"htmlcode": '&quot;',
"escaped_unicode": '\\u20b9',
"unicode": '\u20b9,\uD83D\uDCA9',
"return": '\n',
"null": null,
"number": 123,
"object": {"a": "b", "c": "d", "e": [1, 2, 3]},
"string": "Hello World",
"url": "http://jsoneditoronline.org",
"[0]": "zero"
}
window.editor = new JSONEditor(container, options, json)
console.log('json', json)
console.log('string', JSON.stringify(json))
</script>
</body>
</html>

View File

@ -0,0 +1,109 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | Custom validation</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<style type="text/css">
body {
width: 600px;
font: 11pt sans-serif;
}
#jsoneditor {
width: 100%;
height: 500px;
}
</style>
</head>
<body>
<h1>Custom validation</h1>
<p>
This example demonstrates how to run custom validation on a JSON object.
The validation is available in all modes.
</p>
<div id="jsoneditor"></div>
<script>
const json = {
team: [
{
name: 'Joe',
age: 17
},
{
name: 'Sarah',
age: 13
},
{
name: 'Jack'
}
]
}
const options = {
mode: 'tree',
modes: ['code', 'text', 'tree', 'preview'],
onValidate: function (json) {
// rules:
// - team, names, and ages must be filled in and be of correct type
// - a team must have 4 members
// - at lease one member of the team must be adult
const errors = []
if (json && Array.isArray(json.team)) {
// check whether each team member has name and age filled in correctly
json.team.forEach(function (member, index) {
if (typeof member !== 'object') {
errors.push({path: ['team', index], message: 'Member must be an object with properties "name" and "age"'})
}
if ('name' in member) {
if (typeof member.name !== 'string') {
errors.push({path: ['team', index, 'name'], message: 'Name must be a string'})
}
} else {
errors.push({path: ['team', index], message: 'Required property "name"" missing'})
}
if ('age' in member) {
if (typeof member.age !== 'number') {
errors.push({path: ['team', index, 'age'], message: 'Age must be a number'})
}
} else {
errors.push({path: ['team', index], message: 'Required property "age" missing'})
}
})
// check whether the team consists of exactly four members
if (json.team.length !== 4) {
errors.push({path: ['team'], message: 'A team must have 4 members'})
}
// check whether there is at least one adult member in the team
const adults = json.team.filter(function (member) {
return member ? member.age >= 18 : false
})
if (adults.length === 0) {
errors.push({path: ['team'], message: 'A team must have at least one adult person (age >= 18)'})
}
} else {
errors.push({path: [], message: 'Required property "team" missing or not an Array'})
}
return errors
}
}
// create the editor
const container = document.getElementById('jsoneditor')
const editor = new JSONEditor(container, options, json)
editor.expandAll()
</script>
</body>
</html>

View File

@ -0,0 +1,92 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | Custom validation (asynchronous)</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<style type="text/css">
body {
width: 600px;
font: 11pt sans-serif;
}
#jsoneditor {
width: 100%;
height: 500px;
}
</style>
</head>
<body>
<h1>Asynchronous custom validation</h1>
<p>
This example demonstrates how to run asynchronous custom validation on a JSON object.
The names are checked asynchronously and the results "come in" half a second later.
Known names in this example are 'Joe', 'Harry', 'Megan'. For other names, a validation error will be displayed.
</p>
<div id="jsoneditor"></div>
<script>
const json = {
customers: [
{name: 'Joe'},
{name: 'Sarah'},
{name: 'Harry'},
]
}
const options = {
mode: 'tree',
modes: ['code', 'text', 'tree', 'preview'],
onValidate: function (json) {
// in this validation function we fake sending a request to a server
// to validate the existence of customers
if (json && Array.isArray(json.customers)) {
return Promise
.all(json.customers.map(function (customer, index) {
return isExistingCustomer(customer && customer.name).then(function (exists) {
if (!exists) {
return {
path: ['customers', index],
message: 'Customer ' + customer.name + ' doesn\'t exist in our database'
}
}
else {
return null
}
})
}))
.then(function (errors) {
return errors.filter(function (error) {
return error != null
})
})
}
else {
return null
}
}
}
// create the editor
const container = document.getElementById('jsoneditor')
const editor = new JSONEditor(container, options, json)
editor.expandAll()
// this function fakes a request (asynchronous) to a server to validate the existence of a customer
function isExistingCustomer (customerName) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
const customers = ['Joe', 'Harry', 'Megan']
const exists = customers.indexOf(customerName) !== -1
resolve(exists)
}, 500)
})
}
</script>
</body>
</html>

View File

@ -0,0 +1,160 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<style type="text/css">
body {
font: 10.5pt arial;
color: #4d4d4d;
line-height: 150%;
width: 100%;
padding-left: 10px;
}
code {
background-color: #f5f5f5;
}
#containerLeft {
display: inline-block;
width: 500px;
height: 500px;
margin-right: 10px;
}
#containerRight {
display: inline-block;
width: 500px;
height: 500px;
}
#containerRight .different_element {
background-color: #acee61;
}
#containerRight .different_element div.jsoneditor-field,
#containerRight .different_element div.jsoneditor-value {
color: red;
}
#containerLeft .different_element {
background-color: pink;
}
#containerLeft .different_element div.jsoneditor-field,
#containerLeft .different_element div.jsoneditor-value {
color: red;
}
</style>
</head>
<body>
<h3>JSON Diff</h3>
<p>
This example highlights the differences between two JSON objects using the option <code>onClassName</code>.
Make a change in the left or right editor to see the changes update accordingly.
</p>
<div id="wrapper">
<div id="containerLeft"></div>
<div id="containerRight"></div>
</div>
<script>
const containerLeft = document.getElementById('containerLeft')
const containerRight = document.getElementById('containerRight')
function findNodeInJson(json, path){
if(!json || path.length ===0) {
return {field: undefined, value: undefined}
}
const first = path[0]
const remainingPath = path.slice(1)
if(remainingPath.length === 0) {
return {field: (typeof json[first] !== 'undefined' ? first : undefined), value: json[first]}
} else {
return findNodeInJson(json[first], remainingPath)
}
}
function onClassName({ path, field, value }) {
const thisNode = findNodeInJson(jsonRight, path)
const oppositeNode = findNodeInJson(jsonLeft, path)
let isValueEqual = JSON.stringify(thisNode.value) === JSON.stringify(oppositeNode.value)
if(Array.isArray(thisNode.value) && Array.isArray(oppositeNode.value)) {
isValueEqual = thisNode.value.every(function (e) {
return oppositeNode.value.includes(e)
})
}
if (thisNode.field === oppositeNode.field && isValueEqual) {
return 'the_same_element'
} else {
return 'different_element'
}
}
const optionsLeft = {
mode: 'tree',
onError: function (err) {
alert(err.toString())
},
onClassName: onClassName,
onChangeJSON: function (j) {
jsonLeft = j
window.editorRight.refresh()
}
}
const optionsRight = {
mode: 'tree',
onError: function (err) {
alert(err.toString())
},
onClassName: onClassName,
onChangeJSON: function (j) {
jsonRight = j
window.editorLeft.refresh()
}
}
let jsonLeft = {
"arrayOfArrays": [1, 2, 999, [3,4,5]],
"someField": true,
"boolean": true,
"htmlcode": '&quot;',
"escaped_unicode": '\\u20b9',
"unicode": '\u20b9,\uD83D\uDCA9',
"return": '\n',
"null": null,
"thisObjectDoesntExistOnTheRight" : {key: "value"},
"number": 123,
"object": {"a": "b","new":4, "c": "d", "e": [1, 2, 3]},
"string": "Hello World",
"url": "http://jsoneditoronline.org",
"[0]": "zero"
}
let jsonRight = {
"arrayOfArrays": [1, 2, [3,4,5]],
"boolean": true,
"htmlcode": '&quot;',
"escaped_unicode": '\\u20b9',
"thisFieldDoesntExistOnTheLeft": 'foobar',
"unicode": '\u20b9,\uD83D\uDCA9',
"return": '\n',
"null": null,
"number": 123,
"object": {"a": "b", "c": "d", "e": [1, 2, 3]},
"string": "Hello World",
"url": "http://jsoneditoronline.org",
"[0]": "zero"
}
window.editorLeft = new JSONEditor(containerLeft, optionsLeft, jsonLeft)
window.editorRight = new JSONEditor(containerRight, optionsRight, jsonRight)
</script>
</body>
</html>

View File

@ -0,0 +1,148 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | Basic usage</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;
}
.submenu-highlight {
background-color: yellow !important;
}
.rainbow {
background: linear-gradient(to right, cyan, yellow, violet, green, orange, blue) !important;
}
.example-class > .jsoneditor-icon {
background-position: -168px -48px; /* warning triangle */
}
.dotty {
border-top : 1px dotted #e5e5e5 !important;
}
</style>
</head>
<body>
<h1>Context Menu Customization</h1>
<p>
This example demonstrates the use of the onCreateMenu callback option, which
allows you to customise context menus after they are created but before they
are shown to the user. You can alter/delete existing items as well as
adding new menu items. See the source code for this example for more
information.
</p>
<div id="jsoneditor"></div>
<script>
// create the editor
const container = document.getElementById('jsoneditor')
const options = {
// onCreateMenu allows us to register a call back function to customise
// the context menu. The callback accpets two parameters, items and path.
// Items is an array containing the current menu items, and path
// (if present) contains the path of the current node (as an array).
// The callback should return the modified (or unmodified) list of menu
// items.
// Every time the user clicks on a context menu button, the menu
// is created from scratch and this callback is called.
onCreateMenu: function (items, node) {
const path = node.path
// log the current items and node for inspection
console.log('items:', items, 'node:', node)
// We are going to add a menu item which returns the current node path
// as a jq path selector ( https://stedolan.github.io/jq/ ). First we
// will create a function, and then We will connect this function to
// the menu item click property in a moment.
function pathTojq() {
let pathString = ''
path.forEach(function (segment, index) { // path is an array, loop through it
if (typeof segment == 'number') { // format the selector for array indexs ...
pathString += '[' + segment + ']'
} else { // ... or object keys
pathString += '."' + segment + '"'
}
})
alert(pathString) // show it to the user.
}
// Create a new menu item. For our example, we only want to do this
// if there is a path (in the case of appendnodes (for new objects)
// path is null until a node is created)
if (path) {
// Each item in the items array represents a menu item,
// and requires the following details :
items.push({
text: 'jq Path', // the text for the menu item
title: 'Show the jq path for this node', // the HTML title attribute
className: 'example-class', // the css class name(s) for the menu item
click: pathTojq // the function to call when the menu item is clicked
})
}
// Now we will iterate through the menu items, which includes the items
// created by jsoneditor, and the new item we added above. In this
// example we will just alter the className property for the items, but
// you can alter any property (e.g. the click callback, text property etc.)
// for any item, or even delete the whole menu item.
items.forEach(function (item, index, items) {
if ("submenu" in item) {
// if the item has a submenu property, it is a submenu heading
// and contains another array of menu items. Let's colour
// that yellow...
items[index].className += ' submenu-highlight'
} else {
// if it's not a submenu heading, let's make it colorful
items[index].className += ' rainbow'
}
})
// note that the above loop isn't recursive, so it only alters the classes
// on the top-level menu items. To also process menu items in submenus
// you should iterate through any "submenu" arrays of items if the item has one.
// next, just for fun, let's remove any menu separators (again just at the
// top level menu). A menu separator is an item with a type : 'separator'
// property
items = items.filter(function (item) {
return item.type !== 'separator'
})
// finally we need to return the items array. If we don't, the menu
// will be empty.
return items
}
}
const json = {
'array': [1, 2, 3],
'boolean': true,
'color': '#82b92c',
'null': null,
'number': 123,
'object': {'a': 'b', 'c': 'd'},
'string': 'Hello World'
}
const editor = new JSONEditor(container, options, json)
</script>
</body>
</html>

View File

@ -0,0 +1,153 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | onValidationError</title>
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<style type="text/css">
body {
width: 600px;
font: 11pt sans-serif;
}
#jsoneditor {
width: 100%;
height: 500px;
}
#onValidationOutput {
margin: 5px;
}
/* custom bold styling for non-default JSON schema values */
.jsoneditor-is-not-default {
font-weight: bold;
}
</style>
</head>
<body>
<h1>JSON schema validation</h1>
<p>
This example demonstrates onValidationError callback.
</p>
<div id="jsoneditor"></div>
<div id="onValidationOutput"></div>
<script>
var schema = {
"title": "Employee",
"description": "Object containing employee details",
"type": "object",
"properties": {
"firstName": {
"title": "First Name",
"description": "The given name.",
"examples": [
"John"
],
"type": "string"
},
"lastName": {
"title": "Last Name",
"description": "The family name.",
"examples": [
"Smith"
],
"type": "string"
},
"gender": {
"title": "Gender",
"enum": ["male", "female"]
},
"availableToHire": {
"type": "boolean",
"default": false
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0,
"examples": [28, 32]
},
"job": {
"$ref": "job"
}
},
"required": ["firstName", "lastName"]
};
var job = {
"title": "Job description",
"type": "object",
"required": ["address"],
"properties": {
"company": {
"type": "string",
"examples": [
"ACME",
"Dexter Industries"
]
},
"role": {
"description": "Job title.",
"type": "string",
"examples": [
"Human Resources Coordinator",
"Software Developer"
],
"default": "Software Developer"
},
"address": {
"type": "string"
},
"salary": {
"type": "number",
"minimum": 120,
"examples": [100, 110, 120]
}
}
};
var json = {
firstName: 'John',
lastName: 'Doe',
gender: null,
age: "28",
availableToHire: true,
job: {
company: 'freelance',
role: 'developer',
salary: 100
}
};
var options = {
schema: schema,
schemaRefs: {"job": job},
mode: 'code',
modes: ['code', 'text', 'tree', 'preview'],
onValidationError: function(errors) {
console.error('onValidationError', errors);
const outputEL = document.getElementById('onValidationOutput')
outputEL.innerHTML = '<code>onValidationError</code> was called with ' + errors.length + ' error' + (errors.length > 1 ? 's' : '') + ' <br> ' +
'open the browser console to see the error objects';
},
onValidate: function (json) {
var errors = [];
if(!isNaN(json.age) && json.age < 30) {
errors.push({ path: ['age'], message: 'Member age must be 30 or higher' });
}
return errors;
}
};
// create the editor
var container = document.getElementById('jsoneditor');
var editor = new JSONEditor(container, options, json);
</script>
</body>
</html>

View File

@ -0,0 +1,123 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>JSONEditor | Custom query language</title>
<meta charset="utf-8" />
<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>
<script src="https://unpkg.com/lodash@4.17.15/lodash.min.js"></script>
<style type="text/css">
p {
max-width: 500px;
font-family: sans-serif;
font-size: 11pt;
}
code {
font-size: 11pt;
background: #e5e5e5;
}
#jsoneditor {
width: 500px;
height: 500px;
}
.warning {
color: red;
}
</style>
</head>
<body>
<p>
This demo shows how to configure a custom query language.
Click on the "Transform" button and try it out.
</p>
<p>
This basic example uses lodash functions <code>filter</code>, <code>sort</code>, and <code>pick</code>,
but you can run any JavaScript code.
</p>
<p class="warning">
WARNING: this example uses <code>new Function()</code> which can be dangerous when executed with arbitrary code.
Don't use it in production.
</p>
<div id="jsoneditor"></div>
<script>
const container = document.getElementById('jsoneditor')
const options = {
createQuery: function (json, queryOptions) {
console.log('createQuery', queryOptions)
const { filter, sort, projection } = queryOptions
let query = 'data'
if (filter) {
// Note that the comparisons embrace type coercion,
// so a filter value like '5' (text) will match numbers like 5 too.
const getActualValue = filter.field !== '@'
? `item => _.get(item, '${filter.field}')`
: `item => item`
query = `_.filter(${query}, ${getActualValue} ${filter.relation} '${filter.value}')`
}
if (sort) {
// The '@' field name is a special case,
// which means that the field itself is selected.
// For example when we have an array containing numbers.
query = sort.field !== '@'
? `_.orderBy(${query}, '${sort.field}', '${sort.direction}')`
: `_.sortBy(${query}, '${sort.direction}')`
}
if (projection) {
// It is possible to make a util function "pickFlat"
// and use that when building the query to make it more readable.
if (projection.fields.length > 1) {
const fields = projection.fields.map(field => {
const name = _.last(field.split('.'))
return ` '${name}': _.get(item, '${field}')`
})
query = `_.map(${query}, item => ({\n${fields.join(',\n')}})\n)`
} else {
const field = projection.fields[0]
query = `_.map(${query}, item => _.get(item, '${field}'))`
}
}
return query
},
executeQuery: function (json, query) {
console.log('executeQuery', query)
// WARNING: Using new Function() with arbitrary input can be dangerous! Be careful.
const execute = new Function('data', 'return ' + query)
return execute(json)
},
queryDescription: 'Enter a JavaScript query to filter, sort, or transform the JSON data.<br/>' +
'The <a href="https://lodash.com/" target="_blank">Lodash</a> library is available via <code>_</code> to facilitate this.'
}
const json = []
for (let i = 0; i < 100; i++) {
var longitude = 4 + i / 100
var latitude = 51 + i / 100
json.push({
name: 'Item ' + i,
id: String(i),
index: i,
time: new Date().toISOString(),
location: {
latitude: longitude,
longitude: latitude,
coordinates: [longitude, latitude]
},
random: Math.random()
})
}
const editor = new JSONEditor(container, options, json)
</script>
</body>
</html>

View File

@ -0,0 +1,89 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSONEditor | New window</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>
<button id="openNewEditor">Open Editor in New Window</button>
<button id="setJSON">Set JSON</button>
<button id="getJSON">Get JSON</button>
</p>
<script>
let editor
function openNewEditor() {
const child = window.open("", "_blank", "width=400,height=400")
child.document.title = 'JSONEditor | New window'
child.onunload = function () {
editor = undefined
}
// make the necessary styles available within the child window
// for JSONEditor
const baseUrl = window.location.href.slice(0, window.location.href.lastIndexOf('/'))
const jsonEditorStyles = child.document.createElement("link")
jsonEditorStyles.setAttribute("href", baseUrl + "/../dist/jsoneditor.css")
jsonEditorStyles.setAttribute("rel", "stylesheet")
child.document.head.append(jsonEditorStyles)
// for vanilla-picker
const colorPickerStyles = JSONEditor.VanillaPicker.StyleElement.cloneNode(true)
child.document.head.append(colorPickerStyles)
const container = child.document.createElement("div")
child.document.body.append(container)
// create the editor
const options = {
// Show sort and transform modals in the child window, not the parent.
modalAnchor: child.document.body
}
editor = new JSONEditor(container, options)
}
// create a new window
document.getElementById('openNewEditor').onclick = openNewEditor
// set json
document.getElementById('setJSON').onclick = function () {
if (!editor) {
openNewEditor()
}
const json = {
'array': [1, 2, 3],
'boolean': true,
'color': '#82b92c',
'null': null,
'number': 123,
'object': {'a': 'b', 'c': 'd'},
'time': 1575599819000,
'string': 'Hello World'
}
editor.set(json)
}
// get json
document.getElementById('getJSON').onclick = function () {
if (!editor) {
alert('No editor is open')
} else {
const json = editor.get()
alert(JSON.stringify(json, null, 2))
}
}
</script>
</body>
</html>

View File

@ -0,0 +1 @@
SKIP_PREFLIGHT_CHECK=true

21
examples/react_advanced_demo/.gitignore vendored Normal file
View File

@ -0,0 +1,21 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View File

@ -0,0 +1,21 @@
# JSONEditor React advanced demo
This project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app).
## Install
Install dependencies once:
```
npm install
```
## Run
To run the demo:
```
npm start
```
This will open a development server at http://localhost:3000

View File

@ -0,0 +1,30 @@
{
"name": "react_advanced_demo",
"version": "0.1.0",
"private": true,
"dependencies": {
"jsoneditor": "latest",
"lodash": "4.17.15",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-scripts": "3.4.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

View File

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>JSONEditor | React advanced demo</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

View File

@ -0,0 +1,13 @@
.app .contents {
width: 500px;
height: 400px;
}
.app .contents .mode {
padding: 10px 0;
}
.app .contents .code {
background: #f5f5f5;
overflow: auto;
}

View File

@ -0,0 +1,90 @@
import React, { Component } from 'react';
import JSONEditorReact from './JSONEditorReact';
import './App.css';
const schema = {
title: 'Example Schema',
type: 'object',
properties: {
array: {
type: 'array',
items: {
type: 'number'
}
},
boolean: {
type: 'boolean'
},
number: {
type: 'number'
}
},
required: ['array', 'string', 'boolean']
};
const json = {
'array': [1, 2, 3],
'boolean': true,
'null': null,
'number': 'four',
'object': {'a': 'b', 'c': 'd'},
'string': 'Hello World'
};
const modes = ['tree', 'form', 'view', 'code', 'text'];
class App extends Component {
state = {
schema,
text: JSON.stringify(json, null, 2),
mode: 'tree'
};
render() {
return (
<div className="app">
<h1>JSONEditor React advanced demo</h1>
<div className="contents">
<div className="mode">
mode: <select value={this.state.mode} onChange={this.onModeChangeSelect}>
{
modes.map(mode => <option key={mode} value={mode}>{mode}</option>)
}
</select>
</div>
<JSONEditorReact
schema={this.state.schema}
text={this.state.text}
mode={this.state.mode}
modes={modes}
indentation={4}
onChangeText={this.onChangeText}
onModeChange={this.onModeChange}
/>
<div className="code">
<pre>
<code>
{this.state.text}
</code>
</pre>
</div>
</div>
</div>
);
}
onChangeText = (text) => {
this.setState({ text });
};
onModeChangeSelect = (event) => {
this.setState({ mode: event.target.value });
};
onModeChange = (mode) => {
this.setState({ mode });
};
}
export default App;

View File

@ -0,0 +1,9 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});

View File

@ -0,0 +1,4 @@
.jsoneditor-react-container {
width: 100%;
height: 100%;
}

View File

@ -0,0 +1,65 @@
import React, {Component} from 'react';
import isEqual from 'lodash/isEqual';
import cloneDeep from 'lodash/cloneDeep';
import JSONEditor from 'jsoneditor';
import 'jsoneditor/dist/jsoneditor.css';
import './JSONEditorReact.css';
export default class JSONEditorReact extends Component {
componentDidMount () {
// copy all properties into options for the editor
// (except the properties for the JSONEditorReact component itself)
const options = Object.assign({}, this.props);
delete options.json;
delete options.text;
this.jsoneditor = new JSONEditor(this.container, options);
if ('json' in this.props) {
this.jsoneditor.set(this.props.json);
}
if ('text' in this.props) {
this.jsoneditor.setText(this.props.text);
}
this.schema = cloneDeep(this.props.schema);
this.schemaRefs = cloneDeep(this.props.schemaRefs);
}
componentDidUpdate() {
if ('json' in this.props) {
this.jsoneditor.update(this.props.json);
}
if ('text' in this.props) {
this.jsoneditor.updateText(this.props.text);
}
if ('mode' in this.props) {
this.jsoneditor.setMode(this.props.mode);
}
// store a clone of the schema to keep track on when it actually changes.
// (When using a PureComponent all of this would be redundant)
const schemaChanged = !isEqual(this.props.schema, this.schema);
const schemaRefsChanged = !isEqual(this.props.schemaRefs, this.schemaRefs);
if (schemaChanged || schemaRefsChanged) {
this.schema = cloneDeep(this.props.schema);
this.schemaRefs = cloneDeep(this.props.schemaRefs);
this.jsoneditor.setSchema(this.props.schema, this.props.schemaRefs);
}
}
componentWillUnmount () {
if (this.jsoneditor) {
this.jsoneditor.destroy();
}
}
render() {
return (
<div className="jsoneditor-react-container" ref={elem => this.container = elem} />
);
}
}

View File

@ -0,0 +1,3 @@
body {
font-family: sans-serif;
}

View File

@ -0,0 +1,6 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

1
examples/react_demo/.env Normal file
View File

@ -0,0 +1 @@
SKIP_PREFLIGHT_CHECK=true

21
examples/react_demo/.gitignore vendored Normal file
View File

@ -0,0 +1,21 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View File

@ -0,0 +1,21 @@
# JSONEditor React demo
This project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app).
## Install
Install dependencies once:
```
npm install
```
## Run
To run the demo:
```
npm start
```
This will open a development server at http://localhost:3000

View File

@ -0,0 +1,29 @@
{
"name": "react_demo",
"version": "0.1.0",
"private": true,
"dependencies": {
"jsoneditor": "latest",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-scripts": "3.4.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

View File

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>JSONEditor | React demo</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

View File

@ -0,0 +1,12 @@
.app .contents {
width: 500px;
height: 400px;
}
.app .contents .menu {
padding: 10px 0;
}
.app .contents .code {
background: #f5f5f5;
}

View File

@ -0,0 +1,57 @@
import React, { Component } from 'react';
import JSONEditorDemo from './JSONEditorDemo';
import './App.css';
class App extends Component {
state = {
json: {
'array': [1, 2, 3],
'boolean': true,
'null': null,
'number': 123,
'object': {'a': 'b', 'c': 'd'},
'string': 'Hello World'
}
};
render() {
return (
<div className="app">
<h1>JSONEditor React demo</h1>
<div className="contents">
<div className="menu">
<button onClick={this.updateTime}>
Create/update a field "time"
</button>
</div>
<JSONEditorDemo
json={this.state.json}
onChangeJSON={this.onChangeJSON}
/>
<div className="code">
<pre>
<code>
{JSON.stringify(this.state.json, null, 2)}
</code>
</pre>
</div>
</div>
</div>
);
}
onChangeJSON = (json) => {
this.setState({ json });
};
updateTime = () => {
const time = new Date().toISOString();
this.setState({
json: Object.assign({}, this.state.json, { time })
})
};
}
export default App;

View File

@ -0,0 +1,9 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});

View File

@ -0,0 +1,4 @@
.jsoneditor-react-container {
width: 100%;
height: 100%;
}

View File

@ -0,0 +1,34 @@
import React, {Component} from 'react';
import JSONEditor from 'jsoneditor';
import 'jsoneditor/dist/jsoneditor.css';
import './JSONEditorDemo.css';
export default class JSONEditorDemo extends Component {
componentDidMount () {
const options = {
mode: 'tree',
onChangeJSON: this.props.onChangeJSON
};
this.jsoneditor = new JSONEditor(this.container, options);
this.jsoneditor.set(this.props.json);
}
componentWillUnmount () {
if (this.jsoneditor) {
this.jsoneditor.destroy();
}
}
componentDidUpdate() {
this.jsoneditor.update(this.props.json);
}
render() {
return (
<div className="jsoneditor-react-container" ref={elem => this.container = elem} />
);
}
}

View File

@ -0,0 +1,3 @@
body {
font-family: sans-serif;
}

View File

@ -0,0 +1,6 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));

View File

@ -9,7 +9,7 @@
}
</style>
<link rel="stylesheet" type="text/css" href="../../dist/jsoneditor.css">
<script data-main="scripts/main" src="scripts/require.js"></script>
<script data-main="scripts/main" src="https://requirejs.org/docs/release/2.3.6/minified/require.js"></script>
</head>
<body>
<p>

View File

@ -1,25 +1,25 @@
var module = '../../../dist/jsoneditor';
const module = '../../../dist/jsoneditor'
require([module], function (JSONEditor) {
// create the editor
var container = document.getElementById('jsoneditor');
var editor = new JSONEditor(container);
const container = document.getElementById('jsoneditor')
const editor = new JSONEditor(container)
// set json
document.getElementById('setJSON').onclick = function () {
var json = {
'array': [1, 2, 3],
'boolean': true,
'null': null,
'number': 123,
'object': {'a': 'b', 'c': 'd'},
'string': 'Hello World'
};
editor.set(json);
};
const json = {
array: [1, 2, 3],
boolean: true,
null: null,
number: 123,
object: { a: 'b', c: 'd' },
string: 'Hello World'
}
editor.set(json)
}
// get json
document.getElementById('getJSON').onclick = function () {
var json = editor.get();
alert(JSON.stringify(json, null, 2));
};
});
const json = editor.get()
window.alert(JSON.stringify(json, null, 2))
}
})

View File

@ -1,36 +0,0 @@
/*
RequireJS 2.1.13 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.
Available via the MIT or new BSD license.
see: http://github.com/jrburke/requirejs for details
*/
var requirejs,require,define;
(function(ba){function G(b){return"[object Function]"===K.call(b)}function H(b){return"[object Array]"===K.call(b)}function v(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function T(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function t(b,c){return fa.call(b,c)}function m(b,c){return t(b,c)&&b[c]}function B(b,c){for(var d in b)if(t(b,d)&&c(b[d],d))break}function U(b,c,d,e){c&&B(c,function(c,g){if(d||!t(b,g))e&&"object"===typeof c&&c&&!H(c)&&!G(c)&&!(c instanceof
RegExp)?(b[g]||(b[g]={}),U(b[g],c,d,e)):b[g]=c});return b}function u(b,c){return function(){return c.apply(b,arguments)}}function ca(b){throw b;}function da(b){if(!b)return b;var c=ba;v(b.split("."),function(b){c=c[b]});return c}function C(b,c,d,e){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=e;d&&(c.originalError=d);return c}function ga(b){function c(a,k,b){var f,l,c,d,e,g,i,p,k=k&&k.split("/"),h=j.map,n=h&&h["*"];if(a){a=a.split("/");l=a.length-1;j.nodeIdCompat&&
Q.test(a[l])&&(a[l]=a[l].replace(Q,""));"."===a[0].charAt(0)&&k&&(l=k.slice(0,k.length-1),a=l.concat(a));l=a;for(c=0;c<l.length;c++)if(d=l[c],"."===d)l.splice(c,1),c-=1;else if(".."===d&&!(0===c||1==c&&".."===l[2]||".."===l[c-1])&&0<c)l.splice(c-1,2),c-=2;a=a.join("/")}if(b&&h&&(k||n)){l=a.split("/");c=l.length;a:for(;0<c;c-=1){e=l.slice(0,c).join("/");if(k)for(d=k.length;0<d;d-=1)if(b=m(h,k.slice(0,d).join("/")))if(b=m(b,e)){f=b;g=c;break a}!i&&(n&&m(n,e))&&(i=m(n,e),p=c)}!f&&i&&(f=i,g=p);f&&(l.splice(0,
g,f),a=l.join("/"))}return(f=m(j.pkgs,a))?f:a}function d(a){z&&v(document.getElementsByTagName("script"),function(k){if(k.getAttribute("data-requiremodule")===a&&k.getAttribute("data-requirecontext")===i.contextName)return k.parentNode.removeChild(k),!0})}function e(a){var k=m(j.paths,a);if(k&&H(k)&&1<k.length)return k.shift(),i.require.undef(a),i.makeRequire(null,{skipMap:!0})([a]),!0}function n(a){var k,c=a?a.indexOf("!"):-1;-1<c&&(k=a.substring(0,c),a=a.substring(c+1,a.length));return[k,a]}function p(a,
k,b,f){var l,d,e=null,g=k?k.name:null,j=a,p=!0,h="";a||(p=!1,a="_@r"+(K+=1));a=n(a);e=a[0];a=a[1];e&&(e=c(e,g,f),d=m(r,e));a&&(e?h=d&&d.normalize?d.normalize(a,function(a){return c(a,g,f)}):c(a,g,f):(h=c(a,g,f),a=n(h),e=a[0],h=a[1],b=!0,l=i.nameToUrl(h)));b=e&&!d&&!b?"_unnormalized"+(O+=1):"";return{prefix:e,name:h,parentMap:k,unnormalized:!!b,url:l,originalName:j,isDefine:p,id:(e?e+"!"+h:h)+b}}function s(a){var k=a.id,b=m(h,k);b||(b=h[k]=new i.Module(a));return b}function q(a,k,b){var f=a.id,c=m(h,
f);if(t(r,f)&&(!c||c.defineEmitComplete))"defined"===k&&b(r[f]);else if(c=s(a),c.error&&"error"===k)b(c.error);else c.on(k,b)}function w(a,b){var c=a.requireModules,f=!1;if(b)b(a);else if(v(c,function(b){if(b=m(h,b))b.error=a,b.events.error&&(f=!0,b.emit("error",a))}),!f)g.onError(a)}function x(){R.length&&(ha.apply(A,[A.length,0].concat(R)),R=[])}function y(a){delete h[a];delete V[a]}function F(a,b,c){var f=a.map.id;a.error?a.emit("error",a.error):(b[f]=!0,v(a.depMaps,function(f,d){var e=f.id,g=
m(h,e);g&&(!a.depMatched[d]&&!c[e])&&(m(b,e)?(a.defineDep(d,r[e]),a.check()):F(g,b,c))}),c[f]=!0)}function D(){var a,b,c=(a=1E3*j.waitSeconds)&&i.startTime+a<(new Date).getTime(),f=[],l=[],g=!1,h=!0;if(!W){W=!0;B(V,function(a){var i=a.map,j=i.id;if(a.enabled&&(i.isDefine||l.push(a),!a.error))if(!a.inited&&c)e(j)?g=b=!0:(f.push(j),d(j));else if(!a.inited&&(a.fetched&&i.isDefine)&&(g=!0,!i.prefix))return h=!1});if(c&&f.length)return a=C("timeout","Load timeout for modules: "+f,null,f),a.contextName=
i.contextName,w(a);h&&v(l,function(a){F(a,{},{})});if((!c||b)&&g)if((z||ea)&&!X)X=setTimeout(function(){X=0;D()},50);W=!1}}function E(a){t(r,a[0])||s(p(a[0],null,!0)).init(a[1],a[2])}function I(a){var a=a.currentTarget||a.srcElement,b=i.onScriptLoad;a.detachEvent&&!Y?a.detachEvent("onreadystatechange",b):a.removeEventListener("load",b,!1);b=i.onScriptError;(!a.detachEvent||Y)&&a.removeEventListener("error",b,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function J(){var a;for(x();A.length;){a=
A.shift();if(null===a[0])return w(C("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));E(a)}}var W,Z,i,L,X,j={waitSeconds:7,baseUrl:"./",paths:{},bundles:{},pkgs:{},shim:{},config:{}},h={},V={},$={},A=[],r={},S={},aa={},K=1,O=1;L={require:function(a){return a.require?a.require:a.require=i.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?r[a.map.id]=a.exports:a.exports=r[a.map.id]={}},module:function(a){return a.module?a.module:a.module=
{id:a.map.id,uri:a.map.url,config:function(){return m(j.config,a.map.id)||{}},exports:a.exports||(a.exports={})}}};Z=function(a){this.events=m($,a.id)||{};this.map=a;this.shim=m(j.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};Z.prototype={init:function(a,b,c,f){f=f||{};if(!this.inited){this.factory=b;if(c)this.on("error",c);else this.events.error&&(c=u(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=
!0;this.ignore=f.ignore;f.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=b)},fetch:function(){if(!this.fetched){this.fetched=!0;i.startTime=(new Date).getTime();var a=this.map;if(this.shim)i.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],u(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=
this.map.url;S[a]||(S[a]=!0,i.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,b,c=this.map.id;b=this.depExports;var f=this.exports,l=this.factory;if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(G(l)){if(this.events.error&&this.map.isDefine||g.onError!==ca)try{f=i.execCb(c,l,b,f)}catch(d){a=d}else f=i.execCb(c,l,b,f);this.map.isDefine&&void 0===f&&((b=this.module)?f=b.exports:this.usingExports&&
(f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=l;this.exports=f;if(this.map.isDefine&&!this.ignore&&(r[c]=f,g.onResourceLoad))g.onResourceLoad(i,this.map,this.depMaps);y(c);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=
this.map,b=a.id,d=p(a.prefix);this.depMaps.push(d);q(d,"defined",u(this,function(f){var l,d;d=m(aa,this.map.id);var e=this.map.name,P=this.map.parentMap?this.map.parentMap.name:null,n=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(e=f.normalize(e,function(a){return c(a,P,!0)})||""),f=p(a.prefix+"!"+e,this.map.parentMap),q(f,"defined",u(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=m(h,f.id)){this.depMaps.push(f);
if(this.events.error)d.on("error",u(this,function(a){this.emit("error",a)}));d.enable()}}else d?(this.map.url=i.nameToUrl(d),this.load()):(l=u(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),l.error=u(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];B(h,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),l.fromText=u(this,function(f,c){var d=a.name,e=p(d),P=M;c&&(f=c);P&&(M=!1);s(e);t(j.config,b)&&(j.config[d]=j.config[b]);try{g.exec(f)}catch(h){return w(C("fromtexteval",
"fromText eval for "+b+" failed: "+h,h,[b]))}P&&(M=!0);this.depMaps.push(e);i.completeLoad(d);n([d],l)}),f.load(a.name,n,l,j))}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){V[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,u(this,function(a,b){var c,f;if("string"===typeof a){a=p(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=m(L,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;q(a,"defined",u(this,function(a){this.defineDep(b,
a);this.check()}));this.errback&&q(a,"error",u(this,this.errback))}c=a.id;f=h[c];!t(L,c)&&(f&&!f.enabled)&&i.enable(a,this)}));B(this.pluginMaps,u(this,function(a){var b=m(h,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:j,contextName:b,registry:h,defined:r,urlFetched:S,defQueue:A,Module:Z,makeModuleMap:p,
nextTick:g.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=j.shim,c={paths:!0,bundles:!0,config:!0,map:!0};B(a,function(a,b){c[b]?(j[b]||(j[b]={}),U(j[b],a,!0,!0)):j[b]=a});a.bundles&&B(a.bundles,function(a,b){v(a,function(a){a!==b&&(aa[a]=b)})});a.shim&&(B(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);b[c]=a}),j.shim=b);a.packages&&v(a.packages,function(a){var b,
a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(j.paths[b]=a.location);j.pkgs[b]=a.name+"/"+(a.main||"main").replace(ia,"").replace(Q,"")});B(h,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=p(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ba,arguments));return b||a.exports&&da(a.exports)}},makeRequire:function(a,e){function j(c,d,m){var n,q;e.enableBuildCallback&&(d&&G(d))&&(d.__requireJsBuild=
!0);if("string"===typeof c){if(G(d))return w(C("requireargs","Invalid require call"),m);if(a&&t(L,c))return L[c](h[a.id]);if(g.get)return g.get(i,c,a,j);n=p(c,a,!1,!0);n=n.id;return!t(r,n)?w(C("notloaded",'Module name "'+n+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):r[n]}J();i.nextTick(function(){J();q=s(p(null,a));q.skipMap=e.skipMap;q.init(c,d,m,{enabled:!0});D()});return j}e=e||{};U(j,{isBrowser:z,toUrl:function(b){var d,e=b.lastIndexOf("."),k=b.split("/")[0];if(-1!==
e&&(!("."===k||".."===k)||1<e))d=b.substring(e,b.length),b=b.substring(0,e);return i.nameToUrl(c(b,a&&a.id,!0),d,!0)},defined:function(b){return t(r,p(b,a,!1,!0).id)},specified:function(b){b=p(b,a,!1,!0).id;return t(r,b)||t(h,b)}});a||(j.undef=function(b){x();var c=p(b,a,!0),e=m(h,b);d(b);delete r[b];delete S[c.url];delete $[b];T(A,function(a,c){a[0]===b&&A.splice(c,1)});e&&(e.events.defined&&($[b]=e.events),y(b))});return j},enable:function(a){m(h,a.id)&&s(a).enable()},completeLoad:function(a){var b,
c,d=m(j.shim,a)||{},g=d.exports;for(x();A.length;){c=A.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);E(c)}c=m(h,a);if(!b&&!t(r,a)&&c&&!c.inited){if(j.enforceDefine&&(!g||!da(g)))return e(a)?void 0:w(C("nodefine","No define call for "+a,null,[a]));E([a,d.deps||[],d.exportsFn])}D()},nameToUrl:function(a,b,c){var d,e,h;(d=m(j.pkgs,a))&&(a=d);if(d=m(aa,a))return i.nameToUrl(d,b,c);if(g.jsExtRegExp.test(a))d=a+(b||"");else{d=j.paths;a=a.split("/");for(e=a.length;0<e;e-=1)if(h=a.slice(0,
e).join("/"),h=m(d,h)){H(h)&&(h=h[0]);a.splice(0,e,h);break}d=a.join("/");d+=b||(/^data\:|\?/.test(d)||c?"":".js");d=("/"===d.charAt(0)||d.match(/^[\w\+\.\-]+:/)?"":j.baseUrl)+d}return j.urlArgs?d+((-1===d.indexOf("?")?"?":"&")+j.urlArgs):d},load:function(a,b){g.load(i,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if("load"===a.type||ja.test((a.currentTarget||a.srcElement).readyState))N=null,a=I(a),i.completeLoad(a.id)},onScriptError:function(a){var b=I(a);if(!e(b.id))return w(C("scripterror",
"Script error for: "+b.id,a,[b.id]))}};i.require=i.makeRequire();return i}var g,x,y,D,I,E,N,J,s,O,ka=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,la=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,Q=/\.js$/,ia=/^\.\//;x=Object.prototype;var K=x.toString,fa=x.hasOwnProperty,ha=Array.prototype.splice,z=!!("undefined"!==typeof window&&"undefined"!==typeof navigator&&window.document),ea=!z&&"undefined"!==typeof importScripts,ja=z&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,
Y="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),F={},q={},R=[],M=!1;if("undefined"===typeof define){if("undefined"!==typeof requirejs){if(G(requirejs))return;q=requirejs;requirejs=void 0}"undefined"!==typeof require&&!G(require)&&(q=require,require=void 0);g=requirejs=function(b,c,d,e){var n,p="_";!H(b)&&"string"!==typeof b&&(n=b,H(c)?(b=c,c=d,d=e):b=[]);n&&n.context&&(p=n.context);(e=m(F,p))||(e=F[p]=g.s.newContext(p));n&&e.configure(n);return e.require(b,c,d)};g.config=function(b){return g(b)};
g.nextTick="undefined"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=g);g.version="2.1.13";g.jsExtRegExp=/^\/|:|\?|\.js$/;g.isBrowser=z;x=g.s={contexts:F,newContext:ga};g({});v(["toUrl","undef","defined","specified"],function(b){g[b]=function(){var c=F._;return c.require[b].apply(c,arguments)}});if(z&&(y=x.head=document.getElementsByTagName("head")[0],D=document.getElementsByTagName("base")[0]))y=x.head=D.parentNode;g.onError=ca;g.createNode=function(b){var c=
b.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script");c.type=b.scriptType||"text/javascript";c.charset="utf-8";c.async=!0;return c};g.load=function(b,c,d){var e=b&&b.config||{};if(z)return e=g.createNode(e,c,d),e.setAttribute("data-requirecontext",b.contextName),e.setAttribute("data-requiremodule",c),e.attachEvent&&!(e.attachEvent.toString&&0>e.attachEvent.toString().indexOf("[native code"))&&!Y?(M=!0,e.attachEvent("onreadystatechange",b.onScriptLoad)):
(e.addEventListener("load",b.onScriptLoad,!1),e.addEventListener("error",b.onScriptError,!1)),e.src=d,J=e,D?y.insertBefore(e,D):y.appendChild(e),J=null,e;if(ea)try{importScripts(d),b.completeLoad(c)}catch(m){b.onError(C("importscripts","importScripts failed for "+c+" at "+d,m,[c]))}};z&&!q.skipDataMain&&T(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(I=b.getAttribute("data-main"))return s=I,q.baseUrl||(E=s.split("/"),s=E.pop(),O=E.length?E.join("/")+"/":"./",q.baseUrl=
O),s=s.replace(Q,""),g.jsExtRegExp.test(s)&&(s=I),q.deps=q.deps?q.deps.concat(s):[s],!0});define=function(b,c,d){var e,g;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(ka,"").replace(la,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(M){if(!(e=J))N&&"interactive"===N.readyState||T(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return N=b}),e=N;e&&(b||
(b=e.getAttribute("data-requiremodule")),g=F[e.getAttribute("data-requirecontext")])}(g?g.defQueue:R).push([b,c,d])};define.amd={jQuery:!0};g.exec=function(b){return eval(b)};g(q)}})(this);

11
greenkeeper.json Normal file
View File

@ -0,0 +1,11 @@
{
"groups": {
"default": {
"packages": [
"examples/react_advanced_demo/package.json",
"examples/react_demo/package.json",
"package.json"
]
}
}
}

View File

@ -1,38 +1,59 @@
var fs = require('fs');
var gulp = require('gulp');
var gutil = require('gulp-util');
var concatCss = require('gulp-concat-css');
var minifyCSS = require('gulp-clean-css');
var shell = require('gulp-shell');
var mkdirp = require('mkdirp');
var webpack = require('webpack');
var uglify = require('uglify-js');
const fs = require('fs')
const path = require('path')
const gulp = require('gulp')
const log = require('fancy-log')
const format = require('date-format')
const concatCss = require('gulp-concat-css')
const minifyCSS = require('gulp-clean-css')
const sass = require('gulp-sass')
const mkdirp = require('mkdirp')
const webpack = require('webpack')
const uglify = require('uglify-js')
const btoa = require('btoa')
var NAME = 'jsoneditor';
var NAME_MINIMALIST = 'jsoneditor-minimalist';
var ENTRY = './src/js/JSONEditor.js';
var HEADER = './src/js/header.js';
var IMAGE = './src/css/img/jsoneditor-icons.svg';
var DOCS = './src/docs/*';
var DIST = './dist';
const NAME = 'jsoneditor'
const NAME_MINIMALIST = 'jsoneditor-minimalist'
const ENTRY = './src/js/JSONEditor.js'
const HEADER = './src/js/header.js'
const IMAGE = './src/scss/img/jsoneditor-icons.svg'
const DOCS = './src/docs/*'
const DIST = path.join(__dirname, 'dist')
// generate banner with today's date and correct version
function createBanner() {
var today = gutil.date(new Date(), 'yyyy-mm-dd'); // today, formatted as yyyy-mm-dd
var version = require('./package.json').version; // math.js version
function createBanner () {
const today = format.asString('yyyy-MM-dd', new Date()) // today, formatted as yyyy-MM-dd
const version = require('./package.json').version // math.js version
return String(fs.readFileSync(HEADER))
.replace('@@date', today)
.replace('@@version', version);
.replace('@@date', today)
.replace('@@version', version)
}
var bannerPlugin = new webpack.BannerPlugin(createBanner(), {
const bannerPlugin = new webpack.BannerPlugin({
banner: createBanner(),
entryOnly: true,
raw: true
});
})
const webpackConfigModule = {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.js$/,
use: ['source-map-loader'],
enforce: 'pre'
}
]
}
// create a single instance of the compiler to allow caching
var compiler = webpack({
const compiler = webpack({
entry: ENTRY,
output: {
library: 'JSONEditor',
@ -40,17 +61,21 @@ var compiler = webpack({
path: DIST,
filename: NAME + '.js'
},
plugins: [ bannerPlugin ],
module: {
loaders: [
{ test: /\.json$/, loader: "json" }
]
plugins: [bannerPlugin],
optimization: {
// We no not want to minimize our code.
minimize: false
},
module: webpackConfigModule,
resolve: {
extensions: ['.js'],
mainFields: ['main'] // pick ES5 version of vanilla-picker
},
cache: true
});
})
// create a single instance of the compiler to allow caching
var compilerMinimalist = webpack({
const compilerMinimalist = webpack({
entry: ENTRY,
output: {
library: 'JSONEditor',
@ -58,131 +83,161 @@ var compilerMinimalist = webpack({
path: DIST,
filename: NAME_MINIMALIST + '.js'
},
module: webpackConfigModule,
plugins: [
bannerPlugin,
new webpack.IgnorePlugin(new RegExp('^brace$')),
new webpack.IgnorePlugin(new RegExp('^ajv'))
new webpack.IgnorePlugin(new RegExp('^ace-builds')),
new webpack.IgnorePlugin(new RegExp('worker-json-data-url')),
new webpack.IgnorePlugin(new RegExp('^ajv')),
new webpack.IgnorePlugin(new RegExp('^vanilla-picker'))
],
optimization: {
// We no not want to minimize our code.
minimize: false
},
cache: true
});
})
function minify(name) {
var result = uglify.minify([DIST + '/' + name + '.js'], {
outSourceMap: name + '.map',
function minify (name) {
const code = String(fs.readFileSync(DIST + '/' + name + '.js'))
const result = uglify.minify(code, {
sourceMap: {
url: name + '.map'
},
output: {
comments: /@license/
comments: /@license/,
max_line_len: 64000 // extra large because we have embedded code for workers
}
});
})
var fileMin = DIST + '/' + name + '.min.js';
var fileMap = DIST + '/' + name + '.map';
if (result.error) {
throw result.error
}
fs.writeFileSync(fileMin, result.code);
fs.writeFileSync(fileMap, result.map);
const fileMin = DIST + '/' + name + '.min.js'
const fileMap = DIST + '/' + name + '.map'
gutil.log('Minified ' + fileMin);
gutil.log('Mapped ' + fileMap);
fs.writeFileSync(fileMin, result.code)
fs.writeFileSync(fileMap, result.map)
log('Minified ' + fileMin)
log('Mapped ' + fileMap)
}
// make dist and dist/img folders
gulp.task('mkdir', function () {
mkdirp.sync(DIST);
mkdirp.sync(DIST + '/img');
});
// make dist folder structure
gulp.task('mkdir', function (done) {
mkdirp.sync(DIST)
mkdirp.sync(DIST + '/img')
done()
})
// Create an embedded version of the json worker code: a data url
gulp.task('embed-json-worker', function (done) {
const workerBundleFile = './node_modules/ace-builds/src-noconflict/worker-json.js'
const workerEmbeddedFile = './src/js/generated/worker-json-data-url.js'
const workerScript = String(fs.readFileSync(workerBundleFile))
const workerDataUrl = 'data:application/javascript;base64,' + btoa(workerScript)
fs.writeFileSync(workerEmbeddedFile, 'module.exports = \'' + workerDataUrl + '\'\n')
done()
})
// bundle javascript
gulp.task('bundle', ['mkdir'], function (done) {
gulp.task('bundle', function (done) {
// update the banner contents (has a date in it which should stay up to date)
bannerPlugin.banner = createBanner();
bannerPlugin.banner = createBanner()
compiler.run(function (err, stats) {
if (err) {
gutil.log(err);
log(err)
}
gutil.log('bundled ' + NAME + '.js');
log('bundled ' + NAME + '.js')
done();
});
});
done()
})
})
// bundle minimalist version of javascript
gulp.task('bundle-minimalist', ['mkdir'], function (done) {
gulp.task('bundle-minimalist', function (done) {
// update the banner contents (has a date in it which should stay up to date)
bannerPlugin.banner = createBanner();
bannerPlugin.banner = createBanner()
compilerMinimalist.run(function (err, stats) {
if (err) {
gutil.log(err);
log(err)
}
gutil.log('bundled ' + NAME_MINIMALIST + '.js');
log('bundled ' + NAME_MINIMALIST + '.js')
done();
});
});
done()
})
})
// bundle css
gulp.task('bundle-css', ['mkdir'], function () {
gulp.src([
'src/css/reset.css',
'src/css/jsoneditor.css',
'src/css/contextmenu.css',
'src/css/menu.css',
'src/css/searchbox.css'
])
.pipe(concatCss(NAME + '.css'))
.pipe(gulp.dest(DIST))
.pipe(concatCss(NAME + '.min.css'))
.pipe(minifyCSS())
.pipe(gulp.dest(DIST));
gutil.log('bundled ' + DIST + '/' + NAME + '.css');
gutil.log('bundled ' + DIST + '/' + NAME + '.min.css');
});
gulp.task('bundle-css', function (done) {
gulp
.src(['src/scss/jsoneditor.scss'])
.pipe(
sass({
// importer: tildeImporter
})
)
.pipe(concatCss(NAME + '.css'))
.pipe(gulp.dest(DIST))
.pipe(concatCss(NAME + '.min.css'))
.pipe(minifyCSS())
.pipe(gulp.dest(DIST))
done()
})
// create a folder img and copy the icons
gulp.task('copy-img', ['mkdir'], function () {
gulp.src(IMAGE)
.pipe(gulp.dest(DIST +'/img'));
gutil.log('Copied images');
});
gulp.task('copy-img', function (done) {
gulp.src(IMAGE).pipe(gulp.dest(DIST + '/img'))
log('Copied images')
done()
})
// create a folder img and copy the icons
gulp.task('copy-docs', ['mkdir'], function () {
gulp.src(DOCS)
.pipe(gulp.dest(DIST));
gutil.log('Copied doc');
});
gulp.task('copy-docs', function (done) {
gulp.src(DOCS).pipe(gulp.dest(DIST))
log('Copied doc')
gulp.task('minify', ['bundle'], function () {
done()
})
gulp.task('minify', function (done) {
minify(NAME)
});
gulp.task('minify-minimalist', ['bundle-minimalist'], function () {
done()
})
gulp.task('minify-minimalist', function (done) {
minify(NAME_MINIMALIST)
});
// TODO: zip file using archiver
var pkg = 'jsoneditor-' + require('./package.json').version + '.zip';
gulp.task('zip', shell.task([
'zip ' + pkg + ' ' + 'README.md NOTICE LICENSE HISTORY.md index.html src dist docs examples -r '
]));
done()
})
// The watch task (to automatically rebuild when the source code changes)
// Does only generate jsoneditor.js and jsoneditor.css, and copy the image
// Does NOT minify the code and does NOT generate the minimalist version
gulp.task('watch', ['bundle', 'bundle-css', 'copy-img'], function () {
gulp.watch(['src/**/*'], ['bundle', 'bundle-css', 'copy-img']);
});
gulp.task('watch', gulp.series('bundle', 'bundle-css', 'copy-img', function () {
gulp.watch(['src/**/*'], gulp.series('bundle', 'bundle-css', 'copy-img'))
}))
// The default task (called when you run `gulp`)
gulp.task('default', [
'bundle',
'bundle-minimalist',
'bundle-css',
'copy-img',
'copy-docs',
'minify',
'minify-minimalist'
]);
gulp.task('default', gulp.series(
'mkdir',
'embed-json-worker',
gulp.parallel(
'copy-img',
'copy-docs',
'bundle-css',
gulp.series('bundle', 'minify'),
gulp.series('bundle-minimalist', 'minify-minimalist')
)
))

View File

@ -1 +1 @@
module.exports = require('./src/js/JSONEditor');
module.exports = require('./dist/jsoneditor')

BIN
misc/browserstack.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

12954
misc/browserstack.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 950 KiB

View File

@ -7,6 +7,10 @@ This document describes the steps required to publish a new version of jsonedito
Update the version number in package.json.
Update package-lock.json:
npm install
## Update history
@ -33,13 +37,8 @@ correct date and version number in the header.
## Test
Test whether the npm library is ok by installing it locally:
cd ../tmp-folder
npm install ./path/to/jsoneditor
Check whether the examples in the library work ok, and whether the necessary
files are included.
Test whether the npm library is ok by opening some examples, and check whether
the files under `dists` are created and have contents.
## Commit
@ -60,9 +59,6 @@ Publish to npm:
npm publish
Publish at cdnjs: test after 30 to 60 minutes whether the new version is
published at cdnjs (should auto update).
## Test published library

10952
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
{
"name": "jsoneditor",
"version": "5.5.6",
"main": "./index",
"version": "9.1.1",
"main": "./dist/jsoneditor.min.js",
"description": "A web-based tool to view, edit, format, and validate JSON",
"tags": [
"json",
@ -19,24 +19,58 @@
"bugs": "https://github.com/josdejong/jsoneditor/issues",
"scripts": {
"build": "gulp",
"watch": "gulp watch",
"test": "mocha test"
"minify": "gulp minify",
"start": "gulp watch",
"test": "mocha test --require @babel/register",
"lint": "standard --env=mocha",
"prepublishOnly": "npm test && npm run build"
},
"dependencies": {
"ajv": "3.8.8",
"brace": "0.8.0",
"javascript-natural-sort": "0.7.1"
"ace-builds": "^1.4.12",
"ajv": "^6.12.5",
"javascript-natural-sort": "^0.7.1",
"jmespath": "^0.15.0",
"json-source-map": "^0.6.1",
"mobius1-selectr": "^2.4.13",
"picomodal": "^3.0.0",
"vanilla-picker": "^2.10.1"
},
"devDependencies": {
"gulp": "3.9.1",
"gulp-clean-css": "2.0.5",
"gulp-concat-css": "2.2.0",
"gulp-shell": "0.5.2",
"gulp-util": "3.0.7",
"json-loader": "0.5.4",
"mkdirp": "0.5.1",
"mocha": "2.4.5",
"uglify-js": "2.6.2",
"webpack": "1.12.14"
"@babel/core": "7.11.6",
"@babel/preset-env": "7.11.5",
"@babel/register": "7.11.5",
"babel-loader": "8.1.0",
"btoa": "1.2.1",
"date-format": "3.0.0",
"fancy-log": "1.3.3",
"gulp": "4.0.2",
"gulp-clean-css": "4.3.0",
"gulp-concat-css": "3.1.0",
"gulp-sass": "4.1.0",
"jsdom": "16.4.0",
"json-loader": "0.5.7",
"mkdirp": "1.0.4",
"mocha": "8.1.3",
"source-map-loader": "1.1.0",
"standard": "14.3.4",
"uglify-js": "3.11.1",
"webpack": "4.44.2"
},
"files": [
"dist",
"docs",
"examples",
"src",
"HISTORY.md",
"index.js",
"LICENSE",
"NOTICE",
"README.md"
],
"standard": {
"ignore": [
"src/js/assets",
"examples/react*"
]
}
}

View File

@ -1,244 +0,0 @@
/* ContextMenu - main menu */
div.jsoneditor-contextmenu-root {
position: relative;
width: 0;
height: 0;
}
div.jsoneditor-contextmenu {
position: absolute;
box-sizing: content-box;
z-index: 99999;
}
div.jsoneditor-contextmenu ul,
div.jsoneditor-contextmenu li {
box-sizing: content-box;
}
div.jsoneditor-contextmenu ul {
position: relative;
left: 0;
top: 0;
width: 124px;
background: white;
border: 1px solid #d3d3d3;
box-shadow: 2px 2px 12px rgba(128, 128, 128, 0.3);
list-style: none;
margin: 0;
padding: 0;
}
div.jsoneditor-contextmenu ul li button {
padding: 0;
margin: 0;
width: 124px;
height: 24px;
border: none;
cursor: pointer;
color: #4d4d4d;
background: transparent;
font-size: 10pt;
font-family: arial, sans-serif;
box-sizing: border-box;
line-height: 26px;
text-align: left;
}
/* Fix button padding in firefox */
div.jsoneditor-contextmenu ul li button::-moz-focus-inner {
padding: 0;
border: 0;
}
div.jsoneditor-contextmenu ul li button:hover,
div.jsoneditor-contextmenu ul li button:focus {
color: #1a1a1a;
background-color: #f5f5f5;
outline: none;
}
div.jsoneditor-contextmenu ul li button.jsoneditor-default {
width: 92px;
}
div.jsoneditor-contextmenu ul li button.jsoneditor-expand {
float: right;
width: 32px;
height: 24px;
border-left: 1px solid #e5e5e5;
}
div.jsoneditor-contextmenu div.jsoneditor-icon {
float: left;
width: 24px;
height: 24px;
border: none;
padding: 0;
margin: 0;
background-image: url('img/jsoneditor-icons.svg');
}
div.jsoneditor-contextmenu ul li button div.jsoneditor-expand {
float: right;
width: 24px;
height: 24px;
padding: 0;
margin: 0 4px 0 0;
background: url('img/jsoneditor-icons.svg') 0 -72px;
opacity: 0.4;
}
div.jsoneditor-contextmenu ul li button:hover div.jsoneditor-expand,
div.jsoneditor-contextmenu ul li button:focus div.jsoneditor-expand,
div.jsoneditor-contextmenu ul li.jsoneditor-selected div.jsoneditor-expand,
div.jsoneditor-contextmenu ul li button.jsoneditor-expand:hover div.jsoneditor-expand,
div.jsoneditor-contextmenu ul li button.jsoneditor-expand:focus div.jsoneditor-expand {
opacity: 1;
}
div.jsoneditor-contextmenu div.jsoneditor-separator {
height: 0;
border-top: 1px solid #e5e5e5;
padding-top: 5px;
margin-top: 5px;
}
div.jsoneditor-contextmenu button.jsoneditor-remove > div.jsoneditor-icon {
background-position: -24px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-remove:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-remove:focus > div.jsoneditor-icon {
background-position: -24px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-append > div.jsoneditor-icon {
background-position: 0 -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-append:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-append:focus > div.jsoneditor-icon {
background-position: 0 0;
}
div.jsoneditor-contextmenu button.jsoneditor-insert > div.jsoneditor-icon {
background-position: 0 -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-insert:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-insert:focus > div.jsoneditor-icon {
background-position: 0 0;
}
div.jsoneditor-contextmenu button.jsoneditor-duplicate > div.jsoneditor-icon {
background-position: -48px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-duplicate:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-duplicate:focus > div.jsoneditor-icon {
background-position: -48px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-sort-asc > div.jsoneditor-icon {
background-position: -168px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-sort-asc:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-sort-asc:focus > div.jsoneditor-icon {
background-position: -168px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-sort-desc > div.jsoneditor-icon {
background-position: -192px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-sort-desc:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-sort-desc:focus > div.jsoneditor-icon {
background-position: -192px 0;
}
/* ContextMenu - sub menu */
div.jsoneditor-contextmenu ul li button.jsoneditor-selected,
div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover,
div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus {
color: white;
background-color: #ee422e;
}
div.jsoneditor-contextmenu ul li {
overflow: hidden;
}
div.jsoneditor-contextmenu ul li ul {
display: none;
position: relative;
left: -10px;
top: 0;
border: none;
box-shadow: inset 0 0 10px rgba(128, 128, 128, 0.5);
padding: 0 10px;
/* TODO: transition is not supported on IE8-9 */
-webkit-transition: all 0.3s ease-out;
-moz-transition: all 0.3s ease-out;
-o-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
div.jsoneditor-contextmenu ul li.jsoneditor-selected ul {
}
div.jsoneditor-contextmenu ul li ul li button {
padding-left: 24px;
animation: all ease-in-out 1s;
}
div.jsoneditor-contextmenu ul li ul li button:hover,
div.jsoneditor-contextmenu ul li ul li button:focus {
background-color: #f5f5f5;
}
div.jsoneditor-contextmenu button.jsoneditor-type-string > div.jsoneditor-icon {
background-position: -144px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-type-string:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-string:focus > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-string.jsoneditor-selected > div.jsoneditor-icon{
background-position: -144px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-type-auto > div.jsoneditor-icon {
background-position: -120px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-type-auto:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-auto:focus > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-auto.jsoneditor-selected > div.jsoneditor-icon {
background-position: -120px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-type-object > div.jsoneditor-icon {
background-position: -72px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-type-object:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-object:focus > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-object.jsoneditor-selected > div.jsoneditor-icon{
background-position: -72px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-type-array > div.jsoneditor-icon {
background-position: -96px -24px;
}
div.jsoneditor-contextmenu button.jsoneditor-type-array:hover > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-array:focus > div.jsoneditor-icon,
div.jsoneditor-contextmenu button.jsoneditor-type-array.jsoneditor-selected > div.jsoneditor-icon{
background-position: -96px 0;
}
div.jsoneditor-contextmenu button.jsoneditor-type-modes > div.jsoneditor-icon {
background-image: none;
width: 6px;
}

View File

@ -1,893 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="216"
height="144"
id="svg4136"
version="1.1"
inkscape:version="0.91 r"
sodipodi:docname="jsoneditor-icons.svg">
<title
id="title6512">JSON Editor Icons</title>
<metadata
id="metadata4148">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>JSON Editor Icons</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4146" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1028"
id="namedview4144"
showgrid="true"
inkscape:zoom="4"
inkscape:cx="97.217248"
inkscape:cy="59.950227"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4136"
showguides="false"
borderlayer="false"
inkscape:showpageshadow="true"
showborder="true">
<inkscape:grid
type="xygrid"
id="grid4640"
empspacing="24" />
</sodipodi:namedview>
<!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
<g
id="g4394">
<rect
x="4"
y="4"
width="16"
height="16"
id="svg_1"
style="fill:#1aae1c;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
style="fill:#ec3f29;fill-opacity:0.94117647;stroke:none;stroke-width:0"
x="28.000006"
y="3.999995"
width="16"
height="16"
id="svg_1-7" />
<rect
id="rect4165"
height="16"
width="16"
y="3.999995"
x="52.000004"
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
x="172.00002"
y="3.9999852"
width="16"
height="16"
id="rect4175" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
x="196"
y="3.999995"
width="16"
height="16"
id="rect4175-3" />
<g
style="stroke:none"
id="g4299">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1-1"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<g
style="stroke:none"
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,19.029435,12.000001)"
id="g4299-3">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1-0"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1-1-9"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="55.000004"
y="7.0000048"
width="6.9999909"
height="6.9999905"
id="svg_1-7-5" />
<rect
id="rect4354"
height="6.9999905"
width="6.9999909"
y="10.00001"
x="58"
style="fill:#ffffff;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#3c80df;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
x="58.000004"
y="10.000005"
width="6.9999909"
height="6.9999905"
id="svg_1-7-5-7" />
<g
id="g4378">
<rect
id="svg_1-7-5-3"
height="1.9999965"
width="7.9999909"
y="10.999999"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="7.0000005"
width="11.999995"
height="1.9999946"
id="rect4374" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="14.999996"
width="3.9999928"
height="1.9999995"
id="rect4376" />
</g>
<g
id="g4383"
transform="matrix(1,0,0,-1,-23.999995,23.999995)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="10.999999"
width="7.9999909"
height="1.9999965"
id="rect4385" />
<rect
id="rect4387"
height="1.9999946"
width="11.999995"
y="7.0000005"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
id="rect4389"
height="1.9999995"
width="3.9999928"
y="14.999996"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
</g>
<rect
y="3.9999199"
x="76"
height="16"
width="16"
id="rect3754-4"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0"
id="path4351"
d="m 85.10447,6.0157384 -0.0156,1.4063 c 3.02669,-0.2402 0.33008,3.6507996 2.48438,4.5780996 -2.18694,1.0938 0.49191,4.9069 -2.45313,4.5781 l -0.0156,1.4219 c 5.70828,0.559 1.03264,-5.1005 4.70313,-5.2656 l 0,-1.4063 c -3.61303,-0.027 1.11893,-5.7069996 -4.70313,-5.3124996 z"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0"
id="path4351-9"
d="m 82.78125,5.9984384 0.0156,1.4063 c -3.02668,-0.2402 -0.33007,3.6506996 -2.48437,4.5780996 2.18694,1.0938 -0.49192,4.9069 2.45312,4.5781 l 0.0156,1.4219 c -5.70827,0.559 -1.03263,-5.1004 -4.70312,-5.2656 l 0,-1.4063 c 3.61303,-0.027 -1.11894,-5.7070996 4.70312,-5.3124996 z"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
y="3.9999199"
x="100"
height="16"
width="16"
id="rect3754-25"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path2987"
d="m 103.719,5.6719384 0,12.7187996 3.03125,0 0,-1.5313 -1.34375,0 0,-9.6249996 1.375,0 0,-1.5625 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path2987-1"
d="m 112.2185,5.6721984 0,12.7187996 -3.03125,0 0,-1.5313 1.34375,0 0,-9.6249996 -1.375,0 0,-1.5625 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<rect
y="3.9999199"
x="124"
height="16"
width="16"
id="rect3754-73"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0"
id="path3780"
d="m 126.2824,17.602938 1.78957,0 1.14143,-2.8641 5.65364,0 1.14856,2.8641 1.76565,0 -4.78687,-11.1610996 -1.91903,0 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path3782"
d="m 129.72704,13.478838 4.60852,0.01 -2.30426,-5.5497996 z"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<rect
y="3.9999199"
x="148"
height="16"
width="16"
id="rect3754-35"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="path5008-2"
d="m 156.47655,5.8917384 0,2.1797 0.46093,2.3983996 1.82813,0 0.39844,-2.3983996 0,-2.1797 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="path5008-2-8"
d="m 152.51561,5.8906384 0,2.1797 0.46094,2.3983996 1.82812,0 0.39844,-2.3983996 0,-2.1797 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
</g>
<rect
x="4"
y="27.999994"
width="16"
height="16"
id="rect4432"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0"
x="28.000006"
y="27.99999"
width="16"
height="16"
id="rect4434" />
<rect
id="rect4436"
height="16"
width="16"
y="27.99999"
x="52.000004"
style="fill:#d3d3d3;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#d3d3d3;stroke:#000000;stroke-width:0"
x="172.00002"
y="27.999981"
width="16"
height="16"
id="rect4446" />
<rect
style="fill:#d3d3d3;stroke:#000000;stroke-width:0"
x="196"
y="27.99999"
width="16"
height="16"
id="rect4448" />
<g
id="g4466"
style="stroke:none"
transform="translate(0,23.999995)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4468"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4470"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<g
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,19.029435,35.999996)"
id="g4472"
style="stroke:none">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4474"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4476"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="55.000004"
y="31"
width="6.9999909"
height="6.9999905"
id="rect4478" />
<rect
id="rect4480"
height="6.9999905"
width="6.9999909"
y="34.000008"
x="58"
style="fill:#ffffff;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#d3d3d3;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
x="58.000004"
y="34.000004"
width="6.9999909"
height="6.9999905"
id="rect4482" />
<g
id="g4484"
transform="translate(0,23.999995)">
<rect
id="rect4486"
height="1.9999965"
width="7.9999909"
y="10.999999"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="7.0000005"
width="11.999995"
height="1.9999946"
id="rect4488" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="14.999996"
width="3.9999928"
height="1.9999995"
id="rect4490" />
</g>
<g
id="g4492"
transform="matrix(1,0,0,-1,-23.999995,47.99999)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="10.999999"
width="7.9999909"
height="1.9999965"
id="rect4494" />
<rect
id="rect4496"
height="1.9999946"
width="11.999995"
y="7.0000005"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
id="rect4498"
height="1.9999995"
width="3.9999928"
y="14.999996"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
</g>
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-8"
width="16"
height="16"
x="76"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 85.10448,30.015537 -0.0156,1.4063 c 3.02668,-0.2402 0.33007,3.6508 2.48438,4.5781 -2.18695,1.0938 0.49191,4.90688 -2.45313,4.57808 l -0.0156,1.4219 c 5.70827,0.559 1.03263,-5.10048 4.70313,-5.26558 l 0,-1.4063 c -3.61304,-0.027 1.11893,-5.707 -4.70313,-5.3125 z"
id="path4351-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 82.78126,29.998237 0.0156,1.4063 c -3.02668,-0.2402 -0.33008,3.6507 -2.48438,4.5781 2.18694,1.0938 -0.49191,4.90688 2.45313,4.57808 l 0.0156,1.4219 c -5.70828,0.559 -1.03264,-5.10038 -4.70313,-5.26558 l 0,-1.4063 c 3.61303,-0.027 -1.11893,-5.7071 4.70313,-5.3125 z"
id="path4351-9-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-65"
width="16"
height="16"
x="100"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 103.719,29.671937 0,12.71878 3.03125,0 0,-1.5313 -1.34375,0 0,-9.62498 1.375,0 0,-1.5625 z"
id="path2987-8"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 112.2185,29.671937 0,12.71878 -3.03125,0 0,-1.5313 1.34375,0 0,-9.62498 -1.375,0 0,-1.5625 z"
id="path2987-1-9"
inkscape:connector-curvature="0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-92"
width="16"
height="16"
x="124"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 126.2824,41.602917 1.78957,0 1.14143,-2.86408 5.65364,0 1.14856,2.86408 1.76565,0 -4.78687,-11.16108 -1.91902,0 z"
id="path3780-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
<path
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
d="m 129.72704,37.478837 4.60852,0.01 -2.30426,-5.5498 z"
id="path3782-2"
inkscape:connector-curvature="0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-47"
width="16"
height="16"
x="148"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 156.47656,29.891737 0,2.1797 0.46093,2.3984 1.82813,0 0.39844,-2.3984 0,-2.1797 z"
id="path5008-2-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 152.51562,29.890637 0,2.1797 0.46094,2.3984 1.82812,0 0.39844,-2.3984 0,-2.1797 z"
id="path5008-2-8-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<rect
id="svg_1-7-2"
height="1.9999961"
width="11.999996"
y="64"
x="54"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
id="svg_1-7-2-2"
height="2.9999905"
width="2.9999907"
y="52"
x="80.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="85.000008"
y="52"
width="2.9999907"
height="2.9999905"
id="rect4561" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="80.000008"
y="58"
width="2.9999907"
height="2.9999905"
id="rect4563" />
<rect
id="rect4565"
height="2.9999905"
width="2.9999907"
y="58"
x="85.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
id="rect4567"
height="2.9999905"
width="2.9999907"
y="64"
x="80.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="85.000008"
y="64"
width="2.9999907"
height="2.9999905"
id="rect4569" />
<circle
style="opacity:1;fill:none;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4571"
cx="110.06081"
cy="57.939209"
r="4.7438836" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="116.64566"
y="-31.79752"
width="4.229713"
height="6.4053884"
id="rect4563-2"
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" />
<path
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 125,56 138.77027,56.095 132,64 Z"
id="path4613"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4615"
d="M 149,64 162.77027,63.905 156,56 Z"
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="54"
y="53"
width="11.999996"
height="1.9999961"
id="rect4638" />
<rect
id="svg_1-7-2-24"
height="1.9999957"
width="12.99999"
y="-56"
x="53"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
transform="matrix(0,1,-1,0,0,0)" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="53"
y="-66"
width="12.99999"
height="1.9999957"
id="rect4657" />
<rect
id="rect4659"
height="0.99999291"
width="11.999999"
y="57"
x="54"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="54"
y="88.000122"
width="11.999996"
height="1.9999961"
id="rect4661" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="80.000008"
y="76.000122"
width="2.9999907"
height="2.9999905"
id="rect4663" />
<rect
id="rect4665"
height="2.9999905"
width="2.9999907"
y="76.000122"
x="85.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
id="rect4667"
height="2.9999905"
width="2.9999907"
y="82.000122"
x="80.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="85.000008"
y="82.000122"
width="2.9999907"
height="2.9999905"
id="rect4669" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="80.000008"
y="88.000122"
width="2.9999907"
height="2.9999905"
id="rect4671" />
<rect
id="rect4673"
height="2.9999905"
width="2.9999907"
y="88.000122"
x="85.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<circle
r="4.7438836"
cy="81.939331"
cx="110.06081"
id="circle4675"
style="opacity:1;fill:none;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)"
id="rect4677"
height="6.4053884"
width="4.229713"
y="-14.826816"
x="133.6163"
style="fill:#d3d3d3;fill-opacity:1;stroke:#d3d3d3;stroke-width:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4679"
d="m 125,80.000005 13.77027,0.09499 L 132,87.999992 Z"
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 149,88.0002 162.77027,87.9052 156,80.0002 Z"
id="path4681"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<rect
id="rect4683"
height="1.9999961"
width="11.999996"
y="77.000122"
x="54"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="77.000122"
y="-56"
width="12.99999"
height="1.9999957"
id="rect4685" />
<rect
id="rect4687"
height="1.9999957"
width="12.99999"
y="-66"
x="77.000122"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
transform="matrix(0,1,-1,0,0,0)" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="54"
y="81.000122"
width="11.999999"
height="0.99999291"
id="rect4689" />
<rect
id="rect4761-1"
height="1.9999945"
width="15.99999"
y="101"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-0"
height="1.9999945"
width="15.99999"
y="105"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-7"
height="1.9999945"
width="9"
y="109"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1"
height="1.9999945"
width="12"
y="125"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4"
height="1.9999945"
width="10"
y="137"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4-4"
height="1.9999945"
width="10"
y="129"
x="82"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4-4-3"
height="1.9999945"
width="9"
y="133"
x="82"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 36.398438,100.0254 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,100.5991 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1452 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533865,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550756,0 6.710442,-2.4113 7.650391,-5.9414 0.939949,-3.5301 -0.618463,-7.2736 -3.710938,-9.0703 -1.159678,-0.6738 -2.431087,-1.0231 -3.701171,-1.0625 z"
id="path4138" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 59.722656,99.9629 c -1.270084,0.039 -2.541493,0.3887 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5402 -3.710937,9.0703 0.939949,3.5301 4.09768,5.9414 7.648437,5.9414 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4056 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
id="path4138-1" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
d="m 10.5,100 0,2 -2.4999996,0 L 12,107 l 4,-5 -2.5,0 0,-2 -3,0 z"
id="path3055-0-77" />
<path
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.966;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.9850574,108.015 14.0298856,-0.03"
id="path5244-5-0-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.966;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.9849874,132.015 14.0298866,-0.03"
id="path5244-5-0-5-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 36.398438,123.9629 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,124.5366 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1453 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533864,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550757,0 6.710442,-2.4093 7.650391,-5.9394 0.939949,-3.5301 -0.618463,-7.2756 -3.710938,-9.0723 -1.159678,-0.6737 -2.431087,-1.0231 -3.701171,-1.0625 z"
id="path4138-12" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 59.722656,123.9629 c -1.270084,0.039 -2.541493,0.3888 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5422 -3.710937,9.0723 0.939949,3.5301 4.09768,5.9394 7.648437,5.9394 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4055 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
id="path4138-1-3" />
<path
id="path6191"
d="m 10.5,116 0,-2 -2.4999996,0 L 12,109 l 4,5 -2.5,0 0,2 -3,0 z"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
d="m 10.5,129 0,-2 -2.4999996,0 L 12,122 l 4,5 -2.5,0 0,2 -3,0 z"
id="path6193" />
<path
id="path6195"
d="m 10.5,135 0,2 -2.4999996,0 L 12,142 l 4,-5 -2.5,0 0,-2 -3,0 z"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
sodipodi:type="star"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4500"
sodipodi:sides="3"
sodipodi:cx="11.55581"
sodipodi:cy="60.073242"
sodipodi:r1="5.1116104"
sodipodi:r2="2.5558052"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 16.66742,60.073242 -3.833708,2.213392 -3.8337072,2.213393 0,-4.426785 0,-4.426784 3.8337082,2.213392 z"
inkscape:transform-center-x="-1.2779026" />
<path
inkscape:transform-center-x="1.277902"
d="m -31.500004,60.073242 -3.833708,2.213392 -3.833707,2.213393 0,-4.426785 0,-4.426784 3.833707,2.213392 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="false"
sodipodi:arg2="1.0471976"
sodipodi:arg1="0"
sodipodi:r2="2.5558052"
sodipodi:r1="5.1116104"
sodipodi:cy="60.073242"
sodipodi:cx="-36.611614"
sodipodi:sides="3"
id="path4502"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="star"
transform="scale(-1,1)" />
<path
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="false"
sodipodi:arg2="1.0471976"
sodipodi:arg1="0"
sodipodi:r2="2.5558052"
sodipodi:r1="5.1116104"
sodipodi:cy="60.073212"
sodipodi:cx="11.55581"
sodipodi:sides="3"
id="path4504"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="star"
transform="matrix(0,1,-1,0,72.0074,71.7877)"
inkscape:transform-center-y="1.2779029" />
<path
inkscape:transform-center-y="-1.2779026"
transform="matrix(0,-1,-1,0,96,96)"
sodipodi:type="star"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4506"
sodipodi:sides="3"
sodipodi:cx="11.55581"
sodipodi:cy="60.073212"
sodipodi:r1="5.1116104"
sodipodi:r2="2.5558052"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4615-5"
d="m 171.82574,65.174193 16.34854,0 -8.17427,-13.348454 z"
style="fill:#fbb917;fill-opacity:1;fill-rule:evenodd;stroke:#fbb917;stroke-width:1.65161395;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 179,55 0,6 2,0 0,-6"
id="path4300"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 179,62 0,2 2,0 0,-2"
id="path4300-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</svg>

Before

Width:  |  Height:  |  Size: 35 KiB

View File

@ -1,449 +0,0 @@
div.jsoneditor {
}
div.jsoneditor-field,
div.jsoneditor-value,
div.jsoneditor-readonly {
border: 1px solid transparent;
min-height: 16px;
min-width: 32px;
padding: 2px;
margin: 1px;
word-wrap: break-word;
float: left;
}
/* adjust margin of p elements inside editable divs, needed for Opera, IE */
div.jsoneditor-field p,
div.jsoneditor-value p {
margin: 0;
}
div.jsoneditor-value {
word-break: break-word;
}
div.jsoneditor-readonly {
min-width: 16px;
color: gray;
}
div.jsoneditor-empty {
border-color: lightgray;
border-style: dashed;
border-radius: 2px;
}
div.jsoneditor-field.jsoneditor-empty::after,
div.jsoneditor-value.jsoneditor-empty::after {
pointer-events: none;
color: lightgray;
font-size: 8pt;
}
div.jsoneditor-field.jsoneditor-empty::after {
content: "field";
}
div.jsoneditor-value.jsoneditor-empty::after {
content: "value";
}
div.jsoneditor-value.jsoneditor-url,
a.jsoneditor-value.jsoneditor-url {
color: green;
text-decoration: underline;
}
a.jsoneditor-value.jsoneditor-url {
display: inline-block;
padding: 2px;
margin: 2px;
}
a.jsoneditor-value.jsoneditor-url:hover,
a.jsoneditor-value.jsoneditor-url:focus {
color: #ee422e;
}
div.jsoneditor td.jsoneditor-separator {
padding: 3px 0;
vertical-align: top;
color: gray;
}
div.jsoneditor-field[contenteditable=true]:focus,
div.jsoneditor-field[contenteditable=true]:hover,
div.jsoneditor-value[contenteditable=true]:focus,
div.jsoneditor-value[contenteditable=true]:hover,
div.jsoneditor-field.jsoneditor-highlight,
div.jsoneditor-value.jsoneditor-highlight {
background-color: #FFFFAB;
border: 1px solid yellow;
border-radius: 2px;
}
div.jsoneditor-field.jsoneditor-highlight-active,
div.jsoneditor-field.jsoneditor-highlight-active:focus,
div.jsoneditor-field.jsoneditor-highlight-active:hover,
div.jsoneditor-value.jsoneditor-highlight-active,
div.jsoneditor-value.jsoneditor-highlight-active:focus,
div.jsoneditor-value.jsoneditor-highlight-active:hover {
background-color: #ffee00;
border: 1px solid #ffc700;
border-radius: 2px;
}
div.jsoneditor-value.jsoneditor-string {
color: #008000;
}
div.jsoneditor-value.jsoneditor-object,
div.jsoneditor-value.jsoneditor-array {
min-width: 16px;
color: #808080;
}
div.jsoneditor-value.jsoneditor-number {
color: #ee422e;
}
div.jsoneditor-value.jsoneditor-boolean {
color: #ff8c00;
}
div.jsoneditor-value.jsoneditor-null {
color: #004ED0;
}
div.jsoneditor-value.jsoneditor-invalid {
color: #000000;
}
div.jsoneditor-tree button {
width: 24px;
height: 24px;
padding: 0;
margin: 0;
border: none;
cursor: pointer;
background: transparent url('img/jsoneditor-icons.svg');
}
div.jsoneditor-mode-view tr.jsoneditor-expandable td.jsoneditor-tree,
div.jsoneditor-mode-form tr.jsoneditor-expandable td.jsoneditor-tree {
cursor: pointer;
}
div.jsoneditor-tree button.jsoneditor-collapsed {
background-position: 0 -48px;
}
div.jsoneditor-tree button.jsoneditor-expanded {
background-position: 0 -72px;
}
div.jsoneditor-tree button.jsoneditor-contextmenu {
background-position: -48px -72px;
}
div.jsoneditor-tree button.jsoneditor-contextmenu:hover,
div.jsoneditor-tree button.jsoneditor-contextmenu:focus,
div.jsoneditor-tree button.jsoneditor-contextmenu.jsoneditor-selected,
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu {
background-position: -48px -48px;
}
div.jsoneditor-tree *:focus {
outline: none;
}
div.jsoneditor-tree button:focus {
/* TODO: nice outline for buttons with focus
outline: #97B0F8 solid 2px;
box-shadow: 0 0 8px #97B0F8;
*/
background-color: #f5f5f5;
outline: #e5e5e5 solid 1px;
}
div.jsoneditor-tree button.jsoneditor-invisible {
visibility: hidden;
background: none;
}
div.jsoneditor {
color: #1A1A1A;
border: 1px solid #3883fa;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
padding: 0;
line-height: 100%;
}
div.jsoneditor-tree table.jsoneditor-tree {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
margin: 0;
}
div.jsoneditor-outer {
width: 100%;
height: 100%;
margin: -35px 0 0 0;
padding: 35px 0 0 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
textarea.jsoneditor-text,
.ace-jsoneditor {
min-height: 150px;
}
div.jsoneditor-tree {
width: 100%;
height: 100%;
position: relative;
overflow: auto;
}
textarea.jsoneditor-text {
width: 100%;
height: 100%;
margin: 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
outline-width: 0;
border: none;
background-color: white;
resize: none;
}
tr.jsoneditor-highlight,
tr.jsoneditor-selected {
background-color: #e6e6e6;
}
tr.jsoneditor-selected button.jsoneditor-dragarea,
tr.jsoneditor-selected button.jsoneditor-contextmenu {
visibility: hidden;
}
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea,
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-contextmenu {
visibility: visible;
}
div.jsoneditor-tree button.jsoneditor-dragarea {
background: url('img/jsoneditor-icons.svg') -72px -72px;
cursor: move;
}
div.jsoneditor-tree button.jsoneditor-dragarea:hover,
div.jsoneditor-tree button.jsoneditor-dragarea:focus,
tr.jsoneditor-selected.jsoneditor-first button.jsoneditor-dragarea {
background-position: -72px -48px;
}
div.jsoneditor tr,
div.jsoneditor th,
div.jsoneditor td {
padding: 0;
margin: 0;
}
div.jsoneditor td {
vertical-align: top;
}
div.jsoneditor td.jsoneditor-tree {
vertical-align: top;
}
div.jsoneditor-field,
div.jsoneditor-value,
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-size: 10pt;
color: #1A1A1A;
}
/* popover */
.jsoneditor-schema-error {
cursor: default;
display: inline-block;
/*font-family: arial, sans-serif;*/
height: 24px;
line-height: 24px;
position: relative;
text-align: center;
width: 24px;
}
div.jsoneditor-tree .jsoneditor-schema-error {
width: 24px;
height: 24px;
padding: 0;
margin: 0 4px 0 0;
background: url('img/jsoneditor-icons.svg') -168px -48px;
}
.jsoneditor-schema-error .jsoneditor-popover {
background-color: #4c4c4c;
border-radius: 3px;
box-shadow: 0 0 5px rgba(0,0,0,0.4);
color: #fff;
display: none;
padding: 7px 10px;
position: absolute;
width: 200px;
z-index: 4;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above {
bottom: 32px;
left: -98px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below {
top: 32px;
left: -98px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left {
top: -7px;
right: 32px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right {
top: -7px;
left: 32px;
}
.jsoneditor-schema-error .jsoneditor-popover:before {
border-right: 7px solid transparent;
border-left: 7px solid transparent;
content: '';
display: block;
left: 50%;
margin-left: -7px;
position: absolute;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-above:before {
border-top: 7px solid #4c4c4c;
bottom: -7px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-below:before {
border-bottom: 7px solid #4c4c4c;
top: -7px;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-left:before {
border-left: 7px solid #4c4c4c;
border-top: 7px solid transparent;
border-bottom: 7px solid transparent;
content: '';
top: 19px;
right: -14px;
left: inherit;
margin-left: inherit;
margin-top: -7px;
position: absolute;
}
.jsoneditor-schema-error .jsoneditor-popover.jsoneditor-right:before {
border-right: 7px solid #4c4c4c;
border-top: 7px solid transparent;
border-bottom: 7px solid transparent;
content: '';
top: 19px;
left: -14px;
margin-left: inherit;
margin-top: -7px;
position: absolute;
}
.jsoneditor-schema-error:hover .jsoneditor-popover,
.jsoneditor-schema-error:focus .jsoneditor-popover {
display: block;
-webkit-animation: fade-in .3s linear 1, move-up .3s linear 1;
-moz-animation: fade-in .3s linear 1, move-up .3s linear 1;
-ms-animation: fade-in .3s linear 1, move-up .3s linear 1;
}
@-webkit-keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@-moz-keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@-ms-keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
/*@-webkit-keyframes move-up {*/
/*from { bottom: 24px; }*/
/*to { bottom: 32px; }*/
/*}*/
/*@-moz-keyframes move-up {*/
/*from { bottom: 24px; }*/
/*to { bottom: 32px; }*/
/*}*/
/*@-ms-keyframes move-up {*/
/*from { bottom: 24px; }*/
/*to { bottom: 32px; }*/
/*}*/
/* JSON schema errors displayed at the bottom of the editor in mode text and code */
.jsoneditor .jsoneditor-text-errors {
width: 100%;
border-collapse: collapse;
background-color: #ffef8b;
border-top: 1px solid #ffd700;
}
.jsoneditor .jsoneditor-text-errors td {
padding: 3px 6px;
vertical-align: middle;
}
.jsoneditor-text-errors .jsoneditor-schema-error {
border: none;
width: 24px;
height: 24px;
padding: 0;
margin: 0 4px 0 0;
background: url('img/jsoneditor-icons.svg') -168px -48px;
}

View File

@ -1,110 +0,0 @@
div.jsoneditor-menu {
width: 100%;
height: 35px;
padding: 2px;
margin: 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: white;
background-color: #3883fa;
border-bottom: 1px solid #3883fa;
}
div.jsoneditor-menu > button,
div.jsoneditor-menu > div.jsoneditor-modes > button {
width: 26px;
height: 26px;
margin: 2px;
padding: 0;
border-radius: 2px;
border: 1px solid transparent;
background: transparent url('img/jsoneditor-icons.svg');
color: white;
opacity: 0.8;
font-family: arial, sans-serif;
font-size: 10pt;
float: left;
}
div.jsoneditor-menu > button:hover,
div.jsoneditor-menu > div.jsoneditor-modes > button:hover {
background-color: rgba(255,255,255,0.2);
border: 1px solid rgba(255,255,255,0.4);
}
div.jsoneditor-menu > button:focus,
div.jsoneditor-menu > button:active,
div.jsoneditor-menu > div.jsoneditor-modes > button:focus,
div.jsoneditor-menu > div.jsoneditor-modes > button:active {
background-color: rgba(255,255,255,0.3);
}
div.jsoneditor-menu > button:disabled,
div.jsoneditor-menu > div.jsoneditor-modes > button:disabled {
opacity: 0.5;
}
div.jsoneditor-menu > button.jsoneditor-collapse-all {
background-position: 0 -96px;
}
div.jsoneditor-menu > button.jsoneditor-expand-all {
background-position: 0 -120px;
}
div.jsoneditor-menu > button.jsoneditor-undo {
background-position: -24px -96px;
}
div.jsoneditor-menu > button.jsoneditor-undo:disabled {
background-position: -24px -120px;
}
div.jsoneditor-menu > button.jsoneditor-redo {
background-position: -48px -96px;
}
div.jsoneditor-menu > button.jsoneditor-redo:disabled {
background-position: -48px -120px;
}
div.jsoneditor-menu > button.jsoneditor-compact {
background-position: -72px -96px;
}
div.jsoneditor-menu > button.jsoneditor-format {
background-position: -72px -120px;
}
div.jsoneditor-menu > div.jsoneditor-modes {
display: inline-block;
float: left;
}
div.jsoneditor-menu > div.jsoneditor-modes > button {
background-image: none;
width: auto;
padding-left: 6px;
padding-right: 6px;
}
div.jsoneditor-menu > button.jsoneditor-separator,
div.jsoneditor-menu > div.jsoneditor-modes > button.jsoneditor-separator {
margin-left: 10px;
}
div.jsoneditor-menu a {
font-family: arial, sans-serif;
font-size: 10pt;
color: white;
opacity: 0.8;
vertical-align: middle;
}
div.jsoneditor-menu a:hover {
opacity: 1;
}
div.jsoneditor-menu a.jsoneditor-poweredBy {
font-size: 8pt;
position: absolute;
right: 0;
top: 0;
padding: 10px;
}

View File

@ -1,25 +0,0 @@
/* reset styling (prevent conflicts with bootstrap, materialize.css, etc.) */
div.jsoneditor input {
height: auto;
border: inherit;
}
div.jsoneditor input:focus {
border: none !important;
box-shadow: none !important;
}
div.jsoneditor table {
border-collapse: collapse;
width: auto;
}
div.jsoneditor td,
div.jsoneditor th {
padding: 0;
display: table-cell;
text-align: left;
vertical-align: inherit;
border-radius: inherit;
}

View File

@ -1,77 +0,0 @@
table.jsoneditor-search input,
table.jsoneditor-search div.jsoneditor-results {
font-family: arial, sans-serif;
font-size: 10pt;
color: #1A1A1A;
background: transparent; /* For Firefox */
}
table.jsoneditor-search div.jsoneditor-results {
color: white;
padding-right: 5px;
line-height: 24px;
}
table.jsoneditor-search {
position: absolute;
right: 4px;
top: 4px;
border-collapse: collapse;
border-spacing: 0;
}
table.jsoneditor-search div.jsoneditor-frame {
border: 1px solid transparent;
background-color: white;
padding: 0 2px;
margin: 0;
}
table.jsoneditor-search div.jsoneditor-frame table {
border-collapse: collapse;
}
table.jsoneditor-search input {
width: 120px;
border: none;
outline: none;
margin: 1px;
line-height: 20px;
}
table.jsoneditor-search button {
width: 16px;
height: 24px;
padding: 0;
margin: 0;
border: none;
background: url('img/jsoneditor-icons.svg');
vertical-align: top;
}
table.jsoneditor-search button:hover {
background-color: transparent;
}
table.jsoneditor-search button.jsoneditor-refresh {
width: 18px;
background-position: -99px -73px;
}
table.jsoneditor-search button.jsoneditor-next {
cursor: pointer;
background-position: -124px -73px;
}
table.jsoneditor-search button.jsoneditor-next:hover {
background-position: -124px -49px;
}
table.jsoneditor-search button.jsoneditor-previous {
cursor: pointer;
background-position: -148px -73px;
margin-right: 2px;
}
table.jsoneditor-search button.jsoneditor-previous:hover {
background-position: -148px -49px;
}

View File

@ -21,9 +21,10 @@ The minimalist version has excluded the following libraries:
- `ace` (via `brace`), used for the code editor.
- `ajv`, used for JSON schema validation.
- `vanilla-picker`, used as color picker.
This reduces the the size of the minified and gzipped JavaScript file from
about 160 kB to about 40 kB.
This reduces the the size of the minified and gzipped JavaScript file
from about 210 kB to about 70 kB (one third).
When to use the minimalist version?
@ -31,6 +32,8 @@ When to use the minimalist version?
- Or if you want to provide `ace` and/or `ajv` yourself via the configuration
options, for example when you already use Ace in other parts of your
web application too and don't want to bundle the library twice.
- You don't need the color picker, or want to provide your own
color picker using `onColorPicker`.
Which files are needed when using the minimalist version?

View File

@ -1,6 +1,8 @@
'use strict';
'use strict'
var util = require('./util');
import { createAbsoluteAnchor } from './createAbsoluteAnchor'
import { addClassName, getSelection, removeClassName, setSelection } from './util'
import { translate } from './i18n'
/**
* A context menu
@ -11,447 +13,423 @@ var util = require('./util');
* context menu is being closed.
* @constructor
*/
function ContextMenu (items, options) {
this.dom = {};
export class ContextMenu {
constructor (items, options) {
this.dom = {}
var me = this;
var dom = this.dom;
this.anchor = undefined;
this.items = items;
this.eventListeners = {};
this.selection = undefined; // holds the selection before the menu was opened
this.onClose = options ? options.close : undefined;
const me = this
const dom = this.dom
this.anchor = undefined
this.items = items
this.eventListeners = {}
this.selection = undefined // holds the selection before the menu was opened
this.onClose = options ? options.close : undefined
// create root element
var root = document.createElement('div');
root.className = 'jsoneditor-contextmenu-root';
dom.root = root;
// create root element
const root = document.createElement('div')
root.className = 'jsoneditor-contextmenu-root'
dom.root = root
// create a container element
var menu = document.createElement('div');
menu.className = 'jsoneditor-contextmenu';
dom.menu = menu;
root.appendChild(menu);
// create a container element
const menu = document.createElement('div')
menu.className = 'jsoneditor-contextmenu'
dom.menu = menu
root.appendChild(menu)
// create a list to hold the menu items
var list = document.createElement('ul');
list.className = 'jsoneditor-menu';
menu.appendChild(list);
dom.list = list;
dom.items = []; // list with all buttons
// create a list to hold the menu items
const list = document.createElement('ul')
list.className = 'jsoneditor-menu'
menu.appendChild(list)
dom.list = list
dom.items = [] // list with all buttons
// create a (non-visible) button to set the focus to the menu
var focusButton = document.createElement('button');
dom.focusButton = focusButton;
var li = document.createElement('li');
li.style.overflow = 'hidden';
li.style.height = '0';
li.appendChild(focusButton);
list.appendChild(li);
// create a (non-visible) button to set the focus to the menu
const focusButton = document.createElement('button')
focusButton.type = 'button'
dom.focusButton = focusButton
const li = document.createElement('li')
li.style.overflow = 'hidden'
li.style.height = '0'
li.appendChild(focusButton)
list.appendChild(li)
function createMenuItems (list, domItems, items) {
items.forEach(function (item) {
if (item.type == 'separator') {
// create a separator
var separator = document.createElement('div');
separator.className = 'jsoneditor-separator';
li = document.createElement('li');
li.appendChild(separator);
list.appendChild(li);
}
else {
var domItem = {};
function createMenuItems (list, domItems, items) {
items.forEach(item => {
if (item.type === 'separator') {
// create a separator
const separator = document.createElement('div')
separator.className = 'jsoneditor-separator'
const li = document.createElement('li')
li.appendChild(separator)
list.appendChild(li)
} else {
const domItem = {}
// create a menu item
var li = document.createElement('li');
list.appendChild(li);
// create a menu item
const li = document.createElement('li')
list.appendChild(li)
// create a button in the menu item
var button = document.createElement('button');
button.className = item.className;
domItem.button = button;
if (item.title) {
button.title = item.title;
}
if (item.click) {
button.onclick = function (event) {
event.preventDefault();
me.hide();
item.click();
};
}
li.appendChild(button);
// create the contents of the button
if (item.submenu) {
// add the icon to the button
var divIcon = document.createElement('div');
divIcon.className = 'jsoneditor-icon';
button.appendChild(divIcon);
button.appendChild(document.createTextNode(item.text));
var buttonSubmenu;
// create a button in the menu item
const button = document.createElement('button')
button.type = 'button'
button.className = item.className
domItem.button = button
if (item.title) {
button.title = item.title
}
if (item.click) {
// submenu and a button with a click handler
button.className += ' jsoneditor-default';
button.onclick = event => {
event.preventDefault()
me.hide()
item.click()
}
}
li.appendChild(button)
var buttonExpand = document.createElement('button');
domItem.buttonExpand = buttonExpand;
buttonExpand.className = 'jsoneditor-expand';
buttonExpand.innerHTML = '<div class="jsoneditor-expand"></div>';
li.appendChild(buttonExpand);
if (item.submenuTitle) {
buttonExpand.title = item.submenuTitle;
// create the contents of the button
if (item.submenu) {
// add the icon to the button
const divIcon = document.createElement('div')
divIcon.className = 'jsoneditor-icon'
button.appendChild(divIcon)
const divText = document.createElement('div')
divText.className = 'jsoneditor-text' +
(item.click ? '' : ' jsoneditor-right-margin')
divText.appendChild(document.createTextNode(item.text))
button.appendChild(divText)
let buttonSubmenu
if (item.click) {
// submenu and a button with a click handler
button.className += ' jsoneditor-default'
const buttonExpand = document.createElement('button')
buttonExpand.type = 'button'
domItem.buttonExpand = buttonExpand
buttonExpand.className = 'jsoneditor-expand'
const buttonExpandInner = document.createElement('div')
buttonExpandInner.className = 'jsoneditor-expand'
buttonExpand.appendChild(buttonExpandInner)
li.appendChild(buttonExpand)
if (item.submenuTitle) {
buttonExpand.title = item.submenuTitle
}
buttonSubmenu = buttonExpand
} else {
// submenu and a button without a click handler
const divExpand = document.createElement('div')
divExpand.className = 'jsoneditor-expand'
button.appendChild(divExpand)
buttonSubmenu = button
}
buttonSubmenu = buttonExpand;
}
else {
// submenu and a button without a click handler
var divExpand = document.createElement('div');
divExpand.className = 'jsoneditor-expand';
button.appendChild(divExpand);
// attach a handler to expand/collapse the submenu
buttonSubmenu.onclick = event => {
event.preventDefault()
me._onExpandItem(domItem)
buttonSubmenu.focus()
}
buttonSubmenu = button;
// create the submenu
const domSubItems = []
domItem.subItems = domSubItems
const ul = document.createElement('ul')
domItem.ul = ul
ul.className = 'jsoneditor-menu'
ul.style.height = '0'
li.appendChild(ul)
createMenuItems(ul, domSubItems, item.submenu)
} else {
// no submenu, just a button with clickhandler
const icon = document.createElement('div')
icon.className = 'jsoneditor-icon'
button.appendChild(icon)
const text = document.createElement('div')
text.className = 'jsoneditor-text'
text.appendChild(document.createTextNode(translate(item.text)))
button.appendChild(text)
}
// attach a handler to expand/collapse the submenu
buttonSubmenu.onclick = function (event) {
event.preventDefault();
me._onExpandItem(domItem);
buttonSubmenu.focus();
};
// create the submenu
var domSubItems = [];
domItem.subItems = domSubItems;
var ul = document.createElement('ul');
domItem.ul = ul;
ul.className = 'jsoneditor-menu';
ul.style.height = '0';
li.appendChild(ul);
createMenuItems(ul, domSubItems, item.submenu);
}
else {
// no submenu, just a button with clickhandler
button.innerHTML = '<div class="jsoneditor-icon"></div>' + item.text;
domItems.push(domItem)
}
})
}
createMenuItems(list, this.dom.items, items)
domItems.push(domItem);
}
});
// TODO: when the editor is small, show the submenu on the right instead of inline?
// calculate the max height of the menu with one submenu expanded
this.maxHeight = 0 // height in pixels
items.forEach(item => {
const height = (items.length + (item.submenu ? item.submenu.length : 0)) * 24
me.maxHeight = Math.max(me.maxHeight, height)
})
}
createMenuItems(list, this.dom.items, items);
// TODO: when the editor is small, show the submenu on the right instead of inline?
/**
* Get the currently visible buttons
* @return {Array.<HTMLElement>} buttons
* @private
*/
_getVisibleButtons () {
const buttons = []
const me = this
this.dom.items.forEach(item => {
buttons.push(item.button)
if (item.buttonExpand) {
buttons.push(item.buttonExpand)
}
if (item.subItems && item === me.expandedItem) {
item.subItems.forEach(subItem => {
buttons.push(subItem.button)
if (subItem.buttonExpand) {
buttons.push(subItem.buttonExpand)
}
// TODO: change to fully recursive method
})
}
})
// calculate the max height of the menu with one submenu expanded
this.maxHeight = 0; // height in pixels
items.forEach(function (item) {
var height = (items.length + (item.submenu ? item.submenu.length : 0)) * 24;
me.maxHeight = Math.max(me.maxHeight, height);
});
}
return buttons
}
/**
* Get the currently visible buttons
* @return {Array.<HTMLElement>} buttons
* @private
*/
ContextMenu.prototype._getVisibleButtons = function () {
var buttons = [];
var me = this;
this.dom.items.forEach(function (item) {
buttons.push(item.button);
if (item.buttonExpand) {
buttons.push(item.buttonExpand);
}
if (item.subItems && item == me.expandedItem) {
item.subItems.forEach(function (subItem) {
buttons.push(subItem.button);
if (subItem.buttonExpand) {
buttons.push(subItem.buttonExpand);
}
// TODO: change to fully recursive method
});
}
});
/**
* Attach the menu to an anchor
* @param {HTMLElement} anchor Anchor where the menu will be attached as sibling.
* @param {HTMLElement} frame The root of the JSONEditor window
* @param {Boolean=} ignoreParent ignore anchor parent in regard to the calculation of the position, needed when the parent position is absolute
*/
show (anchor, frame, ignoreParent) {
this.hide()
return buttons;
};
// determine whether to display the menu below or above the anchor
let showBelow = true
const parent = anchor.parentNode
const anchorRect = anchor.getBoundingClientRect()
const parentRect = parent.getBoundingClientRect()
const frameRect = frame.getBoundingClientRect()
// currently displayed context menu, a singleton. We may only have one visible context menu
ContextMenu.visibleMenu = undefined;
const me = this
this.dom.absoluteAnchor = createAbsoluteAnchor(anchor, frame, () => {
me.hide()
})
/**
* Attach the menu to an anchor
* @param {HTMLElement} anchor Anchor where the menu will be attached
* as sibling.
* @param {HTMLElement} [contentWindow] The DIV with with the (scrollable) contents
*/
ContextMenu.prototype.show = function (anchor, contentWindow) {
this.hide();
// determine whether to display the menu below or above the anchor
var showBelow = true;
if (contentWindow) {
var anchorRect = anchor.getBoundingClientRect();
var contentRect = contentWindow.getBoundingClientRect();
if (anchorRect.bottom + this.maxHeight < contentRect.bottom) {
if (anchorRect.bottom + this.maxHeight < frameRect.bottom) {
// fits below -> show below
}
else if (anchorRect.top - this.maxHeight > contentRect.top) {
} else if (anchorRect.top - this.maxHeight > frameRect.top) {
// fits above -> show above
showBelow = false;
}
else {
showBelow = false
} else {
// doesn't fit above nor below -> show below
}
}
// position the menu
if (showBelow) {
// display the menu below the anchor
var anchorHeight = anchor.offsetHeight;
this.dom.menu.style.left = '0px';
this.dom.menu.style.top = anchorHeight + 'px';
this.dom.menu.style.bottom = '';
}
else {
// display the menu above the anchor
this.dom.menu.style.left = '0px';
this.dom.menu.style.top = '';
this.dom.menu.style.bottom = '0px';
}
const topGap = ignoreParent ? 0 : (anchorRect.top - parentRect.top)
// attach the menu to the parent of the anchor
var parent = anchor.parentNode;
parent.insertBefore(this.dom.root, parent.firstChild);
// create and attach event listeners
var me = this;
var list = this.dom.list;
this.eventListeners.mousedown = util.addEventListener(window, 'mousedown', function (event) {
// hide menu on click outside of the menu
var target = event.target;
if ((target != list) && !me._isChildOf(target, list)) {
me.hide();
event.stopPropagation();
event.preventDefault();
}
});
this.eventListeners.keydown = util.addEventListener(window, 'keydown', function (event) {
me._onKeyDown(event);
});
// move focus to the first button in the context menu
this.selection = util.getSelection();
this.anchor = anchor;
setTimeout(function () {
me.dom.focusButton.focus();
}, 0);
if (ContextMenu.visibleMenu) {
ContextMenu.visibleMenu.hide();
}
ContextMenu.visibleMenu = this;
};
/**
* Hide the context menu if visible
*/
ContextMenu.prototype.hide = function () {
// remove the menu from the DOM
if (this.dom.root.parentNode) {
this.dom.root.parentNode.removeChild(this.dom.root);
if (this.onClose) {
this.onClose();
}
}
// remove all event listeners
// all event listeners are supposed to be attached to document.
for (var name in this.eventListeners) {
if (this.eventListeners.hasOwnProperty(name)) {
var fn = this.eventListeners[name];
if (fn) {
util.removeEventListener(window, name, fn);
}
delete this.eventListeners[name];
}
}
if (ContextMenu.visibleMenu == this) {
ContextMenu.visibleMenu = undefined;
}
};
/**
* Expand a submenu
* Any currently expanded submenu will be hided.
* @param {Object} domItem
* @private
*/
ContextMenu.prototype._onExpandItem = function (domItem) {
var me = this;
var alreadyVisible = (domItem == this.expandedItem);
// hide the currently visible submenu
var expandedItem = this.expandedItem;
if (expandedItem) {
//var ul = expandedItem.ul;
expandedItem.ul.style.height = '0';
expandedItem.ul.style.padding = '';
setTimeout(function () {
if (me.expandedItem != expandedItem) {
expandedItem.ul.style.display = '';
util.removeClassName(expandedItem.ul.parentNode, 'jsoneditor-selected');
}
}, 300); // timeout duration must match the css transition duration
this.expandedItem = undefined;
}
if (!alreadyVisible) {
var ul = domItem.ul;
ul.style.display = 'block';
var height = ul.clientHeight; // force a reflow in Firefox
setTimeout(function () {
if (me.expandedItem == domItem) {
ul.style.height = (ul.childNodes.length * 24) + 'px';
ul.style.padding = '5px 10px';
}
}, 0);
util.addClassName(ul.parentNode, 'jsoneditor-selected');
this.expandedItem = domItem;
}
};
/**
* Handle onkeydown event
* @param {Event} event
* @private
*/
ContextMenu.prototype._onKeyDown = function (event) {
var target = event.target;
var keynum = event.which;
var handled = false;
var buttons, targetIndex, prevButton, nextButton;
if (keynum == 27) { // ESC
// hide the menu on ESC key
// restore previous selection and focus
if (this.selection) {
util.setSelection(this.selection);
}
if (this.anchor) {
this.anchor.focus();
// position the menu
if (showBelow) {
// display the menu below the anchor
const anchorHeight = anchor.offsetHeight
this.dom.menu.style.left = '0'
this.dom.menu.style.top = topGap + anchorHeight + 'px'
this.dom.menu.style.bottom = ''
} else {
// display the menu above the anchor
this.dom.menu.style.left = '0'
this.dom.menu.style.top = ''
this.dom.menu.style.bottom = '0px'
}
this.hide();
// attach the menu to the temporary, absolute anchor
// parent.insertBefore(this.dom.root, anchor);
this.dom.absoluteAnchor.appendChild(this.dom.root)
handled = true;
// move focus to the first button in the context menu
this.selection = getSelection()
this.anchor = anchor
setTimeout(() => {
me.dom.focusButton.focus()
}, 0)
if (ContextMenu.visibleMenu) {
ContextMenu.visibleMenu.hide()
}
ContextMenu.visibleMenu = this
}
else if (keynum == 9) { // Tab
if (!event.shiftKey) { // Tab
buttons = this._getVisibleButtons();
targetIndex = buttons.indexOf(target);
if (targetIndex == buttons.length - 1) {
// move to first button
buttons[0].focus();
handled = true;
/**
* Hide the context menu if visible
*/
hide () {
// remove temporary absolutely positioned anchor
if (this.dom.absoluteAnchor) {
this.dom.absoluteAnchor.destroy()
delete this.dom.absoluteAnchor
}
// remove the menu from the DOM
if (this.dom.root.parentNode) {
this.dom.root.parentNode.removeChild(this.dom.root)
if (this.onClose) {
this.onClose()
}
}
else { // Shift+Tab
buttons = this._getVisibleButtons();
targetIndex = buttons.indexOf(target);
if (targetIndex == 0) {
if (ContextMenu.visibleMenu === this) {
ContextMenu.visibleMenu = undefined
}
}
/**
* Expand a submenu
* Any currently expanded submenu will be hided.
* @param {Object} domItem
* @private
*/
_onExpandItem (domItem) {
const me = this
const alreadyVisible = (domItem === this.expandedItem)
// hide the currently visible submenu
const expandedItem = this.expandedItem
if (expandedItem) {
// var ul = expandedItem.ul;
expandedItem.ul.style.height = '0'
expandedItem.ul.style.padding = ''
setTimeout(() => {
if (me.expandedItem !== expandedItem) {
expandedItem.ul.style.display = ''
removeClassName(expandedItem.ul.parentNode, 'jsoneditor-selected')
}
}, 300) // timeout duration must match the css transition duration
this.expandedItem = undefined
}
if (!alreadyVisible) {
const ul = domItem.ul
ul.style.display = 'block'
// eslint-disable-next-line no-unused-expressions
ul.clientHeight // force a reflow in Firefox
setTimeout(() => {
if (me.expandedItem === domItem) {
let childsHeight = 0
for (let i = 0; i < ul.childNodes.length; i++) {
childsHeight += ul.childNodes[i].clientHeight
}
ul.style.height = childsHeight + 'px'
ul.style.padding = '5px 10px'
}
}, 0)
addClassName(ul.parentNode, 'jsoneditor-selected')
this.expandedItem = domItem
}
}
/**
* Handle onkeydown event
* @param {Event} event
* @private
*/
_onKeyDown (event) {
const target = event.target
const keynum = event.which
let handled = false
let buttons, targetIndex, prevButton, nextButton
if (keynum === 27) { // ESC
// hide the menu on ESC key
// restore previous selection and focus
if (this.selection) {
setSelection(this.selection)
}
if (this.anchor) {
this.anchor.focus()
}
this.hide()
handled = true
} else if (keynum === 9) { // Tab
if (!event.shiftKey) { // Tab
buttons = this._getVisibleButtons()
targetIndex = buttons.indexOf(target)
if (targetIndex === buttons.length - 1) {
// move to first button
buttons[0].focus()
handled = true
}
} else { // Shift+Tab
buttons = this._getVisibleButtons()
targetIndex = buttons.indexOf(target)
if (targetIndex === 0) {
// move to last button
buttons[buttons.length - 1].focus()
handled = true
}
}
} else if (keynum === 37) { // Arrow Left
if (target.className === 'jsoneditor-expand') {
buttons = this._getVisibleButtons()
targetIndex = buttons.indexOf(target)
prevButton = buttons[targetIndex - 1]
if (prevButton) {
prevButton.focus()
}
}
handled = true
} else if (keynum === 38) { // Arrow Up
buttons = this._getVisibleButtons()
targetIndex = buttons.indexOf(target)
prevButton = buttons[targetIndex - 1]
if (prevButton && prevButton.className === 'jsoneditor-expand') {
// skip expand button
prevButton = buttons[targetIndex - 2]
}
if (!prevButton) {
// move to last button
buttons[buttons.length - 1].focus();
handled = true;
prevButton = buttons[buttons.length - 1]
}
}
}
else if (keynum == 37) { // Arrow Left
if (target.className == 'jsoneditor-expand') {
buttons = this._getVisibleButtons();
targetIndex = buttons.indexOf(target);
prevButton = buttons[targetIndex - 1];
if (prevButton) {
prevButton.focus();
prevButton.focus()
}
handled = true
} else if (keynum === 39) { // Arrow Right
buttons = this._getVisibleButtons()
targetIndex = buttons.indexOf(target)
nextButton = buttons[targetIndex + 1]
if (nextButton && nextButton.className === 'jsoneditor-expand') {
nextButton.focus()
}
handled = true
} else if (keynum === 40) { // Arrow Down
buttons = this._getVisibleButtons()
targetIndex = buttons.indexOf(target)
nextButton = buttons[targetIndex + 1]
if (nextButton && nextButton.className === 'jsoneditor-expand') {
// skip expand button
nextButton = buttons[targetIndex + 2]
}
if (!nextButton) {
// move to first button
nextButton = buttons[0]
}
if (nextButton) {
nextButton.focus()
handled = true
}
handled = true
}
handled = true;
}
else if (keynum == 38) { // Arrow Up
buttons = this._getVisibleButtons();
targetIndex = buttons.indexOf(target);
prevButton = buttons[targetIndex - 1];
if (prevButton && prevButton.className == 'jsoneditor-expand') {
// skip expand button
prevButton = buttons[targetIndex - 2];
}
if (!prevButton) {
// move to last button
prevButton = buttons[buttons.length - 1];
}
if (prevButton) {
prevButton.focus();
}
handled = true;
}
else if (keynum == 39) { // Arrow Right
buttons = this._getVisibleButtons();
targetIndex = buttons.indexOf(target);
nextButton = buttons[targetIndex + 1];
if (nextButton && nextButton.className == 'jsoneditor-expand') {
nextButton.focus();
}
handled = true;
}
else if (keynum == 40) { // Arrow Down
buttons = this._getVisibleButtons();
targetIndex = buttons.indexOf(target);
nextButton = buttons[targetIndex + 1];
if (nextButton && nextButton.className == 'jsoneditor-expand') {
// skip expand button
nextButton = buttons[targetIndex + 2];
}
if (!nextButton) {
// move to first button
nextButton = buttons[0];
}
if (nextButton) {
nextButton.focus();
handled = true;
}
handled = true;
}
// TODO: arrow left and right
// TODO: arrow left and right
if (handled) {
event.stopPropagation();
event.preventDefault();
}
};
/**
* Test if an element is a child of a parent element.
* @param {Element} child
* @param {Element} parent
* @return {boolean} isChild
*/
ContextMenu.prototype._isChildOf = function (child, parent) {
var e = child.parentNode;
while (e) {
if (e == parent) {
return true;
if (handled) {
event.stopPropagation()
event.preventDefault()
}
e = e.parentNode;
}
}
return false;
};
module.exports = ContextMenu;
// currently displayed context menu, a singleton. We may only have one visible context menu
ContextMenu.visibleMenu = undefined

194
src/js/ErrorTable.js Normal file
View File

@ -0,0 +1,194 @@
/**
* Show errors and schema warnings in a clickable table view
* @param {Object} config
* @property {boolean} errorTableVisible
* @property {function (boolean) : void} onToggleVisibility
* @property {function (number)} [onFocusLine]
* @property {function (number)} onChangeHeight
* @constructor
*/
export class ErrorTable {
constructor (config) {
this.errorTableVisible = config.errorTableVisible
this.onToggleVisibility = config.onToggleVisibility
this.onFocusLine = config.onFocusLine || (() => {})
this.onChangeHeight = config.onChangeHeight
this.dom = {}
const validationErrorsContainer = document.createElement('div')
validationErrorsContainer.className = 'jsoneditor-validation-errors-container'
this.dom.validationErrorsContainer = validationErrorsContainer
const additionalErrorsIndication = document.createElement('div')
additionalErrorsIndication.style.display = 'none'
additionalErrorsIndication.className = 'jsoneditor-additional-errors fadein'
additionalErrorsIndication.textContent = 'Scroll for more \u25BF'
this.dom.additionalErrorsIndication = additionalErrorsIndication
validationErrorsContainer.appendChild(additionalErrorsIndication)
const validationErrorIcon = document.createElement('span')
validationErrorIcon.className = 'jsoneditor-validation-error-icon'
validationErrorIcon.style.display = 'none'
this.dom.validationErrorIcon = validationErrorIcon
const validationErrorCount = document.createElement('span')
validationErrorCount.className = 'jsoneditor-validation-error-count'
validationErrorCount.style.display = 'none'
this.dom.validationErrorCount = validationErrorCount
this.dom.parseErrorIndication = document.createElement('span')
this.dom.parseErrorIndication.className = 'jsoneditor-parse-error-icon'
this.dom.parseErrorIndication.style.display = 'none'
}
getErrorTable () {
return this.dom.validationErrorsContainer
}
getErrorCounter () {
return this.dom.validationErrorCount
}
getWarningIcon () {
return this.dom.validationErrorIcon
}
getErrorIcon () {
return this.dom.parseErrorIndication
}
toggleTableVisibility () {
this.errorTableVisible = !this.errorTableVisible
this.onToggleVisibility(this.errorTableVisible)
}
setErrors (errors, errorLocations) {
// clear any previous errors
if (this.dom.validationErrors) {
this.dom.validationErrors.parentNode.removeChild(this.dom.validationErrors)
this.dom.validationErrors = null
this.dom.additionalErrorsIndication.style.display = 'none'
}
// create the table with errors
// keep default behavior for parse errors
if (this.errorTableVisible && errors.length > 0) {
const validationErrors = document.createElement('div')
validationErrors.className = 'jsoneditor-validation-errors'
const table = document.createElement('table')
table.className = 'jsoneditor-text-errors'
validationErrors.appendChild(table)
const tbody = document.createElement('tbody')
table.appendChild(tbody)
errors.forEach(error => {
let line
if (!isNaN(error.line)) {
line = error.line
} else if (error.dataPath) {
const errLoc = errorLocations.find(loc => loc.path === error.dataPath)
if (errLoc) {
line = errLoc.line + 1
}
}
const trEl = document.createElement('tr')
trEl.className = !isNaN(line) ? 'jump-to-line' : ''
if (error.type === 'error') {
trEl.className += ' parse-error'
} else {
trEl.className += ' validation-error'
}
const td1 = document.createElement('td')
const button = document.createElement('button')
button.className = 'jsoneditor-schema-error'
td1.appendChild(button)
trEl.appendChild(td1)
const td2 = document.createElement('td')
td2.style = 'white-space: nowrap;'
td2.textContent = (!isNaN(line) ? ('Ln ' + line) : '')
trEl.appendChild(td2)
if (typeof error === 'string') {
const td34 = document.createElement('td')
td34.colSpan = 2
const pre = document.createElement('pre')
pre.appendChild(document.createTextNode(error))
td34.appendChild(pre)
trEl.appendChild(td34)
} else {
const td3 = document.createElement('td')
td3.appendChild(document.createTextNode(error.dataPath || ''))
trEl.appendChild(td3)
const td4 = document.createElement('td')
const pre = document.createElement('pre')
pre.appendChild(document.createTextNode(error.message))
td4.appendChild(pre)
trEl.appendChild(td4)
}
trEl.onclick = () => {
this.onFocusLine(line)
}
tbody.appendChild(trEl)
})
this.dom.validationErrors = validationErrors
this.dom.validationErrorsContainer.appendChild(validationErrors)
this.dom.additionalErrorsIndication.title = errors.length + ' errors total'
if (this.dom.validationErrorsContainer.clientHeight < this.dom.validationErrorsContainer.scrollHeight) {
this.dom.additionalErrorsIndication.style.display = 'block'
this.dom.validationErrorsContainer.onscroll = () => {
this.dom.additionalErrorsIndication.style.display =
(this.dom.validationErrorsContainer.clientHeight > 0 && this.dom.validationErrorsContainer.scrollTop === 0) ? 'block' : 'none'
}
} else {
this.dom.validationErrorsContainer.onscroll = undefined
}
const height = this.dom.validationErrorsContainer.clientHeight + (this.dom.statusBar ? this.dom.statusBar.clientHeight : 0)
// this.content.style.marginBottom = (-height) + 'px';
// this.content.style.paddingBottom = height + 'px';
this.onChangeHeight(height)
} else {
this.onChangeHeight(0)
}
// update the status bar
const validationErrorsCount = errors.filter(error => error.type !== 'error').length
if (validationErrorsCount > 0) {
this.dom.validationErrorCount.style.display = 'inline'
this.dom.validationErrorCount.innerText = validationErrorsCount
this.dom.validationErrorCount.onclick = this.toggleTableVisibility.bind(this)
this.dom.validationErrorIcon.style.display = 'inline'
this.dom.validationErrorIcon.title = validationErrorsCount + ' schema validation error(s) found'
this.dom.validationErrorIcon.onclick = this.toggleTableVisibility.bind(this)
} else {
this.dom.validationErrorCount.style.display = 'none'
this.dom.validationErrorIcon.style.display = 'none'
}
// update the parse error icon
const hasParseErrors = errors.some(error => error.type === 'error')
if (hasParseErrors) {
const line = errors[0].line
this.dom.parseErrorIndication.style.display = 'block'
this.dom.parseErrorIndication.title = !isNaN(line)
? ('parse error on line ' + line)
: 'parse error - check that the json is valid'
this.dom.parseErrorIndication.onclick = this.toggleTableVisibility.bind(this)
} else {
this.dom.parseErrorIndication.style.display = 'none'
}
}
}

100
src/js/FocusTracker.js Normal file
View File

@ -0,0 +1,100 @@
'use strict'
/**
* @constructor FocusTracker
* A custom focus tracker for a DOM element with complex internal DOM structure
* @param {[Object]} config A set of configurations for the FocusTracker
* {DOM Object} target * The DOM object to track (required)
* {Function} onFocus onFocus callback
* {Function} onBlur onBlur callback
*
* @return
*/
export class FocusTracker {
constructor (config) {
this.target = config.target || null
if (!this.target) {
throw new Error('FocusTracker constructor called without a "target" to track.')
}
this.onFocus = (typeof config.onFocus === 'function') ? config.onFocus : null
this.onBlur = (typeof config.onBlur === 'function') ? config.onBlur : null
this._onClick = this._onEvent.bind(this)
this._onKeyUp = function (event) {
if (event.which === 9 || event.keyCode === 9) {
this._onEvent(event)
}
}.bind(this)
this.focusFlag = false
this.firstEventFlag = true
/*
Adds required (click and keyup) event listeners to the 'document' object
to track the focus of the given 'target'
*/
if (this.onFocus || this.onBlur) {
document.addEventListener('click', this._onClick)
document.addEventListener('keyup', this._onKeyUp)
}
}
/**
* Removes the event listeners on the 'document' object
* that were added to track the focus of the given 'target'
*/
destroy () {
document.removeEventListener('click', this._onClick)
document.removeEventListener('keyup', this._onKeyUp)
this._onEvent({ target: document.body }) // calling _onEvent with body element in the hope that the FocusTracker is added to an element inside the body tag
}
/**
* Tracks the focus of the target and calls the onFocus and onBlur
* event callbacks if available.
* @param {Event} [event] The 'click' or 'keyup' event object,
* from the respective events set on
* document object
* @private
*/
_onEvent (event) {
const target = event.target
let focusFlag
if (target === this.target) {
focusFlag = true
} else if (this.target.contains(target) || this.target.contains(document.activeElement)) {
focusFlag = true
} else {
focusFlag = false
}
if (focusFlag) {
if (!this.focusFlag) {
// trigger the onFocus callback
if (this.onFocus) {
this.onFocus({ type: 'focus', target: this.target })
}
this.focusFlag = true
}
} else {
if (this.focusFlag || this.firstEventFlag) {
// trigger the onBlur callback
if (this.onBlur) {
this.onBlur({ type: 'blur', target: this.target })
}
this.focusFlag = false
/*
When switching from one mode to another in the editor, the FocusTracker gets recreated.
At that time, this.focusFlag will be init to 'false' and will fail the above if condition, when blur occurs
this.firstEventFlag is added to overcome that issue
*/
if (this.firstEventFlag) {
this.firstEventFlag = false
}
}
}
}
}

View File

@ -1,86 +1,86 @@
'use strict';
'use strict'
/**
* The highlighter can highlight/unhighlight a node, and
* animate the visibility of a context menu.
* @constructor Highlighter
*/
function Highlighter () {
this.locked = false;
}
/**
* Hightlight given node and its childs
* @param {Node} node
*/
Highlighter.prototype.highlight = function (node) {
if (this.locked) {
return;
export class Highlighter {
constructor () {
this.locked = false
}
if (this.node != node) {
// unhighlight current node
if (this.node) {
this.node.setHighlight(false);
/**
* Hightlight given node and its childs
* @param {Node} node
*/
highlight (node) {
if (this.locked) {
return
}
// highlight new node
this.node = node;
this.node.setHighlight(true);
if (this.node !== node) {
// unhighlight current node
if (this.node) {
this.node.setHighlight(false)
}
// highlight new node
this.node = node
this.node.setHighlight(true)
}
// cancel any current timeout
this._cancelUnhighlight()
}
// cancel any current timeout
this._cancelUnhighlight();
};
/**
* Unhighlight currently highlighted node.
* Will be done after a delay
*/
unhighlight () {
if (this.locked) {
return
}
/**
* Unhighlight currently highlighted node.
* Will be done after a delay
*/
Highlighter.prototype.unhighlight = function () {
if (this.locked) {
return;
const me = this
if (this.node) {
this._cancelUnhighlight()
// do the unhighlighting after a small delay, to prevent re-highlighting
// the same node when moving from the drag-icon to the contextmenu-icon
// or vice versa.
this.unhighlightTimer = setTimeout(() => {
me.node.setHighlight(false)
me.node = undefined
me.unhighlightTimer = undefined
}, 0)
}
}
var me = this;
if (this.node) {
this._cancelUnhighlight();
// do the unhighlighting after a small delay, to prevent re-highlighting
// the same node when moving from the drag-icon to the contextmenu-icon
// or vice versa.
this.unhighlightTimer = setTimeout(function () {
me.node.setHighlight(false);
me.node = undefined;
me.unhighlightTimer = undefined;
}, 0);
/**
* Cancel an unhighlight action (if before the timeout of the unhighlight action)
* @private
*/
_cancelUnhighlight () {
if (this.unhighlightTimer) {
clearTimeout(this.unhighlightTimer)
this.unhighlightTimer = undefined
}
}
};
/**
* Cancel an unhighlight action (if before the timeout of the unhighlight action)
* @private
*/
Highlighter.prototype._cancelUnhighlight = function () {
if (this.unhighlightTimer) {
clearTimeout(this.unhighlightTimer);
this.unhighlightTimer = undefined;
/**
* Lock highlighting or unhighlighting nodes.
* methods highlight and unhighlight do not work while locked.
*/
lock () {
this.locked = true
}
};
/**
* Lock highlighting or unhighlighting nodes.
* methods highlight and unhighlight do not work while locked.
*/
Highlighter.prototype.lock = function () {
this.locked = true;
};
/**
* Unlock highlighting or unhighlighting nodes
*/
Highlighter.prototype.unlock = function () {
this.locked = false;
};
module.exports = Highlighter;
/**
* Unlock highlighting or unhighlighting nodes
*/
unlock () {
this.locked = false
}
}

View File

@ -1,267 +1,85 @@
'use strict';
var util = require('./util');
/**
* @constructor History
* Store action history, enables undo and redo
* @param {JSONEditor} editor
* Keep track on any history, be able
* @param {function} onChange
* @param {function} calculateItemSize
* @param {number} limit Maximum size of all items in history
* @constructor
*/
function History (editor) {
this.editor = editor;
this.history = [];
this.index = -1;
export class History {
constructor (onChange, calculateItemSize, limit) {
this.onChange = onChange
this.calculateItemSize = calculateItemSize || (() => 1)
this.limit = limit
this.clear();
this.items = []
this.index = -1
}
// map with all supported actions
this.actions = {
'editField': {
'undo': function (params) {
params.node.updateField(params.oldValue);
},
'redo': function (params) {
params.node.updateField(params.newValue);
}
},
'editValue': {
'undo': function (params) {
params.node.updateValue(params.oldValue);
},
'redo': function (params) {
params.node.updateValue(params.newValue);
}
},
'changeType': {
'undo': function (params) {
params.node.changeType(params.oldType);
},
'redo': function (params) {
params.node.changeType(params.newType);
}
},
'appendNodes': {
'undo': function (params) {
params.nodes.forEach(function (node) {
params.parent.removeChild(node);
});
},
'redo': function (params) {
params.nodes.forEach(function (node) {
params.parent.appendChild(node);
});
}
},
'insertBeforeNodes': {
'undo': function (params) {
params.nodes.forEach(function (node) {
params.parent.removeChild(node);
});
},
'redo': function (params) {
params.nodes.forEach(function (node) {
params.parent.insertBefore(node, params.beforeNode);
});
}
},
'insertAfterNodes': {
'undo': function (params) {
params.nodes.forEach(function (node) {
params.parent.removeChild(node);
});
},
'redo': function (params) {
var afterNode = params.afterNode;
params.nodes.forEach(function (node) {
params.parent.insertAfter(params.node, afterNode);
afterNode = node;
});
}
},
'removeNodes': {
'undo': function (params) {
var parent = params.parent;
var beforeNode = parent.childs[params.index] || parent.append;
params.nodes.forEach(function (node) {
parent.insertBefore(node, beforeNode);
});
},
'redo': function (params) {
params.nodes.forEach(function (node) {
params.parent.removeChild(node);
});
}
},
'duplicateNodes': {
'undo': function (params) {
params.nodes.forEach(function (node) {
params.parent.removeChild(node);
});
},
'redo': function (params) {
var afterNode = params.afterNode;
params.nodes.forEach(function (node) {
params.parent.insertAfter(node, afterNode);
afterNode = node;
});
}
},
'moveNodes': {
'undo': function (params) {
params.nodes.forEach(function (node) {
params.oldBeforeNode.parent.moveBefore(node, params.oldBeforeNode);
});
},
'redo': function (params) {
params.nodes.forEach(function (node) {
params.newBeforeNode.parent.moveBefore(node, params.newBeforeNode);
});
}
},
'sort': {
'undo': function (params) {
var node = params.node;
node.hideChilds();
node.sort = params.oldSort;
node.childs = params.oldChilds;
node.showChilds();
},
'redo': function (params) {
var node = params.node;
node.hideChilds();
node.sort = params.newSort;
node.childs = params.newChilds;
node.showChilds();
}
add (item) {
// limit number of items in history so that the total size doesn't
// always keep at least one item in memory
while (this._calculateHistorySize() > this.limit && this.items.length > 1) {
this.items.shift()
this.index--
}
// TODO: restore the original caret position and selection with each undo
// TODO: implement history for actions "expand", "collapse", "scroll", "setDocument"
};
// cleanup any redo action that are not valid anymore
this.items = this.items.slice(0, this.index + 1)
this.items.push(item)
this.index++
this.onChange()
}
_calculateHistorySize () {
const calculateItemSize = this.calculateItemSize
let totalSize = 0
this.items.forEach(item => {
totalSize += calculateItemSize(item)
})
return totalSize
}
undo () {
if (!this.canUndo()) {
return
}
this.index--
this.onChange()
return this.items[this.index]
}
redo () {
if (!this.canRedo()) {
return
}
this.index++
this.onChange()
return this.items[this.index]
}
canUndo () {
return this.index > 0
}
canRedo () {
return this.index < this.items.length - 1
}
clear () {
this.items = []
this.index = -1
this.onChange()
}
}
/**
* The method onChange is executed when the History is changed, and can
* be overloaded.
*/
History.prototype.onChange = function () {};
/**
* Add a new action to the history
* @param {String} action The executed action. Available actions: "editField",
* "editValue", "changeType", "appendNode",
* "removeNode", "duplicateNode", "moveNode"
* @param {Object} params Object containing parameters describing the change.
* The parameters in params depend on the action (for
* example for "editValue" the Node, old value, and new
* value are provided). params contains all information
* needed to undo or redo the action.
*/
History.prototype.add = function (action, params) {
this.index++;
this.history[this.index] = {
'action': action,
'params': params,
'timestamp': new Date()
};
// remove redo actions which are invalid now
if (this.index < this.history.length - 1) {
this.history.splice(this.index + 1, this.history.length - this.index - 1);
}
// fire onchange event
this.onChange();
};
/**
* Clear history
*/
History.prototype.clear = function () {
this.history = [];
this.index = -1;
// fire onchange event
this.onChange();
};
/**
* Check if there is an action available for undo
* @return {Boolean} canUndo
*/
History.prototype.canUndo = function () {
return (this.index >= 0);
};
/**
* Check if there is an action available for redo
* @return {Boolean} canRedo
*/
History.prototype.canRedo = function () {
return (this.index < this.history.length - 1);
};
/**
* Undo the last action
*/
History.prototype.undo = function () {
if (this.canUndo()) {
var obj = this.history[this.index];
if (obj) {
var action = this.actions[obj.action];
if (action && action.undo) {
action.undo(obj.params);
if (obj.params.oldSelection) {
this.editor.setSelection(obj.params.oldSelection);
}
}
else {
console.error(new Error('unknown action "' + obj.action + '"'));
}
}
this.index--;
// fire onchange event
this.onChange();
}
};
/**
* Redo the last action
*/
History.prototype.redo = function () {
if (this.canRedo()) {
this.index++;
var obj = this.history[this.index];
if (obj) {
var action = this.actions[obj.action];
if (action && action.redo) {
action.redo(obj.params);
if (obj.params.newSelection) {
this.editor.setSelection(obj.params.newSelection);
}
}
else {
console.error(new Error('unknown action "' + obj.action + '"'));
}
}
// fire onchange event
this.onChange();
}
};
/**
* Destroy history
*/
History.prototype.destroy = function () {
this.editor = null;
this.history = [];
this.index = -1;
};
module.exports = History;

View File

@ -1,16 +1,20 @@
'use strict';
'use strict'
var Ajv;
try {
Ajv = require('ajv');
}
catch (err) {
// no problem... when we need Ajv we will throw a neat exception
}
const ace = require('./ace') // may be undefined in case of minimalist bundle
const VanillaPicker = require('./vanilla-picker') // may be undefined in case of minimalist bundle
const { treeModeMixins } = require('./treemode')
const { textModeMixins } = require('./textmode')
const { previewModeMixins } = require('./previewmode')
const { clear, extend, getInnerText, getInternetExplorerVersion, parse } = require('./util')
const { tryRequireAjv } = require('./tryRequireAjv')
const { showTransformModal } = require('./showTransformModal')
const { showSortModal } = require('./showSortModal')
var treemode = require('./treemode');
var textmode = require('./textmode');
var util = require('./util');
const Ajv = tryRequireAjv()
if (typeof Promise === 'undefined') {
console.error('Promise undefined. Please load a Promise polyfill in the browser in order to use JSONEditor')
}
/**
* @constructor JSONEditor
@ -20,7 +24,20 @@ var util = require('./util');
* 'tree' (default), 'view',
* 'form', 'text', and 'code'.
* {function} onChange Callback method, triggered
* on change of contents
* on change of contents.
* Does not pass the contents itself.
* See also `onChangeJSON` and
* `onChangeText`.
* {function} onChangeJSON Callback method, triggered
* in modes on change of contents,
* passing the changed contents
* as JSON.
* Only applicable for modes
* 'tree', 'view', and 'form'.
* {function} onChangeText Callback method, triggered
* in modes on change of contents,
* passing the changed contents
* as stringified JSON.
* {function} onError Callback method, triggered
* when an error occurs
* {Boolean} search Enable search box.
@ -44,57 +61,96 @@ var util = require('./util');
* {boolean} sortObjectKeys If true, object keys are
* sorted before display.
* false by default.
* {function} onSelectionChange Callback method,
* triggered on node selection change
* Only applicable for modes
* 'tree', 'view', and 'form'
* {function} onTextSelectionChange Callback method,
* triggered on text selection change
* Only applicable for modes
* {HTMLElement} modalAnchor The anchor element to apply an
* overlay and display the modals in a
* centered location.
* Defaults to document.body
* 'text' and 'code'
* {function} onEvent Callback method, triggered
* when an event occurs in
* a JSON field or value.
* Only applicable for
* modes 'form', 'tree' and
* 'view'
* {function} onFocus Callback method, triggered
* when the editor comes into focus,
* passing an object {type, target},
* Applicable for all modes
* {function} onBlur Callback method, triggered
* when the editor goes out of focus,
* passing an object {type, target},
* Applicable for all modes
* {function} onClassName Callback method, triggered
* when a Node DOM is rendered. Function returns
* a css class name to be set on a node.
* Only applicable for
* modes 'form', 'tree' and
* 'view'
* {Number} maxVisibleChilds Number of children allowed for a node
* in 'tree', 'view', or 'form' mode before
* the "show more/show all" buttons appear.
* 100 by default.
*
* @param {Object | undefined} json JSON object
*/
function JSONEditor (container, options, json) {
if (!(this instanceof JSONEditor)) {
throw new Error('JSONEditor constructor called without "new".');
throw new Error('JSONEditor constructor called without "new".')
}
// check for unsupported browser (IE8 and older)
var ieVersion = util.getInternetExplorerVersion();
if (ieVersion != -1 && ieVersion < 9) {
const ieVersion = getInternetExplorerVersion()
if (ieVersion !== -1 && ieVersion < 9) {
throw new Error('Unsupported browser, IE9 or newer required. ' +
'Please install the newest version of your browser.');
'Please install the newest version of your browser.')
}
if (options) {
// check for deprecated options
if (options.error) {
console.warn('Option "error" has been renamed to "onError"');
options.onError = options.error;
delete options.error;
console.warn('Option "error" has been renamed to "onError"')
options.onError = options.error
delete options.error
}
if (options.change) {
console.warn('Option "change" has been renamed to "onChange"');
options.onChange = options.change;
delete options.change;
console.warn('Option "change" has been renamed to "onChange"')
options.onChange = options.change
delete options.change
}
if (options.editable) {
console.warn('Option "editable" has been renamed to "onEditable"');
options.onEditable = options.editable;
delete options.editable;
console.warn('Option "editable" has been renamed to "onEditable"')
options.onEditable = options.editable
delete options.editable
}
// warn if onChangeJSON is used when mode can be `text` or `code`
if (options.onChangeJSON) {
if (options.mode === 'text' || options.mode === 'code' ||
(options.modes && (options.modes.indexOf('text') !== -1 || options.modes.indexOf('code') !== -1))) {
console.warn('Option "onChangeJSON" is not applicable to modes "text" and "code". ' +
'Use "onChangeText" or "onChange" instead.')
}
}
// validate options
if (options) {
var VALID_OPTIONS = [
'ace', 'theme',
'ajv', 'schema',
'onChange', 'onEditable', 'onError', 'onModeChange',
'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation', 'sortObjectKeys'
];
Object.keys(options).forEach(function (option) {
if (VALID_OPTIONS.indexOf(option) === -1) {
console.warn('Unknown option "' + option + '". This option will be ignored');
Object.keys(options).forEach(option => {
if (JSONEditor.VALID_OPTIONS.indexOf(option) === -1) {
console.warn('Unknown option "' + option + '". This option will be ignored')
}
});
})
}
}
if (arguments.length) {
this._create(container, options, json);
this._create(container, options, json)
}
}
@ -113,10 +169,26 @@ function JSONEditor (container, options, json) {
*
* @type { Object.<String, {mixin: Object, data: String} > }
*/
JSONEditor.modes = {};
JSONEditor.modes = {}
// debounce interval for JSON schema vaidation in milliseconds
JSONEditor.prototype.DEBOUNCE_INTERVAL = 150;
// debounce interval for JSON schema validation in milliseconds
JSONEditor.prototype.DEBOUNCE_INTERVAL = 150
JSONEditor.VALID_OPTIONS = [
'ajv', 'schema', 'schemaRefs', 'templates',
'ace', 'theme', 'autocomplete',
'onChange', 'onChangeJSON', 'onChangeText',
'onEditable', 'onError', 'onEvent', 'onModeChange', 'onNodeName', 'onValidate', 'onCreateMenu',
'onSelectionChange', 'onTextSelectionChange', 'onClassName',
'onFocus', 'onBlur',
'colorPicker', 'onColorPicker',
'timestampTag', 'timestampFormat',
'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation',
'sortObjectKeys', 'navigationBar', 'statusBar', 'mainMenuBar', 'languages', 'language', 'enableSort', 'enableTransform', 'limitDragging',
'maxVisibleChilds', 'onValidationError',
'modalAnchor', 'popupAnchor',
'createQuery', 'executeQuery', 'queryDescription'
]
/**
* Create the JSONEditor
@ -126,50 +198,50 @@ JSONEditor.prototype.DEBOUNCE_INTERVAL = 150;
* @private
*/
JSONEditor.prototype._create = function (container, options, json) {
this.container = container;
this.options = options || {};
this.json = json || {};
this.container = container
this.options = options || {}
this.json = json || {}
var mode = this.options.mode || 'tree';
this.setMode(mode);
};
const mode = this.options.mode || (this.options.modes && this.options.modes[0]) || 'tree'
this.setMode(mode)
}
/**
* Destroy the editor. Clean up DOM, event listeners, and web workers.
*/
JSONEditor.prototype.destroy = function () {};
JSONEditor.prototype.destroy = () => {}
/**
* Set JSON object in editor
* @param {Object | undefined} json JSON data
*/
JSONEditor.prototype.set = function (json) {
this.json = json;
};
this.json = json
}
/**
* Get JSON from the editor
* @returns {Object} json
*/
JSONEditor.prototype.get = function () {
return this.json;
};
return this.json
}
/**
* Set string containing JSON for the editor
* @param {String | undefined} jsonText
*/
JSONEditor.prototype.setText = function (jsonText) {
this.json = util.parse(jsonText);
};
this.json = parse(jsonText)
}
/**
* Get stringified JSON contents from the editor
* @returns {String} jsonText
*/
JSONEditor.prototype.getText = function () {
return JSON.stringify(this.json);
};
return JSON.stringify(this.json)
}
/**
* Set a field name for the root node.
@ -177,18 +249,18 @@ JSONEditor.prototype.getText = function () {
*/
JSONEditor.prototype.setName = function (name) {
if (!this.options) {
this.options = {};
this.options = {}
}
this.options.name = name;
};
this.options.name = name
}
/**
* Get the field name for the root node.
* @return {String | undefined} name
*/
JSONEditor.prototype.getName = function () {
return this.options && this.options.name;
};
return this.options && this.options.name
}
/**
* Change the mode of the editor.
@ -197,62 +269,63 @@ JSONEditor.prototype.getName = function () {
* 'text', and 'code'.
*/
JSONEditor.prototype.setMode = function (mode) {
var container = this.container;
var options = util.extend({}, this.options);
var oldMode = options.mode;
var data;
var name;
// if the mode is the same as current mode (and it's not the first time), do nothing.
if (mode === this.options.mode && this.create) {
return
}
options.mode = mode;
var config = JSONEditor.modes[mode];
const container = this.container
const options = extend({}, this.options)
const oldMode = options.mode
let data
let name
options.mode = mode
const config = JSONEditor.modes[mode]
if (config) {
try {
var asText = (config.data == 'text');
name = this.getName();
data = this[asText ? 'getText' : 'get'](); // get text or json
const asText = (config.data === 'text')
name = this.getName()
data = this[asText ? 'getText' : 'get']() // get text or json
this.destroy();
util.clear(this);
util.extend(this, config.mixin);
this.create(container, options);
this.destroy()
clear(this)
extend(this, config.mixin)
this.create(container, options)
this.setName(name);
this[asText ? 'setText' : 'set'](data); // set text or json
this.setName(name)
this[asText ? 'setText' : 'set'](data) // set text or json
if (typeof config.load === 'function') {
try {
config.load.call(this);
}
catch (err) {
console.error(err);
config.load.call(this)
} catch (err) {
console.error(err)
}
}
if (typeof options.onModeChange === 'function' && mode !== oldMode) {
try {
options.onModeChange(mode, oldMode);
}
catch (err) {
console.error(err);
options.onModeChange(mode, oldMode)
} catch (err) {
console.error(err)
}
}
} catch (err) {
this._onError(err)
}
catch (err) {
this._onError(err);
}
} else {
throw new Error('Unknown mode "' + options.mode + '"')
}
else {
throw new Error('Unknown mode "' + options.mode + '"');
}
};
}
/**
* Get the current mode
* @return {string}
*/
JSONEditor.prototype.getMode = function () {
return this.options.mode;
};
return this.options.mode
}
/**
* Throw an error. If an error callback is configured in options.error, this
@ -260,69 +333,90 @@ JSONEditor.prototype.getMode = function () {
* @param {Error} err
* @private
*/
JSONEditor.prototype._onError = function(err) {
JSONEditor.prototype._onError = function (err) {
if (this.options && typeof this.options.onError === 'function') {
this.options.onError(err);
this.options.onError(err)
} else {
throw err
}
else {
throw err;
}
};
}
/**
* Set a JSON schema for validation of the JSON object.
* To remove the schema, call JSONEditor.setSchema(null)
* @param {Object | null} schema
* @param {Object.<string, Object>=} schemaRefs Schemas that are referenced using the `$ref` property from the JSON schema that are set in the `schema` option,
+ the object structure in the form of `{reference_key: schemaObject}`
*/
JSONEditor.prototype.setSchema = function (schema) {
JSONEditor.prototype.setSchema = function (schema, schemaRefs) {
// compile a JSON schema validator if a JSON schema is provided
if (schema) {
var ajv;
let ajv
try {
// grab ajv from options if provided, else create a new instance
ajv = this.options.ajv || Ajv({ allErrors: true, verbose: true });
if (this.options.ajv) {
ajv = this.options.ajv
} else {
ajv = Ajv({
allErrors: true,
verbose: true,
schemaId: 'auto',
$data: true
})
}
catch (err) {
console.warn('Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.');
// support both draft-04 and draft-06 alongside the latest draft-07
ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json'))
ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json'))
}
} catch (err) {
console.warn('Failed to create an instance of Ajv, JSON Schema validation is not available. Please use a JSONEditor bundle including Ajv, or pass an instance of Ajv as via the configuration option `ajv`.')
}
if (ajv) {
this.validateSchema = ajv.compile(schema);
if (schemaRefs) {
for (const ref in schemaRefs) {
ajv.removeSchema(ref) // When updating a schema - old refs has to be removed first
if (schemaRefs[ref]) {
ajv.addSchema(schemaRefs[ref], ref)
}
}
this.options.schemaRefs = schemaRefs
}
this.validateSchema = ajv.compile(schema)
// add schema to the options, so that when switching to an other mode,
// the set schema is not lost
this.options.schema = schema;
this.options.schema = schema
// validate now
this.validate();
this.validate()
}
this.refresh(); // update DOM
}
else {
this.refresh() // update DOM
} else {
// remove current schema
this.validateSchema = null;
this.options.schema = null;
this.validate(); // to clear current error messages
this.refresh(); // update DOM
this.validateSchema = null
this.options.schema = null
this.options.schemaRefs = null
this.validate() // to clear current error messages
this.refresh() // update DOM
}
};
}
/**
* Validate current JSON object against the configured JSON schema
* Throws an exception when no JSON schema is configured
*/
JSONEditor.prototype.validate = function () {
JSONEditor.prototype.validate = () => {
// must be implemented by treemode and textmode
};
}
/**
* Refresh the rendered contents
*/
JSONEditor.prototype.refresh = function () {
JSONEditor.prototype.refresh = () => {
// can be implemented by treemode and textmode
};
}
/**
* Register a plugin with one ore multiple modes for the JSON Editor.
@ -343,43 +437,56 @@ JSONEditor.prototype.refresh = function () {
*
* @param {Object | Array} mode A mode object or an array with multiple mode objects.
*/
JSONEditor.registerMode = function (mode) {
var i, prop;
JSONEditor.registerMode = mode => {
let i, prop
if (util.isArray(mode)) {
if (Array.isArray(mode)) {
// multiple modes
for (i = 0; i < mode.length; i++) {
JSONEditor.registerMode(mode[i]);
JSONEditor.registerMode(mode[i])
}
}
else {
} else {
// validate the new mode
if (!('mode' in mode)) throw new Error('Property "mode" missing');
if (!('mixin' in mode)) throw new Error('Property "mixin" missing');
if (!('data' in mode)) throw new Error('Property "data" missing');
var name = mode.mode;
if (!('mode' in mode)) throw new Error('Property "mode" missing')
if (!('mixin' in mode)) throw new Error('Property "mixin" missing')
if (!('data' in mode)) throw new Error('Property "data" missing')
const name = mode.mode
if (name in JSONEditor.modes) {
throw new Error('Mode "' + name + '" already registered');
throw new Error('Mode "' + name + '" already registered')
}
// validate the mixin
if (typeof mode.mixin.create !== 'function') {
throw new Error('Required function "create" missing on mixin');
throw new Error('Required function "create" missing on mixin')
}
var reserved = ['setMode', 'registerMode', 'modes'];
const reserved = ['setMode', 'registerMode', 'modes']
for (i = 0; i < reserved.length; i++) {
prop = reserved[i];
prop = reserved[i]
if (prop in mode.mixin) {
throw new Error('Reserved property "' + prop + '" not allowed in mixin');
throw new Error('Reserved property "' + prop + '" not allowed in mixin')
}
}
JSONEditor.modes[name] = mode;
JSONEditor.modes[name] = mode
}
};
}
// register tree and text modes
JSONEditor.registerMode(treemode);
JSONEditor.registerMode(textmode);
// register tree, text, and preview modes
JSONEditor.registerMode(treeModeMixins)
JSONEditor.registerMode(textModeMixins)
JSONEditor.registerMode(previewModeMixins)
module.exports = JSONEditor;
// expose some of the libraries that can be used customized
JSONEditor.ace = ace
JSONEditor.Ajv = Ajv
JSONEditor.VanillaPicker = VanillaPicker
// expose some utils (this is undocumented, unofficial)
JSONEditor.showTransformModal = showTransformModal
JSONEditor.showSortModal = showSortModal
JSONEditor.getInnerText = getInnerText
// default export for TypeScript ES6 projects
JSONEditor.default = JSONEditor
module.exports = JSONEditor

View File

@ -1,114 +1,123 @@
'use strict';
'use strict'
var ContextMenu = require('./ContextMenu');
import { ContextMenu } from './ContextMenu'
import { translate } from './i18n'
/**
* Create a select box to be used in the editor menu's, which allows to switch mode
* @param {HTMLElement} container
* @param {String[]} modes Available modes: 'code', 'form', 'text', 'tree', 'view'
* @param {String} current Available modes: 'code', 'form', 'text', 'tree', 'view'
* @param {String[]} modes Available modes: 'code', 'form', 'text', 'tree', 'view', 'preview'
* @param {String} current Available modes: 'code', 'form', 'text', 'tree', 'view', 'preview'
* @param {function(mode: string)} onSwitch Callback invoked on switch
* @constructor
*/
function ModeSwitcher(container, modes, current, onSwitch) {
// available modes
var availableModes = {
code: {
'text': 'Code',
'title': 'Switch to code highlighter',
'click': function () {
onSwitch('code')
}
},
form: {
'text': 'Form',
'title': 'Switch to form editor',
'click': function () {
onSwitch('form');
}
},
text: {
'text': 'Text',
'title': 'Switch to plain text editor',
'click': function () {
onSwitch('text');
}
},
tree: {
'text': 'Tree',
'title': 'Switch to tree editor',
'click': function () {
onSwitch('tree');
}
},
view: {
'text': 'View',
'title': 'Switch to tree view',
'click': function () {
onSwitch('view');
export class ModeSwitcher {
constructor (container, modes, current, onSwitch) {
// available modes
const availableModes = {
code: {
text: translate('modeCodeText'),
title: translate('modeCodeTitle'),
click: function () {
onSwitch('code')
}
},
form: {
text: translate('modeFormText'),
title: translate('modeFormTitle'),
click: function () {
onSwitch('form')
}
},
text: {
text: translate('modeTextText'),
title: translate('modeTextTitle'),
click: function () {
onSwitch('text')
}
},
tree: {
text: translate('modeTreeText'),
title: translate('modeTreeTitle'),
click: function () {
onSwitch('tree')
}
},
view: {
text: translate('modeViewText'),
title: translate('modeViewTitle'),
click: function () {
onSwitch('view')
}
},
preview: {
text: translate('modePreviewText'),
title: translate('modePreviewTitle'),
click: function () {
onSwitch('preview')
}
}
}
};
// list the selected modes
var items = [];
for (var i = 0; i < modes.length; i++) {
var mode = modes[i];
var item = availableModes[mode];
if (!item) {
throw new Error('Unknown mode "' + mode + '"');
// list the selected modes
const items = []
for (let i = 0; i < modes.length; i++) {
const mode = modes[i]
const item = availableModes[mode]
if (!item) {
throw new Error('Unknown mode "' + mode + '"')
}
item.className = 'jsoneditor-type-modes' + ((current === mode) ? ' jsoneditor-selected' : '')
items.push(item)
}
item.className = 'jsoneditor-type-modes' + ((current == mode) ? ' jsoneditor-selected' : '');
items.push(item);
// retrieve the title of current mode
const currentMode = availableModes[current]
if (!currentMode) {
throw new Error('Unknown mode "' + current + '"')
}
const currentTitle = currentMode.text
// create the html element
const box = document.createElement('button')
box.type = 'button'
box.className = 'jsoneditor-modes jsoneditor-separator'
box.textContent = currentTitle + ' \u25BE'
box.title = translate('modeEditorTitle')
box.onclick = () => {
const menu = new ContextMenu(items)
menu.show(box, container)
}
const frame = document.createElement('div')
frame.className = 'jsoneditor-modes'
frame.style.position = 'relative'
frame.appendChild(box)
container.appendChild(frame)
this.dom = {
container: container,
box: box,
frame: frame
}
}
// retrieve the title of current mode
var currentMode = availableModes[current];
if (!currentMode) {
throw new Error('Unknown mode "' + current + '"');
/**
* Set focus to switcher
*/
focus () {
this.dom.box.focus()
}
var currentTitle = currentMode.text;
// create the html element
var box = document.createElement('button');
box.className = 'jsoneditor-modes jsoneditor-separator';
box.innerHTML = currentTitle + ' &#x25BE;';
box.title = 'Switch editor mode';
box.onclick = function () {
var menu = new ContextMenu(items);
menu.show(box);
};
var frame = document.createElement('div');
frame.className = 'jsoneditor-modes';
frame.style.position = 'relative';
frame.appendChild(box);
container.appendChild(frame);
this.dom = {
container: container,
box: box,
frame: frame
};
/**
* Destroy the ModeSwitcher, remove from DOM
*/
destroy () {
if (this.dom && this.dom.frame && this.dom.frame.parentNode) {
this.dom.frame.parentNode.removeChild(this.dom.frame)
}
this.dom = null
}
}
/**
* Set focus to switcher
*/
ModeSwitcher.prototype.focus = function () {
this.dom.box.focus();
};
/**
* Destroy the ModeSwitcher, remove from DOM
*/
ModeSwitcher.prototype.destroy = function () {
if (this.dom && this.dom.frame && this.dom.frame.parentNode) {
this.dom.frame.parentNode.removeChild(this.dom.frame);
}
this.dom = null;
};
module.exports = ModeSwitcher;

File diff suppressed because it is too large Load Diff

333
src/js/NodeHistory.js Normal file
View File

@ -0,0 +1,333 @@
'use strict'
import { findUniqueName } from './util'
/**
* @constructor History
* Store action history, enables undo and redo
* @param {JSONEditor} editor
*/
export class NodeHistory {
constructor (editor) {
this.editor = editor
this.history = []
this.index = -1
this.clear()
// helper function to find a Node from a path
function findNode (path) {
return editor.node.findNodeByInternalPath(path)
}
// map with all supported actions
this.actions = {
editField: {
undo: function (params) {
const parentNode = findNode(params.parentPath)
const node = parentNode.childs[params.index]
node.updateField(params.oldValue)
},
redo: function (params) {
const parentNode = findNode(params.parentPath)
const node = parentNode.childs[params.index]
node.updateField(params.newValue)
}
},
editValue: {
undo: function (params) {
findNode(params.path).updateValue(params.oldValue)
},
redo: function (params) {
findNode(params.path).updateValue(params.newValue)
}
},
changeType: {
undo: function (params) {
findNode(params.path).changeType(params.oldType)
},
redo: function (params) {
findNode(params.path).changeType(params.newType)
}
},
appendNodes: {
undo: function (params) {
const parentNode = findNode(params.parentPath)
params.paths.map(findNode).forEach(node => {
parentNode.removeChild(node)
})
},
redo: function (params) {
const parentNode = findNode(params.parentPath)
params.nodes.forEach(node => {
parentNode.appendChild(node)
})
}
},
insertBeforeNodes: {
undo: function (params) {
const parentNode = findNode(params.parentPath)
params.paths.map(findNode).forEach(node => {
parentNode.removeChild(node)
})
},
redo: function (params) {
const parentNode = findNode(params.parentPath)
const beforeNode = findNode(params.beforePath)
params.nodes.forEach(node => {
parentNode.insertBefore(node, beforeNode)
})
}
},
insertAfterNodes: {
undo: function (params) {
const parentNode = findNode(params.parentPath)
params.paths.map(findNode).forEach(node => {
parentNode.removeChild(node)
})
},
redo: function (params) {
const parentNode = findNode(params.parentPath)
let afterNode = findNode(params.afterPath)
params.nodes.forEach(node => {
parentNode.insertAfter(node, afterNode)
afterNode = node
})
}
},
removeNodes: {
undo: function (params) {
const parentNode = findNode(params.parentPath)
const beforeNode = parentNode.childs[params.index] || parentNode.append
params.nodes.forEach(node => {
parentNode.insertBefore(node, beforeNode)
})
},
redo: function (params) {
const parentNode = findNode(params.parentPath)
params.paths.map(findNode).forEach(node => {
parentNode.removeChild(node)
})
}
},
duplicateNodes: {
undo: function (params) {
const parentNode = findNode(params.parentPath)
params.clonePaths.map(findNode).forEach(node => {
parentNode.removeChild(node)
})
},
redo: function (params) {
const parentNode = findNode(params.parentPath)
let afterNode = findNode(params.afterPath)
const nodes = params.paths.map(findNode)
nodes.forEach(node => {
const clone = node.clone()
if (parentNode.type === 'object') {
const existingFieldNames = parentNode.getFieldNames()
clone.field = findUniqueName(node.field, existingFieldNames)
}
parentNode.insertAfter(clone, afterNode)
afterNode = clone
})
}
},
moveNodes: {
undo: function (params) {
const oldParentNode = findNode(params.oldParentPath)
const newParentNode = findNode(params.newParentPath)
const oldBeforeNode = oldParentNode.childs[params.oldIndex] || oldParentNode.append
// first copy the nodes, then move them
const nodes = newParentNode.childs.slice(params.newIndex, params.newIndex + params.count)
nodes.forEach((node, index) => {
node.field = params.fieldNames[index]
oldParentNode.moveBefore(node, oldBeforeNode)
})
// This is a hack to work around an issue that we don't know tha original
// path of the new parent after dragging, as the node is already moved at that time.
if (params.newParentPathRedo === null) {
params.newParentPathRedo = newParentNode.getInternalPath()
}
},
redo: function (params) {
const oldParentNode = findNode(params.oldParentPathRedo)
const newParentNode = findNode(params.newParentPathRedo)
const newBeforeNode = newParentNode.childs[params.newIndexRedo] || newParentNode.append
// first copy the nodes, then move them
const nodes = oldParentNode.childs.slice(params.oldIndexRedo, params.oldIndexRedo + params.count)
nodes.forEach((node, index) => {
node.field = params.fieldNames[index]
newParentNode.moveBefore(node, newBeforeNode)
})
}
},
sort: {
undo: function (params) {
const node = findNode(params.path)
node.hideChilds()
node.childs = params.oldChilds
node.updateDom({ updateIndexes: true })
node.showChilds()
},
redo: function (params) {
const node = findNode(params.path)
node.hideChilds()
node.childs = params.newChilds
node.updateDom({ updateIndexes: true })
node.showChilds()
}
},
transform: {
undo: function (params) {
findNode(params.path).setInternalValue(params.oldValue)
// TODO: would be nice to restore the state of the node and childs
},
redo: function (params) {
findNode(params.path).setInternalValue(params.newValue)
// TODO: would be nice to restore the state of the node and childs
}
}
// TODO: restore the original caret position and selection with each undo
// TODO: implement history for actions "expand", "collapse", "scroll", "setDocument"
}
}
/**
* The method onChange is executed when the History is changed, and can
* be overloaded.
*/
onChange () {}
/**
* Add a new action to the history
* @param {String} action The executed action. Available actions: "editField",
* "editValue", "changeType", "appendNode",
* "removeNode", "duplicateNode", "moveNode"
* @param {Object} params Object containing parameters describing the change.
* The parameters in params depend on the action (for
* example for "editValue" the Node, old value, and new
* value are provided). params contains all information
* needed to undo or redo the action.
*/
add (action, params) {
this.index++
this.history[this.index] = {
action: action,
params: params,
timestamp: new Date()
}
// remove redo actions which are invalid now
if (this.index < this.history.length - 1) {
this.history.splice(this.index + 1, this.history.length - this.index - 1)
}
// fire onchange event
this.onChange()
}
/**
* Clear history
*/
clear () {
this.history = []
this.index = -1
// fire onchange event
this.onChange()
}
/**
* Check if there is an action available for undo
* @return {Boolean} canUndo
*/
canUndo () {
return (this.index >= 0)
}
/**
* Check if there is an action available for redo
* @return {Boolean} canRedo
*/
canRedo () {
return (this.index < this.history.length - 1)
}
/**
* Undo the last action
*/
undo () {
if (this.canUndo()) {
const obj = this.history[this.index]
if (obj) {
const action = this.actions[obj.action]
if (action && action.undo) {
action.undo(obj.params)
if (obj.params.oldSelection) {
try {
this.editor.setDomSelection(obj.params.oldSelection)
} catch (err) {
console.error(err)
}
}
} else {
console.error(new Error('unknown action "' + obj.action + '"'))
}
}
this.index--
// fire onchange event
this.onChange()
}
}
/**
* Redo the last action
*/
redo () {
if (this.canRedo()) {
this.index++
const obj = this.history[this.index]
if (obj) {
const action = this.actions[obj.action]
if (action && action.redo) {
action.redo(obj.params)
if (obj.params.newSelection) {
try {
this.editor.setDomSelection(obj.params.newSelection)
} catch (err) {
console.error(err)
}
}
} else {
console.error(new Error('unknown action "' + obj.action + '"'))
}
}
// fire onchange event
this.onChange()
}
}
/**
* Destroy history
*/
destroy () {
this.editor = null
this.history = []
this.index = -1
}
}

View File

@ -1,4 +1,5 @@
'use strict';
'use strict'
import { translate } from './i18n'
/**
* @constructor SearchBox
@ -7,306 +8,318 @@
* @param {Element} container HTML container element of where to
* create the search box
*/
function SearchBox (editor, container) {
var searchBox = this;
export class SearchBox {
constructor (editor, container) {
const searchBox = this
this.editor = editor;
this.timeout = undefined;
this.delay = 200; // ms
this.lastText = undefined;
this.editor = editor
this.timeout = undefined
this.delay = 200 // ms
this.lastText = undefined
this.results = null
this.dom = {};
this.dom.container = container;
this.dom = {}
this.dom.container = container
var table = document.createElement('table');
this.dom.table = table;
table.className = 'jsoneditor-search';
container.appendChild(table);
var tbody = document.createElement('tbody');
this.dom.tbody = tbody;
table.appendChild(tbody);
var tr = document.createElement('tr');
tbody.appendChild(tr);
const wrapper = document.createElement('div')
this.dom.wrapper = wrapper
wrapper.className = 'jsoneditor-search'
container.appendChild(wrapper)
var td = document.createElement('td');
tr.appendChild(td);
var results = document.createElement('div');
this.dom.results = results;
results.className = 'jsoneditor-results';
td.appendChild(results);
const results = document.createElement('div')
this.dom.results = results
results.className = 'jsoneditor-results'
wrapper.appendChild(results)
td = document.createElement('td');
tr.appendChild(td);
var divInput = document.createElement('div');
this.dom.input = divInput;
divInput.className = 'jsoneditor-frame';
divInput.title = 'Search fields and values';
td.appendChild(divInput);
const divInput = document.createElement('div')
this.dom.input = divInput
divInput.className = 'jsoneditor-frame'
divInput.title = translate('searchTitle')
wrapper.appendChild(divInput)
// table to contain the text input and search button
var tableInput = document.createElement('table');
divInput.appendChild(tableInput);
var tbodySearch = document.createElement('tbody');
tableInput.appendChild(tbodySearch);
tr = document.createElement('tr');
tbodySearch.appendChild(tr);
const refreshSearch = document.createElement('button')
refreshSearch.type = 'button'
refreshSearch.className = 'jsoneditor-refresh'
divInput.appendChild(refreshSearch)
var refreshSearch = document.createElement('button');
refreshSearch.className = 'jsoneditor-refresh';
td = document.createElement('td');
td.appendChild(refreshSearch);
tr.appendChild(td);
var search = document.createElement('input');
this.dom.search = search;
search.oninput = function (event) {
searchBox._onDelayedSearch(event);
};
search.onchange = function (event) { // For IE 9
searchBox._onSearch();
};
search.onkeydown = function (event) {
searchBox._onKeyDown(event);
};
search.onkeyup = function (event) {
searchBox._onKeyUp(event);
};
refreshSearch.onclick = function (event) {
search.select();
};
// TODO: ESC in FF restores the last input, is a FF bug, https://bugzilla.mozilla.org/show_bug.cgi?id=598819
td = document.createElement('td');
td.appendChild(search);
tr.appendChild(td);
var searchNext = document.createElement('button');
searchNext.title = 'Next result (Enter)';
searchNext.className = 'jsoneditor-next';
searchNext.onclick = function () {
searchBox.next();
};
td = document.createElement('td');
td.appendChild(searchNext);
tr.appendChild(td);
var searchPrevious = document.createElement('button');
searchPrevious.title = 'Previous result (Shift+Enter)';
searchPrevious.className = 'jsoneditor-previous';
searchPrevious.onclick = function () {
searchBox.previous();
};
td = document.createElement('td');
td.appendChild(searchPrevious);
tr.appendChild(td);
}
/**
* Go to the next search result
* @param {boolean} [focus] If true, focus will be set to the next result
* focus is false by default.
*/
SearchBox.prototype.next = function(focus) {
if (this.results != undefined) {
var index = (this.resultIndex != undefined) ? this.resultIndex + 1 : 0;
if (index > this.results.length - 1) {
index = 0;
const search = document.createElement('input')
search.type = 'text'
this.dom.search = search
search.oninput = event => {
searchBox._onDelayedSearch(event)
}
this._setActiveResult(index, focus);
}
};
/**
* Go to the prevous search result
* @param {boolean} [focus] If true, focus will be set to the next result
* focus is false by default.
*/
SearchBox.prototype.previous = function(focus) {
if (this.results != undefined) {
var max = this.results.length - 1;
var index = (this.resultIndex != undefined) ? this.resultIndex - 1 : max;
if (index < 0) {
index = max;
search.onchange = event => {
// For IE 9
searchBox._onSearch()
}
this._setActiveResult(index, focus);
}
};
/**
* Set new value for the current active result
* @param {Number} index
* @param {boolean} [focus] If true, focus will be set to the next result.
* focus is false by default.
* @private
*/
SearchBox.prototype._setActiveResult = function(index, focus) {
// de-activate current active result
if (this.activeResult) {
var prevNode = this.activeResult.node;
var prevElem = this.activeResult.elem;
if (prevElem == 'field') {
delete prevNode.searchFieldActive;
search.onkeydown = event => {
searchBox._onKeyDown(event)
}
else {
delete prevNode.searchValueActive;
search.onkeyup = event => {
searchBox._onKeyUp(event)
}
prevNode.updateDom();
}
if (!this.results || !this.results[index]) {
// out of range, set to undefined
this.resultIndex = undefined;
this.activeResult = undefined;
return;
}
this.resultIndex = index;
// set new node active
var node = this.results[this.resultIndex].node;
var elem = this.results[this.resultIndex].elem;
if (elem == 'field') {
node.searchFieldActive = true;
}
else {
node.searchValueActive = true;
}
this.activeResult = this.results[this.resultIndex];
node.updateDom();
// TODO: not so nice that the focus is only set after the animation is finished
node.scrollTo(function () {
if (focus) {
node.focus(elem);
refreshSearch.onclick = event => {
search.select()
}
});
};
/**
* Cancel any running onDelayedSearch.
* @private
*/
SearchBox.prototype._clearDelay = function() {
if (this.timeout != undefined) {
clearTimeout(this.timeout);
delete this.timeout;
// TODO: ESC in FF restores the last input, is a FF bug, https://bugzilla.mozilla.org/show_bug.cgi?id=598819
divInput.appendChild(search)
const searchNext = document.createElement('button')
searchNext.type = 'button'
searchNext.title = translate('searchNextResultTitle')
searchNext.className = 'jsoneditor-next'
searchNext.onclick = () => {
searchBox.next()
}
divInput.appendChild(searchNext)
const searchPrevious = document.createElement('button')
searchPrevious.type = 'button'
searchPrevious.title = translate('searchPreviousResultTitle')
searchPrevious.className = 'jsoneditor-previous'
searchPrevious.onclick = () => {
searchBox.previous()
}
divInput.appendChild(searchPrevious)
}
};
/**
* Start a timer to execute a search after a short delay.
* Used for reducing the number of searches while typing.
* @param {Event} event
* @private
*/
SearchBox.prototype._onDelayedSearch = function (event) {
// execute the search after a short delay (reduces the number of
// search actions while typing in the search text box)
this._clearDelay();
var searchBox = this;
this.timeout = setTimeout(function (event) {
searchBox._onSearch();
},
this.delay);
};
/**
* Go to the next search result
* @param {boolean} [focus] If true, focus will be set to the next result
* focus is false by default.
*/
next (focus) {
if (this.results) {
let index = this.resultIndex !== null ? this.resultIndex + 1 : 0
if (index > this.results.length - 1) {
index = 0
}
this._setActiveResult(index, focus)
}
}
/**
* Handle onSearch event
* @param {boolean} [forceSearch] If true, search will be executed again even
* when the search text is not changed.
* Default is false.
* @private
*/
SearchBox.prototype._onSearch = function (forceSearch) {
this._clearDelay();
/**
* Go to the prevous search result
* @param {boolean} [focus] If true, focus will be set to the next result
* focus is false by default.
*/
previous (focus) {
if (this.results) {
const max = this.results.length - 1
let index = this.resultIndex !== null ? this.resultIndex - 1 : max
if (index < 0) {
index = max
}
this._setActiveResult(index, focus)
}
}
var value = this.dom.search.value;
var text = (value.length > 0) ? value : undefined;
if (text != this.lastText || forceSearch) {
// only search again when changed
this.lastText = text;
this.results = this.editor.search(text);
this._setActiveResult(undefined);
/**
* Set new value for the current active result
* @param {Number} index
* @param {boolean} [focus] If true, focus will be set to the next result.
* focus is false by default.
* @private
*/
_setActiveResult (index, focus) {
// de-activate current active result
if (this.activeResult) {
const prevNode = this.activeResult.node
const prevElem = this.activeResult.elem
if (prevElem === 'field') {
delete prevNode.searchFieldActive
} else {
delete prevNode.searchValueActive
}
prevNode.updateDom()
}
// display search results
if (text != undefined) {
var resultCount = this.results.length;
switch (resultCount) {
case 0: this.dom.results.innerHTML = 'no&nbsp;results'; break;
case 1: this.dom.results.innerHTML = '1&nbsp;result'; break;
default: this.dom.results.innerHTML = resultCount + '&nbsp;results'; break;
if (!this.results || !this.results[index]) {
// out of range, set to undefined
this.resultIndex = undefined
this.activeResult = undefined
return
}
this.resultIndex = index
// set new node active
const node = this.results[this.resultIndex].node
const elem = this.results[this.resultIndex].elem
if (elem === 'field') {
node.searchFieldActive = true
} else {
node.searchValueActive = true
}
this.activeResult = this.results[this.resultIndex]
node.updateDom()
// TODO: not so nice that the focus is only set after the animation is finished
node.scrollTo(() => {
if (focus) {
node.focus(elem)
}
})
}
/**
* Cancel any running onDelayedSearch.
* @private
*/
_clearDelay () {
if (this.timeout !== undefined) {
clearTimeout(this.timeout)
delete this.timeout
}
}
/**
* Start a timer to execute a search after a short delay.
* Used for reducing the number of searches while typing.
* @param {Event} event
* @private
*/
_onDelayedSearch (event) {
// execute the search after a short delay (reduces the number of
// search actions while typing in the search text box)
this._clearDelay()
const searchBox = this
this.timeout = setTimeout(event => {
searchBox._onSearch()
}, this.delay)
}
/**
* Handle onSearch event
* @param {boolean} [forceSearch] If true, search will be executed again even
* when the search text is not changed.
* Default is false.
* @private
*/
_onSearch (forceSearch) {
this._clearDelay()
const value = this.dom.search.value
const text = value.length > 0 ? value : undefined
if (text !== this.lastText || forceSearch) {
// only search again when changed
this.lastText = text
this.results = this.editor.search(text)
const MAX_SEARCH_RESULTS = this.results[0]
? this.results[0].node.MAX_SEARCH_RESULTS
: Infinity
// try to maintain the current active result if this is still part of the new search results
let activeResultIndex = 0
if (this.activeResult) {
for (let i = 0; i < this.results.length; i++) {
if (this.results[i].node === this.activeResult.node) {
activeResultIndex = i
break
}
}
}
this._setActiveResult(activeResultIndex, false)
// display search results
if (text !== undefined) {
const resultCount = this.results.length
if (resultCount === 0) {
this.dom.results.textContent = 'no\u00A0results'
} else if (resultCount === 1) {
this.dom.results.textContent = '1\u00A0result'
} else if (resultCount > MAX_SEARCH_RESULTS) {
this.dom.results.textContent = MAX_SEARCH_RESULTS + '+\u00A0results'
} else {
this.dom.results.textContent = resultCount + '\u00A0results'
}
} else {
this.dom.results.textContent = ''
}
}
else {
this.dom.results.innerHTML = '';
}
/**
* Handle onKeyDown event in the input box
* @param {Event} event
* @private
*/
_onKeyDown (event) {
const keynum = event.which
if (keynum === 27) {
// ESC
this.dom.search.value = '' // clear search
this._onSearch()
event.preventDefault()
event.stopPropagation()
} else if (keynum === 13) {
// Enter
if (event.ctrlKey) {
// force to search again
this._onSearch(true)
} else if (event.shiftKey) {
// move to the previous search result
this.previous()
} else {
// move to the next search result
this.next()
}
event.preventDefault()
event.stopPropagation()
}
}
};
/**
* Handle onKeyDown event in the input box
* @param {Event} event
* @private
*/
SearchBox.prototype._onKeyDown = function (event) {
var keynum = event.which;
if (keynum == 27) { // ESC
this.dom.search.value = ''; // clear search
this._onSearch();
event.preventDefault();
event.stopPropagation();
}
else if (keynum == 13) { // Enter
if (event.ctrlKey) {
// force to search again
this._onSearch(true);
/**
* Handle onKeyUp event in the input box
* @param {Event} event
* @private
*/
_onKeyUp (event) {
const keynum = event.keyCode
if (keynum !== 27 && keynum !== 13) {
// !show and !Enter
this._onDelayedSearch(event) // For IE 9
}
else if (event.shiftKey) {
// move to the previous search result
this.previous();
}
else {
// move to the next search result
this.next();
}
event.preventDefault();
event.stopPropagation();
}
};
/**
* Handle onKeyUp event in the input box
* @param {Event} event
* @private
*/
SearchBox.prototype._onKeyUp = function (event) {
var keynum = event.keyCode;
if (keynum != 27 && keynum != 13) { // !show and !Enter
this._onDelayedSearch(event); // For IE 9
/**
* Clear the search results
*/
clear () {
this.dom.search.value = ''
this._onSearch()
}
};
/**
* Clear the search results
*/
SearchBox.prototype.clear = function () {
this.dom.search.value = '';
this._onSearch();
};
/**
* Refresh searchResults if there is a search value
*/
forceSearch () {
this._onSearch(true)
}
/**
* Destroy the search box
*/
SearchBox.prototype.destroy = function () {
this.editor = null;
this.dom.container.removeChild(this.dom.table);
this.dom = null;
/**
* Test whether the search box value is empty
* @returns {boolean} Returns true when empty.
*/
isEmpty () {
return this.dom.search.value === ''
}
this.results = null;
this.activeResult = null;
/**
* Destroy the search box
*/
destroy () {
this.editor = null
this.dom.container.removeChild(this.dom.wrapper)
this.dom = null
this._clearDelay();
this.results = null
this.activeResult = null
};
module.exports = SearchBox;
this._clearDelay()
}
}

142
src/js/TreePath.js Normal file
View File

@ -0,0 +1,142 @@
'use strict'
import { ContextMenu } from './ContextMenu'
import { translate } from './i18n'
import { addClassName, removeClassName } from './util'
/**
* Creates a component that visualize path selection in tree based editors
* @param {HTMLElement} container
* @param {HTMLElement} root
* @constructor
*/
export class TreePath {
constructor (container, root) {
if (container) {
this.root = root
this.path = document.createElement('div')
this.path.className = 'jsoneditor-treepath'
this.path.setAttribute('tabindex', 0)
this.contentMenuClicked = false
container.appendChild(this.path)
this.reset()
}
}
/**
* Reset component to initial status
*/
reset () {
this.path.textContent = translate('selectNode')
}
/**
* Renders the component UI according to a given path objects
* @param {Array<{name: String, childs: Array}>} pathObjs a list of path objects
*
*/
setPath (pathObjs) {
const me = this
this.path.textContent = ''
if (pathObjs && pathObjs.length) {
pathObjs.forEach((pathObj, idx) => {
const pathEl = document.createElement('span')
let sepEl
pathEl.className = 'jsoneditor-treepath-element'
pathEl.innerText = pathObj.name
pathEl.onclick = _onSegmentClick.bind(me, pathObj)
me.path.appendChild(pathEl)
if (pathObj.children.length) {
sepEl = document.createElement('span')
sepEl.className = 'jsoneditor-treepath-seperator'
sepEl.textContent = '\u25BA'
sepEl.onclick = () => {
me.contentMenuClicked = true
const items = []
pathObj.children.forEach(child => {
items.push({
text: child.name,
className: 'jsoneditor-type-modes' + (pathObjs[idx + 1] + 1 && pathObjs[idx + 1].name === child.name ? ' jsoneditor-selected' : ''),
click: _onContextMenuItemClick.bind(me, pathObj, child.name)
})
})
const menu = new ContextMenu(items)
menu.show(sepEl, me.root, true)
}
me.path.appendChild(sepEl)
}
if (idx === pathObjs.length - 1) {
const leftRectPos = (sepEl || pathEl).getBoundingClientRect().right
if (me.path.offsetWidth < leftRectPos) {
me.path.scrollLeft = leftRectPos
}
if (me.path.scrollLeft) {
const showAllBtn = document.createElement('span')
showAllBtn.className = 'jsoneditor-treepath-show-all-btn'
showAllBtn.title = 'show all path'
showAllBtn.textContent = '...'
showAllBtn.onclick = _onShowAllClick.bind(me, pathObjs)
me.path.insertBefore(showAllBtn, me.path.firstChild)
}
}
})
}
function _onShowAllClick (pathObjs) {
me.contentMenuClicked = false
addClassName(me.path, 'show-all')
me.path.style.width = me.path.parentNode.getBoundingClientRect().width - 10 + 'px'
me.path.onblur = () => {
if (me.contentMenuClicked) {
me.contentMenuClicked = false
me.path.focus()
return
}
removeClassName(me.path, 'show-all')
me.path.onblur = undefined
me.path.style.width = ''
me.setPath(pathObjs)
}
}
function _onSegmentClick (pathObj) {
if (this.selectionCallback) {
this.selectionCallback(pathObj)
}
}
function _onContextMenuItemClick (pathObj, selection) {
if (this.contextMenuCallback) {
this.contextMenuCallback(pathObj, selection)
}
}
}
/**
* set a callback function for selection of path section
* @param {Function} callback function to invoke when section is selected
*/
onSectionSelected (callback) {
if (typeof callback === 'function') {
this.selectionCallback = callback
}
}
/**
* set a callback function for selection of path section
* @param {Function} callback function to invoke when section is selected
*/
onContextMenuItemSelected (callback) {
if (typeof callback === 'function') {
this.contextMenuCallback = callback
}
}
}

View File

@ -1,9 +1,25 @@
// load brace
var ace = require('brace');
let ace
if (window.ace) {
// use the already loaded instance of Ace
ace = window.ace
} else {
try {
// load Ace editor
ace = require('ace-builds/src-noconflict/ace')
// load required ace modules
require('brace/mode/json');
require('brace/ext/searchbox');
require('./theme-jsoneditor');
// load required Ace plugins
require('ace-builds/src-noconflict/mode-json')
require('ace-builds/src-noconflict/mode-text')
require('ace-builds/src-noconflict/ext-searchbox')
module.exports = ace;
// embed Ace json worker
// https://github.com/ajaxorg/ace/issues/3913
const jsonWorkerDataUrl = require('../generated/worker-json-data-url')
ace.config.setModuleUrl('ace/mode/json_worker', jsonWorkerDataUrl)
} catch (err) {
// failed to load Ace (can be minimalist bundle).
// No worries, the editor will fall back to plain text if needed.
}
}
module.exports = ace

Some files were not shown because too many files have changed in this diff Show More