@wirenboard/json-editor 2.5.3-wb13

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.
Files changed (283) hide show
  1. package/.env-dist +2 -0
  2. package/.eslintrc +7 -0
  3. package/.gitattributes +1 -0
  4. package/.github/PULL_REQUEST_TEMPLATE.md +9 -0
  5. package/.github/issue_template +25 -0
  6. package/.github/workflows/build.yml +58 -0
  7. package/.travis.yml +70 -0
  8. package/CHANGELOG.md +915 -0
  9. package/CONTRIBUTING.md +92 -0
  10. package/LICENSE +20 -0
  11. package/Makefile +26 -0
  12. package/README.md +1646 -0
  13. package/README_ADDON.md +573 -0
  14. package/UPGRADING.md +46 -0
  15. package/build/CssToJson.js +55 -0
  16. package/codecept.conf.js +35 -0
  17. package/config/.eslintrc +7 -0
  18. package/config/codeceptjs_helpers.js +139 -0
  19. package/config/helpers.js +10 -0
  20. package/config/karma.conf.js +93 -0
  21. package/config/readme.md +31 -0
  22. package/config/webpack.common.js +75 -0
  23. package/config/webpack.dev.js +15 -0
  24. package/config/webpack.nonmin.js +19 -0
  25. package/config/webpack.prod.js +25 -0
  26. package/dist/jsoneditor.js +14 -0
  27. package/dist/nonmin/jsoneditor.js +29097 -0
  28. package/dist/nonmin/jsoneditor.js.map +1 -0
  29. package/docs/ace_editor.html +56 -0
  30. package/docs/advanced.html +136 -0
  31. package/docs/basic.html +63 -0
  32. package/docs/basic_person.json +26 -0
  33. package/docs/choices.html +86 -0
  34. package/docs/cleave.html +132 -0
  35. package/docs/colorpicker.html +194 -0
  36. package/docs/css_integration.html +135 -0
  37. package/docs/datetime.html +305 -0
  38. package/docs/describedby.html +161 -0
  39. package/docs/enumsource.html +67 -0
  40. package/docs/images/categoriesDemo.png +0 -0
  41. package/docs/images/inheritance_tree.png +0 -0
  42. package/docs/images/jsoneditor.png +0 -0
  43. package/docs/imask.html +192 -0
  44. package/docs/index.html +579 -0
  45. package/docs/materialize_css.html +164 -0
  46. package/docs/meta_schema.json +705 -0
  47. package/docs/multiple_upload_base64.html +65 -0
  48. package/docs/person.json +73 -0
  49. package/docs/polyfills/assign.js +29 -0
  50. package/docs/radio.html +156 -0
  51. package/docs/recursive.html +170 -0
  52. package/docs/select2.html +99 -0
  53. package/docs/selectize.html +100 -0
  54. package/docs/signature.html +42 -0
  55. package/docs/starrating.html +137 -0
  56. package/docs/upload.html +131 -0
  57. package/docs/uuid.html +70 -0
  58. package/docs/wysiwyg.html +56 -0
  59. package/jasmine.json +11 -0
  60. package/json-editor-json-editor-2.5.3-wb13.tgz +0 -0
  61. package/package.json +100 -0
  62. package/release-notes.md +88 -0
  63. package/src/core.js +412 -0
  64. package/src/defaults.js +402 -0
  65. package/src/editor.js +707 -0
  66. package/src/editors/ace.js +89 -0
  67. package/src/editors/array/choices.js +103 -0
  68. package/src/editors/array/select2.js +110 -0
  69. package/src/editors/array/selectize.js +103 -0
  70. package/src/editors/array.css +9 -0
  71. package/src/editors/array.css.js +3 -0
  72. package/src/editors/array.js +818 -0
  73. package/src/editors/autocomplete.js +58 -0
  74. package/src/editors/base64.js +157 -0
  75. package/src/editors/button.js +97 -0
  76. package/src/editors/checkbox.js +95 -0
  77. package/src/editors/choices.css +3 -0
  78. package/src/editors/choices.css.js +3 -0
  79. package/src/editors/choices.js +69 -0
  80. package/src/editors/colorpicker.js +103 -0
  81. package/src/editors/datetime.js +141 -0
  82. package/src/editors/describedby.js +188 -0
  83. package/src/editors/enum.js +136 -0
  84. package/src/editors/hidden.js +127 -0
  85. package/src/editors/index.js +81 -0
  86. package/src/editors/info.js +20 -0
  87. package/src/editors/integer.js +19 -0
  88. package/src/editors/ip.js +36 -0
  89. package/src/editors/jodit.js +64 -0
  90. package/src/editors/multiple.js +409 -0
  91. package/src/editors/multiselect.js +218 -0
  92. package/src/editors/null.js +18 -0
  93. package/src/editors/number.js +51 -0
  94. package/src/editors/object.css +41 -0
  95. package/src/editors/object.css.js +3 -0
  96. package/src/editors/object.js +1290 -0
  97. package/src/editors/radio.js +111 -0
  98. package/src/editors/sceditor.js +72 -0
  99. package/src/editors/select.js +370 -0
  100. package/src/editors/select2.js +110 -0
  101. package/src/editors/selectize.js +112 -0
  102. package/src/editors/signature.js +113 -0
  103. package/src/editors/simplemde.js +100 -0
  104. package/src/editors/starrating.css +52 -0
  105. package/src/editors/starrating.css.js +3 -0
  106. package/src/editors/starrating.js +135 -0
  107. package/src/editors/stepper.js +27 -0
  108. package/src/editors/string.js +372 -0
  109. package/src/editors/table.js +516 -0
  110. package/src/editors/upload.js +321 -0
  111. package/src/editors/uuid.js +56 -0
  112. package/src/iconlib.js +24 -0
  113. package/src/iconlibs/bootstrap2.js +28 -0
  114. package/src/iconlibs/bootstrap3.js +28 -0
  115. package/src/iconlibs/fontawesome3.js +28 -0
  116. package/src/iconlibs/fontawesome4.js +28 -0
  117. package/src/iconlibs/fontawesome5.js +28 -0
  118. package/src/iconlibs/foundation2.js +24 -0
  119. package/src/iconlibs/foundation3.js +28 -0
  120. package/src/iconlibs/index.js +25 -0
  121. package/src/iconlibs/jqueryui.js +28 -0
  122. package/src/iconlibs/materialicons.js +49 -0
  123. package/src/iconlibs/openiconic.js +28 -0
  124. package/src/iconlibs/spectre.js +28 -0
  125. package/src/resolvers.js +128 -0
  126. package/src/schemaloader.js +408 -0
  127. package/src/style.css +150 -0
  128. package/src/style.css.js +3 -0
  129. package/src/templates/default.js +52 -0
  130. package/src/templates/ejs.js +13 -0
  131. package/src/templates/handlebars.js +1 -0
  132. package/src/templates/hogan.js +10 -0
  133. package/src/templates/index.js +21 -0
  134. package/src/templates/lodash.js +9 -0
  135. package/src/templates/markup.js +9 -0
  136. package/src/templates/mustache.js +9 -0
  137. package/src/templates/swig.js +1 -0
  138. package/src/templates/underscore.js +9 -0
  139. package/src/theme.js +659 -0
  140. package/src/themes/barebones.css +35 -0
  141. package/src/themes/barebones.css.js +3 -0
  142. package/src/themes/barebones.js +28 -0
  143. package/src/themes/bootstrap2.js +319 -0
  144. package/src/themes/bootstrap3.css +0 -0
  145. package/src/themes/bootstrap3.css.js +3 -0
  146. package/src/themes/bootstrap3.js +315 -0
  147. package/src/themes/bootstrap4.css +89 -0
  148. package/src/themes/bootstrap4.css.js +3 -0
  149. package/src/themes/bootstrap4.js +690 -0
  150. package/src/themes/bootstrap5.css.js +3 -0
  151. package/src/themes/foundation.js +569 -0
  152. package/src/themes/html.css +60 -0
  153. package/src/themes/html.css.js +3 -0
  154. package/src/themes/html.js +71 -0
  155. package/src/themes/index.js +28 -0
  156. package/src/themes/jqueryui.js +198 -0
  157. package/src/themes/materialize.js +426 -0
  158. package/src/themes/spectre.css +208 -0
  159. package/src/themes/spectre.css.js +3 -0
  160. package/src/themes/spectre.js +406 -0
  161. package/src/themes/tailwind.css +249 -0
  162. package/src/themes/tailwind.css.js +3 -0
  163. package/src/themes/tailwind.js +443 -0
  164. package/src/utilities.js +138 -0
  165. package/src/validator.js +877 -0
  166. package/src/validators/ip-validator.js +51 -0
  167. package/tests/Dockerfile +3 -0
  168. package/tests/README.md +48 -0
  169. package/tests/codeceptjs/codecept.json +42 -0
  170. package/tests/codeceptjs/constrains/if-then-else_test.js +143 -0
  171. package/tests/codeceptjs/core_test.js +217 -0
  172. package/tests/codeceptjs/editors/advanced_test.js +13 -0
  173. package/tests/codeceptjs/editors/array_any_of_test.js +50 -0
  174. package/tests/codeceptjs/editors/array_test.js +900 -0
  175. package/tests/codeceptjs/editors/button_test.js +35 -0
  176. package/tests/codeceptjs/editors/checkbox_test.js +21 -0
  177. package/tests/codeceptjs/editors/colorpicker_test.js +27 -0
  178. package/tests/codeceptjs/editors/datetime_test.js +33 -0
  179. package/tests/codeceptjs/editors/inheritance_test.js +11 -0
  180. package/tests/codeceptjs/editors/integer_test.js +84 -0
  181. package/tests/codeceptjs/editors/issues/issue-gh-812_test.js +32 -0
  182. package/tests/codeceptjs/editors/jodit_test.js +24 -0
  183. package/tests/codeceptjs/editors/multiselect_test.js +8 -0
  184. package/tests/codeceptjs/editors/number_test.js +82 -0
  185. package/tests/codeceptjs/editors/object_test.js +204 -0
  186. package/tests/codeceptjs/editors/option-no_default_values_test.js +42 -0
  187. package/tests/codeceptjs/editors/programmatic-changes_test.js +20 -0
  188. package/tests/codeceptjs/editors/radio_test.js +10 -0
  189. package/tests/codeceptjs/editors/rating_test.js +13 -0
  190. package/tests/codeceptjs/editors/select_test.js +22 -0
  191. package/tests/codeceptjs/editors/stepper_test.js +27 -0
  192. package/tests/codeceptjs/editors/string_test.js +118 -0
  193. package/tests/codeceptjs/editors/table-confirm-delete_test.js +67 -0
  194. package/tests/codeceptjs/editors/tabs_test.js +14 -0
  195. package/tests/codeceptjs/editors/uuid_test.js +21 -0
  196. package/tests/codeceptjs/editors/validation_test.js +14 -0
  197. package/tests/codeceptjs/meta-schema_test.js +17 -0
  198. package/tests/codeceptjs/schemaloader_test.js +13 -0
  199. package/tests/codeceptjs/steps.d.ts +13 -0
  200. package/tests/codeceptjs/steps_file.js +12 -0
  201. package/tests/codeceptjs/themes_test.js +519 -0
  202. package/tests/docker-compose.yml +34 -0
  203. package/tests/fixtures/basic_person.json +26 -0
  204. package/tests/fixtures/nested_object.json +26 -0
  205. package/tests/fixtures/person.json +55 -0
  206. package/tests/fixtures/recursive.json +8 -0
  207. package/tests/fixtures/some_types.json +32 -0
  208. package/tests/fixtures/string.json +3 -0
  209. package/tests/fixtures/validation.json +1140 -0
  210. package/tests/pages/_demo.html +475 -0
  211. package/tests/pages/advanced.html +137 -0
  212. package/tests/pages/anyof.html +80 -0
  213. package/tests/pages/array-anyof.html +142 -0
  214. package/tests/pages/array-checkboxes.html +41 -0
  215. package/tests/pages/array-choices.html +45 -0
  216. package/tests/pages/array-integers.html +37 -0
  217. package/tests/pages/array-move-events.html +61 -0
  218. package/tests/pages/array-multiselects.html +42 -0
  219. package/tests/pages/array-nested-arrays.html +40 -0
  220. package/tests/pages/array-numbers.html +37 -0
  221. package/tests/pages/array-objects.html +42 -0
  222. package/tests/pages/array-ratings.html +40 -0
  223. package/tests/pages/array-selectize.html +51 -0
  224. package/tests/pages/array-selects.html +36 -0
  225. package/tests/pages/array-strings.html +36 -0
  226. package/tests/pages/array.html +42 -0
  227. package/tests/pages/assets/pages.css +130 -0
  228. package/tests/pages/button-callbacks.html +77 -0
  229. package/tests/pages/checkbox-labels.html +114 -0
  230. package/tests/pages/colorpicker-no-3rd-party.html +43 -0
  231. package/tests/pages/colorpicker-use-vanilla-picker.html +50 -0
  232. package/tests/pages/core.html +118 -0
  233. package/tests/pages/datetime.html +76 -0
  234. package/tests/pages/form-name.html +108 -0
  235. package/tests/pages/grid-strict.html +311 -0
  236. package/tests/pages/grid.html +284 -0
  237. package/tests/pages/if-then-else-allOf.html +117 -0
  238. package/tests/pages/inheritance.html +76 -0
  239. package/tests/pages/integer.html +68 -0
  240. package/tests/pages/issues/_template.html +50 -0
  241. package/tests/pages/issues/issue-gh-812.html +110 -0
  242. package/tests/pages/issues/issue-gh-823-meta-schema.html +35 -0
  243. package/tests/pages/issues/issue-gh-848.html +81 -0
  244. package/tests/pages/meta_schema.json +705 -0
  245. package/tests/pages/number.html +89 -0
  246. package/tests/pages/object-no-additional-properties.html +65 -0
  247. package/tests/pages/object-no-duplicated-id.html +68 -0
  248. package/tests/pages/object-required-properties.html +236 -0
  249. package/tests/pages/object-with-dependencies-array.html +46 -0
  250. package/tests/pages/object-with-dependencies.html +60 -0
  251. package/tests/pages/object.html +79 -0
  252. package/tests/pages/oneof.html +103 -0
  253. package/tests/pages/option-no_default_values.html +58 -0
  254. package/tests/pages/programmatic-changes.html +120 -0
  255. package/tests/pages/read-only.html +105 -0
  256. package/tests/pages/select.html +41 -0
  257. package/tests/pages/stepper.html +59 -0
  258. package/tests/pages/string-ace-editor.html +52 -0
  259. package/tests/pages/string-cleave.html +46 -0
  260. package/tests/pages/string-custom-attributes.html +62 -0
  261. package/tests/pages/string-formats.html +52 -0
  262. package/tests/pages/string-formats2.html +57 -0
  263. package/tests/pages/string-jodit-editor.html +49 -0
  264. package/tests/pages/string-sceditor.html +62 -0
  265. package/tests/pages/table-move-events.html +56 -0
  266. package/tests/pages/table.html +46 -0
  267. package/tests/pages/tabs.html +131 -0
  268. package/tests/pages/themes.html +527 -0
  269. package/tests/pages/translate-property.html +247 -0
  270. package/tests/pages/urn.html +93 -0
  271. package/tests/pages/uuid.html +72 -0
  272. package/tests/pages/validation.html +99 -0
  273. package/tests/unit/.eslintrc +8 -0
  274. package/tests/unit/core.spec.js +309 -0
  275. package/tests/unit/defaults.spec.js +40 -0
  276. package/tests/unit/editor.spec.js +160 -0
  277. package/tests/unit/editors/array.spec.js +86 -0
  278. package/tests/unit/editors/object.spec.js +79 -0
  279. package/tests/unit/editors/table.spec.js +91 -0
  280. package/tests/unit/readme.md +35 -0
  281. package/tests/unit/schemaloader.spec.js +498 -0
  282. package/tests/unit/validator.spec.js +94 -0
  283. package/tests/unit/validators/ip-validator.spec.js +62 -0
@@ -0,0 +1,58 @@
1
+ import { StringEditor } from './string.js'
2
+ import { extend } from '../utilities.js'
3
+
4
+ export class AutocompleteEditor extends StringEditor {
5
+ postBuild () {
6
+ if (window.Autocomplete) {
7
+ /* create wrapper container */
8
+ this.autocomplete_wrapper = document.createElement('div')
9
+
10
+ /* insert wrapper after this.input in the DOM tree */
11
+ this.input.parentNode.insertBefore(this.autocomplete_wrapper, this.input.nextSibling)
12
+
13
+ /* move this.input into wrapper */
14
+ this.autocomplete_wrapper.appendChild(this.input)
15
+
16
+ /* create dropdown container */
17
+ this.autocomplete_dropdown = document.createElement('ul')
18
+
19
+ /* insert dropdown after this.input in the DOM tree */
20
+ this.input.parentNode.insertBefore(this.autocomplete_dropdown, this.input.nextSibling)
21
+ }
22
+ super.postBuild()
23
+ }
24
+
25
+ afterInputReady () {
26
+ let options
27
+
28
+ if (window.Autocomplete && !this.autocomplete_instance) {
29
+ /* Get options, either global options from "this.defaults.options.autocomplete" or */
30
+ /* single property options from schema "options.autocomplete" */
31
+ options = this.expandCallbacks('autocomplete', extend({}, {
32
+ search: (jseditor, input) => {
33
+ // eslint-disable-next-line no-console
34
+ console.log(`No "search" callback defined for autocomplete in property "${jseditor.key}"`)
35
+ return []
36
+ },
37
+ baseClass: 'autocomplete'
38
+ }, this.defaults.options.autocomplete || {}, this.options.autocomplete || {}))
39
+
40
+ this.autocomplete_wrapper.classList.add(options.baseClass)
41
+ this.autocomplete_dropdown.classList.add(`${options.baseClass}-result-list`)
42
+ /* this.input.classList.add(options.baseClass + '-input'); */
43
+
44
+ this.autocomplete_instance = new window.Autocomplete(this.autocomplete_wrapper, options)
45
+ }
46
+ super.afterInputReady()
47
+ }
48
+
49
+ destroy () {
50
+ if (this.autocomplete_instance) {
51
+ if (this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input)
52
+ if (this.autocomplete_dropdown && this.autocomplete_dropdown.parentNode) this.autocomplete_dropdown.parentNode.removeChild(this.autocomplete_dropdown)
53
+ if (this.autocomplete_wrapper && this.autocomplete_wrapper.parentNode) this.autocomplete_wrapper.parentNode.removeChild(this.autocomplete_wrapper)
54
+ this.autocomplete_instance = null
55
+ }
56
+ super.destroy()
57
+ }
58
+ }
@@ -0,0 +1,157 @@
1
+ import { AbstractEditor } from '../editor.js'
2
+
3
+ export class Base64Editor extends AbstractEditor {
4
+ getNumColumns () {
5
+ return 4
6
+ }
7
+
8
+ setFileReaderListener (frMultiple) {
9
+ frMultiple.addEventListener('load', (event) => {
10
+ if (this.count === this.current_item_index) {
11
+ /* Overwrite existing file by default, leave other properties unchanged */
12
+ this.value[this.count][this.key] = event.target.result
13
+ } else {
14
+ const tempObject = {}
15
+ /* Create empty object */
16
+ for (const key in this.parent.schema.properties) {
17
+ tempObject[key] = ''
18
+ }
19
+ /* Set object media file */
20
+ tempObject[this.key] = event.target.result
21
+ this.value.splice(this.count, 0, tempObject) /* insert new file object */
22
+ }
23
+
24
+ /* Increment using the listener and not the 'for' loop as the listener will be processed asynchronously */
25
+ this.count += 1
26
+ /* When all files have been processed, update the value of the editor */
27
+ if (this.count === (this.total + this.current_item_index)) {
28
+ this.arrayEditor.setValue(this.value)
29
+ }
30
+ })
31
+ }
32
+
33
+ build () {
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
+
37
+ /* Input that holds the base64 string */
38
+ this.input = this.theme.getFormInputField('hidden')
39
+ this.container.appendChild(this.input)
40
+
41
+ /* Don't show uploader if this is readonly */
42
+ if (!this.schema.readOnly && !this.schema.readonly) {
43
+ if (!window.FileReader) throw new Error('FileReader required for base64 editor')
44
+
45
+ /* File uploader */
46
+ this.uploader = this.theme.getFormInputField('file')
47
+
48
+ /* Set attribute of file input field to 'multiple' if: */
49
+ /* 'multiple' key has been set to 'true' in the schema */
50
+ /* and the parent object is of type 'object' */
51
+ /* and the parent of the parent type has been set to 'array' */
52
+ if (this.schema.options && this.schema.options.multiple && this.schema.options.multiple === true && this.parent && this.parent.schema.type === 'object' && this.parent.parent && this.parent.parent.schema.type === 'array') {
53
+ this.uploader.setAttribute('multiple', '')
54
+ }
55
+
56
+ this.uploader.addEventListener('change', e => {
57
+ e.preventDefault()
58
+ e.stopPropagation()
59
+
60
+ if (e.currentTarget.files && e.currentTarget.files.length) {
61
+ /* Check the amount of files uploaded. */
62
+ /* If 1, use the regular upload, otherwise use the multiple upload method */
63
+ if (e.currentTarget.files.length > 1 && this.schema.options && this.schema.options.multiple && this.schema.options.multiple === true && this.parent && this.parent.schema.type === 'object' && this.parent.parent && this.parent.parent.schema.type === 'array') {
64
+ /* Load editor of parent.parent to get the array */
65
+ this.arrayEditor = this.jsoneditor.getEditor(this.parent.parent.path)
66
+ /* Check the current value of this editor */
67
+ this.value = this.arrayEditor.getValue()
68
+ /* Set variables for amount of files, index of current array item and */
69
+ /* count value containing current status of processed files */
70
+ this.total = e.currentTarget.files.length
71
+ this.current_item_index = parseInt(this.parent.key)
72
+ this.count = this.current_item_index
73
+
74
+ for (let i = 0; i < this.total; i++) {
75
+ const frMultiple = new FileReader()
76
+ this.setFileReaderListener(frMultiple)
77
+ frMultiple.readAsDataURL(e.currentTarget.files[i])
78
+ }
79
+ } else {
80
+ let fr = new FileReader()
81
+ fr.onload = (evt) => {
82
+ this.value = evt.target.result
83
+ this.refreshPreview()
84
+ this.onChange(true)
85
+ fr = null
86
+ }
87
+ fr.readAsDataURL(e.currentTarget.files[0])
88
+ }
89
+ }
90
+ })
91
+ }
92
+
93
+ this.preview = this.theme.getFormInputDescription(this.translateProperty(this.schema.description))
94
+ this.container.appendChild(this.preview)
95
+
96
+ this.control = this.theme.getFormControl(this.label, this.uploader || this.input, this.preview, this.infoButton)
97
+ this.container.appendChild(this.control)
98
+ }
99
+
100
+ refreshPreview () {
101
+ if (this.last_preview === this.value) return
102
+ this.last_preview = this.value
103
+
104
+ this.preview.innerHTML = ''
105
+
106
+ if (!this.value) return
107
+
108
+ let mime = this.value.match(/^data:([^;,]+)[;,]/)
109
+ if (mime) mime = mime[1]
110
+
111
+ if (!mime) {
112
+ this.preview.innerHTML = '<em>Invalid data URI</em>'
113
+ } else {
114
+ this.preview.innerHTML = `<strong>Type:</strong> ${mime}, <strong>Size:</strong> ${Math.floor((this.value.length - this.value.split(',')[0].length - 1) / 1.33333)} bytes`
115
+ if (mime.substr(0, 5) === 'image') {
116
+ this.preview.innerHTML += '<br>'
117
+ const img = document.createElement('img')
118
+ img.style.maxWidth = '100%'
119
+ img.style.maxHeight = '100px'
120
+ img.src = this.value
121
+ this.preview.appendChild(img)
122
+ }
123
+ }
124
+ }
125
+
126
+ enable () {
127
+ if (!this.always_disabled) {
128
+ if (this.uploader) this.uploader.disabled = false
129
+ super.enable()
130
+ }
131
+ }
132
+
133
+ disable (alwaysDisabled) {
134
+ if (alwaysDisabled) this.always_disabled = true
135
+ if (this.uploader) this.uploader.disabled = true
136
+ super.disable()
137
+ }
138
+
139
+ setValue (val) {
140
+ if (this.value !== val) {
141
+ if (this.schema.readOnly && this.schema.enum && !this.schema.enum.includes(val)) this.value = this.schema.enum[0]
142
+ else this.value = val
143
+ this.input.value = this.value
144
+ this.refreshPreview()
145
+ this.onChange()
146
+ }
147
+ }
148
+
149
+ destroy () {
150
+ if (this.preview && this.preview.parentNode) this.preview.parentNode.removeChild(this.preview)
151
+ if (this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title)
152
+ if (this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input)
153
+ if (this.uploader && this.uploader.parentNode) this.uploader.parentNode.removeChild(this.uploader)
154
+
155
+ super.destroy()
156
+ }
157
+ }
@@ -0,0 +1,97 @@
1
+ /* Non-Active editor for displaying buttons in form */
2
+ import { AbstractEditor } from '../editor.js'
3
+ import { extend } from '../utilities.js'
4
+
5
+ export class ButtonEditor extends AbstractEditor {
6
+ constructor (options, defaults) {
7
+ super(options, defaults)
8
+ this.active = false
9
+
10
+ /* Set field to required in schema otherwise it will not be displayed */
11
+ if (this.parent && this.parent.schema) {
12
+ if (Array.isArray(this.parent.schema.required)) {
13
+ if (!this.parent.schema.required.includes(this.key)) {
14
+ this.parent.schema.required.push(this.key)
15
+ }
16
+ } else {
17
+ this.parent.schema.required = [this.key]
18
+ }
19
+ }
20
+ }
21
+
22
+ build () {
23
+ this.options.compact = true
24
+
25
+ /* Get options, either global options from "this.defaults.options.button" or */
26
+ /* single property options from schema "options.button" */
27
+ const title = this.translateProperty(this.schema.title) || this.key
28
+ const options = this.expandCallbacks('button', extend({}, {
29
+ icon: '',
30
+ validated: false,
31
+ align: 'left',
32
+ action: (jseditor, e) => {
33
+ window.alert(`No button action defined for "${jseditor.path}"`)
34
+ }
35
+ }, this.defaults.options.button || {}, this.options.button || {}))
36
+
37
+ this.input = this.theme.getFormButton(title, options.icon, title)
38
+ this.input.addEventListener('click', options.action, false)
39
+
40
+ if (this.schema.readOnly || this.schema.readonly || this.schema.template) {
41
+ this.disable(true)
42
+ this.input.setAttribute('readonly', 'true')
43
+ }
44
+
45
+ /* Set custom attributes on input element. Parameter is array of protected keys. Empty array if none. */
46
+ this.setInputAttributes(['readonly'])
47
+
48
+ this.control = this.theme.getFormButtonHolder(options.align)
49
+ this.control.appendChild(this.input)
50
+
51
+ this.container.appendChild(this.control)
52
+
53
+ this.changeHandler = () => {
54
+ if (this.jsoneditor.validate(this.jsoneditor.getValue()).length > 0) this.disable()
55
+ else this.enable()
56
+ }
57
+
58
+ /* Enable/disable the button depending on form validation */
59
+ if (options.validated) this.jsoneditor.on('change', this.changeHandler)
60
+ }
61
+
62
+ enable () {
63
+ if (!this.always_disabled) {
64
+ this.input.disabled = false
65
+ super.enable()
66
+ }
67
+ }
68
+
69
+ disable (alwaysDisabled) {
70
+ if (alwaysDisabled) this.always_disabled = true
71
+ this.input.disabled = true
72
+ super.disable()
73
+ }
74
+
75
+ getNumColumns () {
76
+ return 2
77
+ }
78
+
79
+ activate () {
80
+ this.active = false
81
+ this.enable()
82
+ }
83
+
84
+ deactivate () {
85
+ /* only non required properties can be deactivated. */
86
+ if (!this.isRequired()) {
87
+ this.active = false
88
+ this.disable()
89
+ }
90
+ }
91
+
92
+ destroy () {
93
+ this.jsoneditor.off('change', this.changeHandler)
94
+ this.changeHandler = null
95
+ super.destroy()
96
+ }
97
+ }
@@ -0,0 +1,95 @@
1
+ import { AbstractEditor } from '../editor.js'
2
+
3
+ export class CheckboxEditor extends AbstractEditor {
4
+ setValue (value, initial) {
5
+ value = !!value
6
+ const changed = this.getValue() !== value
7
+ this.value = value
8
+ this.input.checked = this.value
9
+ this.onChange(changed)
10
+ }
11
+
12
+ register () {
13
+ super.register()
14
+ if (!this.input) return
15
+ this.input.setAttribute('name', this.formname)
16
+ }
17
+
18
+ unregister () {
19
+ super.unregister()
20
+ if (!this.input) return
21
+ this.input.removeAttribute('name')
22
+ }
23
+
24
+ getNumColumns () {
25
+ return Math.min(12, Math.max(Math.ceil(this.getTitle().length / 7), 2))
26
+ }
27
+
28
+ build () {
29
+ if (!this.parent.options.table_row) {
30
+ this.label = this.header = this.theme.getCheckboxLabel(this.getTitle(), this.isRequired())
31
+ this.label.htmlFor = this.formname
32
+ }
33
+
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
+ if (this.options.compact) this.container.classList.add('compact')
37
+
38
+ this.input = this.theme.getCheckbox()
39
+ this.input.id = this.formname
40
+ this.control = this.theme.getFormControl(this.label, this.input, this.description, this.infoButton)
41
+
42
+ if (this.schema.readOnly || this.schema.readonly) {
43
+ this.disable(true)
44
+ this.input.disabled = true
45
+ }
46
+
47
+ this.input.addEventListener('change', e => {
48
+ e.preventDefault()
49
+ e.stopPropagation()
50
+ this.value = e.currentTarget.checked
51
+ this.onChange(true)
52
+ })
53
+
54
+ this.container.appendChild(this.control)
55
+ }
56
+
57
+ enable () {
58
+ if (!this.always_disabled) {
59
+ this.input.disabled = false
60
+ super.enable()
61
+ }
62
+ }
63
+
64
+ disable (alwaysDisabled) {
65
+ if (alwaysDisabled) this.always_disabled = true
66
+ this.input.disabled = true
67
+ super.disable()
68
+ }
69
+
70
+ destroy () {
71
+ if (this.label && this.label.parentNode) this.label.parentNode.removeChild(this.label)
72
+ if (this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description)
73
+ if (this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input)
74
+ super.destroy()
75
+ }
76
+
77
+ showValidationErrors (errors) {
78
+ this.previous_error_setting = this.jsoneditor.options.show_errors
79
+
80
+ const addMessage = (messages, error) => {
81
+ if (error.path === this.path) {
82
+ messages.push(error.message)
83
+ }
84
+ return messages
85
+ }
86
+ const messages = errors.reduce(addMessage, [])
87
+ this.input.controlgroup = this.control
88
+
89
+ if (messages.length) {
90
+ this.theme.addInputError(this.input, `${messages.join('. ')}.`)
91
+ } else {
92
+ this.theme.removeInputError(this.input)
93
+ }
94
+ }
95
+ }
@@ -0,0 +1,3 @@
1
+ .choices > * {
2
+ box-sizing: border-box;
3
+ }
@@ -0,0 +1,3 @@
1
+ /* eslint-disable */
2
+ export default {".choices > *":"box-sizing:border-box"}
3
+ /* eslint-enable */
@@ -0,0 +1,69 @@
1
+ import { SelectEditor } from './select.js'
2
+ import { extend } from '../utilities.js'
3
+ import rules from './choices.css.js'
4
+
5
+ export class ChoicesEditor extends SelectEditor {
6
+ setValue (value, initial) {
7
+ if (this.choices_instance) {
8
+ /* Sanitize value before setting it */
9
+ let sanitized = this.typecast(value || '')
10
+
11
+ if (!this.enum_values.includes(sanitized)) sanitized = this.enum_values[0]
12
+
13
+ if (this.value === sanitized) return
14
+
15
+ if (initial) this.is_dirty = false
16
+ else if (this.jsoneditor.options.show_errors === 'change') this.is_dirty = true
17
+
18
+ this.input.value = this.enum_options[this.enum_values.indexOf(sanitized)]
19
+
20
+ this.choices_instance.setChoiceByValue(this.input.value)
21
+
22
+ this.value = sanitized
23
+ this.onChange()
24
+ } else super.setValue(value, initial)
25
+ }
26
+
27
+ afterInputReady () {
28
+ if (window.Choices && !this.choices_instance) {
29
+ /* Get options, either global options from "this.defaults.options.choices" or */
30
+ /* single property options from schema "options.choices" */
31
+ const options = this.expandCallbacks('choices', extend({}, this.defaults.options.choices || {}, this.options.choices || {}))
32
+
33
+ this.choices_instance = new window.Choices(this.input, options)
34
+ }
35
+ super.afterInputReady()
36
+ }
37
+
38
+ onWatchedFieldChange () {
39
+ super.onWatchedFieldChange()
40
+ if (this.choices_instance) {
41
+ const choicesList = this.enum_options.map((v, i) => ({
42
+ value: v,
43
+ label: this.enum_display[i]
44
+ }))
45
+ this.choices_instance.setChoices(choicesList, 'value', 'label', true)
46
+ this.choices_instance.setChoiceByValue(`${this.value}`) /* Set new selection */
47
+ }
48
+ }
49
+
50
+ enable () {
51
+ if (!this.always_disabled && this.choices_instance) this.choices_instance.enable()
52
+ super.enable()
53
+ }
54
+
55
+ disable (alwaysDisabled) {
56
+ if (this.choices_instance) this.choices_instance.disable()
57
+ super.disable(alwaysDisabled)
58
+ }
59
+
60
+ destroy () {
61
+ if (this.choices_instance) {
62
+ this.choices_instance.destroy()
63
+ this.choices_instance = null
64
+ }
65
+ super.destroy()
66
+ }
67
+ }
68
+
69
+ ChoicesEditor.rules = rules
@@ -0,0 +1,103 @@
1
+ /*
2
+
3
+ Edtended handling of oolor type fields.
4
+
5
+ Has optional support for using https://github.com/Sphinxxxx/vanilla-picker.
6
+
7
+ */
8
+ import { StringEditor } from './string.js'
9
+ import { extend } from '../utilities.js'
10
+
11
+ export class ColorEditor extends StringEditor {
12
+ postBuild () {
13
+ if (window.Picker) {
14
+ this.input.type = 'text'
15
+ }
16
+ this.input.style.padding = '3px'
17
+ }
18
+
19
+ setValue (value, initial, fromTemplate) {
20
+ const res = super.setValue(value, initial, fromTemplate)
21
+ if (this.picker_instance && this.picker_instance.domElement && res && res.changed) {
22
+ this.picker_instance.setColor(res.value, true)
23
+ }
24
+ return res
25
+ }
26
+
27
+ getNumColumns () {
28
+ return 2
29
+ }
30
+
31
+ afterInputReady () {
32
+ super.afterInputReady()
33
+ this.createPicker(true)
34
+ }
35
+
36
+ disable () {
37
+ super.disable()
38
+ if (this.picker_instance && this.picker_instance.domElement) {
39
+ /* Disable picker cursor dragging */
40
+ this.picker_instance.domElement.style.pointerEvents = 'none'
41
+ /* Disable picker buttons */
42
+ const buttons = this.picker_instance.domElement.querySelectorAll('button')
43
+ for (let i = 0; i < buttons.length; i++) {
44
+ buttons[i].disabled = true
45
+ }
46
+ }
47
+ }
48
+
49
+ enable () {
50
+ super.enable()
51
+ if (this.picker_instance && this.picker_instance.domElement) {
52
+ /* Enable picker cursor dragging */
53
+ this.picker_instance.domElement.style.pointerEvents = 'auto'
54
+ /* Enable picker buttons */
55
+ const buttons = this.picker_instance.domElement.querySelectorAll('button')
56
+ for (let i = 0; i < buttons.length; i++) {
57
+ buttons[i].disabled = false
58
+ }
59
+ }
60
+ }
61
+
62
+ destroy () {
63
+ this.createPicker(false)
64
+ super.destroy()
65
+ }
66
+
67
+ /* helper functions */
68
+ createPicker (create) {
69
+ if (create) { /* create vanilla-picker */
70
+ if (window.Picker && !this.picker_instance) { /* do when vanilla-picker loaded */
71
+ const options = this.expandCallbacks('colorpicker', extend({}, {
72
+ editor: false, /* default no editor */
73
+ alpha: false, /* default no alpha */
74
+ color: this.value,
75
+ popup: 'bottom' /* show in the bottom */
76
+ }, this.defaults.options.colorpicker || {}, this.options.colorpicker || {}, {
77
+ parent: this.container
78
+ }))
79
+
80
+ const updateHandler = color => {
81
+ const format = this.picker_instance.settings.editorFormat
82
+ const isAlpha = this.picker_instance.settings.alpha
83
+ this.setValue(format === 'hex' ? (isAlpha ? color.hex : color.hex.slice(0, 7)) : color[`${format + (isAlpha ? 'a' : '')}String`])
84
+ }
85
+ if (!options.popup && typeof options.onChange !== 'function') options.onChange = updateHandler
86
+ else if (options.popup && typeof options.onDone !== 'function') options.onDone = updateHandler
87
+
88
+ this.picker_instance = new window.Picker(options)
89
+ /* this.picker_instance.openHandler() */
90
+ if (!options.popup) { /* use inline colorPicker */
91
+ this.input.style.display = 'none'
92
+ this.theme.afterInputReady(this.picker_instance.domElement)
93
+ }
94
+ }
95
+ } else { /* destroy vanilla-picker */
96
+ if (this.picker_instance) {
97
+ this.picker_instance.destroy()
98
+ this.picker_instance = null
99
+ this.input.style.display = ''
100
+ }
101
+ }
102
+ }
103
+ }