@json-editor/json-editor 2.6.1 → 2.9.0-beta.0
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/.github/workflows/build.yml +12 -3
- package/CHANGELOG.md +32 -0
- package/README.md +148 -18
- package/dist/jsoneditor.js +2 -2
- package/dist/nonmin/jsoneditor.js +2920 -643
- package/dist/nonmin/jsoneditor.js.map +1 -1
- package/docs/form-submission.html +162 -0
- package/package.json +4 -3
- package/release-notes.md +2 -0
- package/src/core.js +36 -37
- package/src/defaults.js +10 -2
- package/src/editors/array.js +12 -1
- package/src/editors/autocomplete.js +4 -3
- package/src/editors/button.js +1 -1
- package/src/editors/checkbox.js +3 -1
- package/src/editors/hidden.js +3 -1
- package/src/editors/multiselect.js +17 -6
- package/src/editors/radio.js +8 -3
- package/src/editors/select.js +3 -1
- package/src/editors/signature.js +3 -1
- package/src/editors/string.js +7 -1
- package/src/editors/table.js +20 -2
- package/src/editors/upload.js +1 -1
- package/src/editors/uuid.js +2 -12
- package/src/iconlib.js +1 -1
- package/src/schemaloader.js +319 -103
- package/src/style.css +3 -0
- package/src/style.css.js +1 -1
- package/src/theme.js +0 -2
- package/src/themes/bootstrap3.js +1 -0
- package/src/themes/spectre.js +2 -1
- package/src/utilities.js +18 -0
- package/src/validator.js +36 -34
- package/tests/codeceptjs/codecept.json +1 -1
- package/tests/codeceptjs/core_test.js +125 -0
- package/tests/codeceptjs/editors/advanced_test.js +1 -1
- package/tests/codeceptjs/editors/array_test.js +74 -0
- package/tests/codeceptjs/editors/autocomplete_test.js +16 -0
- package/tests/codeceptjs/editors/button_test.js +10 -3
- package/tests/codeceptjs/editors/integer_test.js +7 -2
- package/tests/codeceptjs/editors/jodit_test.js +3 -3
- package/tests/codeceptjs/editors/range_test.js +12 -0
- package/tests/codeceptjs/editors/uuid_test.js +31 -4
- package/tests/docker-compose.yml +1 -1
- package/tests/fixtures/definitions.json +22 -0
- package/tests/fixtures/properties.json +20 -0
- package/tests/pages/array-checkboxes-infotext.html +52 -0
- package/tests/pages/array-move-events.html +4 -2
- package/tests/pages/array-unique-items-sort.html +78 -0
- package/tests/pages/autocomplete.html +69 -0
- package/tests/pages/button-icons.html +38 -0
- package/tests/pages/core.html +4 -2
- package/tests/pages/error-messages.html +47 -0
- package/tests/pages/grid-strict.html +6 -10
- package/tests/pages/grid.html +0 -4
- package/tests/pages/issues/issue-gh-812.html +4 -2
- package/tests/pages/meta_schema.json +14 -0
- package/tests/pages/object-required-properties.html +7 -7
- package/tests/pages/range.html +60 -0
- package/tests/pages/ready.html +43 -0
- package/tests/pages/references.html +168 -0
- package/tests/pages/string-simplemde-editor.html +81 -0
- package/tests/pages/table-move-events.html +4 -1
- package/tests/pages/urn.html +11 -8
- package/tests/pages/use-name-attributes.html +206 -0
- package/tests/pages/uuid.html +89 -50
- package/tests/pages/validation-messages.json +705 -0
- package/tests/unit/core.spec.js +79 -66
- package/tests/unit/editor.spec.js +20 -8
- package/tests/unit/editors/array.spec.js +3 -2
- package/tests/unit/editors/object.spec.js +3 -1
- package/tests/unit/editors/table.spec.js +4 -2
- package/tests/unit/schemaloader.spec.js +181 -103
- package/tests/unit/validator.spec.js +2 -2
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8"/>
|
|
5
|
+
<title>JSONEditor with forms</title>
|
|
6
|
+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div class="container">
|
|
10
|
+
<p>
|
|
11
|
+
The form is set to send a <code>GET</code> request to the same page.
|
|
12
|
+
A change event listener has been added to the editor so that whenever the form changes, the editor value
|
|
13
|
+
is stored in a hidden input using <code>JSON.stringify()</code>.
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p>
|
|
17
|
+
The option <code>use_name_attributes</code> was set to <code>false</code>
|
|
18
|
+
to avoid sending the other field with the request.
|
|
19
|
+
</p>
|
|
20
|
+
<p>
|
|
21
|
+
When the form is submitted only the hidden input is sent in the request.
|
|
22
|
+
This allows to send data structures like arrays and object.
|
|
23
|
+
Also the same schema that is used to build the form can be used as parameter to backend json validators tools.
|
|
24
|
+
Try yourself, submit the form and look in the network tab of the developer tool.
|
|
25
|
+
</p>
|
|
26
|
+
<div class="form-group"></div>
|
|
27
|
+
<form action="/docs/form-submission.html" method="get">
|
|
28
|
+
<input id="input" type="hidden" name="json">
|
|
29
|
+
<div id='editor-container'></div>
|
|
30
|
+
<input id="submit" class="btn btn-primary" width="100" type="submit">
|
|
31
|
+
</form>
|
|
32
|
+
<br>
|
|
33
|
+
<h2>Get params</h2>
|
|
34
|
+
<pre id="get-params"></pre>
|
|
35
|
+
</div>
|
|
36
|
+
<script src="https://cdn.jsdelivr.net/npm/@json-editor/json-editor@latest/dist/jsoneditor.min.js"></script>
|
|
37
|
+
<script>
|
|
38
|
+
var params = {}
|
|
39
|
+
for (const [key, value] of new URLSearchParams(window.location.search).entries()) {
|
|
40
|
+
params[key] = value
|
|
41
|
+
console.log(key, value)
|
|
42
|
+
}
|
|
43
|
+
document.querySelector('#get-params').textContent = JSON.stringify(params, null, 2)
|
|
44
|
+
var config = {
|
|
45
|
+
use_name_attributes: false,
|
|
46
|
+
theme: 'bootstrap4',
|
|
47
|
+
disable_edit_json: true,
|
|
48
|
+
disable_properties: true,
|
|
49
|
+
disable_collapse: true,
|
|
50
|
+
schema: {
|
|
51
|
+
'title': 'Person',
|
|
52
|
+
'type': 'object',
|
|
53
|
+
'required': [
|
|
54
|
+
'name',
|
|
55
|
+
'age',
|
|
56
|
+
'date',
|
|
57
|
+
'favorite_color',
|
|
58
|
+
'gender',
|
|
59
|
+
'location',
|
|
60
|
+
'pets'
|
|
61
|
+
],
|
|
62
|
+
'properties': {
|
|
63
|
+
'name': {
|
|
64
|
+
'type': 'string',
|
|
65
|
+
'description': 'First and Last name',
|
|
66
|
+
'minLength': 4,
|
|
67
|
+
'default': 'Jeremy Dorn'
|
|
68
|
+
},
|
|
69
|
+
'age': {
|
|
70
|
+
'type': 'integer',
|
|
71
|
+
'default': 25,
|
|
72
|
+
'minimum': 18,
|
|
73
|
+
'maximum': 99
|
|
74
|
+
},
|
|
75
|
+
'favorite_color': {
|
|
76
|
+
'type': 'string',
|
|
77
|
+
'format': 'color',
|
|
78
|
+
'title': 'favorite color',
|
|
79
|
+
'default': '#ffa500'
|
|
80
|
+
},
|
|
81
|
+
'gender': {
|
|
82
|
+
'type': 'string',
|
|
83
|
+
'enum': [
|
|
84
|
+
'male',
|
|
85
|
+
'female',
|
|
86
|
+
'other'
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
'date': {
|
|
90
|
+
'type': 'string',
|
|
91
|
+
'format': 'date',
|
|
92
|
+
'options': {
|
|
93
|
+
'flatpickr': {}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
'location': {
|
|
97
|
+
'type': 'object',
|
|
98
|
+
'title': 'Location',
|
|
99
|
+
'properties': {
|
|
100
|
+
'city': {
|
|
101
|
+
'type': 'string',
|
|
102
|
+
'default': 'San Francisco'
|
|
103
|
+
},
|
|
104
|
+
'state': {
|
|
105
|
+
'type': 'string',
|
|
106
|
+
'default': 'CA'
|
|
107
|
+
},
|
|
108
|
+
'citystate': {
|
|
109
|
+
'type': 'string',
|
|
110
|
+
'description': 'This is generated automatically from the previous two fields',
|
|
111
|
+
'template': '{{city}}, {{state}}',
|
|
112
|
+
'watch': {
|
|
113
|
+
'city': 'location.city',
|
|
114
|
+
'state': 'location.state'
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
'pets': {
|
|
120
|
+
'type': 'array',
|
|
121
|
+
'format': 'table',
|
|
122
|
+
'title': 'Pets',
|
|
123
|
+
'uniqueItems': true,
|
|
124
|
+
'items': {
|
|
125
|
+
'type': 'object',
|
|
126
|
+
'title': 'Pet',
|
|
127
|
+
'properties': {
|
|
128
|
+
'type': {
|
|
129
|
+
'type': 'string',
|
|
130
|
+
'enum': [
|
|
131
|
+
'cat',
|
|
132
|
+
'dog',
|
|
133
|
+
'bird',
|
|
134
|
+
'reptile',
|
|
135
|
+
'other'
|
|
136
|
+
],
|
|
137
|
+
'default': 'dog'
|
|
138
|
+
},
|
|
139
|
+
'name': {
|
|
140
|
+
'type': 'string'
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
'default': [
|
|
145
|
+
{
|
|
146
|
+
'type': 'dog',
|
|
147
|
+
'name': 'Walter'
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
var editor = new JSONEditor(document.querySelector('#editor-container'), config)
|
|
156
|
+
|
|
157
|
+
editor.on('change', function () {
|
|
158
|
+
document.querySelector('#input').value = JSON.stringify(editor.getValue())
|
|
159
|
+
})
|
|
160
|
+
</script>
|
|
161
|
+
</body>
|
|
162
|
+
</html>
|
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.
|
|
5
|
+
"version": "2.9.0-beta.0",
|
|
6
6
|
"main": "dist/jsoneditor.js",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Jeremy Dorn",
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
"http-server": "^0.12.3",
|
|
72
72
|
"jasmine": "^3.7.0",
|
|
73
73
|
"jasmine-core": "^3.7.1",
|
|
74
|
-
"jodit": "
|
|
74
|
+
"jodit": "^3.12.4",
|
|
75
75
|
"jquery": "^3.6.0",
|
|
76
|
-
"karma": "^
|
|
76
|
+
"karma": "^6.3.14",
|
|
77
77
|
"karma-chrome-launcher": "^3.1.0",
|
|
78
78
|
"karma-jasmine": "^2.0.1",
|
|
79
79
|
"karma-jasmine-html-reporter": "^1.6.0",
|
|
@@ -87,6 +87,7 @@
|
|
|
87
87
|
"puppeteer": "^1.20.0",
|
|
88
88
|
"remove-strict-webpack-plugin": "^0.1.2",
|
|
89
89
|
"sceditor": "^2.1.3",
|
|
90
|
+
"simplemde": "^1.11.2",
|
|
90
91
|
"sinon": "^8.1.1",
|
|
91
92
|
"standard": "^14.3.4",
|
|
92
93
|
"style-loader": "^1.3.0",
|
package/release-notes.md
CHANGED
|
@@ -79,6 +79,8 @@ For now I have passed in `JSONEditor.defaults` as `defaults`.
|
|
|
79
79
|
|
|
80
80
|
### NPM Release
|
|
81
81
|
|
|
82
|
+
Set/export `CHROME_BIN=/path/to/chrome_or_chromium`, start stack with `docker-compose up`
|
|
83
|
+
|
|
82
84
|
1. Update `CHANGELOG.md`
|
|
83
85
|
2. Switch to `release` branch and `merge master into release`
|
|
84
86
|
3. NPM login: `npm login`
|
package/src/core.js
CHANGED
|
@@ -31,6 +31,8 @@ export class JSONEditor {
|
|
|
31
31
|
/* Load editors and selected theme style rules */
|
|
32
32
|
if (!themeClass) throw new Error(`Unknown theme ${themeName}`)
|
|
33
33
|
this.element.setAttribute('data-theme', themeName)
|
|
34
|
+
this.element.classList.add('je-not-loaded')
|
|
35
|
+
this.element.classList.remove('je-ready')
|
|
34
36
|
// eslint-disable-next-line new-cap
|
|
35
37
|
this.theme = new themeClass(this)
|
|
36
38
|
const rules = extend(styleRules, this.getEditorsRules())
|
|
@@ -56,67 +58,64 @@ export class JSONEditor {
|
|
|
56
58
|
|
|
57
59
|
this.root_container = this.theme.getContainer()
|
|
58
60
|
this.element.appendChild(this.root_container)
|
|
61
|
+
this.promise = this.load()
|
|
62
|
+
}
|
|
59
63
|
|
|
60
|
-
|
|
64
|
+
async load () {
|
|
61
65
|
const fetchUrl = document.location.origin + document.location.pathname.toString()
|
|
62
66
|
const loader = new SchemaLoader(this.options)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
this.expandSchema = (schema, fileBase) => loader.expandSchema(schema, fileBase)
|
|
67
|
+
this.expandSchema = (schema) => loader.expandSchema(schema)
|
|
66
68
|
this.expandRefs = (schema, fileBase) => loader.expandRefs(schema, fileBase)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
const location = document.location.toString()
|
|
70
|
+
const schema = await loader.load(this.schema, fetchUrl, location)
|
|
71
|
+
const validatorOptions = this.options.custom_validators ? { custom_validators: this.options.custom_validators } : {}
|
|
72
|
+
this.validator = new Validator(this, null, validatorOptions, JSONEditor.defaults)
|
|
73
|
+
const editorClass = this.getEditorClass(schema)
|
|
74
|
+
this.root = this.createEditor(editorClass, {
|
|
75
|
+
jsoneditor: this,
|
|
76
|
+
schema,
|
|
77
|
+
required: true,
|
|
78
|
+
container: this.root_container
|
|
79
|
+
})
|
|
75
80
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
required: true,
|
|
80
|
-
container: this.root_container
|
|
81
|
-
})
|
|
81
|
+
this.root.preBuild()
|
|
82
|
+
this.root.build()
|
|
83
|
+
this.root.postBuild()
|
|
82
84
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
this.root.postBuild()
|
|
85
|
+
/* Starting data */
|
|
86
|
+
if (hasOwnProperty(this.options, 'startval')) this.root.setValue(this.options.startval)
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
this.validation_results = this.validator.validate(this.root.getValue())
|
|
89
|
+
this.root.showValidationErrors(this.validation_results)
|
|
90
|
+
this.ready = true
|
|
91
|
+
this.element.classList.remove('je-not-loaded')
|
|
92
|
+
this.element.classList.add('je-ready')
|
|
89
93
|
|
|
94
|
+
/* Fire ready event asynchronously */
|
|
95
|
+
window.requestAnimationFrame(() => {
|
|
96
|
+
if (!this.ready) return
|
|
90
97
|
this.validation_results = this.validator.validate(this.root.getValue())
|
|
91
98
|
this.root.showValidationErrors(this.validation_results)
|
|
92
|
-
this.ready
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
window.requestAnimationFrame(() => {
|
|
96
|
-
if (!this.ready) return
|
|
97
|
-
this.validation_results = this.validator.validate(this.root.getValue())
|
|
98
|
-
this.root.showValidationErrors(this.validation_results)
|
|
99
|
-
this.trigger('ready')
|
|
100
|
-
this.trigger('change')
|
|
101
|
-
})
|
|
102
|
-
}, fetchUrl, location)
|
|
99
|
+
this.trigger('ready')
|
|
100
|
+
this.trigger('change')
|
|
101
|
+
})
|
|
103
102
|
}
|
|
104
103
|
|
|
105
104
|
getValue () {
|
|
106
|
-
if (!this.ready) throw new Error(
|
|
105
|
+
if (!this.ready) throw new Error('JSON Editor not ready yet. Make sure the load method is complete')
|
|
107
106
|
|
|
108
107
|
return this.root.getValue()
|
|
109
108
|
}
|
|
110
109
|
|
|
111
110
|
setValue (value) {
|
|
112
|
-
if (!this.ready) throw new Error(
|
|
111
|
+
if (!this.ready) throw new Error('JSON Editor not ready yet. Make sure the load method is complete')
|
|
113
112
|
|
|
114
113
|
this.root.setValue(value)
|
|
115
114
|
return this
|
|
116
115
|
}
|
|
117
116
|
|
|
118
117
|
validate (value) {
|
|
119
|
-
if (!this.ready) throw new Error(
|
|
118
|
+
if (!this.ready) throw new Error('JSON Editor not ready yet. Make sure the load method is complete')
|
|
120
119
|
|
|
121
120
|
/* Custom value */
|
|
122
121
|
if (arguments.length === 1) {
|
package/src/defaults.js
CHANGED
|
@@ -350,11 +350,18 @@ function upload (type, file, cbs) {
|
|
|
350
350
|
}
|
|
351
351
|
|
|
352
352
|
/* String translate function */
|
|
353
|
-
function translate (key, variables) {
|
|
353
|
+
function translate (key, variables, schema) {
|
|
354
|
+
let schemaMessages = {}
|
|
355
|
+
|
|
356
|
+
if (schema && schema.options && schema.options.error_messages && schema.options.error_messages[defaults.language]) {
|
|
357
|
+
schemaMessages = schema.options.error_messages[defaults.language]
|
|
358
|
+
}
|
|
359
|
+
|
|
354
360
|
const lang = defaults.languages[defaults.language]
|
|
361
|
+
|
|
355
362
|
if (!lang) throw new Error(`Unknown language ${defaults.language}`)
|
|
356
363
|
|
|
357
|
-
let string = lang[key] || defaults.languages[default_language][key] || key
|
|
364
|
+
let string = schemaMessages[key] || lang[key] || defaults.languages[default_language][key] || key
|
|
358
365
|
|
|
359
366
|
if (variables) {
|
|
360
367
|
for (let i = 0; i < variables.length; i++) {
|
|
@@ -374,6 +381,7 @@ function translateProperty (text, variables) {
|
|
|
374
381
|
/* Default options when initializing JSON Editor */
|
|
375
382
|
const options = {
|
|
376
383
|
upload,
|
|
384
|
+
use_name_attributes: true,
|
|
377
385
|
prompt_before_delete: true,
|
|
378
386
|
use_default_values: true,
|
|
379
387
|
max_depth: 0
|
package/src/editors/array.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AbstractEditor } from '../editor.js'
|
|
2
|
-
import { extend, trigger } from '../utilities.js'
|
|
2
|
+
import { extend, generateUUID, trigger } from '../utilities.js'
|
|
3
3
|
import rules from './array.css.js'
|
|
4
4
|
|
|
5
5
|
export class ArrayEditor extends AbstractEditor {
|
|
@@ -545,6 +545,7 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
545
545
|
|
|
546
546
|
_createCopyButton (i, holder) {
|
|
547
547
|
const button = this.getButton(this.getItemTitle(), 'copy', 'button_copy_row_title', [this.getItemTitle()])
|
|
548
|
+
const schema = this.schema
|
|
548
549
|
button.classList.add('copy', 'json-editor-btntype-copy')
|
|
549
550
|
button.setAttribute('data-i', i)
|
|
550
551
|
button.addEventListener('click', e => {
|
|
@@ -555,6 +556,16 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
555
556
|
|
|
556
557
|
value.forEach((row, j) => {
|
|
557
558
|
if (j === i) {
|
|
559
|
+
/* Force generation of new UUID if the item has been cloned. */
|
|
560
|
+
if (schema.items.type === 'string' && schema.items.format === 'uuid') {
|
|
561
|
+
row = generateUUID()
|
|
562
|
+
} else if (schema.items.type === 'object' && schema.items.properties) {
|
|
563
|
+
for (const key of Object.keys(row)) {
|
|
564
|
+
if (schema.items.properties && schema.items.properties[key] && schema.items.properties[key].format === 'uuid') {
|
|
565
|
+
row[key] = generateUUID()
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
558
569
|
value.push(row)
|
|
559
570
|
}
|
|
560
571
|
})
|
|
@@ -29,18 +29,19 @@ export class AutocompleteEditor extends StringEditor {
|
|
|
29
29
|
/* Get options, either global options from "this.defaults.options.autocomplete" or */
|
|
30
30
|
/* single property options from schema "options.autocomplete" */
|
|
31
31
|
options = this.expandCallbacks('autocomplete', extend({}, {
|
|
32
|
-
search: (jseditor
|
|
32
|
+
search: (jseditor) => {
|
|
33
33
|
// eslint-disable-next-line no-console
|
|
34
34
|
console.log(`No "search" callback defined for autocomplete in property "${jseditor.key}"`)
|
|
35
35
|
return []
|
|
36
36
|
},
|
|
37
|
+
onSubmit: () => {
|
|
38
|
+
this.input.blur()
|
|
39
|
+
},
|
|
37
40
|
baseClass: 'autocomplete'
|
|
38
41
|
}, this.defaults.options.autocomplete || {}, this.options.autocomplete || {}))
|
|
39
42
|
|
|
40
43
|
this.autocomplete_wrapper.classList.add(options.baseClass)
|
|
41
44
|
this.autocomplete_dropdown.classList.add(`${options.baseClass}-result-list`)
|
|
42
|
-
/* this.input.classList.add(options.baseClass + '-input'); */
|
|
43
|
-
|
|
44
45
|
this.autocomplete_instance = new window.Autocomplete(this.autocomplete_wrapper, options)
|
|
45
46
|
}
|
|
46
47
|
super.afterInputReady()
|
package/src/editors/button.js
CHANGED
|
@@ -34,7 +34,7 @@ export class ButtonEditor extends AbstractEditor {
|
|
|
34
34
|
}
|
|
35
35
|
}, this.defaults.options.button || {}, this.options.button || {}))
|
|
36
36
|
|
|
37
|
-
this.input = this.
|
|
37
|
+
this.input = this.getButton(title, options.icon, title)
|
|
38
38
|
this.input.addEventListener('click', options.action, false)
|
|
39
39
|
|
|
40
40
|
if (this.schema.readOnly || this.schema.readonly || this.schema.template) {
|
package/src/editors/checkbox.js
CHANGED
|
@@ -12,7 +12,9 @@ export class CheckboxEditor extends AbstractEditor {
|
|
|
12
12
|
register () {
|
|
13
13
|
super.register()
|
|
14
14
|
if (!this.input) return
|
|
15
|
-
this.
|
|
15
|
+
if (this.jsoneditor.options.use_name_attributes) {
|
|
16
|
+
this.input.setAttribute('name', this.formname)
|
|
17
|
+
}
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
unregister () {
|
package/src/editors/hidden.js
CHANGED
|
@@ -7,7 +7,9 @@ export class HiddenEditor extends AbstractEditor {
|
|
|
7
7
|
register () {
|
|
8
8
|
super.register()
|
|
9
9
|
if (!this.input) return
|
|
10
|
-
this.
|
|
10
|
+
if (this.jsoneditor.options.use_name_attributes) {
|
|
11
|
+
this.input.setAttribute('name', this.formname)
|
|
12
|
+
}
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
unregister () {
|
|
@@ -9,7 +9,9 @@ export class MultiSelectEditor extends AbstractEditor {
|
|
|
9
9
|
register () {
|
|
10
10
|
super.register()
|
|
11
11
|
if (!this.input) return
|
|
12
|
-
this.
|
|
12
|
+
if (this.jsoneditor.options.use_name_attributes) {
|
|
13
|
+
this.input.setAttribute('name', this.formname)
|
|
14
|
+
}
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
unregister () {
|
|
@@ -31,19 +33,24 @@ export class MultiSelectEditor extends AbstractEditor {
|
|
|
31
33
|
this.select_options = {}
|
|
32
34
|
this.select_values = {}
|
|
33
35
|
this.option_keys = []
|
|
34
|
-
this.
|
|
36
|
+
this.option_enum = []
|
|
35
37
|
|
|
36
38
|
let i
|
|
37
39
|
const itemsSchema = this.jsoneditor.expandRefs(this.schema.items || {})
|
|
38
40
|
const e = itemsSchema.enum || []
|
|
41
|
+
const oe = itemsSchema.options ? itemsSchema.options.enum || [] : []
|
|
42
|
+
/* fallback to enum_titles, when options.enum is not present */
|
|
39
43
|
const t = itemsSchema.options ? itemsSchema.options.enum_titles || [] : []
|
|
40
44
|
|
|
41
45
|
for (i = 0; i < e.length; i++) {
|
|
42
46
|
/* If the sanitized value is different from the enum value, don't include it */
|
|
43
47
|
if (this.sanitize(e[i]) !== e[i]) continue
|
|
44
48
|
|
|
49
|
+
const d = oe[i] || {}
|
|
50
|
+
if (!('title' in d)) d.title = `${t[i] || e[i]}`
|
|
51
|
+
|
|
45
52
|
this.option_keys.push(`${e[i]}`)
|
|
46
|
-
this.
|
|
53
|
+
this.option_enum.push(d)
|
|
47
54
|
this.select_values[`${e[i]}`] = e[i]
|
|
48
55
|
}
|
|
49
56
|
}
|
|
@@ -65,9 +72,13 @@ export class MultiSelectEditor extends AbstractEditor {
|
|
|
65
72
|
this.inputs[this.option_keys[i]] = this.theme.getCheckbox()
|
|
66
73
|
this.inputs[this.option_keys[i]].id = id
|
|
67
74
|
this.select_options[this.option_keys[i]] = this.inputs[this.option_keys[i]]
|
|
68
|
-
const label = this.theme.getCheckboxLabel(this.
|
|
75
|
+
const label = this.theme.getCheckboxLabel(this.option_enum[i].title)
|
|
69
76
|
label.htmlFor = id
|
|
70
|
-
|
|
77
|
+
if (this.option_enum[i].infoText) {
|
|
78
|
+
const infoButton = this.theme.getInfoButton(this.translateProperty(this.option_enum[i].infoText))
|
|
79
|
+
label.appendChild(infoButton)
|
|
80
|
+
}
|
|
81
|
+
this.controls['_' + this.option_keys[i]] = this.theme.getFormControl(label, this.inputs[this.option_keys[i]])
|
|
71
82
|
}
|
|
72
83
|
|
|
73
84
|
this.control = this.theme.getMultiCheckboxHolder(this.controls, this.label, this.description, this.infoButton)
|
|
@@ -75,7 +86,7 @@ export class MultiSelectEditor extends AbstractEditor {
|
|
|
75
86
|
} else {
|
|
76
87
|
this.input_type = 'select'
|
|
77
88
|
this.input = this.theme.getSelectInput(this.option_keys, true)
|
|
78
|
-
this.theme.setSelectOptions(this.input, this.option_keys, this.
|
|
89
|
+
this.theme.setSelectOptions(this.input, this.option_keys, this.option_enum.map(e => e.title))
|
|
79
90
|
/* this.input.multiple = true; */
|
|
80
91
|
this.input.setAttribute('multiple', 'multiple')
|
|
81
92
|
this.input.size = Math.min(10, this.option_keys.length)
|
package/src/editors/radio.js
CHANGED
|
@@ -29,11 +29,16 @@ export class RadioEditor extends SelectEditor {
|
|
|
29
29
|
|
|
30
30
|
for (let i = 0; i < this.enum_values.length; i++) {
|
|
31
31
|
/* form radio elements */
|
|
32
|
-
|
|
33
|
-
name: this.formname,
|
|
32
|
+
const attributes = {
|
|
34
33
|
id: `${this.formname}[${i}]`,
|
|
35
34
|
value: this.enum_values[i]
|
|
36
|
-
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (this.jsoneditor.options.use_name_attributes) {
|
|
38
|
+
attributes.name = this.formname
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
this.input = this.theme.getFormRadio(attributes)
|
|
37
42
|
|
|
38
43
|
/* Set custom attributes on input element. Parameter is array of protected keys. Empty array if none. */
|
|
39
44
|
this.setInputAttributes(['id', 'value', 'name'])
|
package/src/editors/select.js
CHANGED
|
@@ -30,7 +30,9 @@ export class SelectEditor extends AbstractEditor {
|
|
|
30
30
|
register () {
|
|
31
31
|
super.register()
|
|
32
32
|
if (!this.input) return
|
|
33
|
-
this.
|
|
33
|
+
if (this.jsoneditor.options.use_name_attributes) {
|
|
34
|
+
this.input.setAttribute('name', this.formname)
|
|
35
|
+
}
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
unregister () {
|
package/src/editors/signature.js
CHANGED
|
@@ -20,7 +20,9 @@ export class SignatureEditor extends StringEditor {
|
|
|
20
20
|
|
|
21
21
|
/* Create canvas for signature pad */
|
|
22
22
|
const canvas = document.createElement('canvas')
|
|
23
|
-
|
|
23
|
+
if (this.jsoneditor.options.use_name_attributes) {
|
|
24
|
+
canvas.setAttribute('name', formname)
|
|
25
|
+
}
|
|
24
26
|
canvas.classList.add('signature')
|
|
25
27
|
signatureContainer.appendChild(canvas)
|
|
26
28
|
|
package/src/editors/string.js
CHANGED
|
@@ -5,7 +5,9 @@ export class StringEditor extends AbstractEditor {
|
|
|
5
5
|
register () {
|
|
6
6
|
super.register()
|
|
7
7
|
if (!this.input) return
|
|
8
|
-
this.
|
|
8
|
+
if (this.jsoneditor.options.use_name_attributes) {
|
|
9
|
+
this.input.setAttribute('name', this.formname)
|
|
10
|
+
}
|
|
9
11
|
this.input.setAttribute('aria-label', this.formname)
|
|
10
12
|
}
|
|
11
13
|
|
|
@@ -213,6 +215,10 @@ export class StringEditor extends AbstractEditor {
|
|
|
213
215
|
/* it will generate an error trying to append it to the missing parentNode */
|
|
214
216
|
if (this.input.parentNode) this.afterInputReady()
|
|
215
217
|
if (this.adjust_height) this.adjust_height(this.input)
|
|
218
|
+
if (this.format === 'range') {
|
|
219
|
+
const output = this.control.querySelector('output')
|
|
220
|
+
output.value = this.input.value
|
|
221
|
+
}
|
|
216
222
|
})
|
|
217
223
|
|
|
218
224
|
/* Compile and store the template */
|
package/src/editors/table.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ArrayEditor } from './array.js'
|
|
2
|
-
import { extend, trigger } from '../utilities.js'
|
|
2
|
+
import { extend, generateUUID, trigger } from '../utilities.js'
|
|
3
3
|
|
|
4
4
|
export class TableEditor extends ArrayEditor {
|
|
5
5
|
register () {
|
|
@@ -347,6 +347,7 @@ export class TableEditor extends ArrayEditor {
|
|
|
347
347
|
|
|
348
348
|
_createCopyButton (i, holder) {
|
|
349
349
|
const button = this.getButton('', 'copy', 'button_copy_row_title_short')
|
|
350
|
+
const schema = this.schema
|
|
350
351
|
button.classList.add('copy', 'json-editor-btntype-copy')
|
|
351
352
|
button.setAttribute('data-i', i)
|
|
352
353
|
button.addEventListener('click', e => {
|
|
@@ -355,8 +356,25 @@ export class TableEditor extends ArrayEditor {
|
|
|
355
356
|
const j = e.currentTarget.getAttribute('data-i') * 1
|
|
356
357
|
const value = this.getValue()
|
|
357
358
|
|
|
358
|
-
|
|
359
|
+
let newValue = value[j]
|
|
360
|
+
|
|
361
|
+
/* On copy, recreate uuid if needed. */
|
|
362
|
+
if (schema.items.type === 'string' && schema.items.format === 'uuid') {
|
|
363
|
+
newValue = generateUUID()
|
|
364
|
+
} else if (schema.items.type === 'object' && schema.items.properties) {
|
|
365
|
+
value.forEach((row, i) => {
|
|
366
|
+
if (j === i) {
|
|
367
|
+
for (const key of Object.keys(row)) {
|
|
368
|
+
if (schema.items.properties && schema.items.properties[key] && schema.items.properties[key].format === 'uuid') {
|
|
369
|
+
newValue = Object.assign({}, value[j])
|
|
370
|
+
newValue[key] = generateUUID()
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
})
|
|
375
|
+
}
|
|
359
376
|
|
|
377
|
+
value.splice(j + 1, 0, newValue)
|
|
360
378
|
this.setValue(value)
|
|
361
379
|
this.onChange(true)
|
|
362
380
|
this.jsoneditor.trigger('copyRow', this.rows[j + 1])
|
package/src/editors/upload.js
CHANGED
|
@@ -257,7 +257,7 @@ export class UploadEditor extends AbstractEditor {
|
|
|
257
257
|
|
|
258
258
|
if (this.options.auto_upload) {
|
|
259
259
|
uploadButton.dispatchEvent(new window.MouseEvent('click'))
|
|
260
|
-
|
|
260
|
+
uploadButton.parentNode.removeChild(uploadButton)
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
|
package/src/editors/uuid.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { generateUUID } from '../utilities.js'
|
|
1
2
|
import { StringEditor } from './string.js'
|
|
2
3
|
|
|
3
4
|
export class UuidEditor extends StringEditor {
|
|
@@ -36,18 +37,7 @@ export class UuidEditor extends StringEditor {
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
getUuid () {
|
|
39
|
-
|
|
40
|
-
let d = new Date().getTime()
|
|
41
|
-
|
|
42
|
-
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
|
|
43
|
-
d += performance.now() /* use high-precision timer if available */
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
47
|
-
const r = (d + Math.random() * 16) % 16 | 0
|
|
48
|
-
d = Math.floor(d / 16)
|
|
49
|
-
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16)
|
|
50
|
-
})
|
|
40
|
+
return generateUUID()
|
|
51
41
|
}
|
|
52
42
|
|
|
53
43
|
testUuid (value) {
|
package/src/iconlib.js
CHANGED