@json-editor/json-editor 2.13.2 → 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 +8 -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 +369 -195
- 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 +5 -1
- package/src/editor.js +14 -1
- package/src/editors/array/selectize.js +13 -0
- package/src/editors/array.js +9 -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 +20 -3
- package/src/editors/select.js +1 -1
- 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 +4 -3
- package/tests/codeceptjs/core_test.js +11 -0
- package/tests/codeceptjs/editors/array_test.js +7 -0
- package/tests/codeceptjs/editors/button_test.js +1 -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-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 +1 -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-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/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 */
|
package/src/editor.js
CHANGED
|
@@ -55,6 +55,10 @@ export class AbstractEditor {
|
|
|
55
55
|
|
|
56
56
|
register () {
|
|
57
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
|
+
}
|
|
58
62
|
this.onChange()
|
|
59
63
|
}
|
|
60
64
|
|
|
@@ -211,9 +215,12 @@ export class AbstractEditor {
|
|
|
211
215
|
setOptInCheckbox (header) {
|
|
212
216
|
/* the active/deactive checbox control. */
|
|
213
217
|
|
|
218
|
+
this.optInLabel = this.theme.getHiddenLabel(this.formname + ' opt-in')
|
|
219
|
+
this.optInLabel.setAttribute('for', this.formname + '-opt-in')
|
|
214
220
|
this.optInCheckbox = document.createElement('input')
|
|
215
221
|
this.optInCheckbox.setAttribute('type', 'checkbox')
|
|
216
222
|
this.optInCheckbox.setAttribute('style', 'margin: 0 10px 0 0;')
|
|
223
|
+
this.optInCheckbox.setAttribute('id', this.formname + '-opt-in')
|
|
217
224
|
this.optInCheckbox.classList.add('json-editor-opt-in')
|
|
218
225
|
|
|
219
226
|
this.optInCheckbox.addEventListener('click', () => {
|
|
@@ -232,6 +239,7 @@ export class AbstractEditor {
|
|
|
232
239
|
if (parentOptInEnabled || (!parentOptInDisabled && globalOptIn) || (!parentOptInDefined && globalOptIn)) {
|
|
233
240
|
/* and control to type object editors if they are not required */
|
|
234
241
|
if (this.parent && this.parent.schema.type === 'object' && !this.isRequired() && this.header) {
|
|
242
|
+
this.header.appendChild(this.optInLabel)
|
|
235
243
|
this.header.appendChild(this.optInCheckbox)
|
|
236
244
|
this.header.insertBefore(this.optInCheckbox, this.header.firstChild)
|
|
237
245
|
}
|
|
@@ -253,6 +261,11 @@ export class AbstractEditor {
|
|
|
253
261
|
this.setValue(this.getDefault(), true)
|
|
254
262
|
this.updateHeaderText()
|
|
255
263
|
this.onWatchedFieldChange()
|
|
264
|
+
|
|
265
|
+
if (this.options.titleHidden) {
|
|
266
|
+
this.theme.visuallyHidden(this.label)
|
|
267
|
+
this.theme.visuallyHidden(this.header)
|
|
268
|
+
}
|
|
256
269
|
}
|
|
257
270
|
|
|
258
271
|
setupWatchListeners () {
|
|
@@ -627,7 +640,7 @@ export class AbstractEditor {
|
|
|
627
640
|
}
|
|
628
641
|
|
|
629
642
|
getTitle () {
|
|
630
|
-
return this.translateProperty(this.schema.title || this.key)
|
|
643
|
+
return this.translateProperty(this.schema.title || this.key || this.formname)
|
|
631
644
|
}
|
|
632
645
|
|
|
633
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)
|
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
|
@@ -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 () {
|
|
@@ -901,7 +918,7 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
901
918
|
|
|
902
919
|
const label = this.theme.getCheckboxLabel(labelText)
|
|
903
920
|
|
|
904
|
-
const control = this.theme.getFormControl(label, checkbox)
|
|
921
|
+
const control = this.theme.getFormControl(label, checkbox, null, null, this.path + '-' + key)
|
|
905
922
|
control.style.paddingBottom = control.style.marginBottom = control.style.paddingTop = control.style.marginTop = 0
|
|
906
923
|
control.style.height = 'auto'
|
|
907
924
|
/* control.style.overflowY = 'hidden'; */
|
package/src/editors/select.js
CHANGED
|
@@ -181,7 +181,7 @@ export class SelectEditor extends AbstractEditor {
|
|
|
181
181
|
this.onInputChange()
|
|
182
182
|
})
|
|
183
183
|
|
|
184
|
-
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)
|
|
185
185
|
this.container.appendChild(this.control)
|
|
186
186
|
|
|
187
187
|
this.value = this.enum_values[0]
|
|
@@ -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
package/src/themes/bootstrap3.js
CHANGED
|
@@ -37,9 +37,9 @@ export class bootstrap3Theme extends AbstractTheme {
|
|
|
37
37
|
return el
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
getRangeInput (min, max, step) {
|
|
40
|
+
getRangeInput (min, max, step, description, formName) {
|
|
41
41
|
/* TODO: use better slider */
|
|
42
|
-
return super.getRangeInput(min, max, step)
|
|
42
|
+
return super.getRangeInput(min, max, step, description, formName)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
getFormInputField (type) {
|
|
@@ -50,7 +50,29 @@ export class bootstrap3Theme extends AbstractTheme {
|
|
|
50
50
|
return el
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
getHiddenLabel (text) {
|
|
54
|
+
const el = document.createElement('label')
|
|
55
|
+
el.textContent = text
|
|
56
|
+
el.classList.add('sr-only')
|
|
57
|
+
return el
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
visuallyHidden (element) {
|
|
61
|
+
if (!element) {
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
element.classList.add('sr-only')
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
getHiddenText (text) {
|
|
69
|
+
const el = document.createElement('span')
|
|
70
|
+
el.textContent = text
|
|
71
|
+
el.classList.add('sr-only')
|
|
72
|
+
return el
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
getFormControl (label, input, description, infoText, formName) {
|
|
54
76
|
const group = document.createElement('div')
|
|
55
77
|
|
|
56
78
|
if (label && (input.type === 'checkbox' || input.type === 'radio')) {
|
|
@@ -70,6 +92,16 @@ export class bootstrap3Theme extends AbstractTheme {
|
|
|
70
92
|
|
|
71
93
|
if (description) group.appendChild(description)
|
|
72
94
|
|
|
95
|
+
if (input.tagName.toLowerCase() !== 'div' && input && label && formName) {
|
|
96
|
+
label.setAttribute('for', formName)
|
|
97
|
+
input.setAttribute('id', formName)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (input.tagName.toLowerCase() !== 'div' && input && description) {
|
|
101
|
+
description.setAttribute('id', formName + '-description')
|
|
102
|
+
input.setAttribute('aria-describedby', formName + '-description')
|
|
103
|
+
}
|
|
104
|
+
|
|
73
105
|
return group
|
|
74
106
|
}
|
|
75
107
|
|
|
@@ -118,6 +150,19 @@ export class bootstrap3Theme extends AbstractTheme {
|
|
|
118
150
|
return el
|
|
119
151
|
}
|
|
120
152
|
|
|
153
|
+
getHeader (text, pathDepth) {
|
|
154
|
+
const el = document.createElement('span')
|
|
155
|
+
el.classList.add('h3')
|
|
156
|
+
|
|
157
|
+
if (typeof text === 'string') {
|
|
158
|
+
el.textContent = text
|
|
159
|
+
} else {
|
|
160
|
+
el.appendChild(text)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return el
|
|
164
|
+
}
|
|
165
|
+
|
|
121
166
|
getHeaderButtonHolder () {
|
|
122
167
|
const el = this.getButtonHolder()
|
|
123
168
|
el.style.marginLeft = '10px'
|
|
@@ -165,6 +210,7 @@ export class bootstrap3Theme extends AbstractTheme {
|
|
|
165
210
|
}
|
|
166
211
|
|
|
167
212
|
input.errmsg.textContent = text
|
|
213
|
+
input.errmsg.setAttribute('role', 'alert')
|
|
168
214
|
}
|
|
169
215
|
|
|
170
216
|
removeInputError (input) {
|
package/src/themes/bootstrap4.js
CHANGED
|
@@ -75,8 +75,8 @@ export class bootstrap4Theme extends AbstractTheme {
|
|
|
75
75
|
return el
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
getRangeInput (min, max, step) {
|
|
79
|
-
const el = super.getRangeInput(min, max, step)
|
|
78
|
+
getRangeInput (min, max, step, description, formName) {
|
|
79
|
+
const el = super.getRangeInput(min, max, step, description, formName)
|
|
80
80
|
|
|
81
81
|
if (this.options.custom_forms === true) {
|
|
82
82
|
el.classList.remove('form-control')
|
|
@@ -188,7 +188,29 @@ export class bootstrap4Theme extends AbstractTheme {
|
|
|
188
188
|
return el
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
|
|
191
|
+
getHiddenLabel (text) {
|
|
192
|
+
const el = document.createElement('label')
|
|
193
|
+
el.textContent = text
|
|
194
|
+
el.classList.add('sr-only')
|
|
195
|
+
return el
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
visuallyHidden (element) {
|
|
199
|
+
if (!element) {
|
|
200
|
+
return
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
element.classList.add('sr-only')
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
getHiddenText (text) {
|
|
207
|
+
const el = document.createElement('span')
|
|
208
|
+
el.textContent = text
|
|
209
|
+
el.classList.add('sr-only')
|
|
210
|
+
return el
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
getFormControl (label, input, description, infoText, formName) {
|
|
192
214
|
const group = document.createElement('div')
|
|
193
215
|
group.classList.add('form-group')
|
|
194
216
|
|
|
@@ -211,10 +233,6 @@ export class bootstrap4Theme extends AbstractTheme {
|
|
|
211
233
|
}
|
|
212
234
|
}
|
|
213
235
|
|
|
214
|
-
const unique = (Date.now() * Math.random()).toFixed(0)
|
|
215
|
-
input.setAttribute('id', unique)
|
|
216
|
-
label.setAttribute('for', unique)
|
|
217
|
-
|
|
218
236
|
check.appendChild(input)
|
|
219
237
|
check.appendChild(label)
|
|
220
238
|
if (infoText) check.appendChild(infoText)
|
|
@@ -234,6 +252,16 @@ export class bootstrap4Theme extends AbstractTheme {
|
|
|
234
252
|
group.appendChild(description)
|
|
235
253
|
}
|
|
236
254
|
|
|
255
|
+
if (input.tagName.toLowerCase() !== 'div' && input && label && formName) {
|
|
256
|
+
label.setAttribute('for', formName)
|
|
257
|
+
input.setAttribute('id', formName)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (input.tagName.toLowerCase() !== 'div' && input && description) {
|
|
261
|
+
description.setAttribute('id', formName + '-description')
|
|
262
|
+
input.setAttribute('aria-describedby', formName + '-description')
|
|
263
|
+
}
|
|
264
|
+
|
|
237
265
|
return group
|
|
238
266
|
}
|
|
239
267
|
|
|
@@ -406,10 +434,8 @@ export class bootstrap4Theme extends AbstractTheme {
|
|
|
406
434
|
}
|
|
407
435
|
|
|
408
436
|
getHeader (text, pathDepth) {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
const el = document.createElement('h3')
|
|
437
|
+
const el = document.createElement('span')
|
|
438
|
+
el.classList.add('h3')
|
|
413
439
|
el.classList.add('card-title')
|
|
414
440
|
el.classList.add('level-' + pathDepth)
|
|
415
441
|
|
|
@@ -421,8 +447,6 @@ export class bootstrap4Theme extends AbstractTheme {
|
|
|
421
447
|
|
|
422
448
|
el.style.display = 'inline-block'
|
|
423
449
|
|
|
424
|
-
/* cardHeader.appendChild(el) */
|
|
425
|
-
|
|
426
450
|
return el
|
|
427
451
|
}
|
|
428
452
|
|
|
@@ -500,6 +524,7 @@ export class bootstrap4Theme extends AbstractTheme {
|
|
|
500
524
|
|
|
501
525
|
input.errmsg.style.display = 'block'
|
|
502
526
|
input.errmsg.textContent = text
|
|
527
|
+
input.errmsg.setAttribute('role', 'alert')
|
|
503
528
|
}
|
|
504
529
|
|
|
505
530
|
removeInputError (input) {
|