@json-editor/json-editor 2.13.0 → 2.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@json-editor/json-editor",
3
3
  "title": "JSONEditor",
4
4
  "description": "JSON Schema based editor",
5
- "version": "2.13.0",
5
+ "version": "2.13.2",
6
6
  "main": "dist/jsoneditor.js",
7
7
  "author": {
8
8
  "name": "Jeremy Dorn",
package/src/defaults.js CHANGED
@@ -408,7 +408,8 @@ const options = {
408
408
  use_default_values: true,
409
409
  max_depth: 0,
410
410
  button_state_mode: 1,
411
- case_sensitive_property_search: true
411
+ case_sensitive_property_search: true,
412
+ show_errors: 'interaction'
412
413
  }
413
414
 
414
415
  /* This assignment was previously in index.js but makes more sense here */
package/src/editor.js CHANGED
@@ -15,6 +15,7 @@ export class AbstractEditor {
15
15
  this.original_schema = options.schema
16
16
  this.schema = this.jsoneditor.expandSchema(this.original_schema)
17
17
  this.active = true
18
+ this.isUiOnly = false
18
19
  this.options = extend({}, (this.options || {}), (this.schema.options || {}), (options.schema.options || {}), options)
19
20
 
20
21
  this.formname = this.jsoneditor.options.form_name_root || 'root'
@@ -522,13 +523,14 @@ export class AbstractEditor {
522
523
 
523
524
  // object properties
524
525
  if (Object.keys(this.editors).length) {
526
+ vars.properties = {}
527
+
525
528
  Object.keys(this.editors).forEach((key) => {
526
529
  const editor = this.editors[key]
527
530
 
528
531
  if (editor.schema && editor.schema.enum && editor.schema.options && editor.schema.options.enum_titles) {
529
532
  const enumIndex = editor.schema.enum.indexOf(editor.value)
530
533
  const enumTitle = editor.options.enum_titles[enumIndex]
531
- vars.properties = {}
532
534
  vars.properties[key] = {
533
535
  enumTitle: enumTitle
534
536
  }
@@ -342,7 +342,12 @@ export class ArrayEditor extends AbstractEditor {
342
342
  value = this.ensureArraySize(value)
343
343
 
344
344
  const serialized = JSON.stringify(value)
345
- if (serialized === this.serialized) return
345
+ if (serialized === this.serialized) {
346
+ if (initial) {
347
+ this.refreshValue(initial)
348
+ }
349
+ return
350
+ }
346
351
 
347
352
  value.forEach((val, i) => {
348
353
  if (this.rows[i]) {
@@ -454,7 +459,7 @@ export class ArrayEditor extends AbstractEditor {
454
459
  this.value[i] = editor.getValue()
455
460
  })
456
461
 
457
- if (!this.collapsed && this.setupButtons(minItems)) {
462
+ if (this.setupButtons(minItems) && !this.collapsed) {
458
463
  this.controls.style.display = 'inline-block'
459
464
  } else {
460
465
  this.controls.style.display = 'none'
@@ -6,6 +6,7 @@ export class ButtonEditor extends AbstractEditor {
6
6
  constructor (options, defaults) {
7
7
  super(options, defaults)
8
8
  this.active = false
9
+ this.isUiOnly = true
9
10
 
10
11
  /* Set field to required in schema otherwise it will not be displayed */
11
12
  if (this.parent && this.parent.schema) {
@@ -6,6 +6,11 @@ export class CheckboxEditor extends AbstractEditor {
6
6
  const changed = this.getValue() !== value
7
7
  this.value = value
8
8
  this.input.checked = this.value
9
+
10
+ if (!initial) {
11
+ this.is_dirty = true
12
+ }
13
+
9
14
  this.onChange(changed)
10
15
  }
11
16
 
@@ -50,6 +55,7 @@ export class CheckboxEditor extends AbstractEditor {
50
55
  e.preventDefault()
51
56
  e.stopPropagation()
52
57
  this.value = e.currentTarget.checked
58
+ this.is_dirty = true
53
59
  this.onChange(true)
54
60
  })
55
61
 
@@ -77,7 +83,17 @@ export class CheckboxEditor extends AbstractEditor {
77
83
  }
78
84
 
79
85
  showValidationErrors (errors) {
80
- this.previous_error_setting = this.jsoneditor.options.show_errors
86
+ const showErrors = this.jsoneditor.options.show_errors
87
+ const changeOrInteraction = showErrors === 'change' || showErrors === 'interaction'
88
+ const never = showErrors === 'never'
89
+
90
+ if (never) {
91
+ return
92
+ }
93
+
94
+ if (changeOrInteraction && !this.is_dirty) {
95
+ return
96
+ }
81
97
 
82
98
  const addMessage = (messages, error) => {
83
99
  if (error.path === this.path) {
@@ -42,7 +42,7 @@ export class ObjectEditor extends AbstractEditor {
42
42
  super.enable()
43
43
  if (this.editors) {
44
44
  Object.values(this.editors).forEach(e => {
45
- if (e.isActive()) {
45
+ if (e.isActive() || e.isUiOnly) {
46
46
  e.enable()
47
47
  }
48
48
  e.optInCheckbox.disabled = false
@@ -60,7 +60,7 @@ export class ObjectEditor extends AbstractEditor {
60
60
  super.disable()
61
61
  if (this.editors) {
62
62
  Object.values(this.editors).forEach(e => {
63
- if (e.isActive()) {
63
+ if (e.isActive() || e.isUiOnly) {
64
64
  e.disable(alwaysDisabled)
65
65
  }
66
66
  e.optInCheckbox.disabled = true
@@ -850,15 +850,8 @@ export class ObjectEditor extends AbstractEditor {
850
850
 
851
851
  copyJSON () {
852
852
  if (!this.editjson_holder) return
853
- const ta = document.createElement('textarea')
854
- ta.value = this.editjson_textarea.value
855
- ta.setAttribute('readonly', '')
856
- ta.style.position = 'absolute'
857
- ta.style.left = '-9999px'
858
- document.body.appendChild(ta)
859
- ta.select()
860
- document.execCommand('copy')
861
- document.body.removeChild(ta)
853
+ navigator.clipboard.writeText(this.editjson_textarea.value)
854
+ .catch((e) => window.alert(e))
862
855
  }
863
856
 
864
857
  saveJSON () {
@@ -17,12 +17,14 @@ export class SelectEditor extends AbstractEditor {
17
17
 
18
18
  if (this.value === sanitized) return
19
19
 
20
- if (initial) this.is_dirty = false
21
- else if (this.jsoneditor.options.show_errors === 'change') this.is_dirty = true
22
-
23
20
  this.input.value = this.enum_options[this.enum_values.indexOf(sanitized)]
24
21
 
25
22
  this.value = sanitized
23
+
24
+ if (!initial) {
25
+ this.is_dirty = true
26
+ }
27
+
26
28
  this.onChange()
27
29
  this.change()
28
30
  }
@@ -345,7 +347,17 @@ export class SelectEditor extends AbstractEditor {
345
347
  }
346
348
 
347
349
  showValidationErrors (errors) {
348
- this.previous_error_setting = this.jsoneditor.options.show_errors
350
+ const showErrors = this.jsoneditor.options.show_errors
351
+ const changeOrInteraction = showErrors === 'change' || showErrors === 'interaction'
352
+ const never = showErrors === 'never'
353
+
354
+ if (never) {
355
+ return
356
+ }
357
+
358
+ if (changeOrInteraction && !this.is_dirty) {
359
+ return
360
+ }
349
361
 
350
362
  const addMessage = (messages, error) => {
351
363
  if (error.path === this.path) {
package/src/validator.js CHANGED
@@ -133,7 +133,8 @@ export class Validator {
133
133
  return []
134
134
  },
135
135
  const (schema, value, path) {
136
- const valid = JSON.stringify(schema.const) === JSON.stringify(value) && !(Array.isArray(value) || typeof value === 'object')
136
+ const valid = JSON.stringify(schema.const) === JSON.stringify(value)
137
+
137
138
  if (!valid) {
138
139
  return [{
139
140
  path,
@@ -5,6 +5,45 @@ const { DEFAULT_WAIT_TIME } = require('./test-config')
5
5
 
6
6
  Feature('core')
7
7
 
8
+ Scenario('should show validation errors based on "show_errors" setting @showValidationErrors', async ({ I }) => {
9
+ I.amOnPage('show-validation-errors.html')
10
+ I.waitForElement('.je-ready')
11
+ I.dontSee('Value must be the constant value.')
12
+ I.dontSee('Value must be the constant value.')
13
+ I.dontSee('Value must be the constant value.')
14
+
15
+ // set invalid values through interaction
16
+ I.checkOption('[name="root[boolean-checkbox]"]')
17
+ I.selectOption('[name="root[boolean-select]"]', '1')
18
+ I.selectOption('[name="root[boolean-choices]"]', '1')
19
+ I.uncheckOption('[name="root[boolean-checkbox]"]')
20
+ I.selectOption('[name="root[boolean-select]"]', 'false')
21
+ I.selectOption('[name="root[boolean-choices]"]', 'false')
22
+ I.waitForText('Value must be the constant value.', DEFAULT_WAIT_TIME, '[data-schemapath="root.boolean-checkbox"] .invalid-feedback')
23
+ I.waitForText('Value must be the constant value.', DEFAULT_WAIT_TIME, '[data-schemapath="root.boolean-select"] .invalid-feedback')
24
+ I.waitForText('Value must be the constant value.', DEFAULT_WAIT_TIME, '[data-schemapath="root.boolean-choices"] .invalid-feedback')
25
+
26
+ // set valid values through interaction
27
+ I.checkOption('[name="root[boolean-checkbox]"]')
28
+ I.selectOption('[name="root[boolean-select]"]', '1')
29
+ I.selectOption('[name="root[boolean-choices]"]', '1')
30
+ I.dontSee('Value must be the constant value.')
31
+ I.dontSee('Value must be the constant value.')
32
+ I.dontSee('Value must be the constant value.')
33
+
34
+ // set invalid values with setValue
35
+ I.click('#set-invalid-values')
36
+ I.waitForText('Value must be the constant value.', DEFAULT_WAIT_TIME, '[data-schemapath="root.boolean-checkbox"] .invalid-feedback')
37
+ I.waitForText('Value must be the constant value.', DEFAULT_WAIT_TIME, '[data-schemapath="root.boolean-select"] .invalid-feedback')
38
+ I.waitForText('Value must be the constant value.', DEFAULT_WAIT_TIME, '[data-schemapath="root.boolean-choices"] .invalid-feedback')
39
+
40
+ // set valid values with setValue
41
+ I.click('#set-valid-values')
42
+ I.waitForInvisible('[data-schemapath="root.boolean-checkbox"] .invalid-feedback')
43
+ I.waitForInvisible('[data-schemapath="root.boolean-select"] .invalid-feedback')
44
+ I.waitForInvisible('[data-schemapath="root.boolean-choices"] .invalid-feedback')
45
+ })
46
+
8
47
  Scenario('should listen to @load-events', async ({ I }) => {
9
48
  I.amOnPage('load-events.html')
10
49
  I.waitForElement('.je-ready')
@@ -42,3 +42,9 @@ Scenario('should set icon @button @button-icon', async ({ I }) => {
42
42
  I.waitForElement('.je-ready', DEFAULT_WAIT_TIME)
43
43
  I.waitForElement('i.fas.fa-search', DEFAULT_WAIT_TIME)
44
44
  })
45
+
46
+ Scenario('should be disable if we disable parent @button-disable', async ({ I }) => {
47
+ I.amOnPage('disable-button-in-object-editors.html')
48
+ I.waitForElement('.je-ready', DEFAULT_WAIT_TIME)
49
+ I.seeDisabledAttribute('[data-schemapath="root.some_button"] button')
50
+ })
@@ -0,0 +1,18 @@
1
+ /* global Feature Scenario */
2
+
3
+ const { DEFAULT_WAIT_TIME } = require('../test-config')
4
+
5
+ Feature('issues')
6
+
7
+ Scenario('GitHub issue 1453 should remain fixed @issue-1453', async ({ I }) => {
8
+ I.amOnPage('issues/issue-gh-1453.html')
9
+ I.waitForElement('.je-ready', DEFAULT_WAIT_TIME)
10
+ I.waitForElement('.json-editor-btntype-add', DEFAULT_WAIT_TIME)
11
+ I.dontSeeElement('.json-editor-btntype-delete')
12
+ I.dontSeeElement('.json-editor-btntype-deletelast')
13
+ I.dontSeeElement('.json-editor-btntype-deleteall')
14
+ I.click('.json-editor-btntype-toggle')
15
+ I.dontSeeElement('.json-editor-btntype-delete')
16
+ I.dontSeeElement('.json-editor-btntype-deletelast')
17
+ I.dontSeeElement('.json-editor-btntype-deleteall')
18
+ })
@@ -0,0 +1,14 @@
1
+ /* global Feature Scenario */
2
+
3
+ const { DEFAULT_WAIT_TIME } = require('../test-config')
4
+
5
+ Feature('issues')
6
+
7
+ Scenario('GitHub issue 1461 should remain fixed @issue-1461', async ({ I }) => {
8
+ I.amOnPage('issues/issue-gh-1461.html')
9
+ I.waitForElement('.je-ready', DEFAULT_WAIT_TIME)
10
+ I.waitForElement('.json-editor-btntype-add', DEFAULT_WAIT_TIME)
11
+ I.dontSeeElement('.json-editor-btntype-delete')
12
+ I.dontSeeElement('.json-editor-btntype-deletelast')
13
+ I.dontSeeElement('.json-editor-btntype-deleteall')
14
+ })
@@ -0,0 +1,9 @@
1
+ /* global Feature Scenario */
2
+
3
+ Feature('issues')
4
+
5
+ Scenario('GitHub issue 1463 should remain fixed @issue-1463', async ({ I }) => {
6
+ I.amOnPage('issues/issue-gh-1463.html')
7
+ I.waitForElement('.je-ready')
8
+ I.dontSee('Value must be the constant value')
9
+ })
@@ -0,0 +1,56 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8"/>
5
+ <title>Button disabled</title>
6
+ <script src="../../dist/jsoneditor.js"></script>
7
+ <link rel="stylesheet" id="theme-link" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
8
+ <link rel="stylesheet" id="iconlib-link" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css">
9
+ </head>
10
+ <body>
11
+
12
+ <div class="container">
13
+ <div id='editor-container'></div>
14
+ </div>
15
+
16
+ <script>
17
+ var editorContainer = document.querySelector('#editor-container')
18
+ var schema = {
19
+ "type": "object",
20
+ "title": "test",
21
+ "properties": {
22
+ "some_button": {
23
+ "format": "button",
24
+ "title": "A button",
25
+ "options": {
26
+ "button": {
27
+ "align": "left",
28
+ "icon": "map-marker",
29
+ "action": "determineCurrentCoordinates"
30
+ }
31
+ }
32
+ }
33
+ }
34
+ }
35
+
36
+ JSONEditor.defaults.callbacks.button = {
37
+ "determineCurrentCoordinates": function() {
38
+ console.log('OK')
39
+ }
40
+ }
41
+
42
+ var editor = new JSONEditor(editorContainer, {
43
+ schema: schema,
44
+ theme: 'bootstrap4',
45
+ iconlib: 'fontawesome',
46
+ show_errors: 'always',
47
+ show_opt_in: true
48
+ })
49
+
50
+ editor.on('ready', function () {
51
+ editor.disable()
52
+ })
53
+ </script>
54
+
55
+ </body>
56
+ </html>
@@ -0,0 +1,45 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>GitHub Issue 1453</title>
6
+ <link rel="stylesheet" id="theme-link" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
7
+ <link rel="stylesheet" id="iconlib-link" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css">
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
9
+ <script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
10
+ <script src="../../../dist/jsoneditor.js"></script>
11
+ </head>
12
+ <body>
13
+ <div class="container">
14
+ <textarea class="form-control" id="value" cols="30" rows="10"></textarea>
15
+ <a href="https://github.com/json-editor/json-editor/issues/1453">GitHub Issue 1453</a>
16
+ <div id='editor_holder'></div>
17
+ </div>
18
+
19
+ <script>
20
+ var value = document.querySelector('#value')
21
+
22
+ var defaultSchema = {
23
+ "type": "object",
24
+ "properties": {
25
+ "list": {
26
+ "type": "array",
27
+ "items": {
28
+ "type": "string"
29
+ },
30
+ "options": {
31
+ "collapsed": true
32
+ }
33
+ }
34
+ }
35
+ }
36
+
37
+ var editor = new JSONEditor(document.getElementById('editor_holder'), {
38
+ schema: defaultSchema,
39
+ show_errors: 'always',
40
+ disable_array_delete_last_row: true,
41
+ disable_array_delete_all_rows: true,
42
+ })
43
+ </script>
44
+ </body>
45
+ </html>
@@ -0,0 +1,55 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>GitHub Issue 1461</title>
6
+ <link rel="stylesheet" id="theme-link" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
7
+ <link rel="stylesheet" id="iconlib-link" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css">
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
9
+ <script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
10
+ <script src="../../../dist/jsoneditor.js"></script>
11
+ </head>
12
+ <body>
13
+ <div class="container">
14
+ <textarea class="form-control" id="value" cols="30" rows="10"></textarea>
15
+ <a href="https://github.com/json-editor/json-editor/issues/1461">GitHub Issue 1461</a>
16
+ <div id='editor_holder'></div>
17
+ </div>
18
+
19
+ <script>
20
+ var value = document.querySelector('#value')
21
+
22
+ var defaultSchema = {
23
+ "type": "object",
24
+ "properties": {
25
+ "enumProperty": {
26
+ "type": "string",
27
+ "default": "secondValue",
28
+ "enum": [
29
+ "firstValue",
30
+ "secondValue"
31
+ ]
32
+ },
33
+ "arrayProperty": {
34
+ "type": "array",
35
+ "items": {
36
+ "type": "object",
37
+ "properties": {
38
+ "attribute": {
39
+ "type": "string"
40
+ }
41
+ }
42
+ }
43
+ }}
44
+ }
45
+
46
+ var editor = new JSONEditor(document.getElementById('editor_holder'), {
47
+ iconlib: 'fontawesome5',
48
+ schema: defaultSchema,
49
+ show_errors: 'always',
50
+ disable_array_delete_last_row: true,
51
+ disable_array_delete_all_rows: true
52
+ })
53
+ </script>
54
+ </body>
55
+ </html>
@@ -0,0 +1,41 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>GitHub Issue 1463</title>
6
+ <link rel="stylesheet" id="theme-link" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
7
+ <link rel="stylesheet" id="iconlib-link" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css">
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
9
+ <script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
10
+ <script src="../../../dist/jsoneditor.js"></script>
11
+ </head>
12
+ <body>
13
+ <div class="container">
14
+ <div id='editor_holder'></div>
15
+ </div>
16
+
17
+ <script>
18
+ const value = document.querySelector('#value')
19
+ const defaultSchema = {
20
+ "title": "const",
21
+ "type": "object",
22
+ "properties": {
23
+ "object": {
24
+ "type": "object",
25
+ "const": {}
26
+ },
27
+ "array": {
28
+ "type": "array",
29
+ "const": []
30
+ }
31
+ }
32
+ }
33
+
34
+ const editor = new JSONEditor(document.getElementById('editor_holder'), {
35
+ iconlib: 'fontawesome5',
36
+ schema: defaultSchema,
37
+ theme: 'bootstrap4'
38
+ })
39
+ </script>
40
+ </body>
41
+ </html>
@@ -0,0 +1,73 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8"/>
5
+ <title>showValidationErrors</title>
6
+ <script src="../../dist/jsoneditor.js"></script>
7
+ <link rel="stylesheet" id="theme-link" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
8
+ <link rel="stylesheet" id="iconlib-link" href="https://use.fontawesome.com/releases/v5.6.1/css/all.css">
9
+ </head>
10
+ <body>
11
+
12
+ <div class="container">
13
+ <div id='editor-container'></div>
14
+ <div class="btn btn-success" id="set-valid-values">Set valid values</div>
15
+ <div class="btn btn-danger" id="set-invalid-values">Set invalid values</div>
16
+ </div>
17
+
18
+ <script>
19
+ const editorContainer = document.querySelector('#editor-container')
20
+ const schema = {
21
+ "type": "object",
22
+ "properties": {
23
+ "boolean-checkbox": {
24
+ "title": "boolean-checkbox",
25
+ "type": "boolean",
26
+ "format": "checkbox",
27
+ "const": true,
28
+ "default": false
29
+ },
30
+ "boolean-select": {
31
+ "title": "boolean-select",
32
+ "type": "boolean",
33
+ "const": true,
34
+ "default": false
35
+ },
36
+ "boolean-choices": {
37
+ "title": "boolean-choices",
38
+ "type": "boolean",
39
+ "format": "choices",
40
+ "const": true,
41
+ "default": false
42
+ }
43
+ }
44
+ }
45
+
46
+ const editor = new JSONEditor(editorContainer, {
47
+ schema: schema,
48
+ theme: 'bootstrap4',
49
+ iconlib: 'fontawesome'
50
+ })
51
+
52
+ const setValidValues = document.querySelector('#set-valid-values')
53
+ const setInvalidValues = document.querySelector('#set-invalid-values')
54
+
55
+ setValidValues.addEventListener('click', () => {
56
+ editor.setValue({
57
+ "boolean-checkbox": true,
58
+ "boolean-select": true,
59
+ "boolean-choices": true
60
+ })
61
+ })
62
+
63
+ setInvalidValues.addEventListener('click', () => {
64
+ editor.setValue({
65
+ "boolean-checkbox": false,
66
+ "boolean-select": false,
67
+ "boolean-choices": false
68
+ })
69
+ })
70
+ </script>
71
+
72
+ </body>
73
+ </html>