@json-editor/json-editor 2.5.2 → 2.6.1
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/.eslintrc +5 -2
- package/.github/PULL_REQUEST_TEMPLATE.md +6 -6
- package/.github/workflows/build.yml +58 -0
- package/CHANGELOG.md +41 -1
- package/CONTRIBUTING.md +1 -1
- package/README.md +39 -4
- package/README_ADDON.md +65 -0
- package/config/codeceptjs_helpers.js +4 -0
- package/dist/jsoneditor.js +2 -2
- package/dist/nonmin/jsoneditor.js +3711 -3324
- package/dist/nonmin/jsoneditor.js.map +1 -1
- package/docs/cleave.html +1 -1
- package/docs/datetime.html +1 -1
- package/docs/describedby.html +1 -1
- package/docs/index.html +4 -2
- package/docs/materialize_css.html +1 -1
- package/docs/meta_schema.json +0 -1
- package/docs/radio.html +1 -1
- package/docs/select2.html +1 -1
- package/docs/selectize.html +1 -1
- package/docs/starrating.html +1 -1
- package/docs/wysiwyg.html +1 -1
- package/package.json +27 -26
- package/release-notes.md +9 -9
- package/src/core.js +1 -0
- package/src/defaults.js +182 -94
- package/src/editor.js +28 -9
- package/src/editors/array.js +20 -16
- package/src/editors/autocomplete.js +1 -0
- package/src/editors/base64.js +5 -4
- package/src/editors/button.js +2 -2
- package/src/editors/checkbox.js +3 -3
- package/src/editors/datetime.js +2 -2
- package/src/editors/info.js +1 -1
- package/src/editors/multiple.js +8 -2
- package/src/editors/multiselect.js +5 -3
- package/src/editors/object.js +35 -21
- package/src/editors/radio.js +9 -4
- package/src/editors/select.js +6 -6
- package/src/editors/signature.js +3 -2
- package/src/editors/starrating.js +5 -5
- package/src/editors/string.js +6 -4
- package/src/editors/table.js +24 -14
- package/src/editors/upload.js +4 -3
- package/src/editors/uuid.js +1 -1
- package/src/iconlibs/index.js +2 -0
- package/src/iconlibs/openiconic.js +28 -0
- package/src/schemaloader.js +112 -28
- package/src/theme.js +6 -3
- package/src/themes/bootstrap3.js +4 -4
- package/src/themes/bootstrap4.js +11 -3
- package/src/themes/html.js +1 -2
- package/src/themes/materialize.js +1 -1
- package/src/themes/spectre.js +11 -8
- package/src/themes/tailwind.js +1 -1
- package/src/validator.js +128 -16
- package/tests/codeceptjs/core_test.js +125 -1
- package/tests/codeceptjs/editors/array_test.js +13 -11
- package/tests/codeceptjs/editors/button_test.js +6 -1
- package/tests/codeceptjs/editors/issues/issue-gh-812_test.js +32 -0
- package/tests/codeceptjs/editors/number_test.js +1 -1
- package/tests/codeceptjs/editors/object_test.js +216 -100
- package/tests/codeceptjs/editors/programmatic-changes_test.js +3 -1
- package/tests/codeceptjs/editors/radio_test.js +10 -0
- package/tests/codeceptjs/editors/rating_test.js +10 -11
- package/tests/codeceptjs/editors/select_test.js +17 -15
- package/tests/codeceptjs/editors/stepper_test.js +13 -1
- package/tests/codeceptjs/editors/string_test.js +81 -80
- package/tests/codeceptjs/editors/table-confirm-delete_test.js +58 -56
- package/tests/codeceptjs/editors/tabs_test.js +12 -10
- package/tests/codeceptjs/editors/validation_test.js +10 -8
- package/tests/codeceptjs/meta-schema_test.js +13 -14
- package/tests/codeceptjs/schemaloader_test.js +13 -0
- package/tests/codeceptjs/steps_file.js +4 -3
- package/tests/codeceptjs/themes_test.js +31 -0
- package/tests/docker-compose.yml +4 -3
- package/tests/fixtures/validation.json +382 -1
- package/tests/pages/_demo.html +2 -0
- package/tests/pages/anyof.html +80 -0
- package/tests/pages/issues/issue-gh-812.html +110 -0
- package/tests/pages/issues/issue-gh-848.html +81 -0
- package/tests/pages/meta_schema.json +0 -1
- package/tests/pages/object-no-additional-properties.html +27 -12
- package/tests/pages/object-required-properties.html +43 -9
- package/tests/pages/object-show-opt-in.html +110 -0
- package/tests/pages/object-with-dependencies-array.html +56 -0
- package/tests/pages/oneof.html +103 -0
- package/tests/pages/read-only.html +19 -4
- package/tests/pages/stepper-manual.html +57 -0
- package/tests/pages/themes.html +2 -0
- package/tests/pages/translate-property.html +247 -0
- package/tests/pages/urn.html +93 -0
- package/tests/unit/core.spec.js +2 -0
- package/tests/unit/defaults.spec.js +4 -2
- package/tests/unit/editor.spec.js +2 -0
- package/tests/unit/editors/array.spec.js +86 -0
- package/tests/unit/editors/table.spec.js +91 -0
- package/tests/unit/schemaloader.spec.js +362 -3
- package/tests/unit/validator.spec.js +14 -2
package/src/editor.js
CHANGED
|
@@ -11,6 +11,7 @@ export class AbstractEditor {
|
|
|
11
11
|
this.template_engine = this.jsoneditor.template
|
|
12
12
|
this.iconlib = this.jsoneditor.iconlib
|
|
13
13
|
this.translate = this.jsoneditor.translate || this.defaults.translate
|
|
14
|
+
this.translateProperty = this.jsoneditor.translateProperty || this.defaults.translateProperty
|
|
14
15
|
this.original_schema = options.schema
|
|
15
16
|
this.schema = this.jsoneditor.expandSchema(this.original_schema)
|
|
16
17
|
this.active = true
|
|
@@ -129,7 +130,12 @@ export class AbstractEditor {
|
|
|
129
130
|
this.notify()
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
|
|
133
|
+
let displayMode = this.dependenciesFulfilled ? 'block' : 'none'
|
|
134
|
+
|
|
135
|
+
if (this.options.hidden) {
|
|
136
|
+
displayMode = 'none'
|
|
137
|
+
}
|
|
138
|
+
|
|
133
139
|
if (wrapper.tagName === 'TD') {
|
|
134
140
|
Object.keys(wrapper.childNodes).forEach(child => (wrapper.childNodes[child].style.display = displayMode))
|
|
135
141
|
} else wrapper.style.display = displayMode
|
|
@@ -146,9 +152,8 @@ export class AbstractEditor {
|
|
|
146
152
|
if (!editor || !editor.dependenciesFulfilled) {
|
|
147
153
|
this.dependenciesFulfilled = false
|
|
148
154
|
} else if (Array.isArray(choices)) {
|
|
149
|
-
choices.some(choice => {
|
|
150
|
-
if (value === choice) {
|
|
151
|
-
this.dependenciesFulfilled = true
|
|
155
|
+
this.dependenciesFulfilled = choices.some(choice => {
|
|
156
|
+
if (JSON.stringify(value) === JSON.stringify(choice)) {
|
|
152
157
|
return true
|
|
153
158
|
}
|
|
154
159
|
})
|
|
@@ -201,7 +206,11 @@ export class AbstractEditor {
|
|
|
201
206
|
})
|
|
202
207
|
|
|
203
208
|
/* append active/deactive checkbox if show_opt_in is true */
|
|
204
|
-
|
|
209
|
+
const globalOptIn = this.jsoneditor.options.show_opt_in
|
|
210
|
+
const parentOptInDefined = (typeof this.parent.options.show_opt_in !== 'undefined')
|
|
211
|
+
const parentOptInEnabled = (parentOptInDefined && this.parent.options.show_opt_in === true)
|
|
212
|
+
const parentOptInDisabled = (parentOptInDefined && this.parent.options.show_opt_in === false)
|
|
213
|
+
if (parentOptInEnabled || (!parentOptInDisabled && globalOptIn) || (!parentOptInDefined && globalOptIn)) {
|
|
205
214
|
/* and control to type object editors if they are not required */
|
|
206
215
|
if (this.parent && this.parent.schema.type === 'object' && !this.isRequired() && this.header) {
|
|
207
216
|
this.header.appendChild(this.optInCheckbox)
|
|
@@ -293,11 +302,14 @@ export class AbstractEditor {
|
|
|
293
302
|
|
|
294
303
|
onMove () {}
|
|
295
304
|
|
|
296
|
-
getButton (text, icon, title) {
|
|
305
|
+
getButton (text, icon, title, args = []) {
|
|
297
306
|
const btnClass = `json-editor-btn-${icon}`
|
|
298
307
|
if (!this.iconlib) icon = null
|
|
299
308
|
else icon = this.iconlib.getIcon(icon)
|
|
300
309
|
|
|
310
|
+
text = this.translate(text, args)
|
|
311
|
+
title = this.translate(title, args)
|
|
312
|
+
|
|
301
313
|
if (!icon && title) {
|
|
302
314
|
text = title
|
|
303
315
|
title = null
|
|
@@ -308,10 +320,13 @@ export class AbstractEditor {
|
|
|
308
320
|
return btn
|
|
309
321
|
}
|
|
310
322
|
|
|
311
|
-
setButtonText (button, text, icon, title) {
|
|
323
|
+
setButtonText (button, text, icon, title, args = []) {
|
|
312
324
|
if (!this.iconlib) icon = null
|
|
313
325
|
else icon = this.iconlib.getIcon(icon)
|
|
314
326
|
|
|
327
|
+
text = this.translate(text, args)
|
|
328
|
+
title = this.translate(title, args)
|
|
329
|
+
|
|
315
330
|
if (!icon && title) {
|
|
316
331
|
text = title
|
|
317
332
|
title = null
|
|
@@ -460,10 +475,14 @@ export class AbstractEditor {
|
|
|
460
475
|
|
|
461
476
|
getHeaderText (titleOnly) {
|
|
462
477
|
if (this.header_text) return this.header_text
|
|
463
|
-
else if (titleOnly) return this.schema.title
|
|
478
|
+
else if (titleOnly) return this.translateProperty(this.schema.title)
|
|
464
479
|
else return this.getTitle()
|
|
465
480
|
}
|
|
466
481
|
|
|
482
|
+
getPathDepth () {
|
|
483
|
+
return this.path.split('.').length
|
|
484
|
+
}
|
|
485
|
+
|
|
467
486
|
cleanText (txt) {
|
|
468
487
|
/* Clean out HTML tags from txt */
|
|
469
488
|
const tmp = document.createElement('div')
|
|
@@ -569,7 +588,7 @@ export class AbstractEditor {
|
|
|
569
588
|
}
|
|
570
589
|
|
|
571
590
|
getTitle () {
|
|
572
|
-
return this.schema.title || this.key
|
|
591
|
+
return this.translateProperty(this.schema.title || this.key)
|
|
573
592
|
}
|
|
574
593
|
|
|
575
594
|
enable () {
|
package/src/editors/array.js
CHANGED
|
@@ -95,12 +95,16 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
95
95
|
if (!this.options.compact) {
|
|
96
96
|
this.header = document.createElement('label')
|
|
97
97
|
this.header.textContent = this.getTitle()
|
|
98
|
-
this.title = this.theme.getHeader(this.header)
|
|
98
|
+
this.title = this.theme.getHeader(this.header, this.getPathDepth())
|
|
99
99
|
this.container.appendChild(this.title)
|
|
100
|
+
if (this.options.infoText) {
|
|
101
|
+
this.infoButton = this.theme.getInfoButton(this.translateProperty(this.options.infoText))
|
|
102
|
+
this.container.appendChild(this.infoButton)
|
|
103
|
+
}
|
|
100
104
|
this.title_controls = this.theme.getHeaderButtonHolder()
|
|
101
105
|
this.title.appendChild(this.title_controls)
|
|
102
106
|
if (this.schema.description) {
|
|
103
|
-
this.description = this.theme.getDescription(this.schema.description)
|
|
107
|
+
this.description = this.theme.getDescription(this.translateProperty(this.schema.description))
|
|
104
108
|
this.container.appendChild(this.description)
|
|
105
109
|
}
|
|
106
110
|
this.error_holder = document.createElement('div')
|
|
@@ -136,7 +140,7 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
136
140
|
}
|
|
137
141
|
} else {
|
|
138
142
|
/* compact mode */
|
|
139
|
-
this.title = this.theme.getHeader('')
|
|
143
|
+
this.title = this.theme.getHeader('', this.getPathDepth())
|
|
140
144
|
this.container.appendChild(this.title)
|
|
141
145
|
this.panel = this.theme.getIndentedPanel()
|
|
142
146
|
this.container.appendChild(this.panel)
|
|
@@ -162,7 +166,7 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
162
166
|
if (!this.item_title) {
|
|
163
167
|
if (this.schema.items && !Array.isArray(this.schema.items)) {
|
|
164
168
|
const tmp = this.jsoneditor.expandRefs(this.schema.items)
|
|
165
|
-
this.item_title = tmp.title || this.translate('default_array_item_title')
|
|
169
|
+
this.item_title = this.translateProperty(tmp.title) || this.translate('default_array_item_title')
|
|
166
170
|
} else {
|
|
167
171
|
this.item_title = this.translate('default_array_item_title')
|
|
168
172
|
}
|
|
@@ -200,7 +204,7 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
200
204
|
schema = this.jsoneditor.expandRefs(schema)
|
|
201
205
|
|
|
202
206
|
this.item_info[stringified] = {
|
|
203
|
-
title: schema.title || this.translate('default_array_item_title'),
|
|
207
|
+
title: this.translateProperty(schema.title) || this.translate('default_array_item_title'),
|
|
204
208
|
default: schema.default,
|
|
205
209
|
width: 12,
|
|
206
210
|
child_editors: schema.properties || schema.items
|
|
@@ -492,14 +496,14 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
492
496
|
this.rows[i].movedown_button = this._createMoveDownButton(i, controlsHolder)
|
|
493
497
|
}
|
|
494
498
|
|
|
495
|
-
if (value) this.rows[i].setValue(value, initial)
|
|
499
|
+
if (typeof value !== 'undefined') this.rows[i].setValue(value, initial)
|
|
496
500
|
this.refreshTabs()
|
|
497
501
|
|
|
498
502
|
return this.rows[i]
|
|
499
503
|
}
|
|
500
504
|
|
|
501
505
|
_createDeleteButton (i, holder) {
|
|
502
|
-
const button = this.getButton(this.getItemTitle(), 'delete',
|
|
506
|
+
const button = this.getButton(this.getItemTitle(), 'delete', 'button_delete_row_title', [this.getItemTitle()])
|
|
503
507
|
button.classList.add('delete', 'json-editor-btntype-delete')
|
|
504
508
|
button.setAttribute('data-i', i)
|
|
505
509
|
button.addEventListener('click', e => {
|
|
@@ -540,7 +544,7 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
540
544
|
}
|
|
541
545
|
|
|
542
546
|
_createCopyButton (i, holder) {
|
|
543
|
-
const button = this.getButton(this.getItemTitle(), 'copy',
|
|
547
|
+
const button = this.getButton(this.getItemTitle(), 'copy', 'button_copy_row_title', [this.getItemTitle()])
|
|
544
548
|
button.classList.add('copy', 'json-editor-btntype-copy')
|
|
545
549
|
button.setAttribute('data-i', i)
|
|
546
550
|
button.addEventListener('click', e => {
|
|
@@ -565,7 +569,7 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
565
569
|
}
|
|
566
570
|
|
|
567
571
|
_createMoveUpButton (i, holder) {
|
|
568
|
-
const button = this.getButton('', (this.schema.format === 'tabs-top' ? 'moveleft' : 'moveup'),
|
|
572
|
+
const button = this.getButton('', (this.schema.format === 'tabs-top' ? 'moveleft' : 'moveup'), 'button_move_up_title')
|
|
569
573
|
button.classList.add('moveup', 'json-editor-btntype-move')
|
|
570
574
|
button.setAttribute('data-i', i)
|
|
571
575
|
button.addEventListener('click', e => {
|
|
@@ -595,7 +599,7 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
595
599
|
}
|
|
596
600
|
|
|
597
601
|
_createMoveDownButton (i, holder) {
|
|
598
|
-
const button = this.getButton('', (this.schema.format === 'tabs-top' ? 'moveright' : 'movedown'),
|
|
602
|
+
const button = this.getButton('', (this.schema.format === 'tabs-top' ? 'moveright' : 'movedown'), 'button_move_down_title')
|
|
599
603
|
button.classList.add('movedown', 'json-editor-btntype-move')
|
|
600
604
|
button.setAttribute('data-i', i)
|
|
601
605
|
button.addEventListener('click', e => {
|
|
@@ -652,7 +656,7 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
652
656
|
}
|
|
653
657
|
|
|
654
658
|
_createToggleButton () {
|
|
655
|
-
const button = this.getButton('', 'collapse',
|
|
659
|
+
const button = this.getButton('', 'collapse', 'button_collapse')
|
|
656
660
|
button.classList.add('json-editor-btntype-toggle')
|
|
657
661
|
this.title.insertBefore(button, this.title.childNodes[0])
|
|
658
662
|
|
|
@@ -667,19 +671,19 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
667
671
|
this.collapsed = false
|
|
668
672
|
this.row_holder.style.display = rowHolderDisplay
|
|
669
673
|
this.controls.style.display = controlsDisplay
|
|
670
|
-
this.setButtonText(e.currentTarget, '', 'collapse',
|
|
674
|
+
this.setButtonText(e.currentTarget, '', 'collapse', 'button_collapse')
|
|
671
675
|
} else {
|
|
672
676
|
this.collapsed = true
|
|
673
677
|
this.row_holder.style.display = 'none'
|
|
674
678
|
this.controls.style.display = 'none'
|
|
675
|
-
this.setButtonText(e.currentTarget, '', 'expand',
|
|
679
|
+
this.setButtonText(e.currentTarget, '', 'expand', 'button_expand')
|
|
676
680
|
}
|
|
677
681
|
})
|
|
678
682
|
return button
|
|
679
683
|
}
|
|
680
684
|
|
|
681
685
|
_createAddRowButton () {
|
|
682
|
-
const button = this.getButton(this.getItemTitle(), 'add',
|
|
686
|
+
const button = this.getButton(this.getItemTitle(), 'add', 'button_add_row_title', [this.getItemTitle()])
|
|
683
687
|
button.classList.add('json-editor-btntype-add')
|
|
684
688
|
button.addEventListener('click', (e) => {
|
|
685
689
|
e.preventDefault()
|
|
@@ -706,7 +710,7 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
706
710
|
}
|
|
707
711
|
|
|
708
712
|
_createDeleteLastRowButton () {
|
|
709
|
-
const button = this.getButton(
|
|
713
|
+
const button = this.getButton('button_delete_last', 'subtract', 'button_delete_last_title', [this.getItemTitle()])
|
|
710
714
|
button.classList.add('json-editor-btntype-deletelast')
|
|
711
715
|
button.addEventListener('click', (e) => {
|
|
712
716
|
e.preventDefault()
|
|
@@ -740,7 +744,7 @@ export class ArrayEditor extends AbstractEditor {
|
|
|
740
744
|
}
|
|
741
745
|
|
|
742
746
|
_createRemoveAllRowsButton () {
|
|
743
|
-
const button = this.getButton(
|
|
747
|
+
const button = this.getButton('button_delete_all', 'delete', 'button_delete_all_title')
|
|
744
748
|
button.classList.add('json-editor-btntype-deleteall')
|
|
745
749
|
button.addEventListener('click', (e) => {
|
|
746
750
|
e.preventDefault()
|
|
@@ -30,6 +30,7 @@ export class AutocompleteEditor extends StringEditor {
|
|
|
30
30
|
/* single property options from schema "options.autocomplete" */
|
|
31
31
|
options = this.expandCallbacks('autocomplete', extend({}, {
|
|
32
32
|
search: (jseditor, input) => {
|
|
33
|
+
// eslint-disable-next-line no-console
|
|
33
34
|
console.log(`No "search" callback defined for autocomplete in property "${jseditor.key}"`)
|
|
34
35
|
return []
|
|
35
36
|
},
|
package/src/editors/base64.js
CHANGED
|
@@ -31,8 +31,8 @@ export class Base64Editor extends AbstractEditor {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
build () {
|
|
34
|
-
this.title = this.header = this.label = this.theme.getFormInputLabel(this.getTitle(), this.isRequired())
|
|
35
|
-
if (this.options.infoText) this.infoButton = this.theme.getInfoButton(this.options.infoText)
|
|
34
|
+
if (!this.options.compact) this.title = this.header = this.label = this.theme.getFormInputLabel(this.getTitle(), this.isRequired())
|
|
35
|
+
if (this.options.infoText) this.infoButton = this.theme.getInfoButton(this.translateProperty(this.options.infoText))
|
|
36
36
|
|
|
37
37
|
/* Input that holds the base64 string */
|
|
38
38
|
this.input = this.theme.getFormInputField('hidden')
|
|
@@ -90,7 +90,7 @@ export class Base64Editor extends AbstractEditor {
|
|
|
90
90
|
})
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
this.preview = this.theme.getFormInputDescription(this.schema.description)
|
|
93
|
+
this.preview = this.theme.getFormInputDescription(this.translateProperty(this.schema.description))
|
|
94
94
|
this.container.appendChild(this.preview)
|
|
95
95
|
|
|
96
96
|
this.control = this.theme.getFormControl(this.label, this.uploader || this.input, this.preview, this.infoButton)
|
|
@@ -138,7 +138,8 @@ export class Base64Editor extends AbstractEditor {
|
|
|
138
138
|
|
|
139
139
|
setValue (val) {
|
|
140
140
|
if (this.value !== val) {
|
|
141
|
-
this.value =
|
|
141
|
+
if (this.schema.readOnly && this.schema.enum && !this.schema.enum.includes(val)) this.value = this.schema.enum[0]
|
|
142
|
+
else this.value = val
|
|
142
143
|
this.input.value = this.value
|
|
143
144
|
this.refreshPreview()
|
|
144
145
|
this.onChange()
|
package/src/editors/button.js
CHANGED
|
@@ -24,7 +24,7 @@ export class ButtonEditor extends AbstractEditor {
|
|
|
24
24
|
|
|
25
25
|
/* Get options, either global options from "this.defaults.options.button" or */
|
|
26
26
|
/* single property options from schema "options.button" */
|
|
27
|
-
const title = this.schema.title || this.key
|
|
27
|
+
const title = this.translateProperty(this.schema.title) || this.key
|
|
28
28
|
const options = this.expandCallbacks('button', extend({}, {
|
|
29
29
|
icon: '',
|
|
30
30
|
validated: false,
|
|
@@ -38,7 +38,7 @@ export class ButtonEditor extends AbstractEditor {
|
|
|
38
38
|
this.input.addEventListener('click', options.action, false)
|
|
39
39
|
|
|
40
40
|
if (this.schema.readOnly || this.schema.readonly || this.schema.template) {
|
|
41
|
-
this.
|
|
41
|
+
this.disable(true)
|
|
42
42
|
this.input.setAttribute('readonly', 'true')
|
|
43
43
|
}
|
|
44
44
|
|
package/src/editors/checkbox.js
CHANGED
|
@@ -31,8 +31,8 @@ export class CheckboxEditor extends AbstractEditor {
|
|
|
31
31
|
this.label.htmlFor = this.formname
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
if (this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description)
|
|
35
|
-
if (this.options.infoText && !this.options.compact) this.infoButton = this.theme.getInfoButton(this.options.infoText)
|
|
34
|
+
if (this.schema.description) this.description = this.theme.getFormInputDescription(this.translateProperty(this.schema.description))
|
|
35
|
+
if (this.options.infoText && !this.options.compact) this.infoButton = this.theme.getInfoButton(this.translateProperty(this.options.infoText))
|
|
36
36
|
if (this.options.compact) this.container.classList.add('compact')
|
|
37
37
|
|
|
38
38
|
this.input = this.theme.getCheckbox()
|
|
@@ -40,7 +40,7 @@ export class CheckboxEditor extends AbstractEditor {
|
|
|
40
40
|
this.control = this.theme.getFormControl(this.label, this.input, this.description, this.infoButton)
|
|
41
41
|
|
|
42
42
|
if (this.schema.readOnly || this.schema.readonly) {
|
|
43
|
-
this.
|
|
43
|
+
this.disable(true)
|
|
44
44
|
this.input.disabled = true
|
|
45
45
|
}
|
|
46
46
|
|
package/src/editors/datetime.js
CHANGED
|
@@ -51,13 +51,13 @@ export class DatetimeEditor extends StringEditor {
|
|
|
51
51
|
/* Create buttons for input group */
|
|
52
52
|
const buttons = []
|
|
53
53
|
if (this.options.flatpickr.showToggleButton !== false) {
|
|
54
|
-
const toggleButton = this.getButton('', this.schema.format === 'time' ? 'time' : 'calendar',
|
|
54
|
+
const toggleButton = this.getButton('', this.schema.format === 'time' ? 'time' : 'calendar', 'flatpickr_toggle_button')
|
|
55
55
|
/* Attribute for flatpicker */
|
|
56
56
|
toggleButton.setAttribute('data-toggle', '')
|
|
57
57
|
buttons.push(toggleButton)
|
|
58
58
|
}
|
|
59
59
|
if (this.options.flatpickr.showClearButton !== false) {
|
|
60
|
-
const clearButton = this.getButton('', 'clear',
|
|
60
|
+
const clearButton = this.getButton('', 'clear', 'flatpickr_clear_button')
|
|
61
61
|
/* Attribute for flatpicker */
|
|
62
62
|
clearButton.setAttribute('data-clear', '')
|
|
63
63
|
buttons.push(clearButton)
|
package/src/editors/info.js
CHANGED
package/src/editors/multiple.js
CHANGED
|
@@ -267,6 +267,8 @@ export class MultipleEditor extends AbstractEditor {
|
|
|
267
267
|
if (fitTestResult !== null) {
|
|
268
268
|
validVal.match = fitTestResult.match
|
|
269
269
|
}
|
|
270
|
+
} else {
|
|
271
|
+
fitTestVal = validVal
|
|
270
272
|
}
|
|
271
273
|
})
|
|
272
274
|
let finalI = validVal.i
|
|
@@ -311,9 +313,13 @@ export class MultipleEditor extends AbstractEditor {
|
|
|
311
313
|
if (!editor) return
|
|
312
314
|
const check = `${this.path}.${checkPart}[${i}]`
|
|
313
315
|
const filterError = (newErrors, error) => {
|
|
314
|
-
if (error.path === check.substr(0, error.path.length)) {
|
|
316
|
+
if (error.path.startsWith(check) || error.path === check.substr(0, error.path.length)) {
|
|
315
317
|
const newError = extend({}, error)
|
|
316
|
-
|
|
318
|
+
|
|
319
|
+
if (error.path.startsWith(check)) {
|
|
320
|
+
newError.path = this.path + newError.path.substr(check.length)
|
|
321
|
+
}
|
|
322
|
+
|
|
317
323
|
newErrors.push(newError)
|
|
318
324
|
}
|
|
319
325
|
return newErrors
|
|
@@ -51,8 +51,8 @@ export class MultiSelectEditor extends AbstractEditor {
|
|
|
51
51
|
build () {
|
|
52
52
|
let i
|
|
53
53
|
if (!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle(), this.isRequired())
|
|
54
|
-
if (this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description)
|
|
55
|
-
if (this.options.infoText) this.infoButton = this.theme.getInfoButton(this.options.infoText)
|
|
54
|
+
if (this.schema.description) this.description = this.theme.getFormInputDescription(this.translateProperty(this.schema.description))
|
|
55
|
+
if (this.options.infoText) this.infoButton = this.theme.getInfoButton(this.translateProperty(this.options.infoText))
|
|
56
56
|
if (this.options.compact) this.container.classList.add('compact')
|
|
57
57
|
|
|
58
58
|
if ((!this.schema.format && this.option_keys.length < 8) || this.schema.format === 'checkbox') {
|
|
@@ -86,7 +86,9 @@ export class MultiSelectEditor extends AbstractEditor {
|
|
|
86
86
|
this.control = this.theme.getFormControl(this.label, this.input, this.description, this.infoButton)
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
if (this.schema.readOnly || this.schema.readonly)
|
|
89
|
+
if (this.schema.readOnly || this.schema.readonly) {
|
|
90
|
+
this.disable(true)
|
|
91
|
+
}
|
|
90
92
|
|
|
91
93
|
this.container.appendChild(this.control)
|
|
92
94
|
|
package/src/editors/object.js
CHANGED
|
@@ -230,7 +230,7 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
230
230
|
const containerSimple = document.createElement('div')
|
|
231
231
|
/* This will be the place to (re)build tabs and panes */
|
|
232
232
|
/* tabs_holder has 2 childs, [0]: ul.nav.nav-tabs and [1]: div.tab-content */
|
|
233
|
-
const newTabsHolder = this.theme.getTopTabHolder(this.schema.title)
|
|
233
|
+
const newTabsHolder = this.theme.getTopTabHolder(this.translateProperty(this.schema.title))
|
|
234
234
|
/* child [1] of previous, stores panes */
|
|
235
235
|
const newTabPanesContainer = this.theme.getTopTabContentHolder(newTabsHolder)
|
|
236
236
|
|
|
@@ -555,7 +555,7 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
555
555
|
this.header = document.createElement('label')
|
|
556
556
|
this.header.textContent = this.getTitle()
|
|
557
557
|
}
|
|
558
|
-
this.title = this.theme.getHeader(this.header)
|
|
558
|
+
this.title = this.theme.getHeader(this.header, this.getPathDepth())
|
|
559
559
|
this.title.classList.add('je-object__title')
|
|
560
560
|
this.controls = this.theme.getButtonHolder()
|
|
561
561
|
this.controls.classList.add('je-object__controls')
|
|
@@ -568,21 +568,21 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
568
568
|
this.editjson_holder = this.theme.getModal()
|
|
569
569
|
this.editjson_textarea = this.theme.getTextareaInput()
|
|
570
570
|
this.editjson_textarea.classList.add('je-edit-json--textarea')
|
|
571
|
-
this.editjson_save = this.getButton('
|
|
571
|
+
this.editjson_save = this.getButton('button_save', 'save', 'button_save')
|
|
572
572
|
this.editjson_save.classList.add('json-editor-btntype-save')
|
|
573
573
|
this.editjson_save.addEventListener('click', (e) => {
|
|
574
574
|
e.preventDefault()
|
|
575
575
|
e.stopPropagation()
|
|
576
576
|
this.saveJSON()
|
|
577
577
|
})
|
|
578
|
-
this.editjson_copy = this.getButton('
|
|
578
|
+
this.editjson_copy = this.getButton('button_copy', 'copy', 'button_copy')
|
|
579
579
|
this.editjson_copy.classList.add('json-editor-btntype-copy')
|
|
580
580
|
this.editjson_copy.addEventListener('click', (e) => {
|
|
581
581
|
e.preventDefault()
|
|
582
582
|
e.stopPropagation()
|
|
583
583
|
this.copyJSON()
|
|
584
584
|
})
|
|
585
|
-
this.editjson_cancel = this.getButton('
|
|
585
|
+
this.editjson_cancel = this.getButton('button_cancel', 'cancel', 'button_cancel')
|
|
586
586
|
this.editjson_cancel.classList.add('json-editor-btntype-cancel')
|
|
587
587
|
this.editjson_cancel.addEventListener('click', (e) => {
|
|
588
588
|
e.preventDefault()
|
|
@@ -598,7 +598,7 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
598
598
|
this.addproperty_holder = this.theme.getModal()
|
|
599
599
|
this.addproperty_list = document.createElement('div')
|
|
600
600
|
this.addproperty_list.classList.add('property-selector')
|
|
601
|
-
this.addproperty_add = this.getButton('
|
|
601
|
+
this.addproperty_add = this.getButton('button_add', 'add', 'button_add')
|
|
602
602
|
this.addproperty_add.classList.add('json-editor-btntype-add')
|
|
603
603
|
|
|
604
604
|
this.addproperty_input = this.theme.getFormInputField('text')
|
|
@@ -637,11 +637,11 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
637
637
|
this.addproperty_holder.appendChild(spacer)
|
|
638
638
|
|
|
639
639
|
/* Close properties modal if clicked outside modal */
|
|
640
|
-
document.addEventListener('click', this.onOutsideModalClick)
|
|
640
|
+
document.addEventListener('click', this.onOutsideModalClick.bind(this))
|
|
641
641
|
|
|
642
642
|
/* Description */
|
|
643
643
|
if (this.schema.description) {
|
|
644
|
-
this.description = this.theme.getDescription(this.schema.description)
|
|
644
|
+
this.description = this.theme.getDescription(this.translateProperty(this.schema.description))
|
|
645
645
|
this.container.appendChild(this.description)
|
|
646
646
|
}
|
|
647
647
|
|
|
@@ -657,11 +657,11 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
657
657
|
this.row_container = this.theme.getGridContainer()
|
|
658
658
|
|
|
659
659
|
if (isCategoriesFormat) {
|
|
660
|
-
this.tabs_holder = this.theme.getTopTabHolder(this.getValidId(this.schema.title))
|
|
660
|
+
this.tabs_holder = this.theme.getTopTabHolder(this.getValidId(this.translateProperty(this.schema.title)))
|
|
661
661
|
this.tabPanesContainer = this.theme.getTopTabContentHolder(this.tabs_holder)
|
|
662
662
|
this.editor_holder.appendChild(this.tabs_holder)
|
|
663
663
|
} else {
|
|
664
|
-
this.tabs_holder = this.theme.getTabHolder(this.getValidId(this.schema.title))
|
|
664
|
+
this.tabs_holder = this.theme.getTabHolder(this.getValidId(this.translateProperty(this.schema.title)))
|
|
665
665
|
this.tabPanesContainer = this.theme.getTabContentHolder(this.tabs_holder)
|
|
666
666
|
this.editor_holder.appendChild(this.row_container)
|
|
667
667
|
}
|
|
@@ -711,7 +711,7 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
711
711
|
|
|
712
712
|
/* Show/Hide button */
|
|
713
713
|
this.collapsed = false
|
|
714
|
-
this.collapse_control = this.getButton('', 'collapse',
|
|
714
|
+
this.collapse_control = this.getButton('', 'collapse', 'button_collapse')
|
|
715
715
|
this.collapse_control.classList.add('json-editor-btntype-toggle')
|
|
716
716
|
this.title.insertBefore(this.collapse_control, this.title.childNodes[0])
|
|
717
717
|
|
|
@@ -721,11 +721,11 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
721
721
|
if (this.collapsed) {
|
|
722
722
|
this.editor_holder.style.display = ''
|
|
723
723
|
this.collapsed = false
|
|
724
|
-
this.setButtonText(this.collapse_control, '', 'collapse',
|
|
724
|
+
this.setButtonText(this.collapse_control, '', 'collapse', 'button_collapse')
|
|
725
725
|
} else {
|
|
726
726
|
this.editor_holder.style.display = 'none'
|
|
727
727
|
this.collapsed = true
|
|
728
|
-
this.setButtonText(this.collapse_control, '', 'expand',
|
|
728
|
+
this.setButtonText(this.collapse_control, '', 'expand', 'button_expand')
|
|
729
729
|
}
|
|
730
730
|
})
|
|
731
731
|
|
|
@@ -742,7 +742,7 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
742
742
|
}
|
|
743
743
|
|
|
744
744
|
/* Edit JSON Button */
|
|
745
|
-
this.editjson_control = this.getButton('JSON', 'edit', '
|
|
745
|
+
this.editjson_control = this.getButton('JSON', 'edit', 'button_edit_json')
|
|
746
746
|
this.editjson_control.classList.add('json-editor-btntype-editjson')
|
|
747
747
|
this.editjson_control.addEventListener('click', (e) => {
|
|
748
748
|
e.preventDefault()
|
|
@@ -760,7 +760,7 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
760
760
|
}
|
|
761
761
|
|
|
762
762
|
/* Object Properties Button */
|
|
763
|
-
this.addproperty_button = this.getButton('
|
|
763
|
+
this.addproperty_button = this.getButton('properties', 'edit_properties', 'button_object_properties')
|
|
764
764
|
this.addproperty_button.classList.add('json-editor-btntype-properties')
|
|
765
765
|
this.addproperty_button.addEventListener('click', (e) => {
|
|
766
766
|
e.preventDefault()
|
|
@@ -793,7 +793,11 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
793
793
|
|
|
794
794
|
deactivateNonRequiredProperties () {
|
|
795
795
|
/* the show_opt_in editor option is for backward compatibility */
|
|
796
|
-
|
|
796
|
+
const globalOptIn = this.jsoneditor.options.show_opt_in
|
|
797
|
+
const editorOptInDefined = (typeof this.options.show_opt_in !== 'undefined')
|
|
798
|
+
const editorOptInEnabled = (editorOptInDefined && this.options.show_opt_in === true)
|
|
799
|
+
const editorOptInDisabled = (editorOptInDefined && this.options.show_opt_in === false)
|
|
800
|
+
if (editorOptInEnabled || (!editorOptInDisabled && globalOptIn) || (!editorOptInDefined && globalOptIn)) {
|
|
797
801
|
Object.entries(this.editors).forEach(([key, editor]) => {
|
|
798
802
|
if (!this.isRequiredObject(editor)) {
|
|
799
803
|
this.editors[key].deactivate()
|
|
@@ -968,6 +972,7 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
968
972
|
[key]: {}
|
|
969
973
|
}
|
|
970
974
|
case 'additionalProperties':
|
|
975
|
+
case 'propertyNames':
|
|
971
976
|
return {
|
|
972
977
|
...acc,
|
|
973
978
|
[key]: true
|
|
@@ -992,7 +997,8 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
992
997
|
this.editors[name].register()
|
|
993
998
|
/* New property */
|
|
994
999
|
} else {
|
|
995
|
-
if (!this.canHaveAdditionalProperties() && (!this.schema.properties || !this.schema.properties[name])
|
|
1000
|
+
if (!this.canHaveAdditionalProperties() && (!this.schema.properties || !this.schema.properties[name]) &&
|
|
1001
|
+
(!this.schema.patternProperties || !(Object.keys(this.schema.patternProperties).find(i => new RegExp(i).test(name))))) {
|
|
996
1002
|
return
|
|
997
1003
|
}
|
|
998
1004
|
|
|
@@ -1036,9 +1042,8 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
1036
1042
|
}
|
|
1037
1043
|
|
|
1038
1044
|
onOutsideModalClick (e) {
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
this.adding_property) {
|
|
1045
|
+
const path = e.path || (e.composedPath && e.composedPath())
|
|
1046
|
+
if (this.addproperty_holder && !this.addproperty_holder.contains(path[0]) && this.adding_property) {
|
|
1042
1047
|
e.preventDefault()
|
|
1043
1048
|
e.stopPropagation()
|
|
1044
1049
|
this.toggleAddProperty()
|
|
@@ -1096,6 +1101,10 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
1096
1101
|
refreshValue () {
|
|
1097
1102
|
this.value = {}
|
|
1098
1103
|
|
|
1104
|
+
if (!this.editors) {
|
|
1105
|
+
return
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1099
1108
|
Object.keys(this.editors).forEach(i => {
|
|
1100
1109
|
if (this.editors[i].isActive()) {
|
|
1101
1110
|
this.value[i] = this.editors[i].getValue()
|
|
@@ -1196,9 +1205,14 @@ export class ObjectEditor extends AbstractEditor {
|
|
|
1196
1205
|
if (typeof value[i] !== 'undefined') {
|
|
1197
1206
|
this.addObjectProperty(i)
|
|
1198
1207
|
editor.setValue(value[i], initial)
|
|
1208
|
+
editor.activate()
|
|
1199
1209
|
/* Otherwise, remove value unless this is the initial set or it's required */
|
|
1200
1210
|
} else if (!initial && !this.isRequiredObject(editor)) {
|
|
1201
|
-
this.
|
|
1211
|
+
if (this.jsoneditor.options.show_opt_in || this.options.show_opt_in) {
|
|
1212
|
+
editor.deactivate()
|
|
1213
|
+
} else {
|
|
1214
|
+
this.removeObjectProperty(i)
|
|
1215
|
+
}
|
|
1202
1216
|
/* Otherwise, set the value to the default */
|
|
1203
1217
|
} else {
|
|
1204
1218
|
editor.setValue(editor.getDefault(), initial)
|
package/src/editors/radio.js
CHANGED
|
@@ -2,15 +2,14 @@ import { SelectEditor } from './select.js'
|
|
|
2
2
|
|
|
3
3
|
export class RadioEditor extends SelectEditor {
|
|
4
4
|
preBuild () {
|
|
5
|
-
this.schema.required = true /* force editor into required mode to prevent creation of empty radio button */
|
|
6
5
|
super.preBuild()
|
|
7
6
|
}
|
|
8
7
|
|
|
9
8
|
build () {
|
|
10
9
|
this.label = ''
|
|
11
10
|
if (!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle(), this.isRequired())
|
|
12
|
-
if (this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description)
|
|
13
|
-
if (this.options.infoText) this.infoButton = this.theme.getInfoButton(this.options.infoText)
|
|
11
|
+
if (this.schema.description) this.description = this.theme.getFormInputDescription(this.translateProperty(this.schema.description))
|
|
12
|
+
if (this.options.infoText) this.infoButton = this.theme.getInfoButton(this.translateProperty(this.options.infoText))
|
|
14
13
|
if (this.options.compact) this.container.classList.add('compact')
|
|
15
14
|
|
|
16
15
|
this.radioContainer = document.createElement('div')
|
|
@@ -22,6 +21,12 @@ export class RadioEditor extends SelectEditor {
|
|
|
22
21
|
this.onChange(true)
|
|
23
22
|
}
|
|
24
23
|
|
|
24
|
+
if (!this.isRequired()) {
|
|
25
|
+
this.enum_display.shift()
|
|
26
|
+
this.enum_options.shift()
|
|
27
|
+
this.enum_values.shift()
|
|
28
|
+
}
|
|
29
|
+
|
|
25
30
|
for (let i = 0; i < this.enum_values.length; i++) {
|
|
26
31
|
/* form radio elements */
|
|
27
32
|
this.input = this.theme.getFormRadio({
|
|
@@ -46,7 +51,7 @@ export class RadioEditor extends SelectEditor {
|
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
if (this.schema.readOnly || this.schema.readonly) {
|
|
49
|
-
this.
|
|
54
|
+
this.disable(true)
|
|
50
55
|
for (let j = 0; j < this.radioGroup.length; j++) {
|
|
51
56
|
this.radioGroup[j].disabled = true
|
|
52
57
|
}
|