@json-editor/json-editor 1.4.0-beta.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (435) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/.env +2 -0
  3. package/.env-dist +2 -0
  4. package/.eslintrc +10 -0
  5. package/.github/PULL_REQUEST_TEMPLATE.md +9 -0
  6. package/.github/workflows/build.yml +70 -0
  7. package/.travis.yml +62 -16
  8. package/CHANGELOG.md +483 -113
  9. package/CONTRIBUTING.md +43 -4
  10. package/Makefile +26 -0
  11. package/README.md +632 -121
  12. package/README_ADDON.md +577 -0
  13. package/UPGRADING.md +46 -0
  14. package/build/CssToJson.js +55 -0
  15. package/codecept.conf.js +35 -0
  16. package/config/.eslintrc +7 -0
  17. package/config/codeceptjs_helpers.js +146 -0
  18. package/config/helpers.js +10 -0
  19. package/config/karma.conf.js +89 -0
  20. package/config/readme.md +31 -0
  21. package/config/webpack.common.js +71 -0
  22. package/config/webpack.dev.js +15 -0
  23. package/config/webpack.nonmin.js +19 -0
  24. package/config/webpack.prod.js +24 -0
  25. package/dist/jsoneditor.js +2 -11550
  26. package/dist/jsoneditor.js.LICENSE.txt +15 -0
  27. package/dist/nonmin/jsoneditor.js +31392 -0
  28. package/dist/nonmin/jsoneditor.js.map +1 -0
  29. package/docs/basic.html +2 -2
  30. package/docs/basic_person.json +2 -1
  31. package/docs/choices.html +86 -0
  32. package/docs/cleave.html +11 -19
  33. package/docs/colorpicker.html +194 -0
  34. package/docs/css_integration.html +56 -54
  35. package/docs/custom-editor.html +92 -0
  36. package/docs/datetime.html +48 -21
  37. package/docs/describedby.html +42 -35
  38. package/docs/enumsource.html +67 -0
  39. package/docs/form-submission.html +162 -0
  40. package/docs/imask.html +192 -0
  41. package/docs/index.html +600 -582
  42. package/docs/materialize_css.html +1 -1
  43. package/docs/meta-schema.html +793 -0
  44. package/docs/meta_schema.json +446 -400
  45. package/docs/polyfills/assign.js +29 -0
  46. package/docs/radio.html +9 -17
  47. package/docs/recursive.html +15 -17
  48. package/docs/scripts/ajv-validator.js +8695 -0
  49. package/docs/select2.html +15 -9
  50. package/docs/selectize.html +11 -9
  51. package/docs/signature.html +12 -11
  52. package/docs/starrating.html +5 -17
  53. package/docs/upload.html +33 -23
  54. package/docs/uuid.html +70 -0
  55. package/docs/wysiwyg.html +14 -7
  56. package/jasmine.json +11 -0
  57. package/package.json +74 -25
  58. package/release-notes.md +90 -0
  59. package/src/core.js +411 -611
  60. package/src/defaults.js +381 -327
  61. package/src/editor.js +733 -544
  62. package/src/editors/ace.js +90 -0
  63. package/src/editors/array/choices.js +104 -0
  64. package/src/editors/array/select2.js +112 -0
  65. package/src/editors/array/selectize.js +107 -130
  66. package/src/editors/array.css +9 -0
  67. package/src/editors/array.css.js +3 -0
  68. package/src/editors/array.js +812 -695
  69. package/src/editors/autocomplete.js +59 -0
  70. package/src/editors/base64.js +148 -129
  71. package/src/editors/button.js +104 -0
  72. package/src/editors/checkbox.js +111 -76
  73. package/src/editors/choices.css +3 -0
  74. package/src/editors/choices.css.js +3 -0
  75. package/src/editors/choices.js +71 -0
  76. package/src/editors/colorpicker.js +105 -0
  77. package/src/editors/datetime.js +93 -79
  78. package/src/editors/describedby.js +141 -125
  79. package/src/editors/enum.js +131 -116
  80. package/src/editors/hidden.js +100 -86
  81. package/src/editors/index.js +81 -0
  82. package/src/editors/info.js +28 -0
  83. package/src/editors/integer.js +21 -8
  84. package/src/editors/ip.js +36 -0
  85. package/src/editors/jodit.js +66 -0
  86. package/src/editors/multiple.js +380 -241
  87. package/src/editors/multiselect.js +207 -207
  88. package/src/editors/null.js +15 -11
  89. package/src/editors/number.js +39 -30
  90. package/src/editors/object.css +41 -0
  91. package/src/editors/object.css.js +3 -0
  92. package/src/editors/object.js +1190 -1068
  93. package/src/editors/radio.js +117 -101
  94. package/src/editors/sceditor.js +74 -0
  95. package/src/editors/select.js +318 -342
  96. package/src/editors/select2.js +112 -0
  97. package/src/editors/selectize.js +89 -338
  98. package/src/editors/signature.js +100 -104
  99. package/src/editors/simplemde.js +103 -0
  100. package/src/{styles → editors}/starrating.css +11 -2
  101. package/src/editors/starrating.css.js +3 -0
  102. package/src/editors/starrating.js +126 -95
  103. package/src/editors/stepper.js +27 -0
  104. package/src/editors/string.js +352 -426
  105. package/src/editors/table.js +486 -410
  106. package/src/editors/upload.js +297 -131
  107. package/src/editors/uuid.js +49 -0
  108. package/src/iconlib.js +22 -27
  109. package/src/iconlibs/bootstrap.js +28 -0
  110. package/src/iconlibs/bootstrap2.js +28 -17
  111. package/src/iconlibs/bootstrap3.js +28 -17
  112. package/src/iconlibs/fontawesome3.js +28 -17
  113. package/src/iconlibs/fontawesome4.js +28 -18
  114. package/src/iconlibs/fontawesome5.js +28 -18
  115. package/src/iconlibs/foundation2.js +24 -17
  116. package/src/iconlibs/foundation3.js +28 -17
  117. package/src/iconlibs/index.js +27 -0
  118. package/src/iconlibs/jqueryui.js +28 -17
  119. package/src/iconlibs/materialicons.js +49 -44
  120. package/src/iconlibs/openiconic.js +28 -0
  121. package/src/iconlibs/spectre.js +28 -0
  122. package/src/resolvers.js +135 -0
  123. package/src/schemaloader.js +639 -0
  124. package/src/style.css +157 -0
  125. package/src/style.css.js +3 -0
  126. package/src/templates/default.js +46 -51
  127. package/src/templates/ejs.js +8 -10
  128. package/src/templates/handlebars.js +1 -3
  129. package/src/templates/hogan.js +7 -9
  130. package/src/templates/index.js +21 -0
  131. package/src/templates/lodash.js +6 -8
  132. package/src/templates/markup.js +6 -8
  133. package/src/templates/mustache.js +6 -8
  134. package/src/templates/swig.js +1 -3
  135. package/src/templates/underscore.js +6 -8
  136. package/src/theme.js +717 -433
  137. package/src/themes/barebones.css +35 -0
  138. package/src/themes/barebones.css.js +3 -0
  139. package/src/themes/barebones.js +31 -0
  140. package/src/themes/bootstrap2.js +302 -265
  141. package/src/themes/bootstrap3.css +53 -0
  142. package/src/themes/bootstrap3.css.js +3 -0
  143. package/src/themes/bootstrap3.js +355 -262
  144. package/src/themes/bootstrap4.css +89 -0
  145. package/src/themes/bootstrap4.css.js +3 -0
  146. package/src/themes/bootstrap4.js +743 -237
  147. package/src/themes/bootstrap5.css +97 -0
  148. package/src/themes/bootstrap5.css.js +3 -0
  149. package/src/themes/bootstrap5.js +687 -0
  150. package/src/themes/foundation.js +535 -472
  151. package/src/themes/html.css +60 -0
  152. package/src/themes/html.css.js +3 -0
  153. package/src/themes/html.js +69 -82
  154. package/src/themes/index.js +29 -0
  155. package/src/themes/jqueryui.js +181 -167
  156. package/src/themes/materialize.js +263 -292
  157. package/src/themes/spectre.css +208 -0
  158. package/src/themes/spectre.css.js +3 -0
  159. package/src/themes/spectre.js +443 -0
  160. package/src/themes/tailwind.css +303 -0
  161. package/src/themes/tailwind.css.js +3 -0
  162. package/src/themes/tailwind.js +469 -0
  163. package/src/utilities.js +127 -68
  164. package/src/validator.js +909 -565
  165. package/src/validators/ip-validator.js +51 -0
  166. package/tests/Dockerfile +3 -0
  167. package/tests/README.md +25 -5
  168. package/tests/codeceptjs/codecept.json +9 -2
  169. package/tests/codeceptjs/constrains/contains_test.js +37 -0
  170. package/tests/codeceptjs/constrains/dependentRequired_test.js +33 -0
  171. package/tests/codeceptjs/constrains/dependentSchemas_test.js +16 -0
  172. package/tests/codeceptjs/constrains/if-then-else_test.js +186 -0
  173. package/tests/codeceptjs/core_test.js +534 -63
  174. package/tests/codeceptjs/editors/advanced_test.js +12 -9
  175. package/tests/codeceptjs/editors/array_any_of_test.js +50 -0
  176. package/tests/codeceptjs/editors/array_test.js +923 -657
  177. package/tests/codeceptjs/editors/autocomplete_test.js +15 -0
  178. package/tests/codeceptjs/editors/button_test.js +50 -0
  179. package/tests/codeceptjs/editors/checkbox_test.js +21 -6
  180. package/tests/codeceptjs/editors/colorpicker_test.js +29 -0
  181. package/tests/codeceptjs/editors/datetime_test.js +33 -0
  182. package/tests/codeceptjs/editors/inheritance_test.js +10 -0
  183. package/tests/codeceptjs/editors/integer_test.js +82 -64
  184. package/tests/codeceptjs/editors/jodit_test.js +23 -0
  185. package/tests/codeceptjs/editors/multiple_test.js +27 -0
  186. package/tests/codeceptjs/editors/multiselect_test.js +6 -7
  187. package/tests/codeceptjs/editors/number_test.js +75 -60
  188. package/tests/codeceptjs/editors/object_test.js +322 -80
  189. package/tests/codeceptjs/editors/option-no_default_values_test.js +42 -0
  190. package/tests/codeceptjs/editors/programmatic-changes_test.js +20 -0
  191. package/tests/codeceptjs/editors/purify_test.js +26 -0
  192. package/tests/codeceptjs/editors/radio_test.js +9 -0
  193. package/tests/codeceptjs/editors/range_test.js +10 -0
  194. package/tests/codeceptjs/editors/rating_test.js +10 -10
  195. package/tests/codeceptjs/editors/select_test.js +47 -18
  196. package/tests/codeceptjs/editors/starrating_test.js +15 -0
  197. package/tests/codeceptjs/editors/stepper_test.js +37 -0
  198. package/tests/codeceptjs/editors/string_test.js +107 -91
  199. package/tests/codeceptjs/editors/table-confirm-delete_test.js +60 -54
  200. package/tests/codeceptjs/editors/tabs_test.js +15 -11
  201. package/tests/codeceptjs/editors/uuid_test.js +48 -0
  202. package/tests/codeceptjs/editors/validation_test.js +13 -9
  203. package/tests/codeceptjs/issues/issue-gh-1133_test.js +9 -0
  204. package/tests/codeceptjs/issues/issue-gh-1158-2_test.js +10 -0
  205. package/tests/codeceptjs/issues/issue-gh-1158_test.js +8 -0
  206. package/tests/codeceptjs/issues/issue-gh-1164_test.js +9 -0
  207. package/tests/codeceptjs/issues/issue-gh-1171_test.js +11 -0
  208. package/tests/codeceptjs/issues/issue-gh-1211_test.js +17 -0
  209. package/tests/codeceptjs/issues/issue-gh-1257_test.js +11 -0
  210. package/tests/codeceptjs/issues/issue-gh-1272_test.js +21 -0
  211. package/tests/codeceptjs/issues/issue-gh-1330_test.js +8 -0
  212. package/tests/codeceptjs/issues/issue-gh-1338_test.js +18 -0
  213. package/tests/codeceptjs/issues/issue-gh-1347_test.js +8 -0
  214. package/tests/codeceptjs/issues/issue-gh-1364_test.js +13 -0
  215. package/tests/codeceptjs/issues/issue-gh-1367_test.js +11 -0
  216. package/tests/codeceptjs/issues/issue-gh-1383_test.js +9 -0
  217. package/tests/codeceptjs/issues/issue-gh-1384_test.js +9 -0
  218. package/tests/codeceptjs/issues/issue-gh-1410_test.js +13 -0
  219. package/tests/codeceptjs/issues/issue-gh-1422_test.js +9 -0
  220. package/tests/codeceptjs/issues/issue-gh-1431_test.js +12 -0
  221. package/tests/codeceptjs/issues/issue-gh-1439_test.js +12 -0
  222. package/tests/codeceptjs/issues/issue-gh-1452_test.js +10 -0
  223. package/tests/codeceptjs/issues/issue-gh-1453_test.js +18 -0
  224. package/tests/codeceptjs/issues/issue-gh-1461_test.js +14 -0
  225. package/tests/codeceptjs/issues/issue-gh-1463_test.js +9 -0
  226. package/tests/codeceptjs/issues/issue-gh-1471_test.js +17 -0
  227. package/tests/codeceptjs/issues/issue-gh-1485_test.js +13 -0
  228. package/tests/codeceptjs/issues/issue-gh-1491_test.js +9 -0
  229. package/tests/codeceptjs/issues/issue-gh-1525_test.js +9 -0
  230. package/tests/codeceptjs/issues/issue-gh-1536_test.js +12 -0
  231. package/tests/codeceptjs/issues/issue-gh-1538_test.js +10 -0
  232. package/tests/codeceptjs/issues/issue-gh-1541_test.js +8 -0
  233. package/tests/codeceptjs/issues/issue-gh-1559_test.js +15 -0
  234. package/tests/codeceptjs/issues/issue-gh-1562_test.js +12 -0
  235. package/tests/codeceptjs/issues/issue-gh-1586_test.js +15 -0
  236. package/tests/codeceptjs/issues/issue-gh-1636_test.js +9 -0
  237. package/tests/codeceptjs/issues/issue-gh-795_test.js +13 -0
  238. package/tests/codeceptjs/issues/issue-gh-810_test.js +52 -0
  239. package/tests/codeceptjs/issues/issue-gh-812_test.js +25 -0
  240. package/tests/codeceptjs/meta-schema_test.js +85 -0
  241. package/tests/codeceptjs/schemaloader_test.js +14 -0
  242. package/tests/codeceptjs/steps.d.ts +13 -0
  243. package/tests/codeceptjs/steps_file.js +4 -4
  244. package/tests/codeceptjs/test-config.js +3 -0
  245. package/tests/codeceptjs/themes_test.js +564 -0
  246. package/tests/docker-compose-local.yml +5 -0
  247. package/tests/docker-compose.yml +11 -19
  248. package/tests/fixtures/basic_person.json +2 -1
  249. package/tests/fixtures/definitions.json +22 -0
  250. package/tests/fixtures/nested_object.json +26 -0
  251. package/tests/fixtures/properties.json +20 -0
  252. package/tests/fixtures/some_types.json +32 -0
  253. package/tests/fixtures/validation.json +1347 -0
  254. package/tests/pages/_demo.html +475 -0
  255. package/tests/pages/advanced.html +1 -1
  256. package/tests/pages/anyof-2.html +91 -0
  257. package/tests/pages/anyof.html +82 -0
  258. package/tests/pages/array-anyof.html +145 -0
  259. package/tests/pages/array-checkboxes-infotext.html +55 -0
  260. package/tests/pages/array-checkboxes.html +5 -2
  261. package/tests/pages/array-choices.html +48 -0
  262. package/tests/pages/array-events-table.html +70 -0
  263. package/tests/pages/array-events.html +75 -0
  264. package/tests/pages/array-header-template.html +60 -0
  265. package/tests/pages/array-integers.html +5 -2
  266. package/tests/pages/array-multiselects.html +5 -2
  267. package/tests/pages/array-nested-arrays.html +5 -2
  268. package/tests/pages/array-numbers.html +5 -2
  269. package/tests/pages/array-objects.html +5 -2
  270. package/tests/pages/array-ratings.html +5 -2
  271. package/tests/pages/array-selectize-create.html +63 -0
  272. package/tests/pages/array-selectize.html +10 -8
  273. package/tests/pages/array-selects.html +5 -2
  274. package/tests/pages/array-strings.html +5 -2
  275. package/tests/pages/array-table-responsive.html +66 -0
  276. package/tests/pages/array-unique-items-sort.html +81 -0
  277. package/tests/pages/array.html +5 -2
  278. package/tests/pages/assets/autocomplete.css +1 -0
  279. package/tests/pages/assets/autocomplete.min.js +1 -0
  280. package/tests/pages/assets/pages.css +130 -0
  281. package/tests/pages/autocomplete.html +72 -0
  282. package/tests/pages/button-callbacks.html +79 -0
  283. package/tests/pages/button-icons.html +39 -0
  284. package/tests/pages/button_state_mode_1.html +35 -0
  285. package/tests/pages/button_state_mode_2.html +36 -0
  286. package/tests/pages/checkbox-labels.html +116 -0
  287. package/tests/pages/colorpicker-no-3rd-party.html +45 -0
  288. package/tests/pages/colorpicker-use-vanilla-picker.html +52 -0
  289. package/tests/pages/container-attributes.html +51 -0
  290. package/tests/pages/contains.html +39 -0
  291. package/tests/pages/core.html +14 -7
  292. package/tests/pages/datetime.html +78 -0
  293. package/tests/pages/dependentRequired.html +72 -0
  294. package/tests/pages/dependentSchemas.html +53 -0
  295. package/tests/pages/disable-button-in-object-editors.html +57 -0
  296. package/tests/pages/editor-show-validation-errors.html +54 -0
  297. package/tests/pages/enforce-const.html +168 -0
  298. package/tests/pages/error-messages.html +48 -0
  299. package/tests/pages/form-name.html +111 -0
  300. package/tests/pages/grid-strict.html +10 -13
  301. package/tests/pages/grid.html +4 -7
  302. package/tests/pages/if-else.html +58 -0
  303. package/tests/pages/if-then-else-allOf.html +118 -0
  304. package/tests/pages/if-then-else-disable-fields.html +70 -0
  305. package/tests/pages/if-then-else.html +65 -0
  306. package/tests/pages/if-then.html +58 -0
  307. package/tests/pages/inheritance.html +80 -0
  308. package/tests/pages/integer.html +17 -10
  309. package/tests/pages/issues/_template.html +50 -0
  310. package/tests/pages/issues/issue-gh-1133.html +64 -0
  311. package/tests/pages/issues/issue-gh-1158-2.html +189 -0
  312. package/tests/pages/issues/issue-gh-1158.html +50 -0
  313. package/tests/pages/issues/issue-gh-1164.html +71 -0
  314. package/tests/pages/issues/issue-gh-1165.html +63 -0
  315. package/tests/pages/issues/issue-gh-1165.json +8 -0
  316. package/tests/pages/issues/issue-gh-1171.html +39 -0
  317. package/tests/pages/issues/issue-gh-1211.html +1022 -0
  318. package/tests/pages/issues/issue-gh-1233-failing.html +46 -0
  319. package/tests/pages/issues/issue-gh-1233-passing.html +49 -0
  320. package/tests/pages/issues/issue-gh-1257.html +77 -0
  321. package/tests/pages/issues/issue-gh-1272.html +167 -0
  322. package/tests/pages/issues/issue-gh-1330.html +52 -0
  323. package/tests/pages/issues/issue-gh-1338.html +74 -0
  324. package/tests/pages/issues/issue-gh-1347.html +142 -0
  325. package/tests/pages/issues/issue-gh-1364.html +64 -0
  326. package/tests/pages/issues/issue-gh-1367.html +49 -0
  327. package/tests/pages/issues/issue-gh-1383.html +31 -0
  328. package/tests/pages/issues/issue-gh-1383.json +14 -0
  329. package/tests/pages/issues/issue-gh-1384.html +31 -0
  330. package/tests/pages/issues/issue-gh-1384.json +36 -0
  331. package/tests/pages/issues/issue-gh-1410.html +57 -0
  332. package/tests/pages/issues/issue-gh-1422.html +68 -0
  333. package/tests/pages/issues/issue-gh-1431.html +49 -0
  334. package/tests/pages/issues/issue-gh-1439.html +69 -0
  335. package/tests/pages/issues/issue-gh-1452.html +98 -0
  336. package/tests/pages/issues/issue-gh-1453.html +45 -0
  337. package/tests/pages/issues/issue-gh-1461.html +55 -0
  338. package/tests/pages/issues/issue-gh-1463.html +41 -0
  339. package/tests/pages/issues/issue-gh-1466.html +63 -0
  340. package/tests/pages/issues/issue-gh-1471.html +49 -0
  341. package/tests/pages/issues/issue-gh-1485.html +59 -0
  342. package/tests/pages/issues/issue-gh-1491.html +59 -0
  343. package/tests/pages/issues/issue-gh-1525.html +62 -0
  344. package/tests/pages/issues/issue-gh-1536.html +55 -0
  345. package/tests/pages/issues/issue-gh-1538.html +56 -0
  346. package/tests/pages/issues/issue-gh-1541.html +51 -0
  347. package/tests/pages/issues/issue-gh-1541.json +9 -0
  348. package/tests/pages/issues/issue-gh-1559.html +68 -0
  349. package/tests/pages/issues/issue-gh-1562.html +170 -0
  350. package/tests/pages/issues/issue-gh-1586.html +48 -0
  351. package/tests/pages/issues/issue-gh-1636.html +52 -0
  352. package/tests/pages/issues/issue-gh-795.html +58 -0
  353. package/tests/pages/issues/issue-gh-810.html +149 -0
  354. package/tests/pages/issues/issue-gh-812.html +113 -0
  355. package/tests/pages/issues/issue-gh-823-meta-schema.html +35 -0
  356. package/tests/pages/issues/issue-gh-848.html +81 -0
  357. package/tests/pages/keep_only_existing_values.html +81 -0
  358. package/tests/pages/load-events.html +61 -0
  359. package/tests/pages/maxContains.html +40 -0
  360. package/tests/pages/meta-schema.html +793 -0
  361. package/tests/pages/meta_schema.json +740 -0
  362. package/tests/pages/minContains.html +40 -0
  363. package/tests/pages/number.html +53 -6
  364. package/tests/pages/object-case-sensitive-property-search-false.html +42 -0
  365. package/tests/pages/object-case-sensitive-property-search-true.html +42 -0
  366. package/tests/pages/object-no-additional-properties.html +68 -0
  367. package/tests/pages/object-no-duplicated-id.html +70 -0
  368. package/tests/pages/object-required-properties.html +56 -20
  369. package/tests/pages/object-show-opt-in.html +111 -0
  370. package/tests/pages/object-with-dependencies-array.html +58 -0
  371. package/tests/pages/object-with-dependencies.html +62 -0
  372. package/tests/pages/object.html +5 -3
  373. package/tests/pages/oneof-2.html +91 -0
  374. package/tests/pages/oneof.html +105 -0
  375. package/tests/pages/opt-in-widget.html +134 -0
  376. package/tests/pages/option-dependencies.html +107 -0
  377. package/tests/pages/option-no_default_values.html +60 -0
  378. package/tests/pages/per-editor-options.html +44 -0
  379. package/tests/pages/placeholder-options.html +57 -0
  380. package/tests/pages/programmatic-changes.html +121 -0
  381. package/tests/pages/prompt-paste-max-length-reached.html +51 -0
  382. package/tests/pages/purify.html +66 -0
  383. package/tests/pages/range.html +62 -0
  384. package/tests/pages/read-only.html +60 -8
  385. package/tests/pages/ready.html +44 -0
  386. package/tests/pages/references.html +168 -0
  387. package/tests/pages/remove-false-properties.html +85 -0
  388. package/tests/pages/select-values.html +91 -0
  389. package/tests/pages/select.html +4 -3
  390. package/tests/pages/show-validation-errors.html +73 -0
  391. package/tests/pages/starrating.html +86 -0
  392. package/tests/pages/stepper-manual.html +59 -0
  393. package/tests/pages/stepper.html +61 -0
  394. package/tests/pages/string-ace-editor.html +7 -3
  395. package/tests/pages/string-cleave.html +48 -0
  396. package/tests/pages/string-custom-attributes.html +9 -6
  397. package/tests/pages/string-formats.html +54 -0
  398. package/tests/pages/string-formats2.html +59 -0
  399. package/tests/pages/{array-move-events.html → string-jodit-editor.html} +21 -29
  400. package/tests/pages/string-sceditor.html +9 -7
  401. package/tests/pages/string-simplemde-editor.html +83 -0
  402. package/tests/pages/switcher-option.html +69 -0
  403. package/tests/pages/table.html +4 -2
  404. package/tests/pages/tabs.html +1 -1
  405. package/tests/pages/themes.html +517 -0
  406. package/tests/pages/title-hidden.html +75 -0
  407. package/tests/pages/translate-property.html +248 -0
  408. package/tests/pages/urn.html +98 -0
  409. package/tests/pages/use-name-attributes.html +207 -0
  410. package/tests/pages/uuid.html +113 -0
  411. package/tests/pages/validation-messages.json +705 -0
  412. package/tests/pages/validation.html +20 -730
  413. package/tests/unit/.eslintrc +8 -0
  414. package/tests/unit/core.spec.js +320 -0
  415. package/tests/unit/defaults.spec.js +40 -0
  416. package/tests/unit/editor.spec.js +172 -0
  417. package/tests/unit/editors/array.spec.js +87 -0
  418. package/tests/unit/editors/object.spec.js +81 -0
  419. package/tests/unit/editors/table.spec.js +93 -0
  420. package/tests/unit/readme.md +35 -0
  421. package/tests/unit/schemaloader.spec.js +576 -0
  422. package/tests/unit/validator.spec.js +104 -0
  423. package/tests/unit/validators/ip-validator.spec.js +62 -0
  424. package/Gruntfile.js +0 -228
  425. package/dist/css/jsoneditor.min.css +0 -1
  426. package/dist/jsoneditor.js.map +0 -1
  427. package/dist/jsoneditor.min.js +0 -19
  428. package/dist/jsoneditor.min.js.map +0 -1
  429. package/src/class.js +0 -68
  430. package/src/editors/rating.js +0 -152
  431. package/src/ie9.js +0 -51
  432. package/src/intro.js +0 -23
  433. package/src/jquery.js +0 -64
  434. package/src/outro.js +0 -2
  435. package/src/themes/jsoneditor.barebones-theme.js +0 -60
package/src/core.js CHANGED
@@ -1,635 +1,435 @@
1
- var JSONEditor = function(element,options) {
2
- if (!(element instanceof Element)) {
3
- throw new Error('element should be an instance of Element');
4
- }
5
- options = $extend({},JSONEditor.defaults.options,options||{});
6
- this.element = element;
7
- this.options = options;
8
- this.init();
9
- };
10
- JSONEditor.prototype = {
11
- // necessary since we remove the ctor property by doing a literal assignment. Without this
12
- // the $isplainobject function will think that this is a plain object.
13
- constructor: JSONEditor,
14
- init: function() {
15
- var self = this;
16
-
17
- this.ready = false;
18
- this.copyClipboard = null;
19
- // full references info
20
- this.refs_with_info = {};
21
- this.refs_prefix = "#/counter/";
22
- this.refs_counter = 1;
23
-
24
- var theme_class = JSONEditor.defaults.themes[this.options.theme || JSONEditor.defaults.theme];
25
- if(!theme_class) throw "Unknown theme " + (this.options.theme || JSONEditor.defaults.theme);
26
-
27
- this.schema = this.options.schema;
28
- this.theme = new theme_class();
29
- this.template = this.options.template;
30
- this.refs = this.options.refs || {};
31
- this.uuid = 0;
32
- this.__data = {};
33
-
34
- var icon_class = JSONEditor.defaults.iconlibs[this.options.iconlib || JSONEditor.defaults.iconlib];
35
- if(icon_class) this.iconlib = new icon_class();
36
-
37
- this.root_container = this.theme.getContainer();
38
- this.element.appendChild(this.root_container);
39
-
40
- this.translate = this.options.translate || JSONEditor.defaults.translate;
41
-
42
- // Fetch all external refs via ajax
43
- var fetchUrl = document.location.toString();
44
- var fileBase = this._getFileBase();
45
- this._loadExternalRefs(this.schema, function() {
46
- self._getDefinitions(self.schema, fetchUrl + '#/definitions/');
47
-
48
- // Validator options
49
- var validator_options = {};
50
- if(self.options.custom_validators) {
51
- validator_options.custom_validators = self.options.custom_validators;
52
- }
53
- self.validator = new JSONEditor.Validator(self,null,validator_options);
54
-
55
- // Create the root editor
56
- var schema = self.expandRefs(self.schema);
57
- var editor_class = self.getEditorClass(schema);
58
- self.root = self.createEditor(editor_class, {
59
- jsoneditor: self,
60
- schema: schema,
61
- required: true,
62
- container: self.root_container
63
- });
64
-
65
- self.root.preBuild();
66
- self.root.build();
67
- self.root.postBuild();
68
-
69
- // Starting data
70
- if(self.options.hasOwnProperty('startval')) self.root.setValue(self.options.startval);
71
-
72
- self.validation_results = self.validator.validate(self.root.getValue());
73
- self.root.showValidationErrors(self.validation_results);
74
- self.ready = true;
75
-
76
- // Fire ready event asynchronously
77
- window.requestAnimationFrame(function() {
78
- if(!self.ready) return;
79
- self.validation_results = self.validator.validate(self.root.getValue());
80
- self.root.showValidationErrors(self.validation_results);
81
- self.trigger('ready');
82
- self.trigger('change');
83
- });
84
- }, fetchUrl, fileBase);
85
- },
86
- getValue: function() {
87
- if(!this.ready) throw "JSON Editor not ready yet. Listen for 'ready' event before getting the value";
88
-
89
- return this.root.getValue();
90
- },
91
- setValue: function(value) {
92
- if(!this.ready) throw "JSON Editor not ready yet. Listen for 'ready' event before setting the value";
93
-
94
- this.root.setValue(value);
95
- return this;
96
- },
97
- validate: function(value) {
98
- if(!this.ready) throw "JSON Editor not ready yet. Listen for 'ready' event before validating";
99
-
100
- // Custom value
101
- if(arguments.length === 1) {
102
- return this.validator.validate(value);
103
- }
104
- // Current value (use cached result)
105
- else {
106
- return this.validation_results;
107
- }
108
- },
109
- destroy: function() {
110
- if(this.destroyed) return;
111
- if(!this.ready) return;
112
-
113
- this.schema = null;
114
- this.options = null;
115
- this.root.destroy();
116
- this.root = null;
117
- this.root_container = null;
118
- this.validator = null;
119
- this.validation_results = null;
120
- this.theme = null;
121
- this.iconlib = null;
122
- this.template = null;
123
- this.__data = null;
124
- this.ready = false;
125
- this.element.innerHTML = '';
126
-
127
- this.destroyed = true;
128
- },
129
- on: function(event, callback) {
130
- this.callbacks = this.callbacks || {};
131
- this.callbacks[event] = this.callbacks[event] || [];
132
- this.callbacks[event].push(callback);
133
-
134
- return this;
135
- },
136
- off: function(event, callback) {
137
- // Specific callback
138
- if(event && callback) {
139
- this.callbacks = this.callbacks || {};
140
- this.callbacks[event] = this.callbacks[event] || [];
141
- var newcallbacks = [];
142
- for(var i=0; i<this.callbacks[event].length; i++) {
143
- if(this.callbacks[event][i]===callback) continue;
144
- newcallbacks.push(this.callbacks[event][i]);
145
- }
146
- this.callbacks[event] = newcallbacks;
147
- }
148
- // All callbacks for a specific event
149
- else if(event) {
150
- this.callbacks = this.callbacks || {};
151
- this.callbacks[event] = [];
152
- }
153
- // All callbacks for all events
154
- else {
155
- this.callbacks = {};
156
- }
157
-
158
- return this;
159
- },
160
- trigger: function(event) {
161
- if(this.callbacks && this.callbacks[event] && this.callbacks[event].length) {
162
- for(var i=0; i<this.callbacks[event].length; i++) {
163
- this.callbacks[event][i].apply(this, []);
164
- }
165
- }
166
-
167
- return this;
168
- },
169
- setOption: function(option, value) {
170
- if(option === "show_errors") {
171
- this.options.show_errors = value;
172
- this.onChange();
173
- }
174
- // Only the `show_errors` option is supported for now
175
- else {
176
- throw "Option "+option+" must be set during instantiation and cannot be changed later";
177
- }
178
-
179
- return this;
180
- },
181
- getEditorClass: function(schema) {
182
- var classname;
183
-
184
- schema = this.expandSchema(schema);
185
-
186
- $each(JSONEditor.defaults.resolvers,function(i,resolver) {
187
- var tmp = resolver(schema);
188
- if(tmp) {
189
- if(JSONEditor.defaults.editors[tmp]) {
190
- classname = tmp;
191
- return false;
192
- }
193
- }
194
- });
195
-
196
- if(!classname) throw "Unknown editor for schema "+JSON.stringify(schema);
197
- if(!JSONEditor.defaults.editors[classname]) throw "Unknown editor "+classname;
198
-
199
- return JSONEditor.defaults.editors[classname];
200
- },
201
- createEditor: function(editor_class, options) {
202
- options = $extend({},editor_class.options||{},options);
203
- return new editor_class(options);
204
- },
205
- onChange: function() {
206
- if(!this.ready) return;
207
-
208
- if(this.firing_change) return;
209
- this.firing_change = true;
210
-
211
- var self = this;
212
-
213
- window.requestAnimationFrame(function() {
214
- self.firing_change = false;
215
- if(!self.ready) return;
216
-
217
- // Validate and cache results
218
- self.validation_results = self.validator.validate(self.root.getValue());
219
-
220
- if(self.options.show_errors !== "never") {
221
- self.root.showValidationErrors(self.validation_results);
222
- }
223
- else {
224
- self.root.showValidationErrors([]);
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
+ this.element.classList.add('je-not-loaded')
35
+ this.element.classList.remove('je-ready')
36
+ // eslint-disable-next-line new-cap
37
+ this.theme = new themeClass(this)
38
+ const rules = extend(styleRules, this.getEditorsRules())
39
+
40
+ /* Call addNewStyleRulesToShadowRoot if shadowRoot is found, otherwise call addNewStyleRules */
41
+ const addRules = (themeName, rules, shadowRoot) => shadowRoot
42
+ ? this.addNewStyleRulesToShadowRoot(themeName, rules, shadowRoot)
43
+ : this.addNewStyleRules(themeName, rules)
44
+
45
+ if (!this.theme.options.disable_theme_rules) {
46
+ /* Attempt to locate a shadowRoot parent (i.e. in Web Components) */
47
+ const shadowRoot = getShadowParent(this.element)
48
+ addRules('default', rules, shadowRoot)
49
+ if (typeof themeClass.rules !== 'undefined') {
50
+ addRules(themeName, themeClass.rules, shadowRoot)
225
51
  }
226
-
227
- // Fire change event
228
- self.trigger('change');
229
- });
230
-
231
- return this;
232
- },
233
- compileTemplate: function(template, name) {
234
- name = name || JSONEditor.defaults.template;
235
-
236
- var engine;
237
-
238
- // Specifying a preset engine
239
- if(typeof name === 'string') {
240
- if(!JSONEditor.defaults.templates[name]) throw "Unknown template engine "+name;
241
- engine = JSONEditor.defaults.templates[name]();
242
-
243
- if(!engine) throw "Template engine "+name+" missing required library.";
244
- }
245
- // Specifying a custom engine
246
- else {
247
- engine = name;
248
52
  }
249
53
 
250
- if(!engine) throw "No template engine set";
251
- if(!engine.compile) throw "Invalid template engine set";
252
-
253
- return engine.compile(template);
254
- },
255
- _data: function(el,key,value) {
256
- // Setting data
257
- if(arguments.length === 3) {
258
- var uuid;
259
- if(el.hasAttribute('data-jsoneditor-'+key)) {
260
- uuid = el.getAttribute('data-jsoneditor-'+key);
261
- }
262
- else {
263
- uuid = this.uuid++;
264
- el.setAttribute('data-jsoneditor-'+key,uuid);
265
- }
54
+ /* Init icon class */
55
+ const iconClass = JSONEditor.defaults.iconlibs[this.options.iconlib || JSONEditor.defaults.iconlib]
56
+ // eslint-disable-next-line new-cap
57
+ if (iconClass) this.iconlib = new iconClass()
266
58
 
267
- this.__data[uuid] = value;
268
- }
269
- // Getting data
270
- else {
271
- // No data stored
272
- if(!el.hasAttribute('data-jsoneditor-'+key)) return null;
273
-
274
- return this.__data[el.getAttribute('data-jsoneditor-'+key)];
275
- }
276
- },
277
- registerEditor: function(editor) {
278
- this.editors = this.editors || {};
279
- this.editors[editor.path] = editor;
280
- return this;
281
- },
282
- unregisterEditor: function(editor) {
283
- this.editors = this.editors || {};
284
- this.editors[editor.path] = null;
285
- return this;
286
- },
287
- getEditor: function(path) {
288
- if(!this.editors) return;
289
- return this.editors[path];
290
- },
291
- watch: function(path,callback) {
292
- this.watchlist = this.watchlist || {};
293
- this.watchlist[path] = this.watchlist[path] || [];
294
- this.watchlist[path].push(callback);
295
-
296
- return this;
297
- },
298
- unwatch: function(path,callback) {
299
- if(!this.watchlist || !this.watchlist[path]) return this;
300
- // If removing all callbacks for a path
301
- if(!callback) {
302
- this.watchlist[path] = null;
303
- return this;
304
- }
305
-
306
- var newlist = [];
307
- for(var i=0; i<this.watchlist[path].length; i++) {
308
- if(this.watchlist[path][i] === callback) continue;
309
- else newlist.push(this.watchlist[path][i]);
59
+ this.root_container = this.theme.getContainer()
60
+ this.element.appendChild(this.root_container)
61
+ this.promise = this.load()
62
+ }
63
+
64
+ async load () {
65
+ const fetchUrl = document.location.origin + document.location.pathname.toString()
66
+ const loader = new SchemaLoader(this.options)
67
+
68
+ loader.onSchemaLoaded = (payload) => {
69
+ this.trigger('schemaLoaded', payload)
310
70
  }
311
- this.watchlist[path] = newlist.length? newlist : null;
312
- return this;
313
- },
314
- notifyWatchers: function(path) {
315
- if(!this.watchlist || !this.watchlist[path]) return this;
316
- for(var i=0; i<this.watchlist[path].length; i++) {
317
- this.watchlist[path][i]();
71
+
72
+ loader.onAllSchemasLoaded = () => {
73
+ this.trigger('allSchemasLoaded')
318
74
  }
319
- },
320
- isEnabled: function() {
321
- return !this.root || this.root.isEnabled();
322
- },
323
- enable: function() {
324
- this.root.enable();
325
- },
326
- disable: function() {
327
- this.root.disable();
328
- },
329
- _getDefinitions: function(schema,path) {
330
- if(schema.definitions) {
331
- for(var i in schema.definitions) {
332
- if(!schema.definitions.hasOwnProperty(i)) continue;
333
- this.refs[path+i] = schema.definitions[i];
334
- if(schema.definitions[i].definitions) {
335
- this._getDefinitions(schema.definitions[i],path+i+'/definitions/');
336
- }
337
- }
75
+
76
+ this.expandSchema = (schema) => loader.expandSchema(schema)
77
+ this.expandRefs = (schema, fileBase) => loader.expandRefs(schema, fileBase)
78
+ const location = document.location.toString()
79
+ const schema = await loader.load(this.schema, fetchUrl, location)
80
+ const validatorOptions = this.options.custom_validators ? { custom_validators: this.options.custom_validators } : {}
81
+ this.validator = new Validator(this, null, validatorOptions, JSONEditor.defaults)
82
+ const editorClass = this.getEditorClass(schema)
83
+ this.root = this.createEditor(editorClass, {
84
+ jsoneditor: this,
85
+ schema,
86
+ required: true,
87
+ container: this.root_container
88
+ })
89
+
90
+ this.root.preBuild()
91
+ this.root.build()
92
+ this.root.postBuild()
93
+
94
+ /* Starting data */
95
+ if (hasOwnProperty(this.options, 'startval')) this.root.setValue(this.options.startval)
96
+
97
+ this.validation_results = this.validator.validate(this.root.getValue())
98
+ this.root.showValidationErrors(this.validation_results)
99
+ this.ready = true
100
+ this.element.classList.remove('je-not-loaded')
101
+ this.element.classList.add('je-ready')
102
+
103
+ /* Fire ready event asynchronously */
104
+ window.requestAnimationFrame(() => {
105
+ if (!this.ready) return
106
+ this.validation_results = this.validator.validate(this.root.getValue())
107
+ this.root.showValidationErrors(this.validation_results)
108
+ this.trigger('ready')
109
+ this.trigger('change')
110
+ })
111
+ }
112
+
113
+ getValue () {
114
+ if (!this.ready) throw new Error('JSON Editor not ready yet. Make sure the load method is complete')
115
+
116
+ return this.root.getValue()
117
+ }
118
+
119
+ setValue (value) {
120
+ if (!this.ready) throw new Error('JSON Editor not ready yet. Make sure the load method is complete')
121
+
122
+ this.root.setValue(value)
123
+ return this
124
+ }
125
+
126
+ validate (value) {
127
+ if (!this.ready) throw new Error('JSON Editor not ready yet. Make sure the load method is complete')
128
+
129
+ /* Custom value */
130
+ if (arguments.length === 1) {
131
+ return this.validator.validate(value)
132
+ /* Current value (use cached result) */
133
+ } else {
134
+ return this.validation_results
338
135
  }
339
- },
340
- _getExternalRefs: function(schema, fetchUrl) {
341
- var refs = {};
342
- var merge_refs = function(newrefs) {
343
- for(var i in newrefs) {
344
- if(newrefs.hasOwnProperty(i)) {
345
- refs[i] = true;
346
- }
347
- }
348
- };
349
-
350
- if(schema.$ref && typeof schema.$ref !== "object") {
351
- var ref_counter = this.refs_prefix + this.refs_counter++;
352
- if(schema.$ref.substr(0,1) !== "#" && !this.refs[schema.$ref]) {
353
- refs[schema.$ref] = true;
136
+ }
137
+
138
+ destroy () {
139
+ if (this.destroyed) return
140
+ if (!this.ready) return
141
+
142
+ this.schema = null
143
+ this.options = null
144
+ this.root.destroy()
145
+ this.root = null
146
+ this.root_container = null
147
+ this.validator = null
148
+ this.validation_results = null
149
+ this.theme = null
150
+ this.iconlib = null
151
+ this.template = null
152
+ this.__data = null
153
+ this.ready = false
154
+ this.element.innerHTML = ''
155
+ this.element.removeAttribute('data-theme')
156
+ this.destroyed = true
157
+ }
158
+
159
+ on (event, callback) {
160
+ this.callbacks = this.callbacks || {}
161
+ this.callbacks[event] = this.callbacks[event] || []
162
+ this.callbacks[event].push(callback)
163
+
164
+ return this
165
+ }
166
+
167
+ off (event, callback) {
168
+ /* Specific callback */
169
+ if (event && callback) {
170
+ this.callbacks = this.callbacks || {}
171
+ this.callbacks[event] = this.callbacks[event] || []
172
+ const newcallbacks = []
173
+ for (let i = 0; i < this.callbacks[event].length; i++) {
174
+ if (this.callbacks[event][i] === callback) continue
175
+ newcallbacks.push(this.callbacks[event][i])
354
176
  }
355
- this.refs_with_info[ref_counter] = { fetchUrl: fetchUrl, "$ref": schema.$ref };
356
- schema.$ref = ref_counter;
177
+ this.callbacks[event] = newcallbacks
178
+ } else if (event) {
179
+ /* All callbacks for a specific event */
180
+ this.callbacks = this.callbacks || {}
181
+ this.callbacks[event] = []
182
+ } else {
183
+ /* All callbacks for all events */
184
+ this.callbacks = {}
357
185
  }
358
-
359
- for(var i in schema) {
360
- if(!schema.hasOwnProperty(i)) continue;
361
- if (!schema[i] || typeof schema[i] !== "object") continue;
362
- if(Array.isArray(schema[i])) {
363
- for(var j=0; j<schema[i].length; j++) {
364
- if(schema[i][j] && typeof schema[i][j]==="object") {
365
- merge_refs(this._getExternalRefs(schema[i][j], fetchUrl));
366
- }
367
- }
368
- }
369
- else {
370
- merge_refs(this._getExternalRefs(schema[i], fetchUrl));
186
+
187
+ return this
188
+ }
189
+
190
+ trigger (event, editor) {
191
+ if (this.callbacks && this.callbacks[event] && this.callbacks[event].length) {
192
+ for (let i = 0; i < this.callbacks[event].length; i++) {
193
+ this.callbacks[event][i].apply(this, [editor])
371
194
  }
372
195
  }
373
- return refs;
374
- },
375
- _getFileBase: function() {
376
- var fileBase = this.options.ajaxBase;
377
- if (typeof fileBase === 'undefined') {
378
- fileBase = this._getFileBaseFromFileLocation(document.location.toString());
379
- }
380
- return fileBase;
381
- },
382
- _getFileBaseFromFileLocation: function(fileLocationString) {
383
- var pathItems = fileLocationString.split("/");
384
- pathItems.pop();
385
- return pathItems.join("/")+"/";
386
- },
387
- _loadExternalRefs: function(schema, callback, fetchUrl, fileBase) {
388
- var self = this;
389
- var refs = this._getExternalRefs(schema, fetchUrl);
390
- var done = 0, waiting = 0, callback_fired = false;
391
-
392
- $each(refs,function(url) {
393
- if(self.refs[url]) return;
394
- if(!self.options.ajax) throw "Must set ajax option to true to load external ref "+url;
395
- self.refs[url] = 'loading';
396
- waiting++;
397
-
398
- var fetchUrl=url;
399
- if( fileBase!=url.substr(0,fileBase.length) && "http"!=url.substr(0,4) && "/"!=url.substr(0,1)) fetchUrl=fileBase+url;
400
-
401
- var r = new XMLHttpRequest();
402
- r.overrideMimeType('application/json');
403
- r.open("GET", fetchUrl, true);
404
- if(self.options.ajaxCredentials) r.withCredentials=self.options.ajaxCredentials;
405
- r.onreadystatechange = function () {
406
- if (r.readyState != 4) return;
407
- // Request succeeded
408
- if(r.status === 200) {
409
- var response;
410
- try {
411
- response = JSON.parse(r.responseText);
412
- }
413
- catch(e) {
414
- window.console.log(e);
415
- throw "Failed to parse external ref "+fetchUrl;
416
- }
417
- if (!(typeof response === "boolean" || typeof response === "object") || response === null || Array.isArray(response)) throw "External ref does not contain a valid schema - "+fetchUrl;
418
-
419
- self.refs[url] = response;
420
- var fileBase = self._getFileBaseFromFileLocation(fetchUrl);
421
- self._getDefinitions(response, fetchUrl + "#/definitions/");
422
- self._loadExternalRefs(response,function() {
423
- done++;
424
- if(done >= waiting && !callback_fired) {
425
- callback_fired = true;
426
- callback();
427
- }
428
- }, fetchUrl, fileBase);
429
- }
430
- // Request failed
431
- else {
432
- window.console.log(r);
433
- throw "Failed to fetch ref via ajax- "+url;
434
- }
435
- };
436
- r.send();
437
- });
438
-
439
- if(!waiting) {
440
- callback();
196
+
197
+ return this
198
+ }
199
+
200
+ setOption (option, value) {
201
+ if (option === 'show_errors') {
202
+ this.options.show_errors = value
203
+ this.onChange()
204
+ } else {
205
+ /* Only the `show_errors` option is supported for now */
206
+ throw new Error(`Option ${option} must be set during instantiation and cannot be changed later`)
441
207
  }
442
- },
443
- expandRefs: function(schema) {
444
- schema = $extend({},schema);
445
-
446
- while (schema.$ref) {
447
- var refObj = this.refs_with_info[schema.$ref];
448
- delete schema.$ref;
449
- var fetchUrl = "";
450
- if (refObj.$ref.startsWith("#")) {
451
- fetchUrl = refObj.fetchUrl;
452
- }
453
- var ref = fetchUrl + refObj.$ref;
454
- if(!this.refs[ref]) ref = fetchUrl + decodeURIComponent(refObj.$ref);
455
- schema = this.extendSchemas(schema, $extend({},this.refs[ref]));
208
+
209
+ return this
210
+ }
211
+
212
+ getEditorsRules () {
213
+ const extendRule = (rules, editorClass) => editorClass.rules ? extend(rules, editorClass.rules) : rules
214
+ return Object.values(JSONEditor.defaults.editors).reduce(extendRule, {})
215
+ }
216
+
217
+ getEditorClass (schema) {
218
+ let classname
219
+
220
+ schema = this.expandSchema(schema)
221
+
222
+ JSONEditor.defaults.resolvers.find(resolver => {
223
+ classname = resolver(schema, this)
224
+ return classname && JSONEditor.defaults.editors[classname]
225
+ })
226
+ if (!classname) throw new Error(`Unknown editor for schema ${JSON.stringify(schema)}`)
227
+ if (!JSONEditor.defaults.editors[classname]) throw new Error(`Unknown editor ${classname}`)
228
+ return JSONEditor.defaults.editors[classname]
229
+ }
230
+
231
+ createEditor (editorClass, options, depthCounter = 1) {
232
+ options = extend({}, editorClass.options || {}, options)
233
+ // eslint-disable-next-line new-cap
234
+ return new editorClass(options, JSONEditor.defaults, depthCounter)
235
+ }
236
+
237
+ onChange (eventData) {
238
+ if (!this.ready) return
239
+
240
+ if (eventData) {
241
+ this.trigger(eventData.event, eventData.data)
456
242
  }
457
- return schema;
458
- },
459
- expandSchema: function(schema, fileBase) {
460
- var self = this;
461
- var extended = $extend({},schema);
462
- var i;
463
-
464
- // Version 3 `type`
465
- if(typeof schema.type === 'object') {
466
- // Array of types
467
- if(Array.isArray(schema.type)) {
468
- $each(schema.type, function(key,value) {
469
- // Schema
470
- if(typeof value === 'object') {
471
- schema.type[key] = self.expandSchema(value);
472
- }
473
- });
474
- }
475
- // Schema
476
- else {
477
- schema.type = self.expandSchema(schema.type);
243
+
244
+ if (this.firing_change) return
245
+ this.firing_change = true
246
+
247
+ window.requestAnimationFrame(() => {
248
+ this.firing_change = false
249
+ if (!this.ready) return
250
+
251
+ /* Validate and cache results */
252
+ this.validation_results = this.validator.validate(this.root.getValue())
253
+
254
+ if (this.options.show_errors !== 'never') {
255
+ this.root.showValidationErrors(this.validation_results)
256
+ } else {
257
+ this.root.showValidationErrors([])
478
258
  }
259
+
260
+ /* Fire change event */
261
+ this.trigger('change')
262
+ })
263
+
264
+ return this
265
+ }
266
+
267
+ compileTemplate (template, name = JSONEditor.defaults.template) {
268
+ let engine
269
+
270
+ /* Specifying a preset engine */
271
+ if (typeof name === 'string') {
272
+ if (!JSONEditor.defaults.templates[name]) throw new Error(`Unknown template engine ${name}`)
273
+ engine = JSONEditor.defaults.templates[name]()
274
+
275
+ if (!engine) throw new Error(`Template engine ${name} missing required library.`)
276
+ } else {
277
+ /* Specifying a custom engine */
278
+ engine = name
479
279
  }
480
- // Version 3 `disallow`
481
- if(typeof schema.disallow === 'object') {
482
- // Array of types
483
- if(Array.isArray(schema.disallow)) {
484
- $each(schema.disallow, function(key,value) {
485
- // Schema
486
- if(typeof value === 'object') {
487
- schema.disallow[key] = self.expandSchema(value);
488
- }
489
- });
490
- }
491
- // Schema
492
- else {
493
- schema.disallow = self.expandSchema(schema.disallow);
280
+
281
+ if (!engine) throw new Error('No template engine set')
282
+ if (!engine.compile) throw new Error('Invalid template engine set')
283
+
284
+ return engine.compile(template)
285
+ }
286
+
287
+ _data (el, key, value) {
288
+ /* Setting data */
289
+ if (arguments.length === 3) {
290
+ let uuid
291
+ if (el.hasAttribute(`data-jsoneditor-${key}`)) {
292
+ uuid = el.getAttribute(`data-jsoneditor-${key}`)
293
+ } else {
294
+ uuid = this.uuid++
295
+ el.setAttribute(`data-jsoneditor-${key}`, uuid)
494
296
  }
297
+
298
+ this.__data[uuid] = value
299
+ } else {
300
+ /* Getting data */
301
+ /* No data stored */
302
+ if (!el.hasAttribute(`data-jsoneditor-${key}`)) return null
303
+
304
+ return this.__data[el.getAttribute(`data-jsoneditor-${key}`)]
495
305
  }
496
- // Version 4 `anyOf`
497
- if(schema.anyOf) {
498
- $each(schema.anyOf, function(key,value) {
499
- schema.anyOf[key] = self.expandSchema(value);
500
- });
501
- }
502
- // Version 4 `dependencies` (schema dependencies)
503
- if(schema.dependencies) {
504
- $each(schema.dependencies,function(key,value) {
505
- if(typeof value === "object" && !(Array.isArray(value))) {
506
- schema.dependencies[key] = self.expandSchema(value);
507
- }
508
- });
306
+ }
307
+
308
+ registerEditor (editor) {
309
+ this.editors = this.editors || {}
310
+ this.editors[editor.path] = editor
311
+ return this
312
+ }
313
+
314
+ unregisterEditor (editor) {
315
+ this.editors = this.editors || {}
316
+ this.editors[editor.path] = null
317
+ return this
318
+ }
319
+
320
+ getEditor (path) {
321
+ if (!this.editors) return
322
+ return this.editors[path]
323
+ }
324
+
325
+ watch (path, callback) {
326
+ this.watchlist = this.watchlist || {}
327
+ this.watchlist[path] = this.watchlist[path] || []
328
+ this.watchlist[path].push(callback)
329
+
330
+ return this
331
+ }
332
+
333
+ unwatch (path, callback) {
334
+ if (!this.watchlist || !this.watchlist[path]) return this
335
+ /* If removing all callbacks for a path */
336
+ if (!callback) {
337
+ this.watchlist[path] = null
338
+ return this
509
339
  }
510
- // Version 4 `not`
511
- if(schema.not) {
512
- schema.not = this.expandSchema(schema.not);
340
+
341
+ const newlist = []
342
+ for (let i = 0; i < this.watchlist[path].length; i++) {
343
+ if (this.watchlist[path][i] === callback) continue
344
+ else newlist.push(this.watchlist[path][i])
513
345
  }
514
-
515
- // allOf schemas should be merged into the parent
516
- if(schema.allOf) {
517
- for(i=0; i<schema.allOf.length; i++) {
518
- extended = this.extendSchemas(extended,this.expandSchema(schema.allOf[i]));
519
- }
520
- delete extended.allOf;
346
+ this.watchlist[path] = newlist.length ? newlist : null
347
+ return this
348
+ }
349
+
350
+ notifyWatchers (path) {
351
+ if (!this.watchlist || !this.watchlist[path]) return this
352
+ for (let i = 0; i < this.watchlist[path].length; i++) {
353
+ this.watchlist[path][i]()
521
354
  }
522
- // extends schemas should be merged into parent
523
- if(schema["extends"]) {
524
- // If extends is a schema
525
- if(!(Array.isArray(schema["extends"]))) {
526
- extended = this.extendSchemas(extended,this.expandSchema(schema["extends"]));
527
- }
528
- // If extends is an array of schemas
529
- else {
530
- for(i=0; i<schema["extends"].length; i++) {
531
- extended = this.extendSchemas(extended,this.expandSchema(schema["extends"][i]));
532
- }
533
- }
534
- delete extended["extends"];
355
+ }
356
+
357
+ isEnabled () {
358
+ return !this.root || this.root.isEnabled()
359
+ }
360
+
361
+ enable () {
362
+ this.root.enable()
363
+ }
364
+
365
+ disable () {
366
+ this.root.disable()
367
+ }
368
+
369
+ setCopyClipboardContents (value) {
370
+ this.copyClipboard = value
371
+ }
372
+
373
+ getCopyClipboardContents () {
374
+ return this.copyClipboard
375
+ }
376
+
377
+ addNewStyleRules (themeName, rules) {
378
+ let styleTag = document.querySelector(`#theme-${themeName}`)
379
+
380
+ if (!styleTag) {
381
+ styleTag = document.createElement('style')
382
+ styleTag.setAttribute('id', `theme-${themeName}`)
383
+ styleTag.appendChild(document.createTextNode(''))
384
+ document.head.appendChild(styleTag)
535
385
  }
536
- // parent should be merged into oneOf schemas
537
- if(schema.oneOf) {
538
- var tmp = $extend({},extended);
539
- delete tmp.oneOf;
540
- for(i=0; i<schema.oneOf.length; i++) {
541
- extended.oneOf[i] = this.extendSchemas(this.expandSchema(schema.oneOf[i]),tmp);
542
- }
386
+
387
+ const sheet = styleTag.sheet ? styleTag.sheet : styleTag.styleSheet
388
+ const qualifier = this.element.nodeName.toLowerCase()
389
+ while (sheet.cssRules.length > 0) {
390
+ sheet.deleteRule(0)
543
391
  }
544
-
545
- return this.expandRefs(extended);
546
- },
547
- extendSchemas: function(obj1, obj2) {
548
- obj1 = $extend({},obj1);
549
- obj2 = $extend({},obj2);
550
-
551
- var self = this;
552
- var extended = {};
553
- $each(obj1, function(prop,val) {
554
- // If this key is also defined in obj2, merge them
555
- if(typeof obj2[prop] !== "undefined") {
556
- // Required and defaultProperties arrays should be unioned together
557
- if((prop === 'required'||prop === 'defaultProperties') && typeof val === "object" && Array.isArray(val)) {
558
- // Union arrays and unique
559
- extended[prop] = val.concat(obj2[prop]).reduce(function(p, c) {
560
- if (p.indexOf(c) < 0) p.push(c);
561
- return p;
562
- }, []);
563
- }
564
- // Type should be intersected and is either an array or string
565
- else if(prop === 'type' && (typeof val === "string" || Array.isArray(val))) {
566
- // Make sure we're dealing with arrays
567
- if(typeof val === "string") val = [val];
568
- if(typeof obj2.type === "string") obj2.type = [obj2.type];
569
-
570
- // If type is only defined in the first schema, keep it
571
- if(!obj2.type || !obj2.type.length) {
572
- extended.type = val;
573
- }
574
- // If type is defined in both schemas, do an intersect
575
- else {
576
- extended.type = val.filter(function(n) {
577
- return obj2.type.indexOf(n) !== -1;
578
- });
579
- }
580
-
581
- // If there's only 1 type and it's a primitive, use a string instead of array
582
- if(extended.type.length === 1 && typeof extended.type[0] === "string") {
583
- extended.type = extended.type[0];
584
- }
585
- // Remove the type property if it's empty
586
- else if(extended.type.length === 0) {
587
- delete extended.type;
588
- }
589
- }
590
- // All other arrays should be intersected (enum, etc.)
591
- else if(typeof val === "object" && Array.isArray(val)){
592
- extended[prop] = val.filter(function(n) {
593
- return obj2[prop].indexOf(n) !== -1;
594
- });
595
- }
596
- // Objects should be recursively merged
597
- else if(typeof val === "object" && val !== null) {
598
- extended[prop] = self.extendSchemas(val,obj2[prop]);
599
- }
600
- // Otherwise, use the first value
601
- else {
602
- extended[prop] = val;
603
- }
604
- }
605
- // Otherwise, just use the one in obj1
606
- else {
607
- extended[prop] = val;
608
- }
609
- });
610
- // Properties in obj2 that aren't in obj1
611
- $each(obj2, function(prop,val) {
612
- if(typeof obj1[prop] === "undefined") {
613
- extended[prop] = val;
392
+ Object.keys(rules).forEach(selector => {
393
+ const sel = themeName === 'default' ? selector : `${qualifier}[data-theme="${themeName}"] ${selector}`
394
+
395
+ // all browsers, except IE before version 9
396
+ if (sheet.insertRule) sheet.insertRule(sel + ' {' + decodeURIComponent(rules[selector]) + '}', 0)
397
+ // Internet Explorer before version 9
398
+ else if (sheet.addRule) sheet.addRule(sel, decodeURIComponent(rules[selector]), 0)
399
+ })
400
+ }
401
+
402
+ addNewStyleRulesToShadowRoot (themeName, rules, shadowRoot) {
403
+ const qualifier = this.element.nodeName.toLowerCase()
404
+ let cssText = ''
405
+
406
+ Object.keys(rules).forEach(selector => {
407
+ const sel = themeName === 'default' ? selector : `${qualifier}[data-theme="${themeName}"] ${selector}`
408
+ cssText += sel + ' {' + decodeURIComponent(rules[selector]) + '}' + '\n'
409
+ })
410
+ const styleSheet = new CSSStyleSheet()
411
+ styleSheet.replaceSync(cssText)
412
+ shadowRoot.adoptedStyleSheets = [...shadowRoot.adoptedStyleSheets, styleSheet]
413
+ }
414
+
415
+ showValidationErrors (errorList) {
416
+ const errors = errorList ?? this.validate()
417
+
418
+ Object.values(this.editors).forEach(editor => {
419
+ if (editor) {
420
+ editor.is_dirty = true
421
+ editor.showValidationErrors(errors)
614
422
  }
615
- });
616
-
617
- return extended;
618
- },
619
- setCopyClipboardContents: function(value) {
620
- this.copyClipboard = value;
621
- },
622
- getCopyClipboardContents: function() {
623
- return this.copyClipboard;
423
+ })
624
424
  }
625
- };
626
-
627
- JSONEditor.defaults = {
628
- themes: {},
629
- templates: {},
630
- iconlibs: {},
631
- editors: {},
632
- languages: {},
633
- resolvers: [],
634
- custom_validators: []
635
- };
425
+ }
426
+
427
+ JSONEditor.defaults = defaults
428
+ JSONEditor.AbstractEditor = AbstractEditor
429
+ JSONEditor.AbstractTheme = AbstractTheme
430
+ JSONEditor.AbstractIconLib = AbstractIconLib
431
+
432
+ Object.assign(JSONEditor.defaults.themes, themes)
433
+ Object.assign(JSONEditor.defaults.editors, editors)
434
+ Object.assign(JSONEditor.defaults.templates, templates)
435
+ Object.assign(JSONEditor.defaults.iconlibs, iconlibs)