@json-editor/json-editor 2.13.1 → 2.14.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/CHANGELOG.md +17 -0
- package/README.md +2 -1
- package/dist/jsoneditor.js +1 -1
- package/dist/jsoneditor.js.LICENSE.txt +1 -1
- package/dist/nonmin/jsoneditor.js +418 -220
- package/dist/nonmin/jsoneditor.js.map +1 -1
- package/docs/imask.html +1 -1
- package/docs/meta_schema.json +3 -0
- package/package.json +1 -1
- package/src/defaults.js +7 -2
- package/src/editor.js +15 -1
- package/src/editors/array/selectize.js +13 -0
- package/src/editors/array.js +16 -3
- package/src/editors/button.js +1 -0
- package/src/editors/checkbox.js +17 -1
- package/src/editors/info.js +1 -1
- package/src/editors/multiple.js +6 -1
- package/src/editors/multiselect.js +3 -2
- package/src/editors/object.js +24 -14
- package/src/editors/select.js +17 -5
- package/src/editors/starrating.js +5 -1
- package/src/editors/string.js +2 -2
- package/src/editors/table.js +3 -2
- package/src/theme.js +56 -4
- package/src/themes/barebones.js +1 -0
- package/src/themes/bootstrap3.js +49 -3
- package/src/themes/bootstrap4.js +38 -13
- package/src/themes/bootstrap5.js +37 -7
- package/src/themes/html.js +1 -0
- package/src/themes/spectre.js +15 -7
- package/src/validator.js +6 -4
- package/tests/codeceptjs/core_test.js +50 -0
- package/tests/codeceptjs/editors/array_test.js +7 -0
- package/tests/codeceptjs/editors/button_test.js +7 -1
- package/tests/codeceptjs/editors/checkbox_test.js +1 -1
- package/tests/codeceptjs/editors/integer_test.js +1 -1
- package/tests/codeceptjs/editors/multiselect_test.js +1 -1
- package/tests/codeceptjs/editors/number_test.js +1 -1
- package/tests/codeceptjs/editors/object_test.js +7 -0
- package/tests/codeceptjs/editors/radio_test.js +1 -2
- package/tests/codeceptjs/editors/rating_test.js +1 -2
- package/tests/codeceptjs/editors/select_test.js +1 -1
- package/tests/codeceptjs/editors/string_test.js +1 -1
- package/tests/codeceptjs/issues/issue-gh-1453_test.js +18 -0
- package/tests/codeceptjs/issues/issue-gh-1461_test.js +14 -0
- package/tests/codeceptjs/issues/issue-gh-1463_test.js +9 -0
- package/tests/codeceptjs/issues/issue-gh-1471_test.js +17 -0
- package/tests/codeceptjs/issues/issue-gh-812_test.js +2 -2
- package/tests/codeceptjs/meta-schema_test.js +1 -1
- package/tests/codeceptjs/schemaloader_test.js +1 -1
- package/tests/pages/advanced.html +1 -1
- package/tests/pages/anyof-2.html +1 -0
- package/tests/pages/anyof.html +4 -2
- package/tests/pages/array-anyof.html +5 -2
- package/tests/pages/array-checkboxes-infotext.html +5 -2
- package/tests/pages/array-checkboxes.html +5 -2
- package/tests/pages/array-choices.html +5 -2
- package/tests/pages/array-events-table.html +5 -2
- package/tests/pages/array-events.html +7 -3
- package/tests/pages/array-header-template.html +1 -0
- package/tests/pages/array-integers.html +5 -2
- package/tests/pages/array-multiselects.html +5 -2
- package/tests/pages/array-nested-arrays.html +5 -2
- package/tests/pages/array-numbers.html +5 -2
- package/tests/pages/array-objects.html +5 -2
- package/tests/pages/array-ratings.html +5 -2
- package/tests/pages/array-selectize-create.html +1 -0
- package/tests/pages/array-selectize.html +5 -2
- package/tests/pages/array-selects.html +5 -2
- package/tests/pages/array-strings.html +5 -2
- package/tests/pages/array-table-responsive.html +1 -0
- package/tests/pages/array-unique-items-sort.html +5 -2
- package/tests/pages/array.html +5 -2
- package/tests/pages/autocomplete.html +3 -1
- package/tests/pages/button-callbacks.html +4 -2
- package/tests/pages/button-icons.html +2 -1
- package/tests/pages/button_state_mode_1.html +1 -0
- package/tests/pages/button_state_mode_2.html +1 -0
- package/tests/pages/checkbox-labels.html +4 -2
- package/tests/pages/colorpicker-no-3rd-party.html +4 -2
- package/tests/pages/colorpicker-use-vanilla-picker.html +4 -2
- package/tests/pages/container-attributes.html +1 -0
- package/tests/pages/contains.html +1 -0
- package/tests/pages/core.html +5 -3
- package/tests/pages/datetime.html +2 -0
- package/tests/pages/dependentRequired.html +1 -0
- package/tests/pages/dependentSchemas.html +1 -0
- package/tests/pages/disable-button-in-object-editors.html +57 -0
- package/tests/pages/error-messages.html +1 -0
- package/tests/pages/form-name.html +4 -1
- package/tests/pages/grid-strict.html +3 -2
- package/tests/pages/grid.html +3 -2
- package/tests/pages/if-else.html +1 -0
- package/tests/pages/if-then-else-allOf.html +1 -0
- package/tests/pages/if-then-else-disable-fields.html +1 -0
- package/tests/pages/if-then-else.html +1 -0
- package/tests/pages/if-then.html +1 -0
- package/tests/pages/inheritance.html +6 -2
- package/tests/pages/integer.html +4 -2
- package/tests/pages/issues/_template.html +1 -1
- package/tests/pages/issues/issue-gh-1158-2.html +1 -1
- package/tests/pages/issues/issue-gh-1158.html +1 -1
- package/tests/pages/issues/issue-gh-1364.html +1 -1
- package/tests/pages/issues/issue-gh-1367.html +1 -1
- package/tests/pages/issues/issue-gh-1453.html +45 -0
- package/tests/pages/issues/issue-gh-1461.html +55 -0
- package/tests/pages/issues/issue-gh-1463.html +41 -0
- package/tests/pages/issues/issue-gh-1471.html +49 -0
- package/tests/pages/issues/issue-gh-812.html +3 -2
- package/tests/pages/issues/issue-gh-823-meta-schema.html +1 -1
- package/tests/pages/issues/issue-gh-848.html +1 -1
- package/tests/pages/keep_only_existing_values.html +1 -0
- package/tests/pages/load-events.html +1 -0
- package/tests/pages/maxContains.html +1 -0
- package/tests/pages/meta-schema.html +4 -0
- package/tests/pages/meta_schema.json +3 -0
- package/tests/pages/minContains.html +1 -0
- package/tests/pages/number.html +4 -2
- package/tests/pages/object-case-sensitive-property-search-false.html +2 -1
- package/tests/pages/object-case-sensitive-property-search-true.html +2 -1
- package/tests/pages/object-no-additional-properties.html +5 -2
- package/tests/pages/object-no-duplicated-id.html +2 -0
- package/tests/pages/object-required-properties.html +5 -3
- package/tests/pages/object-show-opt-in.html +3 -2
- package/tests/pages/object-with-dependencies-array.html +4 -2
- package/tests/pages/object-with-dependencies.html +2 -0
- package/tests/pages/object.html +5 -3
- package/tests/pages/oneof-2.html +1 -0
- package/tests/pages/oneof.html +4 -2
- package/tests/pages/option-dependencies.html +1 -0
- package/tests/pages/option-no_default_values.html +4 -2
- package/tests/pages/per-editor-options.html +1 -1
- package/tests/pages/programmatic-changes.html +4 -3
- package/tests/pages/range.html +4 -2
- package/tests/pages/read-only.html +36 -5
- package/tests/pages/ready.html +2 -1
- package/tests/pages/references.html +1 -1
- package/tests/pages/select.html +4 -3
- package/tests/pages/show-validation-errors.html +73 -0
- package/tests/pages/stepper-manual.html +4 -2
- package/tests/pages/stepper.html +4 -2
- package/tests/pages/string-ace-editor.html +4 -2
- package/tests/pages/string-cleave.html +4 -2
- package/tests/pages/string-custom-attributes.html +4 -2
- package/tests/pages/string-formats.html +4 -2
- package/tests/pages/string-formats2.html +4 -2
- package/tests/pages/string-jodit-editor.html +4 -2
- package/tests/pages/string-sceditor.html +4 -2
- package/tests/pages/string-simplemde-editor.html +4 -2
- package/tests/pages/table.html +4 -2
- package/tests/pages/tabs.html +1 -1
- package/tests/pages/themes.html +38 -52
- package/tests/pages/title-hidden.html +75 -0
- package/tests/pages/translate-property.html +2 -1
- package/tests/pages/urn.html +4 -2
- package/tests/pages/use-name-attributes.html +2 -1
- package/tests/pages/uuid.html +2 -0
- package/tests/pages/validation.html +2 -1
package/docs/imask.html
CHANGED
|
@@ -54,7 +54,7 @@ var jseditor, jedata = {schema:{
|
|
|
54
54
|
},
|
|
55
55
|
"properties": {
|
|
56
56
|
"_header": {
|
|
57
|
-
"
|
|
57
|
+
"format": "info",
|
|
58
58
|
"title": "Example showing how to use Imask.js to format your <input/> content when you are typing.",
|
|
59
59
|
"description": "<p>For documentation on the Imask.js options, look at <a href=\"https://imask.js.org/\" target=\"_blank\" title=\"Imask.js Homepage\">IMask.js</a> homepage.</p>",
|
|
60
60
|
"options": {
|
package/docs/meta_schema.json
CHANGED
package/package.json
CHANGED
package/src/defaults.js
CHANGED
|
@@ -359,7 +359,11 @@ languages.en = {
|
|
|
359
359
|
/**
|
|
360
360
|
* Warning when deleting a node
|
|
361
361
|
*/
|
|
362
|
-
button_delete_node_warning: 'Are you sure you want to remove this item?'
|
|
362
|
+
button_delete_node_warning: 'Are you sure you want to remove this item?',
|
|
363
|
+
/**
|
|
364
|
+
* Warning when deleting a node
|
|
365
|
+
*/
|
|
366
|
+
table_controls: 'Controls'
|
|
363
367
|
}
|
|
364
368
|
|
|
365
369
|
/* Default per-editor options */
|
|
@@ -408,7 +412,8 @@ const options = {
|
|
|
408
412
|
use_default_values: true,
|
|
409
413
|
max_depth: 0,
|
|
410
414
|
button_state_mode: 1,
|
|
411
|
-
case_sensitive_property_search: true
|
|
415
|
+
case_sensitive_property_search: true,
|
|
416
|
+
show_errors: 'interaction'
|
|
412
417
|
}
|
|
413
418
|
|
|
414
419
|
/* 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'
|
|
@@ -54,6 +55,10 @@ export class AbstractEditor {
|
|
|
54
55
|
|
|
55
56
|
register () {
|
|
56
57
|
this.jsoneditor.registerEditor(this)
|
|
58
|
+
if (this.input && !this.label) {
|
|
59
|
+
const ariaLabel = this.getTitle() || this.formname
|
|
60
|
+
this.input.setAttribute('aria-label', ariaLabel)
|
|
61
|
+
}
|
|
57
62
|
this.onChange()
|
|
58
63
|
}
|
|
59
64
|
|
|
@@ -210,9 +215,12 @@ export class AbstractEditor {
|
|
|
210
215
|
setOptInCheckbox (header) {
|
|
211
216
|
/* the active/deactive checbox control. */
|
|
212
217
|
|
|
218
|
+
this.optInLabel = this.theme.getHiddenLabel(this.formname + ' opt-in')
|
|
219
|
+
this.optInLabel.setAttribute('for', this.formname + '-opt-in')
|
|
213
220
|
this.optInCheckbox = document.createElement('input')
|
|
214
221
|
this.optInCheckbox.setAttribute('type', 'checkbox')
|
|
215
222
|
this.optInCheckbox.setAttribute('style', 'margin: 0 10px 0 0;')
|
|
223
|
+
this.optInCheckbox.setAttribute('id', this.formname + '-opt-in')
|
|
216
224
|
this.optInCheckbox.classList.add('json-editor-opt-in')
|
|
217
225
|
|
|
218
226
|
this.optInCheckbox.addEventListener('click', () => {
|
|
@@ -231,6 +239,7 @@ export class AbstractEditor {
|
|
|
231
239
|
if (parentOptInEnabled || (!parentOptInDisabled && globalOptIn) || (!parentOptInDefined && globalOptIn)) {
|
|
232
240
|
/* and control to type object editors if they are not required */
|
|
233
241
|
if (this.parent && this.parent.schema.type === 'object' && !this.isRequired() && this.header) {
|
|
242
|
+
this.header.appendChild(this.optInLabel)
|
|
234
243
|
this.header.appendChild(this.optInCheckbox)
|
|
235
244
|
this.header.insertBefore(this.optInCheckbox, this.header.firstChild)
|
|
236
245
|
}
|
|
@@ -252,6 +261,11 @@ export class AbstractEditor {
|
|
|
252
261
|
this.setValue(this.getDefault(), true)
|
|
253
262
|
this.updateHeaderText()
|
|
254
263
|
this.onWatchedFieldChange()
|
|
264
|
+
|
|
265
|
+
if (this.options.titleHidden) {
|
|
266
|
+
this.theme.visuallyHidden(this.label)
|
|
267
|
+
this.theme.visuallyHidden(this.header)
|
|
268
|
+
}
|
|
255
269
|
}
|
|
256
270
|
|
|
257
271
|
setupWatchListeners () {
|
|
@@ -626,7 +640,7 @@ export class AbstractEditor {
|
|
|
626
640
|
}
|
|
627
641
|
|
|
628
642
|
getTitle () {
|
|
629
|
-
return this.translateProperty(this.schema.title || this.key)
|
|
643
|
+
return this.translateProperty(this.schema.title || this.key || this.formname)
|
|
630
644
|
}
|
|
631
645
|
|
|
632
646
|
enable () {
|
|
@@ -46,6 +46,19 @@ export class ArraySelectizeEditor extends MultiSelectEditor {
|
|
|
46
46
|
/* Add new event handler. */
|
|
47
47
|
/* Note: Must use the "on()" method and not addEventListener() */
|
|
48
48
|
this.selectize_instance.on('change', this.multiselectChangeHandler)
|
|
49
|
+
|
|
50
|
+
const label = this.theme.getHiddenLabel(this.formname)
|
|
51
|
+
this.input.setAttribute('id', this.formname + '-hidden-input')
|
|
52
|
+
label.setAttribute('for', this.formname + '-hidden-input')
|
|
53
|
+
this.input.parentNode.insertBefore(label, this.input)
|
|
54
|
+
|
|
55
|
+
const selectizeControl = this.selectize_instance.$control[0]
|
|
56
|
+
|
|
57
|
+
if (selectizeControl) {
|
|
58
|
+
const selectizeLabel = this.theme.getHiddenLabel(this.formname)
|
|
59
|
+
selectizeLabel.setAttribute('for', this.formname + '-selectized')
|
|
60
|
+
selectizeControl.appendChild(selectizeLabel)
|
|
61
|
+
}
|
|
49
62
|
}
|
|
50
63
|
super.afterInputReady()
|
|
51
64
|
}
|
package/src/editors/array.js
CHANGED
|
@@ -93,7 +93,7 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
93
93
|
|
|
94
94
|
build () {
|
|
95
95
|
if (!this.options.compact) {
|
|
96
|
-
this.header = document.createElement('
|
|
96
|
+
this.header = document.createElement('span')
|
|
97
97
|
this.header.textContent = this.getTitle()
|
|
98
98
|
this.title = this.theme.getHeader(this.header, this.getPathDepth())
|
|
99
99
|
this.container.appendChild(this.title)
|
|
@@ -156,6 +156,14 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
156
156
|
this.addControls()
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
postBuild () {
|
|
160
|
+
super.postBuild()
|
|
161
|
+
|
|
162
|
+
if (this.schema.readOnly || this.schema.readonly) {
|
|
163
|
+
this.disable()
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
159
167
|
onChildEditorChange (editor) {
|
|
160
168
|
this.refreshValue()
|
|
161
169
|
this.refreshTabs(true)
|
|
@@ -342,7 +350,12 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
342
350
|
value = this.ensureArraySize(value)
|
|
343
351
|
|
|
344
352
|
const serialized = JSON.stringify(value)
|
|
345
|
-
if (serialized === this.serialized)
|
|
353
|
+
if (serialized === this.serialized) {
|
|
354
|
+
if (initial) {
|
|
355
|
+
this.refreshValue(initial)
|
|
356
|
+
}
|
|
357
|
+
return
|
|
358
|
+
}
|
|
346
359
|
|
|
347
360
|
value.forEach((val, i) => {
|
|
348
361
|
if (this.rows[i]) {
|
|
@@ -454,7 +467,7 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
454
467
|
this.value[i] = editor.getValue()
|
|
455
468
|
})
|
|
456
469
|
|
|
457
|
-
if (
|
|
470
|
+
if (this.setupButtons(minItems) && !this.collapsed) {
|
|
458
471
|
this.controls.style.display = 'inline-block'
|
|
459
472
|
} else {
|
|
460
473
|
this.controls.style.display = 'none'
|
package/src/editors/button.js
CHANGED
|
@@ -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) {
|
package/src/editors/checkbox.js
CHANGED
|
@@ -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
|
-
|
|
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) {
|
package/src/editors/info.js
CHANGED
|
@@ -4,7 +4,7 @@ import { ButtonEditor } from './button.js'
|
|
|
4
4
|
export class InfoEditor extends ButtonEditor {
|
|
5
5
|
build () {
|
|
6
6
|
this.options.compact = false
|
|
7
|
-
this.header = this.label = this.theme.
|
|
7
|
+
this.header = this.label = this.theme.getLabelLike(this.getTitle())
|
|
8
8
|
this.description = this.theme.getDescription(this.schema.description || '')
|
|
9
9
|
this.control = this.theme.getFormControl(this.label, this.description, null)
|
|
10
10
|
this.container.appendChild(this.control)
|
package/src/editors/multiple.js
CHANGED
|
@@ -208,11 +208,16 @@ export class MultipleEditor extends AbstractEditor {
|
|
|
208
208
|
|
|
209
209
|
build () {
|
|
210
210
|
const { container } = this
|
|
211
|
-
this.header = this.label = this.theme.
|
|
211
|
+
this.header = this.label = this.theme.getLabelLike(this.getTitle(), this.isRequired())
|
|
212
212
|
this.switcher = this.theme.getSwitcher(this.display_text)
|
|
213
|
+
this.switcher.setAttribute('id', this.formname + 'switcher')
|
|
214
|
+
|
|
215
|
+
this.switcherLabel = this.theme.getHiddenLabel(this.formname + ' switcher')
|
|
216
|
+
this.switcherLabel.setAttribute('for', this.formname + 'switcher')
|
|
213
217
|
|
|
214
218
|
if (!this.if) {
|
|
215
219
|
this.container.appendChild(this.header)
|
|
220
|
+
container.appendChild(this.switcherLabel)
|
|
216
221
|
container.appendChild(this.switcher)
|
|
217
222
|
}
|
|
218
223
|
|
|
@@ -58,7 +58,7 @@ export class MultiSelectEditor extends AbstractEditor {
|
|
|
58
58
|
|
|
59
59
|
build () {
|
|
60
60
|
let i
|
|
61
|
-
if (!this.options.compact) this.header = this.label = this.theme.
|
|
61
|
+
if (!this.options.compact) this.header = this.label = this.theme.getLabelLike(this.getTitle(), this.isRequired())
|
|
62
62
|
if (this.schema.description) this.description = this.theme.getFormInputDescription(this.translateProperty(this.schema.description))
|
|
63
63
|
if (this.options.infoText) this.infoButton = this.theme.getInfoButton(this.translateProperty(this.options.infoText))
|
|
64
64
|
if (this.options.compact) this.container.classList.add('compact')
|
|
@@ -85,6 +85,7 @@ export class MultiSelectEditor extends AbstractEditor {
|
|
|
85
85
|
this.control = this.theme.getMultiCheckboxHolder(this.controls, this.label, this.description, this.infoButton)
|
|
86
86
|
this.inputs.controlgroup = this.inputs.controls = this.control /* Enable error messages for checkboxes */
|
|
87
87
|
} else {
|
|
88
|
+
if (!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle(), this.isRequired())
|
|
88
89
|
this.input_type = 'select'
|
|
89
90
|
this.input = this.theme.getSelectInput(this.option_keys, true)
|
|
90
91
|
this.theme.setSelectOptions(this.input, this.option_keys, this.option_enum.map(e => e.title))
|
|
@@ -95,7 +96,7 @@ export class MultiSelectEditor extends AbstractEditor {
|
|
|
95
96
|
this.select_options[this.option_keys[i]] = this.input.children[i]
|
|
96
97
|
}
|
|
97
98
|
|
|
98
|
-
this.control = this.theme.getFormControl(this.label, this.input, this.description, this.infoButton)
|
|
99
|
+
this.control = this.theme.getFormControl(this.label, this.input, this.description, this.infoButton, this.formname)
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
if (this.schema.readOnly || this.schema.readonly) {
|
package/src/editors/object.js
CHANGED
|
@@ -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
|
|
@@ -554,7 +554,7 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
554
554
|
} else {
|
|
555
555
|
this.header = ''
|
|
556
556
|
if (!this.options.compact) {
|
|
557
|
-
this.header = document.createElement('
|
|
557
|
+
this.header = document.createElement('span')
|
|
558
558
|
this.header.textContent = this.getTitle()
|
|
559
559
|
}
|
|
560
560
|
this.title = this.theme.getHeader(this.header, this.getPathDepth())
|
|
@@ -568,7 +568,11 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
568
568
|
|
|
569
569
|
/* Edit JSON modal */
|
|
570
570
|
this.editjson_holder = this.theme.getModal()
|
|
571
|
+
this.editjson_textarea_label = this.theme.getHiddenLabel(this.translate('button_edit_json'))
|
|
572
|
+
this.editjson_textarea_label.setAttribute('for', this.path + '-' + 'edit-json-textarea')
|
|
571
573
|
this.editjson_textarea = this.theme.getTextareaInput()
|
|
574
|
+
this.editjson_textarea.setAttribute('id', this.path + '-' + 'edit-json-textarea')
|
|
575
|
+
this.editjson_textarea.setAttribute('aria-labelledby', this.path + '-' + 'edit-json-textarea')
|
|
572
576
|
this.editjson_textarea.classList.add('je-edit-json--textarea')
|
|
573
577
|
this.editjson_save = this.getButton('button_save', 'save', 'button_save')
|
|
574
578
|
this.editjson_save.classList.add('json-editor-btntype-save')
|
|
@@ -591,6 +595,7 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
591
595
|
e.stopPropagation()
|
|
592
596
|
this.hideEditJSON()
|
|
593
597
|
})
|
|
598
|
+
this.editjson_holder.appendChild(this.editjson_textarea_label)
|
|
594
599
|
this.editjson_holder.appendChild(this.editjson_textarea)
|
|
595
600
|
this.editjson_holder.appendChild(this.editjson_save)
|
|
596
601
|
this.editjson_holder.appendChild(this.editjson_copy)
|
|
@@ -605,7 +610,14 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
605
610
|
|
|
606
611
|
this.addproperty_input = this.theme.getFormInputField('text')
|
|
607
612
|
this.addproperty_input.setAttribute('placeholder', 'Property name...')
|
|
613
|
+
|
|
614
|
+
this.addproperty_input_label = this.theme.getHiddenLabel(this.translate('button_properties'))
|
|
615
|
+
this.addproperty_input_label.setAttribute('for', this.path + '-' + 'property-selector')
|
|
616
|
+
|
|
608
617
|
this.addproperty_input.classList.add('property-selector-input')
|
|
618
|
+
this.addproperty_input.setAttribute('id', this.path + '-' + 'property-selector')
|
|
619
|
+
this.addproperty_input.setAttribute('aria-labelledby', this.path + '-' + 'property-selector')
|
|
620
|
+
|
|
609
621
|
this.addproperty_add.addEventListener('click', (e) => {
|
|
610
622
|
e.preventDefault()
|
|
611
623
|
e.stopPropagation()
|
|
@@ -623,7 +635,7 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
623
635
|
}
|
|
624
636
|
})
|
|
625
637
|
this.addproperty_input.addEventListener('input', (e) => {
|
|
626
|
-
e.target.previousSibling.childNodes.forEach((value) => {
|
|
638
|
+
e.target.previousSibling.previousSibling.childNodes.forEach((value) => {
|
|
627
639
|
let searchTerm = value.innerText
|
|
628
640
|
let propertyTitle = e.target.value
|
|
629
641
|
|
|
@@ -642,6 +654,7 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
642
654
|
})
|
|
643
655
|
})
|
|
644
656
|
this.addproperty_holder.appendChild(this.addproperty_list)
|
|
657
|
+
this.addproperty_holder.appendChild(this.addproperty_input_label)
|
|
645
658
|
this.addproperty_holder.appendChild(this.addproperty_input)
|
|
646
659
|
this.addproperty_holder.appendChild(this.addproperty_add)
|
|
647
660
|
const spacer = document.createElement('div')
|
|
@@ -802,6 +815,10 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
802
815
|
/* Do it again now that we know the approximate heights of elements */
|
|
803
816
|
this.layoutEditors()
|
|
804
817
|
}
|
|
818
|
+
|
|
819
|
+
if (this.schema.readOnly || this.schema.readonly) {
|
|
820
|
+
this.disable()
|
|
821
|
+
}
|
|
805
822
|
}
|
|
806
823
|
|
|
807
824
|
deactivateNonRequiredProperties () {
|
|
@@ -850,15 +867,8 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
850
867
|
|
|
851
868
|
copyJSON () {
|
|
852
869
|
if (!this.editjson_holder) return
|
|
853
|
-
|
|
854
|
-
|
|
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)
|
|
870
|
+
navigator.clipboard.writeText(this.editjson_textarea.value)
|
|
871
|
+
.catch((e) => window.alert(e))
|
|
862
872
|
}
|
|
863
873
|
|
|
864
874
|
saveJSON () {
|
|
@@ -908,7 +918,7 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
908
918
|
|
|
909
919
|
const label = this.theme.getCheckboxLabel(labelText)
|
|
910
920
|
|
|
911
|
-
const control = this.theme.getFormControl(label, checkbox)
|
|
921
|
+
const control = this.theme.getFormControl(label, checkbox, null, null, this.path + '-' + key)
|
|
912
922
|
control.style.paddingBottom = control.style.marginBottom = control.style.paddingTop = control.style.marginTop = 0
|
|
913
923
|
control.style.height = 'auto'
|
|
914
924
|
/* control.style.overflowY = 'hidden'; */
|
package/src/editors/select.js
CHANGED
|
@@ -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
|
}
|
|
@@ -179,7 +181,7 @@ export class SelectEditor extends AbstractEditor {
|
|
|
179
181
|
this.onInputChange()
|
|
180
182
|
})
|
|
181
183
|
|
|
182
|
-
this.control = this.theme.getFormControl(this.label, this.input, this.description, this.infoButton)
|
|
184
|
+
this.control = this.theme.getFormControl(this.label, this.input, this.description, this.infoButton, this.formname)
|
|
183
185
|
this.container.appendChild(this.control)
|
|
184
186
|
|
|
185
187
|
this.value = this.enum_values[0]
|
|
@@ -345,7 +347,17 @@ export class SelectEditor extends AbstractEditor {
|
|
|
345
347
|
}
|
|
346
348
|
|
|
347
349
|
showValidationErrors (errors) {
|
|
348
|
-
|
|
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) {
|
|
@@ -3,7 +3,7 @@ import rules from './starrating.css.js'
|
|
|
3
3
|
|
|
4
4
|
export class StarratingEditor extends StringEditor {
|
|
5
5
|
build () {
|
|
6
|
-
if (!this.options.compact) this.header = this.label = this.theme.
|
|
6
|
+
if (!this.options.compact) this.header = this.label = this.theme.getLabelLike(this.getTitle(), this.isRequired())
|
|
7
7
|
if (this.schema.description) this.description = this.theme.getFormInputDescription(this.translateProperty(this.schema.description))
|
|
8
8
|
if (this.options.infoText) this.infoButton = this.theme.getInfoButton(this.translateProperty(this.options.infoText))
|
|
9
9
|
if (this.options.compact) this.container.classList.add('compact')
|
|
@@ -47,6 +47,10 @@ export class StarratingEditor extends StringEditor {
|
|
|
47
47
|
radioLabel.classList.add('starrating-display-enabled')
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
const radioText = this.theme.getHiddenText('label')
|
|
51
|
+
radioText.textContent = i
|
|
52
|
+
|
|
53
|
+
radioLabel.appendChild(radioText)
|
|
50
54
|
this.ratingContainer.appendChild(radioInput)
|
|
51
55
|
this.ratingContainer.appendChild(radioLabel)
|
|
52
56
|
}
|
package/src/editors/string.js
CHANGED
|
@@ -8,7 +8,6 @@ export class StringEditor extends AbstractEditor {
|
|
|
8
8
|
if (this.jsoneditor.options.use_name_attributes) {
|
|
9
9
|
this.input.setAttribute('name', this.formname)
|
|
10
10
|
}
|
|
11
|
-
this.input.setAttribute('aria-label', this.formname)
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
unregister () {
|
|
@@ -106,7 +105,8 @@ export class StringEditor extends AbstractEditor {
|
|
|
106
105
|
step = this.schema.multipleOf
|
|
107
106
|
}
|
|
108
107
|
|
|
109
|
-
this.input = this.theme.getRangeInput(min, max, step)
|
|
108
|
+
this.input = this.theme.getRangeInput(min, max, step, this.description, this.formname)
|
|
109
|
+
this.input.setAttribute('id', this.formname)
|
|
110
110
|
/* HTML5 Input type */
|
|
111
111
|
} else {
|
|
112
112
|
this.input_type = 'text'
|
package/src/editors/table.js
CHANGED
|
@@ -54,7 +54,7 @@ export class TableEditor extends ArrayEditor {
|
|
|
54
54
|
this.width = tmp.getNumColumns() + 2
|
|
55
55
|
|
|
56
56
|
if (!this.options.compact) {
|
|
57
|
-
this.header = document.createElement('
|
|
57
|
+
this.header = document.createElement('span')
|
|
58
58
|
this.header.textContent = this.getTitle()
|
|
59
59
|
this.title = this.theme.getHeader(this.header, this.getPathDepth())
|
|
60
60
|
this.container.appendChild(this.title)
|
|
@@ -101,8 +101,9 @@ export class TableEditor extends ArrayEditor {
|
|
|
101
101
|
this.row_holder.innerHTML = ''
|
|
102
102
|
|
|
103
103
|
/* Row Controls column */
|
|
104
|
-
this.controls_header_cell = this.theme.getTableHeaderCell('
|
|
104
|
+
this.controls_header_cell = this.theme.getTableHeaderCell(this.translate('table_controls'))
|
|
105
105
|
this.controls_header_cell.setAttribute('aria-hidden', 'true')
|
|
106
|
+
this.controls_header_cell.style.visibility = 'hidden'
|
|
106
107
|
this.header_row.appendChild(this.controls_header_cell)
|
|
107
108
|
|
|
108
109
|
/* Add controls */
|
package/src/theme.js
CHANGED
|
@@ -105,8 +105,15 @@ export class AbstractTheme {
|
|
|
105
105
|
return el
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
getLabelLike (text, req) {
|
|
109
|
+
const el = document.createElement('b')
|
|
110
|
+
el.appendChild(document.createTextNode(text))
|
|
111
|
+
if (req) el.classList.add('required')
|
|
112
|
+
return el
|
|
113
|
+
}
|
|
114
|
+
|
|
108
115
|
getHeader (text, pathDepth) {
|
|
109
|
-
const el = document.createElement('
|
|
116
|
+
const el = document.createElement('span')
|
|
110
117
|
if (typeof text === 'string') {
|
|
111
118
|
el.textContent = text
|
|
112
119
|
} else {
|
|
@@ -177,7 +184,7 @@ export class AbstractTheme {
|
|
|
177
184
|
return el
|
|
178
185
|
}
|
|
179
186
|
|
|
180
|
-
getFormRadioControl (label, input, compact) {
|
|
187
|
+
getFormRadioControl (label, input, compact, formName) {
|
|
181
188
|
const el = document.createElement('div')
|
|
182
189
|
el.appendChild(label)
|
|
183
190
|
input.style.width = 'auto'
|
|
@@ -186,6 +193,12 @@ export class AbstractTheme {
|
|
|
186
193
|
el.classList.add('je-radio-control--compact')
|
|
187
194
|
}
|
|
188
195
|
|
|
196
|
+
if (input.tagName.toLowerCase() !== 'div' && formName && label && input) {
|
|
197
|
+
input.setAttribute('id', formName)
|
|
198
|
+
input.setAttribute('aria-labelledby', formName)
|
|
199
|
+
label.setAttribute('for', formName)
|
|
200
|
+
}
|
|
201
|
+
|
|
189
202
|
return el
|
|
190
203
|
}
|
|
191
204
|
|
|
@@ -225,11 +238,39 @@ export class AbstractTheme {
|
|
|
225
238
|
return el
|
|
226
239
|
}
|
|
227
240
|
|
|
228
|
-
|
|
241
|
+
getHiddenLabel (text) {
|
|
242
|
+
const el = document.createElement('label')
|
|
243
|
+
el.textContent = text
|
|
244
|
+
el.setAttribute('style', 'position: absolute;width: 1px;height: 1px;padding: 0;margin: -1px;overflow: hidden;clip: rect(0,0,0,0);border: 0;')
|
|
245
|
+
return el
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
visuallyHidden (element) {
|
|
249
|
+
if (!element) {
|
|
250
|
+
return
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
element.setAttribute('style', 'position: absolute;width: 1px;height: 1px;padding: 0;margin: -1px;overflow: hidden;clip: rect(0,0,0,0);border: 0;')
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
getHiddenText (text) {
|
|
257
|
+
const el = document.createElement('span')
|
|
258
|
+
el.textContent = text
|
|
259
|
+
el.setAttribute('style', 'position: absolute;width: 1px;height: 1px;padding: 0;margin: -1px;overflow: hidden;clip: rect(0,0,0,0);border: 0;')
|
|
260
|
+
return el
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
getRangeInput (min, max, step, description, formName) {
|
|
229
264
|
const el = this.getFormInputField('range')
|
|
230
265
|
el.setAttribute('min', min)
|
|
231
266
|
el.setAttribute('max', max)
|
|
232
267
|
el.setAttribute('step', step)
|
|
268
|
+
|
|
269
|
+
if (description) {
|
|
270
|
+
description.setAttribute('id', formName + '-description')
|
|
271
|
+
el.setAttribute('aria-describedby', formName + '-description')
|
|
272
|
+
}
|
|
273
|
+
|
|
233
274
|
return el
|
|
234
275
|
}
|
|
235
276
|
|
|
@@ -297,7 +338,7 @@ export class AbstractTheme {
|
|
|
297
338
|
return div
|
|
298
339
|
}
|
|
299
340
|
|
|
300
|
-
getRangeOutput (input
|
|
341
|
+
getRangeOutput (input) {
|
|
301
342
|
const output = document.createElement('output')
|
|
302
343
|
const updateOutput = e => { output.value = e.currentTarget.value }
|
|
303
344
|
input.addEventListener('change', updateOutput, false)
|
|
@@ -339,6 +380,16 @@ export class AbstractTheme {
|
|
|
339
380
|
el.appendChild(input)
|
|
340
381
|
}
|
|
341
382
|
|
|
383
|
+
if (input.tagName.toLowerCase() !== 'div' && input && label && formName) {
|
|
384
|
+
label.setAttribute('for', formName)
|
|
385
|
+
input.setAttribute('id', formName)
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (input.tagName.toLowerCase() !== 'div' && input && description) {
|
|
389
|
+
description.setAttribute('id', formName + '-description')
|
|
390
|
+
input.setAttribute('aria-describedby', formName + '-description')
|
|
391
|
+
}
|
|
392
|
+
|
|
342
393
|
if (description) el.appendChild(description)
|
|
343
394
|
return el
|
|
344
395
|
}
|
|
@@ -455,6 +506,7 @@ export class AbstractTheme {
|
|
|
455
506
|
}
|
|
456
507
|
|
|
457
508
|
addInputError (input, text) {
|
|
509
|
+
input.errmsg.setAttribute('role', 'alert')
|
|
458
510
|
}
|
|
459
511
|
|
|
460
512
|
removeInputError (input) {
|
package/src/themes/barebones.js
CHANGED