@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
package/src/core.js ADDED
@@ -0,0 +1,412 @@
1
+ import { defaults } from './defaults.js'
2
+ import { Validator } from './validator.js'
3
+ import { SchemaLoader } from './schemaloader.js'
4
+ import { editors } from './editors/index.js'
5
+ import { templates } from './templates/index.js'
6
+ import { iconlibs } from './iconlibs/index.js'
7
+ import { themes } from './themes/index.js'
8
+ import { extend, getShadowParent, hasOwnProperty } from './utilities.js'
9
+ import { AbstractEditor } from './editor'
10
+ import { AbstractTheme } from './theme'
11
+ import { AbstractIconLib } from './iconlib'
12
+ import styleRules from './style.css.js'
13
+
14
+ export class JSONEditor {
15
+ constructor (element, options = {}) {
16
+ if (!(element instanceof Element)) throw new Error('element should be an instance of Element')
17
+
18
+ this.element = element
19
+ this.options = extend({}, JSONEditor.defaults.options, options)
20
+ this.ready = false
21
+ this.copyClipboard = null
22
+ this.schema = this.options.schema
23
+ this.template = this.options.template
24
+ this.translate = this.options.translate || JSONEditor.defaults.translate
25
+ this.translateProperty = this.options.translateProperty || JSONEditor.defaults.translateProperty
26
+ this.uuid = 0
27
+ this.__data = {}
28
+ const themeName = this.options.theme || JSONEditor.defaults.theme
29
+ const themeClass = JSONEditor.defaults.themes[themeName]
30
+
31
+ /* Load editors and selected theme style rules */
32
+ if (!themeClass) throw new Error(`Unknown theme ${themeName}`)
33
+ this.element.setAttribute('data-theme', themeName)
34
+ // eslint-disable-next-line new-cap
35
+ this.theme = new themeClass(this)
36
+ const rules = extend(styleRules, this.getEditorsRules())
37
+
38
+ /* Call addNewStyleRulesToShadowRoot if shadowRoot is found, otherwise call addNewStyleRules */
39
+ const addRules = (themeName, rules, shadowRoot) => shadowRoot
40
+ ? this.addNewStyleRulesToShadowRoot(themeName, rules, shadowRoot)
41
+ : this.addNewStyleRules(themeName, rules)
42
+
43
+ if (!this.theme.options.disable_theme_rules) {
44
+ /* Attempt to locate a shadowRoot parent (i.e. in Web Components) */
45
+ const shadowRoot = getShadowParent(this.element)
46
+ addRules('default', rules, shadowRoot)
47
+ if (typeof themeClass.rules !== 'undefined') {
48
+ addRules(themeName, themeClass.rules, shadowRoot)
49
+ }
50
+ }
51
+
52
+ /* Init icon class */
53
+ const iconClass = JSONEditor.defaults.iconlibs[this.options.iconlib || JSONEditor.defaults.iconlib]
54
+ // eslint-disable-next-line new-cap
55
+ if (iconClass) this.iconlib = new iconClass()
56
+
57
+ this.root_container = this.theme.getContainer()
58
+ this.element.appendChild(this.root_container)
59
+
60
+ /* Fetch all external refs via ajax */
61
+ const fetchUrl = document.location.origin + document.location.pathname.toString()
62
+ const loader = new SchemaLoader(this.options)
63
+ const location = document.location.toString()
64
+
65
+ this.expandSchema = (schema, fileBase) => loader.expandSchema(schema, fileBase)
66
+ this.expandRefs = (schema, fileBase) => loader.expandRefs(schema, fileBase)
67
+ this.refs = loader.refs
68
+
69
+ loader.load(this.schema, schema => {
70
+ const validatorOptions = this.options.custom_validators ? { custom_validators: this.options.custom_validators } : {}
71
+
72
+ this.validator = new Validator(this, null, validatorOptions, JSONEditor.defaults)
73
+
74
+ const editorClass = this.getEditorClass(schema)
75
+
76
+ this.root = this.createEditor(editorClass, {
77
+ jsoneditor: this,
78
+ schema,
79
+ required: true,
80
+ container: this.root_container
81
+ })
82
+
83
+ this.root.preBuild()
84
+ this.root.build()
85
+ this.root.postBuild()
86
+
87
+ /* Starting data */
88
+ if (hasOwnProperty(this.options, 'startval')) this.root.setValue(this.options.startval)
89
+
90
+ this.validation_results = this.validator.validate(this.root.getValue())
91
+ this.root.showValidationErrors(this.validation_results)
92
+ this.ready = true
93
+
94
+ /* Fire ready event asynchronously */
95
+ window.requestAnimationFrame(() => {
96
+ if (!this.ready) return
97
+ this.validation_results = this.validator.validate(this.root.getValue())
98
+ this.root.showValidationErrors(this.validation_results)
99
+ this.trigger('ready')
100
+ this.trigger('change')
101
+ })
102
+ }, fetchUrl, location)
103
+ }
104
+
105
+ getValue () {
106
+ if (!this.ready) throw new Error("JSON Editor not ready yet. Listen for 'ready' event before getting the value")
107
+
108
+ return this.root.getValue()
109
+ }
110
+
111
+ setValue (value) {
112
+ if (!this.ready) throw new Error("JSON Editor not ready yet. Listen for 'ready' event before setting the value")
113
+
114
+ this.root.setValue(value)
115
+ return this
116
+ }
117
+
118
+ validate (value) {
119
+ if (!this.ready) throw new Error("JSON Editor not ready yet. Listen for 'ready' event before validating")
120
+
121
+ /* Custom value */
122
+ if (arguments.length === 1) {
123
+ return this.validator.validate(value)
124
+ /* Current value (use cached result) */
125
+ } else {
126
+ return this.validation_results
127
+ }
128
+ }
129
+
130
+ destroy () {
131
+ if (this.destroyed) return
132
+ if (!this.ready) return
133
+
134
+ this.schema = null
135
+ this.options = null
136
+ this.root.destroy()
137
+ this.root = null
138
+ this.root_container = null
139
+ this.validator = null
140
+ this.validation_results = null
141
+ this.theme = null
142
+ this.iconlib = null
143
+ this.template = null
144
+ this.__data = null
145
+ this.ready = false
146
+ this.element.innerHTML = ''
147
+ this.element.removeAttribute('data-theme')
148
+ this.destroyed = true
149
+ }
150
+
151
+ on (event, callback) {
152
+ this.callbacks = this.callbacks || {}
153
+ this.callbacks[event] = this.callbacks[event] || []
154
+ this.callbacks[event].push(callback)
155
+
156
+ return this
157
+ }
158
+
159
+ off (event, callback) {
160
+ /* Specific callback */
161
+ if (event && callback) {
162
+ this.callbacks = this.callbacks || {}
163
+ this.callbacks[event] = this.callbacks[event] || []
164
+ const newcallbacks = []
165
+ for (let i = 0; i < this.callbacks[event].length; i++) {
166
+ if (this.callbacks[event][i] === callback) continue
167
+ newcallbacks.push(this.callbacks[event][i])
168
+ }
169
+ this.callbacks[event] = newcallbacks
170
+ } else if (event) {
171
+ /* All callbacks for a specific event */
172
+ this.callbacks = this.callbacks || {}
173
+ this.callbacks[event] = []
174
+ } else {
175
+ /* All callbacks for all events */
176
+ this.callbacks = {}
177
+ }
178
+
179
+ return this
180
+ }
181
+
182
+ trigger (event, editor) {
183
+ if (this.callbacks && this.callbacks[event] && this.callbacks[event].length) {
184
+ for (let i = 0; i < this.callbacks[event].length; i++) {
185
+ this.callbacks[event][i].apply(this, [editor])
186
+ }
187
+ }
188
+
189
+ return this
190
+ }
191
+
192
+ setOption (option, value) {
193
+ if (option === 'show_errors') {
194
+ this.options.show_errors = value
195
+ this.onChange()
196
+ } else {
197
+ /* Only the `show_errors` option is supported for now */
198
+ throw new Error(`Option ${option} must be set during instantiation and cannot be changed later`)
199
+ }
200
+
201
+ return this
202
+ }
203
+
204
+ getEditorsRules () {
205
+ const extendRule = (rules, editorClass) => editorClass.rules ? extend(rules, editorClass.rules) : rules
206
+ return Object.values(JSONEditor.defaults.editors).reduce(extendRule, {})
207
+ }
208
+
209
+ getEditorClass (schema) {
210
+ let classname
211
+
212
+ schema = this.expandSchema(schema)
213
+
214
+ JSONEditor.defaults.resolvers.find(resolver => {
215
+ classname = resolver(schema)
216
+ return classname && JSONEditor.defaults.editors[classname]
217
+ })
218
+ if (!classname) throw new Error(`Unknown editor for schema ${JSON.stringify(schema)}`)
219
+ if (!JSONEditor.defaults.editors[classname]) throw new Error(`Unknown editor ${classname}`)
220
+ return JSONEditor.defaults.editors[classname]
221
+ }
222
+
223
+ createEditor (editorClass, options, depthCounter = 1) {
224
+ options = extend({}, editorClass.options || {}, options)
225
+ // eslint-disable-next-line new-cap
226
+ return new editorClass(options, JSONEditor.defaults, depthCounter)
227
+ }
228
+
229
+ onChange () {
230
+ if (!this.ready) return
231
+
232
+ if (this.firing_change) return
233
+ this.firing_change = true
234
+
235
+ window.requestAnimationFrame(() => {
236
+ this.firing_change = false
237
+ if (!this.ready) return
238
+
239
+ /* Validate and cache results */
240
+ this.validation_results = this.validator.validate(this.root.getValue())
241
+
242
+ if (this.options.show_errors !== 'never') {
243
+ this.root.showValidationErrors(this.validation_results)
244
+ } else {
245
+ this.root.showValidationErrors([])
246
+ }
247
+
248
+ /* Fire change event */
249
+ this.trigger('change')
250
+ })
251
+
252
+ return this
253
+ }
254
+
255
+ compileTemplate (template, name = JSONEditor.defaults.template) {
256
+ let engine
257
+
258
+ /* Specifying a preset engine */
259
+ if (typeof name === 'string') {
260
+ if (!JSONEditor.defaults.templates[name]) throw new Error(`Unknown template engine ${name}`)
261
+ engine = JSONEditor.defaults.templates[name]()
262
+
263
+ if (!engine) throw new Error(`Template engine ${name} missing required library.`)
264
+ } else {
265
+ /* Specifying a custom engine */
266
+ engine = name
267
+ }
268
+
269
+ if (!engine) throw new Error('No template engine set')
270
+ if (!engine.compile) throw new Error('Invalid template engine set')
271
+
272
+ return engine.compile(template)
273
+ }
274
+
275
+ _data (el, key, value) {
276
+ /* Setting data */
277
+ if (arguments.length === 3) {
278
+ let uuid
279
+ if (el.hasAttribute(`data-jsoneditor-${key}`)) {
280
+ uuid = el.getAttribute(`data-jsoneditor-${key}`)
281
+ } else {
282
+ uuid = this.uuid++
283
+ el.setAttribute(`data-jsoneditor-${key}`, uuid)
284
+ }
285
+
286
+ this.__data[uuid] = value
287
+ } else {
288
+ /* Getting data */
289
+ /* No data stored */
290
+ if (!el.hasAttribute(`data-jsoneditor-${key}`)) return null
291
+
292
+ return this.__data[el.getAttribute(`data-jsoneditor-${key}`)]
293
+ }
294
+ }
295
+
296
+ registerEditor (editor) {
297
+ this.editors = this.editors || {}
298
+ this.editors[editor.path] = editor
299
+ return this
300
+ }
301
+
302
+ unregisterEditor (editor) {
303
+ this.editors = this.editors || {}
304
+ this.editors[editor.path] = null
305
+ return this
306
+ }
307
+
308
+ getEditor (path) {
309
+ if (!this.editors) return
310
+ return this.editors[path]
311
+ }
312
+
313
+ watch (path, callback) {
314
+ this.watchlist = this.watchlist || {}
315
+ this.watchlist[path] = this.watchlist[path] || []
316
+ this.watchlist[path].push(callback)
317
+
318
+ return this
319
+ }
320
+
321
+ unwatch (path, callback) {
322
+ if (!this.watchlist || !this.watchlist[path]) return this
323
+ /* If removing all callbacks for a path */
324
+ if (!callback) {
325
+ this.watchlist[path] = null
326
+ return this
327
+ }
328
+
329
+ const newlist = []
330
+ for (let i = 0; i < this.watchlist[path].length; i++) {
331
+ if (this.watchlist[path][i] === callback) continue
332
+ else newlist.push(this.watchlist[path][i])
333
+ }
334
+ this.watchlist[path] = newlist.length ? newlist : null
335
+ return this
336
+ }
337
+
338
+ notifyWatchers (path) {
339
+ if (!this.watchlist || !this.watchlist[path]) return this
340
+ for (let i = 0; i < this.watchlist[path].length; i++) {
341
+ this.watchlist[path][i]()
342
+ }
343
+ }
344
+
345
+ isEnabled () {
346
+ return !this.root || this.root.isEnabled()
347
+ }
348
+
349
+ enable () {
350
+ this.root.enable()
351
+ }
352
+
353
+ disable () {
354
+ this.root.disable()
355
+ }
356
+
357
+ setCopyClipboardContents (value) {
358
+ this.copyClipboard = value
359
+ }
360
+
361
+ getCopyClipboardContents () {
362
+ return this.copyClipboard
363
+ }
364
+
365
+ addNewStyleRules (themeName, rules) {
366
+ let styleTag = document.querySelector(`#theme-${themeName}`)
367
+
368
+ if (!styleTag) {
369
+ styleTag = document.createElement('style')
370
+ styleTag.setAttribute('id', `theme-${themeName}`)
371
+ styleTag.appendChild(document.createTextNode(''))
372
+ document.head.appendChild(styleTag)
373
+ }
374
+
375
+ const sheet = styleTag.sheet ? styleTag.sheet : styleTag.styleSheet
376
+ const qualifier = this.element.nodeName.toLowerCase()
377
+ while (sheet.cssRules.length > 0) {
378
+ sheet.deleteRule(0)
379
+ }
380
+ Object.keys(rules).forEach(selector => {
381
+ const sel = themeName === 'default' ? selector : `${qualifier}[data-theme="${themeName}"] ${selector}`
382
+
383
+ // all browsers, except IE before version 9
384
+ if (sheet.insertRule) sheet.insertRule(sel + ' {' + decodeURIComponent(rules[selector]) + '}', 0)
385
+ // Internet Explorer before version 9
386
+ else if (sheet.addRule) sheet.addRule(sel, decodeURIComponent(rules[selector]), 0)
387
+ })
388
+ }
389
+
390
+ addNewStyleRulesToShadowRoot (themeName, rules, shadowRoot) {
391
+ const qualifier = this.element.nodeName.toLowerCase()
392
+ let cssText = ''
393
+
394
+ Object.keys(rules).forEach(selector => {
395
+ const sel = themeName === 'default' ? selector : `${qualifier}[data-theme="${themeName}"] ${selector}`
396
+ cssText += sel + ' {' + decodeURIComponent(rules[selector]) + '}' + '\n'
397
+ })
398
+ const styleSheet = new CSSStyleSheet()
399
+ styleSheet.replaceSync(cssText)
400
+ shadowRoot.adoptedStyleSheets = [...shadowRoot.adoptedStyleSheets, styleSheet]
401
+ }
402
+ }
403
+
404
+ JSONEditor.defaults = defaults
405
+ JSONEditor.AbstractEditor = AbstractEditor
406
+ JSONEditor.AbstractTheme = AbstractTheme
407
+ JSONEditor.AbstractIconLib = AbstractIconLib
408
+
409
+ Object.assign(JSONEditor.defaults.themes, themes)
410
+ Object.assign(JSONEditor.defaults.editors, editors)
411
+ Object.assign(JSONEditor.defaults.templates, templates)
412
+ Object.assign(JSONEditor.defaults.iconlibs, iconlibs)