foreman_chef 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/Chef.png +0 -0
  3. data/app/assets/javascripts/foreman_chef/chef_proxy_environment_refresh.js +1 -1
  4. data/app/assets/javascripts/foreman_chef/chef_tab.js +55 -0
  5. data/app/assets/javascripts/jsoneditor.js +7854 -0
  6. data/app/assets/javascripts/jsoneditor.js.map +106 -0
  7. data/app/controllers/foreman_chef/concerns/hosts_controller_rescuer.rb +10 -0
  8. data/app/helpers/foreman_chef/chef_proxy_form.rb +20 -1
  9. data/app/lib/actions/foreman_chef/host/create.rb +9 -7
  10. data/app/lib/actions/foreman_chef/host/destroy.rb +4 -0
  11. data/app/lib/actions/foreman_chef/host/update.rb +38 -0
  12. data/app/lib/actions/foreman_chef/node/update.rb +43 -0
  13. data/app/lib/proxy_api/foreman_chef/chef_proxy.rb +9 -1
  14. data/app/models/foreman_chef/cached_run_list.rb +84 -0
  15. data/app/models/foreman_chef/concerns/host_action_subject.rb +5 -0
  16. data/app/models/foreman_chef/concerns/host_build.rb +12 -1
  17. data/app/models/foreman_chef/concerns/host_extensions.rb +69 -5
  18. data/app/models/foreman_chef/concerns/renderer.rb +1 -1
  19. data/app/models/foreman_chef/concerns/smart_proxy_extensions.rb +7 -0
  20. data/app/models/foreman_chef/fact_name.rb +3 -0
  21. data/app/models/foreman_chef/fact_parser.rb +2 -2
  22. data/app/overrides/add_chef_tab.rb +10 -0
  23. data/app/services/foreman_chef/object_does_not_exist_exception.rb +4 -0
  24. data/app/views/foreman/unattended/snippets/_chef_client_bootstrap.erb +11 -9
  25. data/app/views/foreman_chef/hosts/_chef_tab.html.erb +17 -0
  26. data/db/migrate/20160324151437_create_foreman_chef_cached_run_list.rb +8 -0
  27. data/lib/foreman_chef/engine.rb +5 -9
  28. data/lib/foreman_chef/version.rb +1 -1
  29. metadata +13 -2
@@ -0,0 +1,106 @@
1
+ {
2
+ "version": 3,
3
+ "file": "jsoneditor.js",
4
+ "sources": [
5
+ "src/intro.js",
6
+ "src/class.js",
7
+ "src/ie9.js",
8
+ "src/utilities.js",
9
+ "src/core.js",
10
+ "src/validator.js",
11
+ "src/editor.js",
12
+ "src/editors/null.js",
13
+ "src/editors/string.js",
14
+ "src/editors/number.js",
15
+ "src/editors/integer.js",
16
+ "src/editors/object.js",
17
+ "src/editors/array.js",
18
+ "src/editors/table.js",
19
+ "src/editors/multiple.js",
20
+ "src/editors/enum.js",
21
+ "src/editors/select.js",
22
+ "src/editors/selectize.js",
23
+ "src/editors/multiselect.js",
24
+ "src/editors/base64.js",
25
+ "src/editors/upload.js",
26
+ "src/editors/checkbox.js",
27
+ "src/editors/array/selectize.js",
28
+ "src/theme.js",
29
+ "src/themes/bootstrap2.js",
30
+ "src/themes/bootstrap3.js",
31
+ "src/themes/foundation.js",
32
+ "src/themes/html.js",
33
+ "src/themes/jqueryui.js",
34
+ "src/iconlib.js",
35
+ "src/iconlibs/bootstrap2.js",
36
+ "src/iconlibs/bootstrap3.js",
37
+ "src/iconlibs/fontawesome3.js",
38
+ "src/iconlibs/fontawesome4.js",
39
+ "src/iconlibs/foundation2.js",
40
+ "src/iconlibs/foundation3.js",
41
+ "src/iconlibs/jqueryui.js",
42
+ "src/templates/default.js",
43
+ "src/templates/ejs.js",
44
+ "src/templates/handlebars.js",
45
+ "src/templates/hogan.js",
46
+ "src/templates/markup.js",
47
+ "src/templates/mustache.js",
48
+ "src/templates/swig.js",
49
+ "src/templates/underscore.js",
50
+ "src/defaults.js",
51
+ "src/jquery.js",
52
+ "src/outro.js"
53
+ ],
54
+ "names": [],
55
+ "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACnEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,K;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzkBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9jBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AChcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC9bA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACz2BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5rBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjWA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACzVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC7FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC5VA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACpLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACjFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC3JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC1BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACxDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACdA;AACA;AACA;A;ACFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACVA;AACA;AACA;A;ACFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;ACrTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;AC/DA;AACA;A",
56
+ "sourcesContent": [
57
+ "/*! JSON Editor v0.7.24 - JSON Schema -> HTML Editor\n * By Jeremy Dorn - https://github.com/jdorn/json-editor/\n * Released under the MIT license\n *\n * Date: 2016-02-11\n */\n\n/**\n * See README.md for requirements and usage info\n */\n\n(function() {\n",
58
+ "/*jshint loopfunc: true */\n/* Simple JavaScript Inheritance\n * By John Resig http://ejohn.org/\n * MIT Licensed.\n */\n// Inspired by base2 and Prototype\nvar Class;\n(function(){\n var initializing = false, fnTest = /xyz/.test(function(){window.postMessage(\"xyz\");}) ? /\\b_super\\b/ : /.*/;\n \n // The base Class implementation (does nothing)\n Class = function(){};\n \n // Create a new Class that inherits from this class\n Class.extend = function(prop) {\n var _super = this.prototype;\n \n // Instantiate a base class (but only create the instance,\n // don't run the init constructor)\n initializing = true;\n var prototype = new this();\n initializing = false;\n \n // Copy the properties over onto the new prototype\n for (var name in prop) {\n // Check if we're overwriting an existing function\n prototype[name] = typeof prop[name] == \"function\" &&\n typeof _super[name] == \"function\" && fnTest.test(prop[name]) ?\n (function(name, fn){\n return function() {\n var tmp = this._super;\n \n // Add a new ._super() method that is the same method\n // but on the super-class\n this._super = _super[name];\n \n // The method only need to be bound temporarily, so we\n // remove it when we're done executing\n var ret = fn.apply(this, arguments); \n this._super = tmp;\n \n return ret;\n };\n })(name, prop[name]) :\n prop[name];\n }\n \n // The dummy class constructor\n function Class() {\n // All construction is actually done in the init method\n if ( !initializing && this.init )\n this.init.apply(this, arguments);\n }\n \n // Populate our constructed prototype object\n Class.prototype = prototype;\n \n // Enforce the constructor to be what we expect\n Class.prototype.constructor = Class;\n \n // And make this class extendable\n Class.extend = arguments.callee;\n \n return Class;\n };\n \n return Class;\n})();\n",
59
+ "// CustomEvent constructor polyfill\n// From MDN\n(function () {\n function CustomEvent ( event, params ) {\n params = params || { bubbles: false, cancelable: false, detail: undefined };\n var evt = document.createEvent( 'CustomEvent' );\n evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );\n return evt;\n }\n\n CustomEvent.prototype = window.Event.prototype;\n\n window.CustomEvent = CustomEvent;\n})();\n\n// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel\n// MIT license\n(function() {\n var lastTime = 0;\n var vendors = ['ms', 'moz', 'webkit', 'o'];\n for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {\n window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];\n window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || \n window[vendors[x]+'CancelRequestAnimationFrame'];\n }\n \n if (!window.requestAnimationFrame)\n window.requestAnimationFrame = function(callback, element) {\n var currTime = new Date().getTime();\n var timeToCall = Math.max(0, 16 - (currTime - lastTime));\n var id = window.setTimeout(function() { callback(currTime + timeToCall); }, \n timeToCall);\n lastTime = currTime + timeToCall;\n return id;\n };\n \n if (!window.cancelAnimationFrame)\n window.cancelAnimationFrame = function(id) {\n clearTimeout(id);\n };\n}());\n\n// Array.isArray polyfill\n// From MDN\n(function() {\n\tif(!Array.isArray) {\n\t Array.isArray = function(arg) {\n\t\treturn Object.prototype.toString.call(arg) === '[object Array]';\n\t };\n\t}\n}());",
60
+ "/**\n * Taken from jQuery 2.1.3\n *\n * @param obj\n * @returns {boolean}\n */\nvar $isplainobject = function( obj ) {\n // Not plain objects:\n // - Any object or value whose internal [[Class]] property is not \"[object Object]\"\n // - DOM nodes\n // - window\n if (typeof obj !== \"object\" || obj.nodeType || (obj !== null && obj === obj.window)) {\n return false;\n }\n\n if (obj.constructor && !Object.prototype.hasOwnProperty.call(obj.constructor.prototype, \"isPrototypeOf\")) {\n return false;\n }\n\n // If the function hasn't returned already, we're confident that\n // |obj| is a plain object, created by {} or constructed with new Object\n return true;\n};\n\nvar $extend = function(destination) {\n var source, i,property;\n for(i=1; i<arguments.length; i++) {\n source = arguments[i];\n for (property in source) {\n if(!source.hasOwnProperty(property)) continue;\n if(source[property] && $isplainobject(source[property])) {\n if(!destination.hasOwnProperty(property)) destination[property] = {};\n $extend(destination[property], source[property]);\n }\n else {\n destination[property] = source[property];\n }\n }\n }\n return destination;\n};\n\nvar $each = function(obj,callback) {\n if(!obj || typeof obj !== \"object\") return;\n var i;\n if(Array.isArray(obj) || (typeof obj.length === 'number' && obj.length > 0 && (obj.length - 1) in obj)) {\n for(i=0; i<obj.length; i++) {\n if(callback(i,obj[i])===false) return;\n }\n }\n else {\n if (Object.keys) {\n var keys = Object.keys(obj);\n for(i=0; i<keys.length; i++) {\n if(callback(keys[i],obj[keys[i]])===false) return;\n }\n }\n else {\n for(i in obj) {\n if(!obj.hasOwnProperty(i)) continue;\n if(callback(i,obj[i])===false) return;\n }\n }\n }\n};\n\nvar $trigger = function(el,event) {\n var e = document.createEvent('HTMLEvents');\n e.initEvent(event, true, true);\n el.dispatchEvent(e);\n};\nvar $triggerc = function(el,event) {\n var e = new CustomEvent(event,{\n bubbles: true,\n cancelable: true\n });\n\n el.dispatchEvent(e);\n};\n",
61
+ "var JSONEditor = function(element,options) {\n if (!(element instanceof Element)) {\n throw new Error('element should be an instance of Element');\n }\n options = $extend({},JSONEditor.defaults.options,options||{});\n this.element = element;\n this.options = options;\n this.init();\n};\nJSONEditor.prototype = {\n // necessary since we remove the ctor property by doing a literal assignment. Without this\n // the $isplainobject function will think that this is a plain object.\n constructor: JSONEditor,\n init: function() {\n var self = this;\n \n this.ready = false;\n\n var theme_class = JSONEditor.defaults.themes[this.options.theme || JSONEditor.defaults.theme];\n if(!theme_class) throw \"Unknown theme \" + (this.options.theme || JSONEditor.defaults.theme);\n \n this.schema = this.options.schema;\n this.theme = new theme_class();\n this.template = this.options.template;\n this.refs = this.options.refs || {};\n this.uuid = 0;\n this.__data = {};\n \n var icon_class = JSONEditor.defaults.iconlibs[this.options.iconlib || JSONEditor.defaults.iconlib];\n if(icon_class) this.iconlib = new icon_class();\n\n this.root_container = this.theme.getContainer();\n this.element.appendChild(this.root_container);\n \n this.translate = this.options.translate || JSONEditor.defaults.translate;\n\n // Fetch all external refs via ajax\n this._loadExternalRefs(this.schema, function() {\n self._getDefinitions(self.schema);\n \n // Validator options\n var validator_options = {};\n if(self.options.custom_validators) {\n validator_options.custom_validators = self.options.custom_validators;\n }\n self.validator = new JSONEditor.Validator(self,null,validator_options);\n \n // Create the root editor\n var editor_class = self.getEditorClass(self.schema);\n self.root = self.createEditor(editor_class, {\n jsoneditor: self,\n schema: self.schema,\n required: true,\n container: self.root_container\n });\n \n self.root.preBuild();\n self.root.build();\n self.root.postBuild();\n\n // Starting data\n if(self.options.startval) self.root.setValue(self.options.startval);\n\n self.validation_results = self.validator.validate(self.root.getValue());\n self.root.showValidationErrors(self.validation_results);\n self.ready = true;\n\n // Fire ready event asynchronously\n window.requestAnimationFrame(function() {\n if(!self.ready) return;\n self.validation_results = self.validator.validate(self.root.getValue());\n self.root.showValidationErrors(self.validation_results);\n self.trigger('ready');\n self.trigger('change');\n });\n });\n },\n getValue: function() {\n if(!this.ready) throw \"JSON Editor not ready yet. Listen for 'ready' event before getting the value\";\n\n return this.root.getValue();\n },\n setValue: function(value) {\n if(!this.ready) throw \"JSON Editor not ready yet. Listen for 'ready' event before setting the value\";\n\n this.root.setValue(value);\n return this;\n },\n validate: function(value) {\n if(!this.ready) throw \"JSON Editor not ready yet. Listen for 'ready' event before validating\";\n \n // Custom value\n if(arguments.length === 1) {\n return this.validator.validate(value);\n }\n // Current value (use cached result)\n else {\n return this.validation_results;\n }\n },\n destroy: function() {\n if(this.destroyed) return;\n if(!this.ready) return;\n \n this.schema = null;\n this.options = null;\n this.root.destroy();\n this.root = null;\n this.root_container = null;\n this.validator = null;\n this.validation_results = null;\n this.theme = null;\n this.iconlib = null;\n this.template = null;\n this.__data = null;\n this.ready = false;\n this.element.innerHTML = '';\n \n this.destroyed = true;\n },\n on: function(event, callback) {\n this.callbacks = this.callbacks || {};\n this.callbacks[event] = this.callbacks[event] || [];\n this.callbacks[event].push(callback);\n \n return this;\n },\n off: function(event, callback) {\n // Specific callback\n if(event && callback) {\n this.callbacks = this.callbacks || {};\n this.callbacks[event] = this.callbacks[event] || [];\n var newcallbacks = [];\n for(var i=0; i<this.callbacks[event].length; i++) {\n if(this.callbacks[event][i]===callback) continue;\n newcallbacks.push(this.callbacks[event][i]);\n }\n this.callbacks[event] = newcallbacks;\n }\n // All callbacks for a specific event\n else if(event) {\n this.callbacks = this.callbacks || {};\n this.callbacks[event] = [];\n }\n // All callbacks for all events\n else {\n this.callbacks = {};\n }\n \n return this;\n },\n trigger: function(event) {\n if(this.callbacks && this.callbacks[event] && this.callbacks[event].length) {\n for(var i=0; i<this.callbacks[event].length; i++) {\n this.callbacks[event][i]();\n }\n }\n \n return this;\n },\n setOption: function(option, value) {\n if(option === \"show_errors\") {\n this.options.show_errors = value;\n this.onChange();\n }\n // Only the `show_errors` option is supported for now\n else {\n throw \"Option \"+option+\" must be set during instantiation and cannot be changed later\";\n }\n \n return this;\n },\n getEditorClass: function(schema) {\n var classname;\n\n schema = this.expandSchema(schema);\n\n $each(JSONEditor.defaults.resolvers,function(i,resolver) {\n var tmp = resolver(schema);\n if(tmp) {\n if(JSONEditor.defaults.editors[tmp]) {\n classname = tmp;\n return false;\n }\n }\n });\n\n if(!classname) throw \"Unknown editor for schema \"+JSON.stringify(schema);\n if(!JSONEditor.defaults.editors[classname]) throw \"Unknown editor \"+classname;\n\n return JSONEditor.defaults.editors[classname];\n },\n createEditor: function(editor_class, options) {\n options = $extend({},editor_class.options||{},options);\n return new editor_class(options);\n },\n onChange: function() {\n if(!this.ready) return;\n \n if(this.firing_change) return;\n this.firing_change = true;\n \n var self = this;\n \n window.requestAnimationFrame(function() {\n self.firing_change = false;\n if(!self.ready) return;\n\n // Validate and cache results\n self.validation_results = self.validator.validate(self.root.getValue());\n \n if(self.options.show_errors !== \"never\") {\n self.root.showValidationErrors(self.validation_results);\n }\n else {\n self.root.showValidationErrors([]);\n }\n \n // Fire change event\n self.trigger('change');\n });\n \n return this;\n },\n compileTemplate: function(template, name) {\n name = name || JSONEditor.defaults.template;\n\n var engine;\n\n // Specifying a preset engine\n if(typeof name === 'string') {\n if(!JSONEditor.defaults.templates[name]) throw \"Unknown template engine \"+name;\n engine = JSONEditor.defaults.templates[name]();\n\n if(!engine) throw \"Template engine \"+name+\" missing required library.\";\n }\n // Specifying a custom engine\n else {\n engine = name;\n }\n\n if(!engine) throw \"No template engine set\";\n if(!engine.compile) throw \"Invalid template engine set\";\n\n return engine.compile(template);\n },\n _data: function(el,key,value) {\n // Setting data\n if(arguments.length === 3) {\n var uuid;\n if(el.hasAttribute('data-jsoneditor-'+key)) {\n uuid = el.getAttribute('data-jsoneditor-'+key);\n }\n else {\n uuid = this.uuid++;\n el.setAttribute('data-jsoneditor-'+key,uuid);\n }\n\n this.__data[uuid] = value;\n }\n // Getting data\n else {\n // No data stored\n if(!el.hasAttribute('data-jsoneditor-'+key)) return null;\n \n return this.__data[el.getAttribute('data-jsoneditor-'+key)];\n }\n },\n registerEditor: function(editor) {\n this.editors = this.editors || {};\n this.editors[editor.path] = editor;\n return this;\n },\n unregisterEditor: function(editor) {\n this.editors = this.editors || {};\n this.editors[editor.path] = null;\n return this;\n },\n getEditor: function(path) {\n if(!this.editors) return;\n return this.editors[path];\n },\n watch: function(path,callback) {\n this.watchlist = this.watchlist || {};\n this.watchlist[path] = this.watchlist[path] || [];\n this.watchlist[path].push(callback);\n \n return this;\n },\n unwatch: function(path,callback) {\n if(!this.watchlist || !this.watchlist[path]) return this;\n // If removing all callbacks for a path\n if(!callback) {\n this.watchlist[path] = null;\n return this;\n }\n \n var newlist = [];\n for(var i=0; i<this.watchlist[path].length; i++) {\n if(this.watchlist[path][i] === callback) continue;\n else newlist.push(this.watchlist[path][i]);\n }\n this.watchlist[path] = newlist.length? newlist : null;\n return this;\n },\n notifyWatchers: function(path) {\n if(!this.watchlist || !this.watchlist[path]) return this;\n for(var i=0; i<this.watchlist[path].length; i++) {\n this.watchlist[path][i]();\n }\n },\n isEnabled: function() {\n return !this.root || this.root.isEnabled();\n },\n enable: function() {\n this.root.enable();\n },\n disable: function() {\n this.root.disable();\n },\n _getDefinitions: function(schema,path) {\n path = path || '#/definitions/';\n if(schema.definitions) {\n for(var i in schema.definitions) {\n if(!schema.definitions.hasOwnProperty(i)) continue;\n this.refs[path+i] = schema.definitions[i];\n if(schema.definitions[i].definitions) {\n this._getDefinitions(schema.definitions[i],path+i+'/definitions/');\n }\n }\n }\n },\n _getExternalRefs: function(schema) {\n var refs = {};\n var merge_refs = function(newrefs) {\n for(var i in newrefs) {\n if(newrefs.hasOwnProperty(i)) {\n refs[i] = true;\n }\n }\n };\n \n if(schema.$ref && typeof schema.$ref !== \"object\" && schema.$ref.substr(0,1) !== \"#\" && !this.refs[schema.$ref]) {\n refs[schema.$ref] = true;\n }\n \n for(var i in schema) {\n if(!schema.hasOwnProperty(i)) continue;\n if(schema[i] && typeof schema[i] === \"object\" && Array.isArray(schema[i])) {\n for(var j=0; j<schema[i].length; j++) {\n if(typeof schema[i][j]===\"object\") {\n merge_refs(this._getExternalRefs(schema[i][j]));\n }\n }\n }\n else if(schema[i] && typeof schema[i] === \"object\") {\n merge_refs(this._getExternalRefs(schema[i]));\n }\n }\n \n return refs;\n },\n _loadExternalRefs: function(schema, callback) {\n var self = this;\n var refs = this._getExternalRefs(schema);\n \n var done = 0, waiting = 0, callback_fired = false;\n \n $each(refs,function(url) {\n if(self.refs[url]) return;\n if(!self.options.ajax) throw \"Must set ajax option to true to load external ref \"+url;\n self.refs[url] = 'loading';\n waiting++;\n\n var r = new XMLHttpRequest(); \n r.open(\"GET\", url, true);\n r.onreadystatechange = function () {\n if (r.readyState != 4) return; \n // Request succeeded\n if(r.status === 200) {\n var response;\n try {\n response = JSON.parse(r.responseText);\n }\n catch(e) {\n window.console.log(e);\n throw \"Failed to parse external ref \"+url;\n }\n if(!response || typeof response !== \"object\") throw \"External ref does not contain a valid schema - \"+url;\n \n self.refs[url] = response;\n self._loadExternalRefs(response,function() {\n done++;\n if(done >= waiting && !callback_fired) {\n callback_fired = true;\n callback();\n }\n });\n }\n // Request failed\n else {\n window.console.log(r);\n throw \"Failed to fetch ref via ajax- \"+url;\n }\n };\n r.send();\n });\n \n if(!waiting) {\n callback();\n }\n },\n expandRefs: function(schema) {\n schema = $extend({},schema);\n \n while (schema.$ref) {\n var ref = schema.$ref;\n delete schema.$ref;\n \n if(!this.refs[ref]) ref = decodeURIComponent(ref);\n \n schema = this.extendSchemas(schema,this.refs[ref]);\n }\n return schema;\n },\n expandSchema: function(schema) {\n var self = this;\n var extended = $extend({},schema);\n var i;\n\n // Version 3 `type`\n if(typeof schema.type === 'object') {\n // Array of types\n if(Array.isArray(schema.type)) {\n $each(schema.type, function(key,value) {\n // Schema\n if(typeof value === 'object') {\n schema.type[key] = self.expandSchema(value);\n }\n });\n }\n // Schema\n else {\n schema.type = self.expandSchema(schema.type);\n }\n }\n // Version 3 `disallow`\n if(typeof schema.disallow === 'object') {\n // Array of types\n if(Array.isArray(schema.disallow)) {\n $each(schema.disallow, function(key,value) {\n // Schema\n if(typeof value === 'object') {\n schema.disallow[key] = self.expandSchema(value);\n }\n });\n }\n // Schema\n else {\n schema.disallow = self.expandSchema(schema.disallow);\n }\n }\n // Version 4 `anyOf`\n if(schema.anyOf) {\n $each(schema.anyOf, function(key,value) {\n schema.anyOf[key] = self.expandSchema(value);\n });\n }\n // Version 4 `dependencies` (schema dependencies)\n if(schema.dependencies) {\n $each(schema.dependencies,function(key,value) {\n if(typeof value === \"object\" && !(Array.isArray(value))) {\n schema.dependencies[key] = self.expandSchema(value);\n }\n });\n }\n // Version 4 `not`\n if(schema.not) {\n schema.not = this.expandSchema(schema.not);\n }\n \n // allOf schemas should be merged into the parent\n if(schema.allOf) {\n for(i=0; i<schema.allOf.length; i++) {\n extended = this.extendSchemas(extended,this.expandSchema(schema.allOf[i]));\n }\n delete extended.allOf;\n }\n // extends schemas should be merged into parent\n if(schema[\"extends\"]) {\n // If extends is a schema\n if(!(Array.isArray(schema[\"extends\"]))) {\n extended = this.extendSchemas(extended,this.expandSchema(schema[\"extends\"]));\n }\n // If extends is an array of schemas\n else {\n for(i=0; i<schema[\"extends\"].length; i++) {\n extended = this.extendSchemas(extended,this.expandSchema(schema[\"extends\"][i]));\n }\n }\n delete extended[\"extends\"];\n }\n // parent should be merged into oneOf schemas\n if(schema.oneOf) {\n var tmp = $extend({},extended);\n delete tmp.oneOf;\n for(i=0; i<schema.oneOf.length; i++) {\n extended.oneOf[i] = this.extendSchemas(this.expandSchema(schema.oneOf[i]),tmp);\n }\n }\n \n return this.expandRefs(extended);\n },\n extendSchemas: function(obj1, obj2) {\n obj1 = $extend({},obj1);\n obj2 = $extend({},obj2);\n\n var self = this;\n var extended = {};\n $each(obj1, function(prop,val) {\n // If this key is also defined in obj2, merge them\n if(typeof obj2[prop] !== \"undefined\") {\n // Required arrays should be unioned together\n if(prop === 'required' && typeof val === \"object\" && Array.isArray(val)) {\n // Union arrays and unique\n extended.required = val.concat(obj2[prop]).reduce(function(p, c) {\n if (p.indexOf(c) < 0) p.push(c);\n return p;\n }, []);\n }\n // Type should be intersected and is either an array or string\n else if(prop === 'type' && (typeof val === \"string\" || Array.isArray(val))) {\n // Make sure we're dealing with arrays\n if(typeof val === \"string\") val = [val];\n if(typeof obj2.type === \"string\") obj2.type = [obj2.type];\n\n\n extended.type = val.filter(function(n) {\n return obj2.type.indexOf(n) !== -1;\n });\n\n // If there's only 1 type and it's a primitive, use a string instead of array\n if(extended.type.length === 1 && typeof extended.type[0] === \"string\") {\n extended.type = extended.type[0];\n }\n }\n // All other arrays should be intersected (enum, etc.)\n else if(typeof val === \"object\" && Array.isArray(val)){\n extended[prop] = val.filter(function(n) {\n return obj2[prop].indexOf(n) !== -1;\n });\n }\n // Objects should be recursively merged\n else if(typeof val === \"object\" && val !== null) {\n extended[prop] = self.extendSchemas(val,obj2[prop]);\n }\n // Otherwise, use the first value\n else {\n extended[prop] = val;\n }\n }\n // Otherwise, just use the one in obj1\n else {\n extended[prop] = val;\n }\n });\n // Properties in obj2 that aren't in obj1\n $each(obj2, function(prop,val) {\n if(typeof obj1[prop] === \"undefined\") {\n extended[prop] = val;\n }\n });\n\n return extended;\n }\n};\n\nJSONEditor.defaults = {\n themes: {},\n templates: {},\n iconlibs: {},\n editors: {},\n languages: {},\n resolvers: [],\n custom_validators: []\n};\n",
62
+ "JSONEditor.Validator = Class.extend({\n init: function(jsoneditor,schema,options) {\n this.jsoneditor = jsoneditor;\n this.schema = schema || this.jsoneditor.schema;\n this.options = options || {};\n this.translate = this.jsoneditor.translate || JSONEditor.defaults.translate;\n },\n validate: function(value) {\n return this._validateSchema(this.schema, value);\n },\n _validateSchema: function(schema,value,path) {\n var self = this;\n var errors = [];\n var valid, i, j;\n var stringified = JSON.stringify(value);\n\n path = path || 'root';\n\n // Work on a copy of the schema\n schema = $extend({},this.jsoneditor.expandRefs(schema));\n\n /*\n * Type Agnostic Validation\n */\n\n // Version 3 `required`\n if(schema.required && schema.required === true) {\n if(typeof value === \"undefined\") {\n errors.push({\n path: path,\n property: 'required',\n message: this.translate(\"error_notset\")\n });\n\n // Can't do any more validation at this point\n return errors;\n }\n }\n // Value not defined\n else if(typeof value === \"undefined\") {\n // If required_by_default is set, all fields are required\n if(this.jsoneditor.options.required_by_default) {\n errors.push({\n path: path,\n property: 'required',\n message: this.translate(\"error_notset\")\n });\n }\n // Not required, no further validation needed\n else {\n return errors;\n }\n }\n\n // `enum`\n if(schema[\"enum\"]) {\n valid = false;\n for(i=0; i<schema[\"enum\"].length; i++) {\n if(stringified === JSON.stringify(schema[\"enum\"][i])) valid = true;\n }\n if(!valid) {\n errors.push({\n path: path,\n property: 'enum',\n message: this.translate(\"error_enum\")\n });\n }\n }\n\n // `extends` (version 3)\n if(schema[\"extends\"]) {\n for(i=0; i<schema[\"extends\"].length; i++) {\n errors = errors.concat(this._validateSchema(schema[\"extends\"][i],value,path));\n }\n }\n\n // `allOf`\n if(schema.allOf) {\n for(i=0; i<schema.allOf.length; i++) {\n errors = errors.concat(this._validateSchema(schema.allOf[i],value,path));\n }\n }\n\n // `anyOf`\n if(schema.anyOf) {\n valid = false;\n for(i=0; i<schema.anyOf.length; i++) {\n if(!this._validateSchema(schema.anyOf[i],value,path).length) {\n valid = true;\n break;\n }\n }\n if(!valid) {\n errors.push({\n path: path,\n property: 'anyOf',\n message: this.translate('error_anyOf')\n });\n }\n }\n\n // `oneOf`\n if(schema.oneOf) {\n valid = 0;\n var oneof_errors = [];\n for(i=0; i<schema.oneOf.length; i++) {\n // Set the error paths to be path.oneOf[i].rest.of.path\n var tmp = this._validateSchema(schema.oneOf[i],value,path);\n if(!tmp.length) {\n valid++;\n }\n\n for(j=0; j<tmp.length; j++) {\n tmp[j].path = path+'.oneOf['+i+']'+tmp[j].path.substr(path.length);\n }\n oneof_errors = oneof_errors.concat(tmp);\n\n }\n if(valid !== 1) {\n errors.push({\n path: path,\n property: 'oneOf',\n message: this.translate('error_oneOf', [valid])\n });\n errors = errors.concat(oneof_errors);\n }\n }\n\n // `not`\n if(schema.not) {\n if(!this._validateSchema(schema.not,value,path).length) {\n errors.push({\n path: path,\n property: 'not',\n message: this.translate('error_not')\n });\n }\n }\n\n // `type` (both Version 3 and Version 4 support)\n if(schema.type) {\n // Union type\n if(Array.isArray(schema.type)) {\n valid = false;\n for(i=0;i<schema.type.length;i++) {\n if(this._checkType(schema.type[i], value)) {\n valid = true;\n break;\n }\n }\n if(!valid) {\n errors.push({\n path: path,\n property: 'type',\n message: this.translate('error_type_union')\n });\n }\n }\n // Simple type\n else {\n if(!this._checkType(schema.type, value)) {\n errors.push({\n path: path,\n property: 'type',\n message: this.translate('error_type', [schema.type])\n });\n }\n }\n }\n\n\n // `disallow` (version 3)\n if(schema.disallow) {\n // Union type\n if(Array.isArray(schema.disallow)) {\n valid = true;\n for(i=0;i<schema.disallow.length;i++) {\n if(this._checkType(schema.disallow[i], value)) {\n valid = false;\n break;\n }\n }\n if(!valid) {\n errors.push({\n path: path,\n property: 'disallow',\n message: this.translate('error_disallow_union')\n });\n }\n }\n // Simple type\n else {\n if(this._checkType(schema.disallow, value)) {\n errors.push({\n path: path,\n property: 'disallow',\n message: this.translate('error_disallow', [schema.disallow])\n });\n }\n }\n }\n\n /*\n * Type Specific Validation\n */\n\n // Number Specific Validation\n if(typeof value === \"number\") {\n // `multipleOf` and `divisibleBy`\n if(schema.multipleOf || schema.divisibleBy) {\n var divisor = schema.multipleOf || schema.divisibleBy;\n // Vanilla JS, prone to floating point rounding errors (e.g. 1.14 / .01 == 113.99999)\n valid = (value/divisor === Math.floor(value/divisor));\n\n // Use math.js is available\n if(window.math) {\n valid = window.math.mod(window.math.bignumber(value), window.math.bignumber(divisor)).equals(0);\n }\n // Use decimal.js is available\n else if(window.Decimal) {\n valid = (new window.Decimal(value)).mod(new window.Decimal(divisor)).equals(0);\n }\n\n if(!valid) {\n errors.push({\n path: path,\n property: schema.multipleOf? 'multipleOf' : 'divisibleBy',\n message: this.translate('error_multipleOf', [divisor])\n });\n }\n }\n\n // `maximum`\n if(schema.hasOwnProperty('maximum')) {\n // Vanilla JS, prone to floating point rounding errors (e.g. .999999999999999 == 1)\n valid = schema.exclusiveMaximum? (value < schema.maximum) : (value <= schema.maximum);\n\n // Use math.js is available\n if(window.math) {\n valid = window.math[schema.exclusiveMaximum?'smaller':'smallerEq'](\n window.math.bignumber(value),\n window.math.bignumber(schema.maximum)\n );\n }\n // Use Decimal.js if available\n else if(window.Decimal) {\n valid = (new window.Decimal(value))[schema.exclusiveMaximum?'lt':'lte'](new window.Decimal(schema.maximum));\n }\n\n if(!valid) {\n errors.push({\n path: path,\n property: 'maximum',\n message: this.translate(\n (schema.exclusiveMaximum?'error_maximum_excl':'error_maximum_incl'),\n [schema.maximum]\n )\n });\n }\n }\n\n // `minimum`\n if(schema.hasOwnProperty('minimum')) {\n // Vanilla JS, prone to floating point rounding errors (e.g. .999999999999999 == 1)\n valid = schema.exclusiveMinimum? (value > schema.minimum) : (value >= schema.minimum);\n\n // Use math.js is available\n if(window.math) {\n valid = window.math[schema.exclusiveMinimum?'larger':'largerEq'](\n window.math.bignumber(value),\n window.math.bignumber(schema.minimum)\n );\n }\n // Use Decimal.js if available\n else if(window.Decimal) {\n valid = (new window.Decimal(value))[schema.exclusiveMinimum?'gt':'gte'](new window.Decimal(schema.minimum));\n }\n\n if(!valid) {\n errors.push({\n path: path,\n property: 'minimum',\n message: this.translate(\n (schema.exclusiveMinimum?'error_minimum_excl':'error_minimum_incl'),\n [schema.minimum]\n )\n });\n }\n }\n }\n // String specific validation\n else if(typeof value === \"string\") {\n // `maxLength`\n if(schema.maxLength) {\n if((value+\"\").length > schema.maxLength) {\n errors.push({\n path: path,\n property: 'maxLength',\n message: this.translate('error_maxLength', [schema.maxLength])\n });\n }\n }\n\n // `minLength`\n if(schema.minLength) {\n if((value+\"\").length < schema.minLength) {\n errors.push({\n path: path,\n property: 'minLength',\n message: this.translate((schema.minLength===1?'error_notempty':'error_minLength'), [schema.minLength])\n });\n }\n }\n\n // `pattern`\n if(schema.pattern) {\n if(!(new RegExp(schema.pattern)).test(value)) {\n errors.push({\n path: path,\n property: 'pattern',\n message: this.translate('error_pattern', [schema.pattern])\n });\n }\n }\n }\n // Array specific validation\n else if(typeof value === \"object\" && value !== null && Array.isArray(value)) {\n // `items` and `additionalItems`\n if(schema.items) {\n // `items` is an array\n if(Array.isArray(schema.items)) {\n for(i=0; i<value.length; i++) {\n // If this item has a specific schema tied to it\n // Validate against it\n if(schema.items[i]) {\n errors = errors.concat(this._validateSchema(schema.items[i],value[i],path+'.'+i));\n }\n // If all additional items are allowed\n else if(schema.additionalItems === true) {\n break;\n }\n // If additional items is a schema\n // TODO: Incompatibility between version 3 and 4 of the spec\n else if(schema.additionalItems) {\n errors = errors.concat(this._validateSchema(schema.additionalItems,value[i],path+'.'+i));\n }\n // If no additional items are allowed\n else if(schema.additionalItems === false) {\n errors.push({\n path: path,\n property: 'additionalItems',\n message: this.translate('error_additionalItems')\n });\n break;\n }\n // Default for `additionalItems` is an empty schema\n else {\n break;\n }\n }\n }\n // `items` is a schema\n else {\n // Each item in the array must validate against the schema\n for(i=0; i<value.length; i++) {\n errors = errors.concat(this._validateSchema(schema.items,value[i],path+'.'+i));\n }\n }\n }\n\n // `maxItems`\n if(schema.maxItems) {\n if(value.length > schema.maxItems) {\n errors.push({\n path: path,\n property: 'maxItems',\n message: this.translate('error_maxItems', [schema.maxItems])\n });\n }\n }\n\n // `minItems`\n if(schema.minItems) {\n if(value.length < schema.minItems) {\n errors.push({\n path: path,\n property: 'minItems',\n message: this.translate('error_minItems', [schema.minItems])\n });\n }\n }\n\n // `uniqueItems`\n if(schema.uniqueItems) {\n var seen = {};\n for(i=0; i<value.length; i++) {\n valid = JSON.stringify(value[i]);\n if(seen[valid]) {\n errors.push({\n path: path,\n property: 'uniqueItems',\n message: this.translate('error_uniqueItems')\n });\n break;\n }\n seen[valid] = true;\n }\n }\n }\n // Object specific validation\n else if(typeof value === \"object\" && value !== null) {\n // `maxProperties`\n if(schema.maxProperties) {\n valid = 0;\n for(i in value) {\n if(!value.hasOwnProperty(i)) continue;\n valid++;\n }\n if(valid > schema.maxProperties) {\n errors.push({\n path: path,\n property: 'maxProperties',\n message: this.translate('error_maxProperties', [schema.maxProperties])\n });\n }\n }\n\n // `minProperties`\n if(schema.minProperties) {\n valid = 0;\n for(i in value) {\n if(!value.hasOwnProperty(i)) continue;\n valid++;\n }\n if(valid < schema.minProperties) {\n errors.push({\n path: path,\n property: 'minProperties',\n message: this.translate('error_minProperties', [schema.minProperties])\n });\n }\n }\n\n // Version 4 `required`\n if(schema.required && Array.isArray(schema.required)) {\n for(i=0; i<schema.required.length; i++) {\n if(typeof value[schema.required[i]] === \"undefined\") {\n errors.push({\n path: path,\n property: 'required',\n message: this.translate('error_required', [schema.required[i]])\n });\n }\n }\n }\n\n // `properties`\n var validated_properties = {};\n if(schema.properties) {\n for(i in schema.properties) {\n if(!schema.properties.hasOwnProperty(i)) continue;\n validated_properties[i] = true;\n errors = errors.concat(this._validateSchema(schema.properties[i],value[i],path+'.'+i));\n }\n }\n\n // `patternProperties`\n if(schema.patternProperties) {\n for(i in schema.patternProperties) {\n if(!schema.patternProperties.hasOwnProperty(i)) continue;\n\n var regex = new RegExp(i);\n\n // Check which properties match\n for(j in value) {\n if(!value.hasOwnProperty(j)) continue;\n if(regex.test(j)) {\n validated_properties[j] = true;\n errors = errors.concat(this._validateSchema(schema.patternProperties[i],value[j],path+'.'+j));\n }\n }\n }\n }\n\n // The no_additional_properties option currently doesn't work with extended schemas that use oneOf or anyOf\n if(typeof schema.additionalProperties === \"undefined\" && this.jsoneditor.options.no_additional_properties && !schema.oneOf && !schema.anyOf) {\n schema.additionalProperties = false;\n }\n\n // `additionalProperties`\n if(typeof schema.additionalProperties !== \"undefined\") {\n for(i in value) {\n if(!value.hasOwnProperty(i)) continue;\n if(!validated_properties[i]) {\n // No extra properties allowed\n if(!schema.additionalProperties) {\n errors.push({\n path: path,\n property: 'additionalProperties',\n message: this.translate('error_additional_properties', [i])\n });\n break;\n }\n // Allowed\n else if(schema.additionalProperties === true) {\n break;\n }\n // Must match schema\n // TODO: incompatibility between version 3 and 4 of the spec\n else {\n errors = errors.concat(this._validateSchema(schema.additionalProperties,value[i],path+'.'+i));\n }\n }\n }\n }\n\n // `dependencies`\n if(schema.dependencies) {\n for(i in schema.dependencies) {\n if(!schema.dependencies.hasOwnProperty(i)) continue;\n\n // Doesn't need to meet the dependency\n if(typeof value[i] === \"undefined\") continue;\n\n // Property dependency\n if(Array.isArray(schema.dependencies[i])) {\n for(j=0; j<schema.dependencies[i].length; j++) {\n if(typeof value[schema.dependencies[i][j]] === \"undefined\") {\n errors.push({\n path: path,\n property: 'dependencies',\n message: this.translate('error_dependency', [schema.dependencies[i][j]])\n });\n }\n }\n }\n // Schema dependency\n else {\n errors = errors.concat(this._validateSchema(schema.dependencies[i],value,path));\n }\n }\n }\n }\n\n // Custom type validation (global)\n $each(JSONEditor.defaults.custom_validators,function(i,validator) {\n errors = errors.concat(validator.call(self,schema,value,path));\n });\n // Custom type validation (instance specific)\n if(this.options.custom_validators) {\n $each(this.options.custom_validators,function(i,validator) {\n errors = errors.concat(validator.call(self,schema,value,path));\n });\n }\n\n return errors;\n },\n _checkType: function(type, value) {\n // Simple types\n if(typeof type === \"string\") {\n if(type===\"string\") return typeof value === \"string\";\n else if(type===\"number\") return typeof value === \"number\";\n else if(type===\"integer\") return typeof value === \"number\" && value === Math.floor(value);\n else if(type===\"boolean\") return typeof value === \"boolean\";\n else if(type===\"array\") return Array.isArray(value);\n else if(type === \"object\") return value !== null && !(Array.isArray(value)) && typeof value === \"object\";\n else if(type === \"null\") return value === null;\n else return true;\n }\n // Schema\n else {\n return !this._validateSchema(type,value).length;\n }\n }\n});\n",
63
+ "/**\n * All editors should extend from this class\n */\nJSONEditor.AbstractEditor = Class.extend({\n onChildEditorChange: function(editor) {\n this.onChange(true);\n },\n notify: function() {\n this.jsoneditor.notifyWatchers(this.path);\n },\n change: function() {\n if(this.parent) this.parent.onChildEditorChange(this);\n else this.jsoneditor.onChange();\n },\n onChange: function(bubble) {\n this.notify();\n if(this.watch_listener) this.watch_listener();\n if(bubble) this.change();\n },\n register: function() {\n this.jsoneditor.registerEditor(this);\n this.onChange();\n },\n unregister: function() {\n if(!this.jsoneditor) return;\n this.jsoneditor.unregisterEditor(this);\n },\n getNumColumns: function() {\n return 12;\n },\n init: function(options) {\n this.jsoneditor = options.jsoneditor;\n \n this.theme = this.jsoneditor.theme;\n this.template_engine = this.jsoneditor.template;\n this.iconlib = this.jsoneditor.iconlib;\n \n this.translate = this.jsoneditor.translate || JSONEditor.defaults.translate;\n\n this.original_schema = options.schema;\n this.schema = this.jsoneditor.expandSchema(this.original_schema);\n \n this.options = $extend({}, (this.options || {}), (options.schema.options || {}), options);\n \n if(!options.path && !this.schema.id) this.schema.id = 'root';\n this.path = options.path || 'root';\n this.formname = options.formname || this.path.replace(/\\.([^.]+)/g,'[$1]');\n if(this.jsoneditor.options.form_name_root) this.formname = this.formname.replace(/^root\\[/,this.jsoneditor.options.form_name_root+'[');\n this.key = this.path.split('.').pop();\n this.parent = options.parent;\n \n this.link_watchers = [];\n \n if(options.container) this.setContainer(options.container);\n },\n setContainer: function(container) {\n this.container = container;\n if(this.schema.id) this.container.setAttribute('data-schemaid',this.schema.id);\n if(this.schema.type && typeof this.schema.type === \"string\") this.container.setAttribute('data-schematype',this.schema.type);\n this.container.setAttribute('data-schemapath',this.path);\n },\n \n preBuild: function() {\n\n },\n build: function() {\n \n },\n postBuild: function() {\n this.setupWatchListeners();\n this.addLinks();\n this.setValue(this.getDefault(), true);\n this.updateHeaderText();\n this.register();\n this.onWatchedFieldChange();\n },\n \n setupWatchListeners: function() {\n var self = this;\n \n // Watched fields\n this.watched = {};\n if(this.schema.vars) this.schema.watch = this.schema.vars;\n this.watched_values = {};\n this.watch_listener = function() {\n if(self.refreshWatchedFieldValues()) {\n self.onWatchedFieldChange();\n }\n };\n \n this.register();\n if(this.schema.hasOwnProperty('watch')) {\n var path,path_parts,first,root,adjusted_path;\n\n for(var name in this.schema.watch) {\n if(!this.schema.watch.hasOwnProperty(name)) continue;\n path = this.schema.watch[name];\n\n if(Array.isArray(path)) {\n path_parts = [path[0]].concat(path[1].split('.'));\n }\n else {\n path_parts = path.split('.');\n if(!self.theme.closest(self.container,'[data-schemaid=\"'+path_parts[0]+'\"]')) path_parts.unshift('#');\n }\n first = path_parts.shift();\n\n if(first === '#') first = self.jsoneditor.schema.id || 'root';\n\n // Find the root node for this template variable\n root = self.theme.closest(self.container,'[data-schemaid=\"'+first+'\"]');\n if(!root) throw \"Could not find ancestor node with id \"+first;\n\n // Keep track of the root node and path for use when rendering the template\n adjusted_path = root.getAttribute('data-schemapath') + '.' + path_parts.join('.');\n \n self.jsoneditor.watch(adjusted_path,self.watch_listener);\n \n self.watched[name] = adjusted_path;\n }\n }\n \n // Dynamic header\n if(this.schema.headerTemplate) {\n this.header_template = this.jsoneditor.compileTemplate(this.schema.headerTemplate, this.template_engine);\n }\n },\n \n addLinks: function() {\n // Add links\n if(!this.no_link_holder) {\n this.link_holder = this.theme.getLinksHolder();\n this.container.appendChild(this.link_holder);\n if(this.schema.links) {\n for(var i=0; i<this.schema.links.length; i++) {\n this.addLink(this.getLink(this.schema.links[i]));\n }\n }\n }\n },\n \n \n getButton: function(text, icon, title) {\n var btnClass = 'json-editor-btn-'+icon;\n if(!this.iconlib) icon = null;\n else icon = this.iconlib.getIcon(icon);\n \n if(!icon && title) {\n text = title;\n title = null;\n }\n \n var btn = this.theme.getButton(text, icon, title);\n btn.className += ' ' + btnClass + ' ';\n return btn;\n },\n setButtonText: function(button, text, icon, title) {\n if(!this.iconlib) icon = null;\n else icon = this.iconlib.getIcon(icon);\n \n if(!icon && title) {\n text = title;\n title = null;\n }\n \n return this.theme.setButtonText(button, text, icon, title);\n },\n addLink: function(link) {\n if(this.link_holder) this.link_holder.appendChild(link);\n },\n getLink: function(data) {\n var holder, link;\n \n // Get mime type of the link\n var mime = data.mediaType || 'application/javascript';\n var type = mime.split('/')[0];\n \n // Template to generate the link href\n var href = this.jsoneditor.compileTemplate(data.href,this.template_engine);\n \n // Image links\n if(type === 'image') {\n holder = this.theme.getBlockLinkHolder();\n link = document.createElement('a');\n link.setAttribute('target','_blank');\n var image = document.createElement('img');\n \n this.theme.createImageLink(holder,link,image);\n \n // When a watched field changes, update the url \n this.link_watchers.push(function(vars) {\n var url = href(vars);\n link.setAttribute('href',url);\n link.setAttribute('title',data.rel || url);\n image.setAttribute('src',url);\n });\n }\n // Audio/Video links\n else if(['audio','video'].indexOf(type) >=0) {\n holder = this.theme.getBlockLinkHolder();\n \n link = this.theme.getBlockLink();\n link.setAttribute('target','_blank');\n \n var media = document.createElement(type);\n media.setAttribute('controls','controls');\n \n this.theme.createMediaLink(holder,link,media);\n \n // When a watched field changes, update the url \n this.link_watchers.push(function(vars) {\n var url = href(vars);\n link.setAttribute('href',url);\n link.textContent = data.rel || url;\n media.setAttribute('src',url);\n });\n }\n // Text links\n else {\n holder = this.theme.getBlockLink();\n holder.setAttribute('target','_blank');\n holder.textContent = data.rel;\n \n // When a watched field changes, update the url \n this.link_watchers.push(function(vars) {\n var url = href(vars);\n holder.setAttribute('href',url);\n holder.textContent = data.rel || url;\n });\n }\n \n return holder;\n },\n refreshWatchedFieldValues: function() {\n if(!this.watched_values) return;\n var watched = {};\n var changed = false;\n var self = this;\n \n if(this.watched) {\n var val,editor;\n for(var name in this.watched) {\n if(!this.watched.hasOwnProperty(name)) continue;\n editor = self.jsoneditor.getEditor(this.watched[name]);\n val = editor? editor.getValue() : null;\n if(self.watched_values[name] !== val) changed = true;\n watched[name] = val;\n }\n }\n \n watched.self = this.getValue();\n if(this.watched_values.self !== watched.self) changed = true;\n \n this.watched_values = watched;\n \n return changed;\n },\n getWatchedFieldValues: function() {\n return this.watched_values;\n },\n updateHeaderText: function() {\n if(this.header) {\n // If the header has children, only update the text node's value\n if(this.header.children.length) {\n for(var i=0; i<this.header.childNodes.length; i++) {\n if(this.header.childNodes[i].nodeType===3) {\n this.header.childNodes[i].nodeValue = this.getHeaderText();\n break;\n }\n }\n }\n // Otherwise, just update the entire node\n else {\n this.header.textContent = this.getHeaderText();\n }\n }\n },\n getHeaderText: function(title_only) {\n if(this.header_text) return this.header_text;\n else if(title_only) return this.schema.title;\n else return this.getTitle();\n },\n onWatchedFieldChange: function() {\n var vars;\n if(this.header_template) { \n vars = $extend(this.getWatchedFieldValues(),{\n key: this.key,\n i: this.key,\n i0: (this.key*1),\n i1: (this.key*1+1),\n title: this.getTitle()\n });\n var header_text = this.header_template(vars);\n \n if(header_text !== this.header_text) {\n this.header_text = header_text;\n this.updateHeaderText();\n this.notify();\n //this.fireChangeHeaderEvent();\n }\n }\n if(this.link_watchers.length) {\n vars = this.getWatchedFieldValues();\n for(var i=0; i<this.link_watchers.length; i++) {\n this.link_watchers[i](vars);\n }\n }\n },\n setValue: function(value) {\n this.value = value;\n },\n getValue: function() {\n return this.value;\n },\n refreshValue: function() {\n\n },\n getChildEditors: function() {\n return false;\n },\n destroy: function() {\n var self = this;\n this.unregister(this);\n $each(this.watched,function(name,adjusted_path) {\n self.jsoneditor.unwatch(adjusted_path,self.watch_listener);\n });\n this.watched = null;\n this.watched_values = null;\n this.watch_listener = null;\n this.header_text = null;\n this.header_template = null;\n this.value = null;\n if(this.container && this.container.parentNode) this.container.parentNode.removeChild(this.container);\n this.container = null;\n this.jsoneditor = null;\n this.schema = null;\n this.path = null;\n this.key = null;\n this.parent = null;\n },\n getDefault: function() {\n if(this.schema[\"default\"]) return this.schema[\"default\"];\n if(this.schema[\"enum\"]) return this.schema[\"enum\"][0];\n \n var type = this.schema.type || this.schema.oneOf;\n if(type && Array.isArray(type)) type = type[0];\n if(type && typeof type === \"object\") type = type.type;\n if(type && Array.isArray(type)) type = type[0];\n \n if(typeof type === \"string\") {\n if(type === \"number\") return 0.0;\n if(type === \"boolean\") return false;\n if(type === \"integer\") return 0;\n if(type === \"string\") return \"\";\n if(type === \"object\") return {};\n if(type === \"array\") return [];\n }\n \n return null;\n },\n getTitle: function() {\n return this.schema.title || this.key;\n },\n enable: function() {\n this.disabled = false;\n },\n disable: function() {\n this.disabled = true;\n },\n isEnabled: function() {\n return !this.disabled;\n },\n isRequired: function() {\n if(typeof this.schema.required === \"boolean\") return this.schema.required;\n else if(this.parent && this.parent.schema && Array.isArray(this.parent.schema.required)) return this.parent.schema.required.indexOf(this.key) > -1;\n else if(this.jsoneditor.options.required_by_default) return true;\n else return false;\n }, \n getDisplayText: function(arr) {\n var disp = [];\n var used = {};\n \n // Determine how many times each attribute name is used.\n // This helps us pick the most distinct display text for the schemas.\n $each(arr,function(i,el) {\n if(el.title) {\n used[el.title] = used[el.title] || 0;\n used[el.title]++;\n }\n if(el.description) {\n used[el.description] = used[el.description] || 0;\n used[el.description]++;\n }\n if(el.format) {\n used[el.format] = used[el.format] || 0;\n used[el.format]++;\n }\n if(el.type) {\n used[el.type] = used[el.type] || 0;\n used[el.type]++;\n }\n });\n \n // Determine display text for each element of the array\n $each(arr,function(i,el) {\n var name;\n \n // If it's a simple string\n if(typeof el === \"string\") name = el;\n // Object\n else if(el.title && used[el.title]<=1) name = el.title;\n else if(el.format && used[el.format]<=1) name = el.format;\n else if(el.type && used[el.type]<=1) name = el.type;\n else if(el.description && used[el.description]<=1) name = el.descripton;\n else if(el.title) name = el.title;\n else if(el.format) name = el.format;\n else if(el.type) name = el.type;\n else if(el.description) name = el.description;\n else if(JSON.stringify(el).length < 50) name = JSON.stringify(el);\n else name = \"type\";\n \n disp.push(name);\n });\n \n // Replace identical display text with \"text 1\", \"text 2\", etc.\n var inc = {};\n $each(disp,function(i,name) {\n inc[name] = inc[name] || 0;\n inc[name]++;\n \n if(used[name] > 1) disp[i] = name + \" \" + inc[name];\n });\n \n return disp;\n },\n getOption: function(key) {\n try {\n throw \"getOption is deprecated\";\n }\n catch(e) {\n window.console.error(e);\n }\n \n return this.options[key];\n },\n showValidationErrors: function(errors) {\n\n }\n});\n",
64
+ "JSONEditor.defaults.editors[\"null\"] = JSONEditor.AbstractEditor.extend({\n getValue: function() {\n return null;\n },\n setValue: function() {\n this.onChange();\n },\n getNumColumns: function() {\n return 2;\n }\n});\n",
65
+ "JSONEditor.defaults.editors.string = JSONEditor.AbstractEditor.extend({\n register: function() {\n this._super();\n if(!this.input) return;\n this.input.setAttribute('name',this.formname);\n },\n unregister: function() {\n this._super();\n if(!this.input) return;\n this.input.removeAttribute('name');\n },\n setValue: function(value,initial,from_template) {\n var self = this;\n \n if(this.template && !from_template) {\n return;\n }\n \n if(value === null || typeof value === 'undefined') value = \"\";\n else if(typeof value === \"object\") value = JSON.stringify(value);\n else if(typeof value !== \"string\") value = \"\"+value;\n \n if(value === this.serialized) return;\n\n // Sanitize value before setting it\n var sanitized = this.sanitize(value);\n\n if(this.input.value === sanitized) {\n return;\n }\n\n this.input.value = sanitized;\n \n // If using SCEditor, update the WYSIWYG\n if(this.sceditor_instance) {\n this.sceditor_instance.val(sanitized);\n }\n else if(this.epiceditor) {\n this.epiceditor.importFile(null,sanitized);\n }\n else if(this.ace_editor) {\n this.ace_editor.setValue(sanitized);\n }\n \n var changed = from_template || this.getValue() !== value;\n \n this.refreshValue();\n \n if(initial) this.is_dirty = false;\n else if(this.jsoneditor.options.show_errors === \"change\") this.is_dirty = true;\n \n if(this.adjust_height) this.adjust_height(this.input);\n\n // Bubble this setValue to parents if the value changed\n this.onChange(changed);\n },\n getNumColumns: function() {\n var min = Math.ceil(Math.max(this.getTitle().length,this.schema.maxLength||0,this.schema.minLength||0)/5);\n var num;\n \n if(this.input_type === 'textarea') num = 6;\n else if(['text','email'].indexOf(this.input_type) >= 0) num = 4;\n else num = 2;\n \n return Math.min(12,Math.max(min,num));\n },\n build: function() {\n var self = this, i;\n if(!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());\n if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);\n\n this.format = this.schema.format;\n if(!this.format && this.schema.media && this.schema.media.type) {\n this.format = this.schema.media.type.replace(/(^(application|text)\\/(x-)?(script\\.)?)|(-source$)/g,'');\n }\n if(!this.format && this.options.default_format) {\n this.format = this.options.default_format;\n }\n if(this.options.format) {\n this.format = this.options.format;\n }\n\n // Specific format\n if(this.format) {\n // Text Area\n if(this.format === 'textarea') {\n this.input_type = 'textarea';\n this.input = this.theme.getTextareaInput();\n }\n // Range Input\n else if(this.format === 'range') {\n this.input_type = 'range';\n var min = this.schema.minimum || 0;\n var max = this.schema.maximum || Math.max(100,min+1);\n var step = 1;\n if(this.schema.multipleOf) {\n if(min%this.schema.multipleOf) min = Math.ceil(min/this.schema.multipleOf)*this.schema.multipleOf;\n if(max%this.schema.multipleOf) max = Math.floor(max/this.schema.multipleOf)*this.schema.multipleOf;\n step = this.schema.multipleOf;\n }\n\n this.input = this.theme.getRangeInput(min,max,step);\n }\n // Source Code\n else if([\n 'actionscript',\n 'batchfile',\n 'bbcode',\n 'c',\n 'c++',\n 'cpp',\n 'coffee',\n 'csharp',\n 'css',\n 'dart',\n 'django',\n 'ejs',\n 'erlang',\n 'golang',\n 'handlebars',\n 'haskell',\n 'haxe',\n 'html',\n 'ini',\n 'jade',\n 'java',\n 'javascript',\n 'json',\n 'less',\n 'lisp',\n 'lua',\n 'makefile',\n 'markdown',\n 'matlab',\n 'mysql',\n 'objectivec',\n 'pascal',\n 'perl',\n 'pgsql',\n 'php',\n 'python',\n 'r',\n 'ruby',\n 'sass',\n 'scala',\n 'scss',\n 'smarty',\n 'sql',\n 'stylus',\n 'svg',\n 'twig',\n 'vbscript',\n 'xml',\n 'yaml'\n ].indexOf(this.format) >= 0\n ) {\n this.input_type = this.format;\n this.source_code = true;\n \n this.input = this.theme.getTextareaInput();\n }\n // HTML5 Input type\n else {\n this.input_type = this.format;\n this.input = this.theme.getFormInputField(this.input_type);\n }\n }\n // Normal text input\n else {\n this.input_type = 'text';\n this.input = this.theme.getFormInputField(this.input_type);\n }\n \n // minLength, maxLength, and pattern\n if(typeof this.schema.maxLength !== \"undefined\") this.input.setAttribute('maxlength',this.schema.maxLength);\n if(typeof this.schema.pattern !== \"undefined\") this.input.setAttribute('pattern',this.schema.pattern);\n else if(typeof this.schema.minLength !== \"undefined\") this.input.setAttribute('pattern','.{'+this.schema.minLength+',}');\n\n if(this.options.compact) {\n this.container.className += ' compact';\n }\n else {\n if(this.options.input_width) this.input.style.width = this.options.input_width;\n }\n\n if(this.schema.readOnly || this.schema.readonly || this.schema.template) {\n this.always_disabled = true;\n this.input.disabled = true;\n }\n\n this.input\n .addEventListener('change',function(e) { \n e.preventDefault();\n e.stopPropagation();\n \n // Don't allow changing if this field is a template\n if(self.schema.template) {\n this.value = self.value;\n return;\n }\n\n var val = this.value;\n \n // sanitize value\n var sanitized = self.sanitize(val);\n if(val !== sanitized) {\n this.value = sanitized;\n }\n \n self.is_dirty = true;\n\n self.refreshValue();\n self.onChange(true);\n });\n \n if(this.options.input_height) this.input.style.height = this.options.input_height;\n if(this.options.expand_height) {\n this.adjust_height = function(el) {\n if(!el) return;\n var i, ch=el.offsetHeight;\n // Input too short\n if(el.offsetHeight < el.scrollHeight) {\n i=0;\n while(el.offsetHeight < el.scrollHeight+3) {\n if(i>100) break;\n i++;\n ch++;\n el.style.height = ch+'px';\n }\n }\n else {\n i=0;\n while(el.offsetHeight >= el.scrollHeight+3) {\n if(i>100) break;\n i++;\n ch--;\n el.style.height = ch+'px';\n }\n el.style.height = (ch+1)+'px';\n }\n };\n \n this.input.addEventListener('keyup',function(e) {\n self.adjust_height(this);\n });\n this.input.addEventListener('change',function(e) {\n self.adjust_height(this);\n });\n this.adjust_height();\n }\n\n if(this.format) this.input.setAttribute('data-schemaformat',this.format);\n\n this.control = this.theme.getFormControl(this.label, this.input, this.description);\n this.container.appendChild(this.control);\n\n // Any special formatting that needs to happen after the input is added to the dom\n window.requestAnimationFrame(function() {\n // Skip in case the input is only a temporary editor,\n // otherwise, in the case of an ace_editor creation,\n // it will generate an error trying to append it to the missing parentNode\n if(self.input.parentNode) self.afterInputReady();\n if(self.adjust_height) self.adjust_height(self.input);\n });\n\n // Compile and store the template\n if(this.schema.template) {\n this.template = this.jsoneditor.compileTemplate(this.schema.template, this.template_engine);\n this.refreshValue();\n }\n else {\n this.refreshValue();\n }\n },\n enable: function() {\n if(!this.always_disabled) {\n this.input.disabled = false;\n // TODO: WYSIWYG and Markdown editors\n }\n this._super();\n },\n disable: function() {\n this.input.disabled = true;\n // TODO: WYSIWYG and Markdown editors\n this._super();\n },\n afterInputReady: function() {\n var self = this, options;\n \n // Code editor\n if(this.source_code) { \n // WYSIWYG html and bbcode editor\n if(this.options.wysiwyg && \n ['html','bbcode'].indexOf(this.input_type) >= 0 && \n window.jQuery && window.jQuery.fn && window.jQuery.fn.sceditor\n ) {\n options = $extend({},{\n plugins: self.input_type==='html'? 'xhtml' : 'bbcode',\n emoticonsEnabled: false,\n width: '100%',\n height: 300\n },JSONEditor.plugins.sceditor,self.options.sceditor_options||{});\n \n window.jQuery(self.input).sceditor(options);\n \n self.sceditor_instance = window.jQuery(self.input).sceditor('instance');\n \n self.sceditor_instance.blur(function() {\n // Get editor's value\n var val = window.jQuery(\"<div>\"+self.sceditor_instance.val()+\"</div>\");\n // Remove sceditor spans/divs\n window.jQuery('#sceditor-start-marker,#sceditor-end-marker,.sceditor-nlf',val).remove();\n // Set the value and update\n self.input.value = val.html();\n self.value = self.input.value;\n self.is_dirty = true;\n self.onChange(true);\n });\n }\n // EpicEditor for markdown (if it's loaded)\n else if (this.input_type === 'markdown' && window.EpicEditor) {\n this.epiceditor_container = document.createElement('div');\n this.input.parentNode.insertBefore(this.epiceditor_container,this.input);\n this.input.style.display = 'none';\n \n options = $extend({},JSONEditor.plugins.epiceditor,{\n container: this.epiceditor_container,\n clientSideStorage: false\n });\n \n this.epiceditor = new window.EpicEditor(options).load();\n \n this.epiceditor.importFile(null,this.getValue());\n \n this.epiceditor.on('update',function() {\n var val = self.epiceditor.exportFile();\n self.input.value = val;\n self.value = val;\n self.is_dirty = true;\n self.onChange(true);\n });\n }\n // ACE editor for everything else\n else if(window.ace) {\n var mode = this.input_type;\n // aliases for c/cpp\n if(mode === 'cpp' || mode === 'c++' || mode === 'c') {\n mode = 'c_cpp';\n }\n \n this.ace_container = document.createElement('div');\n this.ace_container.style.width = '100%';\n this.ace_container.style.position = 'relative';\n this.ace_container.style.height = '400px';\n this.input.parentNode.insertBefore(this.ace_container,this.input);\n this.input.style.display = 'none';\n this.ace_editor = window.ace.edit(this.ace_container);\n \n this.ace_editor.setValue(this.getValue());\n \n // The theme\n if(JSONEditor.plugins.ace.theme) this.ace_editor.setTheme('ace/theme/'+JSONEditor.plugins.ace.theme);\n // The mode\n mode = window.ace.require(\"ace/mode/\"+mode);\n if(mode) this.ace_editor.getSession().setMode(new mode.Mode());\n \n // Listen for changes\n this.ace_editor.on('change',function() {\n var val = self.ace_editor.getValue();\n self.input.value = val;\n self.refreshValue();\n self.is_dirty = true;\n self.onChange(true);\n });\n }\n }\n \n self.theme.afterInputReady(self.input);\n },\n refreshValue: function() {\n this.value = this.input.value;\n if(typeof this.value !== \"string\") this.value = '';\n this.serialized = this.value;\n },\n destroy: function() {\n // If using SCEditor, destroy the editor instance\n if(this.sceditor_instance) {\n this.sceditor_instance.destroy();\n }\n else if(this.epiceditor) {\n this.epiceditor.unload();\n }\n else if(this.ace_editor) {\n this.ace_editor.destroy();\n }\n \n \n this.template = null;\n if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);\n if(this.label && this.label.parentNode) this.label.parentNode.removeChild(this.label);\n if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);\n\n this._super();\n },\n /**\n * This is overridden in derivative editors\n */\n sanitize: function(value) {\n return value;\n },\n /**\n * Re-calculates the value if needed\n */\n onWatchedFieldChange: function() { \n var self = this, vars, j;\n \n // If this editor needs to be rendered by a macro template\n if(this.template) {\n vars = this.getWatchedFieldValues();\n this.setValue(this.template(vars),false,true);\n }\n \n this._super();\n },\n showValidationErrors: function(errors) {\n var self = this;\n \n if(this.jsoneditor.options.show_errors === \"always\") {}\n else if(!this.is_dirty && this.previous_error_setting===this.jsoneditor.options.show_errors) return;\n \n this.previous_error_setting = this.jsoneditor.options.show_errors;\n\n var messages = [];\n $each(errors,function(i,error) {\n if(error.path === self.path) {\n messages.push(error.message);\n }\n });\n\n if(messages.length) {\n this.theme.addInputError(this.input, messages.join('. ')+'.');\n }\n else {\n this.theme.removeInputError(this.input);\n }\n }\n});\n",
66
+ "JSONEditor.defaults.editors.number = JSONEditor.defaults.editors.string.extend({\n sanitize: function(value) {\n return (value+\"\").replace(/[^0-9\\.\\-eE]/g,'');\n },\n getNumColumns: function() {\n return 2;\n },\n getValue: function() {\n return this.value*1;\n }\n});\n",
67
+ "JSONEditor.defaults.editors.integer = JSONEditor.defaults.editors.number.extend({\n sanitize: function(value) {\n value = value + \"\";\n return value.replace(/[^0-9\\-]/g,'');\n },\n getNumColumns: function() {\n return 2;\n }\n});\n",
68
+ "JSONEditor.defaults.editors.object = JSONEditor.AbstractEditor.extend({\n getDefault: function() {\n return $extend({},this.schema[\"default\"] || {});\n },\n getChildEditors: function() {\n return this.editors;\n },\n register: function() {\n this._super();\n if(this.editors) {\n for(var i in this.editors) {\n if(!this.editors.hasOwnProperty(i)) continue;\n this.editors[i].register();\n }\n }\n },\n unregister: function() {\n this._super();\n if(this.editors) {\n for(var i in this.editors) {\n if(!this.editors.hasOwnProperty(i)) continue;\n this.editors[i].unregister();\n }\n }\n },\n getNumColumns: function() {\n return Math.max(Math.min(12,this.maxwidth),3);\n },\n enable: function() {\n if(this.editjson_button) this.editjson_button.disabled = false;\n if(this.addproperty_button) this.addproperty_button.disabled = false;\n \n this._super();\n if(this.editors) {\n for(var i in this.editors) {\n if(!this.editors.hasOwnProperty(i)) continue;\n this.editors[i].enable();\n }\n }\n },\n disable: function() {\n if(this.editjson_button) this.editjson_button.disabled = true;\n if(this.addproperty_button) this.addproperty_button.disabled = true;\n this.hideEditJSON();\n \n this._super();\n if(this.editors) {\n for(var i in this.editors) {\n if(!this.editors.hasOwnProperty(i)) continue;\n this.editors[i].disable();\n }\n }\n },\n layoutEditors: function() {\n var self = this, i, j;\n \n if(!this.row_container) return;\n\n // Sort editors by propertyOrder\n this.property_order = Object.keys(this.editors);\n this.property_order = this.property_order.sort(function(a,b) {\n var ordera = self.editors[a].schema.propertyOrder;\n var orderb = self.editors[b].schema.propertyOrder;\n if(typeof ordera !== \"number\") ordera = 1000;\n if(typeof orderb !== \"number\") orderb = 1000;\n\n return ordera - orderb;\n });\n \n var container;\n \n if(this.format === 'grid') {\n var rows = [];\n $each(this.property_order, function(j,key) {\n var editor = self.editors[key];\n if(editor.property_removed) return;\n var found = false;\n var width = editor.options.hidden? 0 : (editor.options.grid_columns || editor.getNumColumns());\n var height = editor.options.hidden? 0 : editor.container.offsetHeight;\n // See if the editor will fit in any of the existing rows first\n for(var i=0; i<rows.length; i++) {\n // If the editor will fit in the row horizontally\n if(rows[i].width + width <= 12) {\n // If the editor is close to the other elements in height\n // i.e. Don't put a really tall editor in an otherwise short row or vice versa\n if(!height || (rows[i].minh*0.5 < height && rows[i].maxh*2 > height)) {\n found = i;\n }\n }\n }\n \n // If there isn't a spot in any of the existing rows, start a new row\n if(found === false) {\n rows.push({\n width: 0,\n minh: 999999,\n maxh: 0,\n editors: []\n });\n found = rows.length-1;\n }\n \n rows[found].editors.push({\n key: key,\n //editor: editor,\n width: width,\n height: height\n });\n rows[found].width += width;\n rows[found].minh = Math.min(rows[found].minh,height);\n rows[found].maxh = Math.max(rows[found].maxh,height);\n });\n \n // Make almost full rows width 12\n // Do this by increasing all editors' sizes proprotionately\n // Any left over space goes to the biggest editor\n // Don't touch rows with a width of 6 or less\n for(i=0; i<rows.length; i++) {\n if(rows[i].width < 12) {\n var biggest = false;\n var new_width = 0;\n for(j=0; j<rows[i].editors.length; j++) {\n if(biggest === false) biggest = j;\n else if(rows[i].editors[j].width > rows[i].editors[biggest].width) biggest = j;\n rows[i].editors[j].width *= 12/rows[i].width;\n rows[i].editors[j].width = Math.floor(rows[i].editors[j].width);\n new_width += rows[i].editors[j].width;\n }\n if(new_width < 12) rows[i].editors[biggest].width += 12-new_width;\n rows[i].width = 12;\n }\n }\n \n // layout hasn't changed\n if(this.layout === JSON.stringify(rows)) return false;\n this.layout = JSON.stringify(rows);\n \n // Layout the form\n container = document.createElement('div');\n for(i=0; i<rows.length; i++) {\n var row = this.theme.getGridRow();\n container.appendChild(row);\n for(j=0; j<rows[i].editors.length; j++) {\n var key = rows[i].editors[j].key;\n var editor = this.editors[key];\n \n if(editor.options.hidden) editor.container.style.display = 'none';\n else this.theme.setGridColumnSize(editor.container,rows[i].editors[j].width);\n row.appendChild(editor.container);\n }\n }\n }\n // Normal layout\n else {\n container = document.createElement('div');\n $each(this.property_order, function(i,key) {\n var editor = self.editors[key];\n if(editor.property_removed) return;\n var row = self.theme.getGridRow();\n container.appendChild(row);\n \n if(editor.options.hidden) editor.container.style.display = 'none';\n else self.theme.setGridColumnSize(editor.container,12);\n row.appendChild(editor.container);\n });\n }\n this.row_container.innerHTML = '';\n this.row_container.appendChild(container);\n },\n getPropertySchema: function(key) {\n // Schema declared directly in properties\n var schema = this.schema.properties[key] || {};\n schema = $extend({},schema);\n var matched = this.schema.properties[key]? true : false;\n \n // Any matching patternProperties should be merged in\n if(this.schema.patternProperties) {\n for(var i in this.schema.patternProperties) {\n if(!this.schema.patternProperties.hasOwnProperty(i)) continue;\n var regex = new RegExp(i);\n if(regex.test(key)) {\n schema.allOf = schema.allOf || [];\n schema.allOf.push(this.schema.patternProperties[i]);\n matched = true;\n }\n }\n }\n \n // Hasn't matched other rules, use additionalProperties schema\n if(!matched && this.schema.additionalProperties && typeof this.schema.additionalProperties === \"object\") {\n schema = $extend({},this.schema.additionalProperties);\n }\n \n return schema;\n },\n preBuild: function() {\n this._super();\n\n this.editors = {};\n this.cached_editors = {};\n var self = this;\n\n this.format = this.options.layout || this.options.object_layout || this.schema.format || this.jsoneditor.options.object_layout || 'normal';\n\n this.schema.properties = this.schema.properties || {};\n\n this.minwidth = 0;\n this.maxwidth = 0;\n\n // If the object should be rendered as a table row\n if(this.options.table_row) {\n $each(this.schema.properties, function(key,schema) {\n var editor = self.jsoneditor.getEditorClass(schema);\n self.editors[key] = self.jsoneditor.createEditor(editor,{\n jsoneditor: self.jsoneditor,\n schema: schema,\n path: self.path+'.'+key,\n parent: self,\n compact: true,\n required: true\n });\n self.editors[key].preBuild();\n\n var width = self.editors[key].options.hidden? 0 : (self.editors[key].options.grid_columns || self.editors[key].getNumColumns());\n\n self.minwidth += width;\n self.maxwidth += width;\n });\n this.no_link_holder = true;\n }\n // If the object should be rendered as a table\n else if(this.options.table) {\n // TODO: table display format\n throw \"Not supported yet\";\n }\n // If the object should be rendered as a div\n else {\n this.defaultProperties = this.schema.defaultProperties || Object.keys(this.schema.properties);\n\n // Increase the grid width to account for padding\n self.maxwidth += 1;\n\n $each(this.defaultProperties, function(i,key) {\n self.addObjectProperty(key, true);\n\n if(self.editors[key]) {\n self.minwidth = Math.max(self.minwidth,(self.editors[key].options.grid_columns || self.editors[key].getNumColumns()));\n self.maxwidth += (self.editors[key].options.grid_columns || self.editors[key].getNumColumns());\n }\n });\n }\n \n // Sort editors by propertyOrder\n this.property_order = Object.keys(this.editors);\n this.property_order = this.property_order.sort(function(a,b) {\n var ordera = self.editors[a].schema.propertyOrder;\n var orderb = self.editors[b].schema.propertyOrder;\n if(typeof ordera !== \"number\") ordera = 1000;\n if(typeof orderb !== \"number\") orderb = 1000;\n\n return ordera - orderb;\n });\n },\n build: function() {\n var self = this;\n\n // If the object should be rendered as a table row\n if(this.options.table_row) {\n this.editor_holder = this.container;\n $each(this.editors, function(key,editor) {\n var holder = self.theme.getTableCell();\n self.editor_holder.appendChild(holder);\n\n editor.setContainer(holder);\n editor.build();\n editor.postBuild();\n\n if(self.editors[key].options.hidden) {\n holder.style.display = 'none';\n }\n if(self.editors[key].options.input_width) {\n holder.style.width = self.editors[key].options.input_width;\n }\n });\n }\n // If the object should be rendered as a table\n else if(this.options.table) {\n // TODO: table display format\n throw \"Not supported yet\";\n }\n // If the object should be rendered as a div\n else {\n this.header = document.createElement('span');\n this.header.textContent = this.getTitle();\n this.title = this.theme.getHeader(this.header);\n this.container.appendChild(this.title);\n this.container.style.position = 'relative';\n \n // Edit JSON modal\n this.editjson_holder = this.theme.getModal();\n this.editjson_textarea = this.theme.getTextareaInput();\n this.editjson_textarea.style.height = '170px';\n this.editjson_textarea.style.width = '300px';\n this.editjson_textarea.style.display = 'block';\n this.editjson_save = this.getButton('Save','save','Save');\n this.editjson_save.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n self.saveJSON();\n });\n this.editjson_cancel = this.getButton('Cancel','cancel','Cancel');\n this.editjson_cancel.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n self.hideEditJSON();\n });\n this.editjson_holder.appendChild(this.editjson_textarea);\n this.editjson_holder.appendChild(this.editjson_save);\n this.editjson_holder.appendChild(this.editjson_cancel);\n \n // Manage Properties modal\n this.addproperty_holder = this.theme.getModal();\n this.addproperty_list = document.createElement('div');\n this.addproperty_list.style.width = '295px';\n this.addproperty_list.style.maxHeight = '160px';\n this.addproperty_list.style.padding = '5px 0';\n this.addproperty_list.style.overflowY = 'auto';\n this.addproperty_list.style.overflowX = 'hidden';\n this.addproperty_list.style.paddingLeft = '5px';\n this.addproperty_list.setAttribute('class', 'property-selector');\n this.addproperty_add = this.getButton('add','add','add');\n this.addproperty_input = this.theme.getFormInputField('text');\n this.addproperty_input.setAttribute('placeholder','Property name...');\n this.addproperty_input.style.width = '220px';\n this.addproperty_input.style.marginBottom = '0';\n this.addproperty_input.style.display = 'inline-block';\n this.addproperty_add.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n if(self.addproperty_input.value) {\n if(self.editors[self.addproperty_input.value]) {\n window.alert('there is already a property with that name');\n return;\n }\n \n self.addObjectProperty(self.addproperty_input.value);\n if(self.editors[self.addproperty_input.value]) {\n self.editors[self.addproperty_input.value].disable();\n }\n self.onChange(true);\n }\n });\n this.addproperty_holder.appendChild(this.addproperty_list);\n this.addproperty_holder.appendChild(this.addproperty_input);\n this.addproperty_holder.appendChild(this.addproperty_add);\n var spacer = document.createElement('div');\n spacer.style.clear = 'both';\n this.addproperty_holder.appendChild(spacer);\n \n \n // Description\n if(this.schema.description) {\n this.description = this.theme.getDescription(this.schema.description);\n this.container.appendChild(this.description);\n }\n \n // Validation error placeholder area\n this.error_holder = document.createElement('div');\n this.container.appendChild(this.error_holder);\n \n // Container for child editor area\n this.editor_holder = this.theme.getIndentedPanel();\n this.container.appendChild(this.editor_holder);\n\n // Container for rows of child editors\n this.row_container = this.theme.getGridContainer();\n this.editor_holder.appendChild(this.row_container);\n\n $each(this.editors, function(key,editor) {\n var holder = self.theme.getGridColumn();\n self.row_container.appendChild(holder);\n\n editor.setContainer(holder);\n editor.build();\n editor.postBuild();\n });\n\n // Control buttons\n this.title_controls = this.theme.getHeaderButtonHolder();\n this.editjson_controls = this.theme.getHeaderButtonHolder();\n this.addproperty_controls = this.theme.getHeaderButtonHolder();\n this.title.appendChild(this.title_controls);\n this.title.appendChild(this.editjson_controls);\n this.title.appendChild(this.addproperty_controls);\n\n // Show/Hide button\n this.collapsed = false;\n this.toggle_button = this.getButton('','collapse','Collapse');\n this.title_controls.appendChild(this.toggle_button);\n this.toggle_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n if(self.collapsed) {\n self.editor_holder.style.display = '';\n self.collapsed = false;\n self.setButtonText(self.toggle_button,'','collapse','Collapse');\n }\n else {\n self.editor_holder.style.display = 'none';\n self.collapsed = true;\n self.setButtonText(self.toggle_button,'','expand','Expand');\n }\n });\n\n // If it should start collapsed\n if(this.options.collapsed) {\n $trigger(this.toggle_button,'click');\n }\n \n // Collapse button disabled\n if(this.schema.options && typeof this.schema.options.disable_collapse !== \"undefined\") {\n if(this.schema.options.disable_collapse) this.toggle_button.style.display = 'none';\n }\n else if(this.jsoneditor.options.disable_collapse) {\n this.toggle_button.style.display = 'none';\n }\n \n // Edit JSON Button\n this.editjson_button = this.getButton('JSON','edit','Edit JSON');\n this.editjson_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n self.toggleEditJSON();\n });\n this.editjson_controls.appendChild(this.editjson_button);\n this.editjson_controls.appendChild(this.editjson_holder);\n \n // Edit JSON Buttton disabled\n if(this.schema.options && typeof this.schema.options.disable_edit_json !== \"undefined\") {\n if(this.schema.options.disable_edit_json) this.editjson_button.style.display = 'none';\n }\n else if(this.jsoneditor.options.disable_edit_json) {\n this.editjson_button.style.display = 'none';\n }\n \n // Object Properties Button\n this.addproperty_button = this.getButton('Properties','edit','Object Properties');\n this.addproperty_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n self.toggleAddProperty();\n });\n this.addproperty_controls.appendChild(this.addproperty_button);\n this.addproperty_controls.appendChild(this.addproperty_holder);\n this.refreshAddProperties();\n }\n \n // Fix table cell ordering\n if(this.options.table_row) {\n this.editor_holder = this.container;\n $each(this.property_order,function(i,key) {\n self.editor_holder.appendChild(self.editors[key].container);\n });\n }\n // Layout object editors in grid if needed\n else {\n // Initial layout\n this.layoutEditors();\n // Do it again now that we know the approximate heights of elements\n this.layoutEditors();\n }\n },\n showEditJSON: function() {\n if(!this.editjson_holder) return;\n this.hideAddProperty();\n \n // Position the form directly beneath the button\n // TODO: edge detection\n this.editjson_holder.style.left = this.editjson_button.offsetLeft+\"px\";\n this.editjson_holder.style.top = this.editjson_button.offsetTop + this.editjson_button.offsetHeight+\"px\";\n \n // Start the textarea with the current value\n this.editjson_textarea.value = JSON.stringify(this.getValue(),null,2);\n \n // Disable the rest of the form while editing JSON\n this.disable();\n \n this.editjson_holder.style.display = '';\n this.editjson_button.disabled = false;\n this.editing_json = true;\n },\n hideEditJSON: function() {\n if(!this.editjson_holder) return;\n if(!this.editing_json) return;\n \n this.editjson_holder.style.display = 'none';\n this.enable();\n this.editing_json = false;\n },\n saveJSON: function() {\n if(!this.editjson_holder) return;\n \n try {\n var json = JSON.parse(this.editjson_textarea.value);\n this.setValue(json);\n this.hideEditJSON();\n }\n catch(e) {\n window.alert('invalid JSON');\n throw e;\n }\n },\n toggleEditJSON: function() {\n if(this.editing_json) this.hideEditJSON();\n else this.showEditJSON();\n },\n insertPropertyControlUsingPropertyOrder: function (property, control, container) {\n var propertyOrder;\n if (this.schema.properties[property])\n propertyOrder = this.schema.properties[property].propertyOrder;\n if (typeof propertyOrder !== \"number\") propertyOrder = 1000;\n control.propertyOrder = propertyOrder;\n\n for (var i = 0; i < container.childNodes.length; i++) {\n var child = container.childNodes[i];\n if (control.propertyOrder < child.propertyOrder) {\n this.addproperty_list.insertBefore(control, child);\n control = null;\n break;\n }\n }\n if (control) {\n this.addproperty_list.appendChild(control);\n }\n },\n addPropertyCheckbox: function(key) {\n var self = this;\n var checkbox, label, labelText, control;\n\n checkbox = self.theme.getCheckbox();\n checkbox.style.width = 'auto';\n\n if (this.schema.properties[key] && this.schema.properties[key].title)\n labelText = this.schema.properties[key].title;\n else\n labelText = key;\n\n label = self.theme.getCheckboxLabel(labelText);\n\n control = self.theme.getFormControl(label,checkbox);\n control.style.paddingBottom = control.style.marginBottom = control.style.paddingTop = control.style.marginTop = 0;\n control.style.height = 'auto';\n //control.style.overflowY = 'hidden';\n\n this.insertPropertyControlUsingPropertyOrder(key, control, this.addproperty_list);\n\n checkbox.checked = key in this.editors;\n checkbox.addEventListener('change',function() {\n if(checkbox.checked) {\n self.addObjectProperty(key);\n }\n else {\n self.removeObjectProperty(key);\n }\n self.onChange(true);\n });\n self.addproperty_checkboxes[key] = checkbox;\n \n return checkbox;\n },\n showAddProperty: function() {\n if(!this.addproperty_holder) return;\n this.hideEditJSON();\n \n // Position the form directly beneath the button\n // TODO: edge detection\n this.addproperty_holder.style.left = this.addproperty_button.offsetLeft+\"px\";\n this.addproperty_holder.style.top = this.addproperty_button.offsetTop + this.addproperty_button.offsetHeight+\"px\";\n \n // Disable the rest of the form while editing JSON\n this.disable();\n \n this.adding_property = true;\n this.addproperty_button.disabled = false;\n this.addproperty_holder.style.display = '';\n this.refreshAddProperties();\n },\n hideAddProperty: function() {\n if(!this.addproperty_holder) return;\n if(!this.adding_property) return;\n \n this.addproperty_holder.style.display = 'none';\n this.enable();\n \n this.adding_property = false;\n },\n toggleAddProperty: function() {\n if(this.adding_property) this.hideAddProperty();\n else this.showAddProperty();\n },\n removeObjectProperty: function(property) {\n if(this.editors[property]) {\n this.editors[property].unregister();\n delete this.editors[property];\n \n this.refreshValue();\n this.layoutEditors();\n }\n },\n addObjectProperty: function(name, prebuild_only) {\n var self = this;\n \n // Property is already added\n if(this.editors[name]) return;\n \n // Property was added before and is cached\n if(this.cached_editors[name]) {\n this.editors[name] = this.cached_editors[name];\n if(prebuild_only) return;\n this.editors[name].register();\n }\n // New property\n else {\n if(!this.canHaveAdditionalProperties() && (!this.schema.properties || !this.schema.properties[name])) {\n return;\n }\n\n var schema = self.getPropertySchema(name);\n \n \n // Add the property\n var editor = self.jsoneditor.getEditorClass(schema);\n\n self.editors[name] = self.jsoneditor.createEditor(editor,{\n jsoneditor: self.jsoneditor,\n schema: schema,\n path: self.path+'.'+name,\n parent: self\n });\n self.editors[name].preBuild();\n \n if(!prebuild_only) {\n var holder = self.theme.getChildEditorHolder();\n self.editor_holder.appendChild(holder);\n self.editors[name].setContainer(holder);\n self.editors[name].build();\n self.editors[name].postBuild();\n }\n \n self.cached_editors[name] = self.editors[name];\n }\n \n // If we're only prebuilding the editors, don't refresh values\n if(!prebuild_only) {\n self.refreshValue();\n self.layoutEditors();\n }\n },\n onChildEditorChange: function(editor) {\n this.refreshValue();\n this._super(editor);\n },\n canHaveAdditionalProperties: function() {\n if (typeof this.schema.additionalProperties === \"boolean\") {\n return this.schema.additionalProperties;\n }\n return !this.jsoneditor.options.no_additional_properties;\n },\n destroy: function() {\n $each(this.cached_editors, function(i,el) {\n el.destroy();\n });\n if(this.editor_holder) this.editor_holder.innerHTML = '';\n if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);\n if(this.error_holder && this.error_holder.parentNode) this.error_holder.parentNode.removeChild(this.error_holder);\n\n this.editors = null;\n this.cached_editors = null;\n if(this.editor_holder && this.editor_holder.parentNode) this.editor_holder.parentNode.removeChild(this.editor_holder);\n this.editor_holder = null;\n\n this._super();\n },\n getValue: function() {\n var result = this._super();\n if(this.jsoneditor.options.remove_empty_properties || this.options.remove_empty_properties) {\n for(var i in result) {\n if(result.hasOwnProperty(i)) {\n if(!result[i]) delete result[i];\n }\n }\n }\n return result;\n },\n refreshValue: function() {\n this.value = {};\n var self = this;\n \n for(var i in this.editors) {\n if(!this.editors.hasOwnProperty(i)) continue;\n this.value[i] = this.editors[i].getValue();\n }\n \n if(this.adding_property) this.refreshAddProperties();\n },\n refreshAddProperties: function() {\n if(this.options.disable_properties || (this.options.disable_properties !== false && this.jsoneditor.options.disable_properties)) {\n this.addproperty_controls.style.display = 'none';\n return;\n }\n\n var can_add = false, can_remove = false, num_props = 0, i, show_modal = false;\n \n // Get number of editors\n for(i in this.editors) {\n if(!this.editors.hasOwnProperty(i)) continue;\n num_props++;\n }\n \n // Determine if we can add back removed properties\n can_add = this.canHaveAdditionalProperties() && !(typeof this.schema.maxProperties !== \"undefined\" && num_props >= this.schema.maxProperties);\n \n if(this.addproperty_checkboxes) {\n this.addproperty_list.innerHTML = '';\n }\n this.addproperty_checkboxes = {};\n \n // Check for which editors can't be removed or added back\n for(i in this.cached_editors) {\n if(!this.cached_editors.hasOwnProperty(i)) continue;\n \n this.addPropertyCheckbox(i);\n \n if(this.isRequired(this.cached_editors[i]) && i in this.editors) {\n this.addproperty_checkboxes[i].disabled = true;\n }\n \n if(typeof this.schema.minProperties !== \"undefined\" && num_props <= this.schema.minProperties) {\n this.addproperty_checkboxes[i].disabled = this.addproperty_checkboxes[i].checked;\n if(!this.addproperty_checkboxes[i].checked) show_modal = true;\n }\n else if(!(i in this.editors)) {\n if(!can_add && !this.schema.properties.hasOwnProperty(i)) {\n this.addproperty_checkboxes[i].disabled = true;\n }\n else {\n this.addproperty_checkboxes[i].disabled = false;\n show_modal = true;\n }\n }\n else {\n show_modal = true;\n can_remove = true;\n }\n }\n \n if(this.canHaveAdditionalProperties()) {\n show_modal = true;\n }\n \n // Additional addproperty checkboxes not tied to a current editor\n for(i in this.schema.properties) {\n if(!this.schema.properties.hasOwnProperty(i)) continue;\n if(this.cached_editors[i]) continue;\n show_modal = true;\n this.addPropertyCheckbox(i);\n }\n \n // If no editors can be added or removed, hide the modal button\n if(!show_modal) {\n this.hideAddProperty();\n this.addproperty_controls.style.display = 'none';\n }\n // If additional properties are disabled\n else if(!this.canHaveAdditionalProperties()) {\n this.addproperty_add.style.display = 'none';\n this.addproperty_input.style.display = 'none';\n }\n // If no new properties can be added\n else if(!can_add) {\n this.addproperty_add.disabled = true;\n }\n // If new properties can be added\n else {\n this.addproperty_add.disabled = false;\n }\n },\n isRequired: function(editor) {\n if(typeof editor.schema.required === \"boolean\") return editor.schema.required;\n else if(Array.isArray(this.schema.required)) return this.schema.required.indexOf(editor.key) > -1;\n else if(this.jsoneditor.options.required_by_default) return true;\n else return false;\n },\n setValue: function(value, initial) {\n var self = this;\n value = value || {};\n \n if(typeof value !== \"object\" || Array.isArray(value)) value = {};\n\n // First, set the values for all of the defined properties\n $each(this.cached_editors, function(i,editor) {\n // Value explicitly set\n if(typeof value[i] !== \"undefined\") {\n self.addObjectProperty(i);\n editor.setValue(value[i],initial);\n }\n // Otherwise, remove value unless this is the initial set or it's required\n else if(!initial && !self.isRequired(editor)) {\n self.removeObjectProperty(i);\n }\n // Otherwise, set the value to the default\n else {\n editor.setValue(editor.getDefault(),initial);\n }\n });\n\n $each(value, function(i,val) {\n if(!self.cached_editors[i]) {\n self.addObjectProperty(i);\n if(self.editors[i]) self.editors[i].setValue(val,initial);\n }\n });\n \n this.refreshValue();\n this.layoutEditors();\n this.onChange();\n },\n showValidationErrors: function(errors) {\n var self = this;\n\n // Get all the errors that pertain to this editor\n var my_errors = [];\n var other_errors = [];\n $each(errors, function(i,error) {\n if(error.path === self.path) {\n my_errors.push(error);\n }\n else {\n other_errors.push(error);\n }\n });\n\n // Show errors for this editor\n if(this.error_holder) {\n if(my_errors.length) {\n var message = [];\n this.error_holder.innerHTML = '';\n this.error_holder.style.display = '';\n $each(my_errors, function(i,error) {\n self.error_holder.appendChild(self.theme.getErrorMessage(error.message));\n });\n }\n // Hide error area\n else {\n this.error_holder.style.display = 'none';\n }\n }\n\n // Show error for the table row if this is inside a table\n if(this.options.table_row) {\n if(my_errors.length) {\n this.theme.addTableRowError(this.container);\n }\n else {\n this.theme.removeTableRowError(this.container);\n }\n }\n\n // Show errors for child editors\n $each(this.editors, function(i,editor) {\n editor.showValidationErrors(other_errors);\n });\n }\n});\n",
69
+ "JSONEditor.defaults.editors.array = JSONEditor.AbstractEditor.extend({\n getDefault: function() {\n return this.schema[\"default\"] || [];\n },\n register: function() {\n this._super();\n if(this.rows) {\n for(var i=0; i<this.rows.length; i++) {\n this.rows[i].register();\n }\n }\n },\n unregister: function() {\n this._super();\n if(this.rows) {\n for(var i=0; i<this.rows.length; i++) {\n this.rows[i].unregister();\n }\n }\n },\n getNumColumns: function() {\n var info = this.getItemInfo(0);\n // Tabs require extra horizontal space\n if(this.tabs_holder) {\n return Math.max(Math.min(12,info.width+2),4);\n }\n else {\n return info.width;\n }\n },\n enable: function() {\n if(this.add_row_button) this.add_row_button.disabled = false;\n if(this.remove_all_rows_button) this.remove_all_rows_button.disabled = false;\n if(this.delete_last_row_button) this.delete_last_row_button.disabled = false;\n \n if(this.rows) {\n for(var i=0; i<this.rows.length; i++) {\n this.rows[i].enable();\n \n if(this.rows[i].moveup_button) this.rows[i].moveup_button.disabled = false;\n if(this.rows[i].movedown_button) this.rows[i].movedown_button.disabled = false;\n if(this.rows[i].delete_button) this.rows[i].delete_button.disabled = false;\n }\n }\n this._super();\n },\n disable: function() {\n if(this.add_row_button) this.add_row_button.disabled = true;\n if(this.remove_all_rows_button) this.remove_all_rows_button.disabled = true;\n if(this.delete_last_row_button) this.delete_last_row_button.disabled = true;\n\n if(this.rows) {\n for(var i=0; i<this.rows.length; i++) {\n this.rows[i].disable();\n \n if(this.rows[i].moveup_button) this.rows[i].moveup_button.disabled = true;\n if(this.rows[i].movedown_button) this.rows[i].movedown_button.disabled = true;\n if(this.rows[i].delete_button) this.rows[i].delete_button.disabled = true;\n }\n }\n this._super();\n },\n preBuild: function() {\n this._super();\n \n this.rows = [];\n this.row_cache = [];\n\n this.hide_delete_buttons = this.options.disable_array_delete || this.jsoneditor.options.disable_array_delete;\n this.hide_move_buttons = this.options.disable_array_reorder || this.jsoneditor.options.disable_array_reorder;\n this.hide_add_button = this.options.disable_array_add || this.jsoneditor.options.disable_array_add;\n },\n build: function() {\n var self = this;\n\n if(!this.options.compact) {\n this.header = document.createElement('span');\n this.header.textContent = this.getTitle();\n this.title = this.theme.getHeader(this.header);\n this.container.appendChild(this.title);\n this.title_controls = this.theme.getHeaderButtonHolder();\n this.title.appendChild(this.title_controls);\n if(this.schema.description) {\n this.description = this.theme.getDescription(this.schema.description);\n this.container.appendChild(this.description);\n }\n this.error_holder = document.createElement('div');\n this.container.appendChild(this.error_holder);\n\n if(this.schema.format === 'tabs') {\n this.controls = this.theme.getHeaderButtonHolder();\n this.title.appendChild(this.controls);\n this.tabs_holder = this.theme.getTabHolder();\n this.container.appendChild(this.tabs_holder);\n this.row_holder = this.theme.getTabContentHolder(this.tabs_holder);\n\n this.active_tab = null;\n }\n else {\n this.panel = this.theme.getIndentedPanel();\n this.container.appendChild(this.panel);\n this.row_holder = document.createElement('div');\n this.panel.appendChild(this.row_holder);\n this.controls = this.theme.getButtonHolder();\n this.panel.appendChild(this.controls);\n }\n }\n else {\n this.panel = this.theme.getIndentedPanel();\n this.container.appendChild(this.panel);\n this.controls = this.theme.getButtonHolder();\n this.panel.appendChild(this.controls);\n this.row_holder = document.createElement('div');\n this.panel.appendChild(this.row_holder);\n }\n\n // Add controls\n this.addControls();\n },\n onChildEditorChange: function(editor) {\n this.refreshValue();\n this.refreshTabs(true);\n this._super(editor);\n },\n getItemTitle: function() {\n if(!this.item_title) {\n if(this.schema.items && !Array.isArray(this.schema.items)) {\n var tmp = this.jsoneditor.expandRefs(this.schema.items);\n this.item_title = tmp.title || 'item';\n }\n else {\n this.item_title = 'item';\n }\n }\n return this.item_title;\n },\n getItemSchema: function(i) {\n if(Array.isArray(this.schema.items)) {\n if(i >= this.schema.items.length) {\n if(this.schema.additionalItems===true) {\n return {};\n }\n else if(this.schema.additionalItems) {\n return $extend({},this.schema.additionalItems);\n }\n }\n else {\n return $extend({},this.schema.items[i]);\n }\n }\n else if(this.schema.items) {\n return $extend({},this.schema.items);\n }\n else {\n return {};\n }\n },\n getItemInfo: function(i) {\n var schema = this.getItemSchema(i);\n \n // Check if it's cached\n this.item_info = this.item_info || {};\n var stringified = JSON.stringify(schema);\n if(typeof this.item_info[stringified] !== \"undefined\") return this.item_info[stringified];\n \n // Get the schema for this item\n schema = this.jsoneditor.expandRefs(schema);\n \n this.item_info[stringified] = {\n title: schema.title || \"item\",\n 'default': schema[\"default\"],\n width: 12,\n child_editors: schema.properties || schema.items\n };\n \n return this.item_info[stringified];\n },\n getElementEditor: function(i) {\n var item_info = this.getItemInfo(i);\n var schema = this.getItemSchema(i);\n schema = this.jsoneditor.expandRefs(schema);\n schema.title = item_info.title+' '+(i+1);\n\n var editor = this.jsoneditor.getEditorClass(schema);\n\n var holder;\n if(this.tabs_holder) {\n holder = this.theme.getTabContent();\n }\n else if(item_info.child_editors) {\n holder = this.theme.getChildEditorHolder();\n }\n else {\n holder = this.theme.getIndentedPanel();\n }\n\n this.row_holder.appendChild(holder);\n\n var ret = this.jsoneditor.createEditor(editor,{\n jsoneditor: this.jsoneditor,\n schema: schema,\n container: holder,\n path: this.path+'.'+i,\n parent: this,\n required: true\n });\n ret.preBuild();\n ret.build();\n ret.postBuild();\n\n if(!ret.title_controls) {\n ret.array_controls = this.theme.getButtonHolder();\n holder.appendChild(ret.array_controls);\n }\n \n return ret;\n },\n destroy: function() {\n this.empty(true);\n if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);\n if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);\n if(this.row_holder && this.row_holder.parentNode) this.row_holder.parentNode.removeChild(this.row_holder);\n if(this.controls && this.controls.parentNode) this.controls.parentNode.removeChild(this.controls);\n if(this.panel && this.panel.parentNode) this.panel.parentNode.removeChild(this.panel);\n \n this.rows = this.row_cache = this.title = this.description = this.row_holder = this.panel = this.controls = null;\n\n this._super();\n },\n empty: function(hard) {\n if(!this.rows) return;\n var self = this;\n $each(this.rows,function(i,row) {\n if(hard) {\n if(row.tab && row.tab.parentNode) row.tab.parentNode.removeChild(row.tab);\n self.destroyRow(row,true);\n self.row_cache[i] = null;\n }\n self.rows[i] = null;\n });\n self.rows = [];\n if(hard) self.row_cache = [];\n },\n destroyRow: function(row,hard) {\n var holder = row.container;\n if(hard) {\n row.destroy();\n if(holder.parentNode) holder.parentNode.removeChild(holder);\n if(row.tab && row.tab.parentNode) row.tab.parentNode.removeChild(row.tab);\n }\n else {\n if(row.tab) row.tab.style.display = 'none';\n holder.style.display = 'none';\n row.unregister();\n }\n },\n getMax: function() {\n if((Array.isArray(this.schema.items)) && this.schema.additionalItems === false) {\n return Math.min(this.schema.items.length,this.schema.maxItems || Infinity);\n }\n else {\n return this.schema.maxItems || Infinity;\n }\n },\n refreshTabs: function(refresh_headers) {\n var self = this;\n $each(this.rows, function(i,row) {\n if(!row.tab) return;\n\n if(refresh_headers) {\n row.tab_text.textContent = row.getHeaderText();\n }\n else {\n if(row.tab === self.active_tab) {\n self.theme.markTabActive(row.tab);\n row.container.style.display = '';\n }\n else {\n self.theme.markTabInactive(row.tab);\n row.container.style.display = 'none';\n }\n }\n });\n },\n setValue: function(value, initial) {\n // Update the array's value, adding/removing rows when necessary\n value = value || [];\n \n if(!(Array.isArray(value))) value = [value];\n \n var serialized = JSON.stringify(value);\n if(serialized === this.serialized) return;\n\n // Make sure value has between minItems and maxItems items in it\n if(this.schema.minItems) {\n while(value.length < this.schema.minItems) {\n value.push(this.getItemInfo(value.length)[\"default\"]);\n }\n }\n if(this.getMax() && value.length > this.getMax()) {\n value = value.slice(0,this.getMax());\n }\n\n var self = this;\n $each(value,function(i,val) {\n if(self.rows[i]) {\n // TODO: don't set the row's value if it hasn't changed\n self.rows[i].setValue(val,initial);\n }\n else if(self.row_cache[i]) {\n self.rows[i] = self.row_cache[i];\n self.rows[i].setValue(val,initial);\n self.rows[i].container.style.display = '';\n if(self.rows[i].tab) self.rows[i].tab.style.display = '';\n self.rows[i].register();\n }\n else {\n self.addRow(val,initial);\n }\n });\n\n for(var j=value.length; j<self.rows.length; j++) {\n self.destroyRow(self.rows[j]);\n self.rows[j] = null;\n }\n self.rows = self.rows.slice(0,value.length);\n\n // Set the active tab\n var new_active_tab = null;\n $each(self.rows, function(i,row) {\n if(row.tab === self.active_tab) {\n new_active_tab = row.tab;\n return false;\n }\n });\n if(!new_active_tab && self.rows.length) new_active_tab = self.rows[0].tab;\n\n self.active_tab = new_active_tab;\n\n self.refreshValue(initial);\n self.refreshTabs(true);\n self.refreshTabs();\n\n self.onChange();\n \n // TODO: sortable\n },\n refreshValue: function(force) {\n var self = this;\n var oldi = this.value? this.value.length : 0;\n this.value = [];\n\n $each(this.rows,function(i,editor) {\n // Get the value for this editor\n self.value[i] = editor.getValue();\n });\n \n if(oldi !== this.value.length || force) {\n // If we currently have minItems items in the array\n var minItems = this.schema.minItems && this.schema.minItems >= this.rows.length;\n \n $each(this.rows,function(i,editor) {\n // Hide the move down button for the last row\n if(editor.movedown_button) {\n if(i === self.rows.length - 1) {\n editor.movedown_button.style.display = 'none';\n }\n else {\n editor.movedown_button.style.display = '';\n }\n }\n\n // Hide the delete button if we have minItems items\n if(editor.delete_button) {\n if(minItems) {\n editor.delete_button.style.display = 'none';\n }\n else {\n editor.delete_button.style.display = '';\n }\n }\n\n // Get the value for this editor\n self.value[i] = editor.getValue();\n });\n \n var controls_needed = false;\n \n if(!this.value.length) {\n this.delete_last_row_button.style.display = 'none';\n this.remove_all_rows_button.style.display = 'none';\n }\n else if(this.value.length === 1) { \n this.remove_all_rows_button.style.display = 'none'; \n\n // If there are minItems items in the array, hide the delete button beneath the rows\n if(minItems || this.hide_delete_buttons) {\n this.delete_last_row_button.style.display = 'none';\n }\n else {\n this.delete_last_row_button.style.display = '';\n controls_needed = true;\n }\n }\n else {\n // If there are minItems items in the array, hide the delete button beneath the rows\n if(minItems || this.hide_delete_buttons) {\n this.delete_last_row_button.style.display = 'none';\n this.remove_all_rows_button.style.display = 'none';\n }\n else {\n this.delete_last_row_button.style.display = '';\n this.remove_all_rows_button.style.display = '';\n controls_needed = true;\n }\n }\n\n // If there are maxItems in the array, hide the add button beneath the rows\n if((this.getMax() && this.getMax() <= this.rows.length) || this.hide_add_button){\n this.add_row_button.style.display = 'none';\n }\n else {\n this.add_row_button.style.display = '';\n controls_needed = true;\n } \n \n if(!this.collapsed && controls_needed) {\n this.controls.style.display = 'inline-block';\n }\n else {\n this.controls.style.display = 'none';\n }\n }\n },\n addRow: function(value, initial) {\n var self = this;\n var i = this.rows.length;\n \n self.rows[i] = this.getElementEditor(i);\n self.row_cache[i] = self.rows[i];\n\n if(self.tabs_holder) {\n self.rows[i].tab_text = document.createElement('span');\n self.rows[i].tab_text.textContent = self.rows[i].getHeaderText();\n self.rows[i].tab = self.theme.getTab(self.rows[i].tab_text);\n self.rows[i].tab.addEventListener('click', function(e) {\n self.active_tab = self.rows[i].tab;\n self.refreshTabs();\n e.preventDefault();\n e.stopPropagation();\n });\n\n self.theme.addTab(self.tabs_holder, self.rows[i].tab);\n }\n \n var controls_holder = self.rows[i].title_controls || self.rows[i].array_controls;\n \n // Buttons to delete row, move row up, and move row down\n if(!self.hide_delete_buttons) {\n self.rows[i].delete_button = this.getButton(self.getItemTitle(),'delete',this.translate('button_delete_row_title',[self.getItemTitle()]));\n self.rows[i].delete_button.className += ' delete';\n self.rows[i].delete_button.setAttribute('data-i',i);\n self.rows[i].delete_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n var i = this.getAttribute('data-i')*1;\n\n var value = self.getValue();\n\n var newval = [];\n var new_active_tab = null;\n $each(value,function(j,row) {\n if(j===i) {\n // If the one we're deleting is the active tab\n if(self.rows[j].tab === self.active_tab) {\n // Make the next tab active if there is one\n // Note: the next tab is going to be the current tab after deletion\n if(self.rows[j+1]) new_active_tab = self.rows[j].tab;\n // Otherwise, make the previous tab active if there is one\n else if(j) new_active_tab = self.rows[j-1].tab;\n }\n \n return; // If this is the one we're deleting\n }\n newval.push(row);\n });\n self.setValue(newval);\n if(new_active_tab) {\n self.active_tab = new_active_tab;\n self.refreshTabs();\n }\n\n self.onChange(true);\n });\n \n if(controls_holder) {\n controls_holder.appendChild(self.rows[i].delete_button);\n }\n }\n \n if(i && !self.hide_move_buttons) {\n self.rows[i].moveup_button = this.getButton('','moveup',this.translate('button_move_up_title'));\n self.rows[i].moveup_button.className += ' moveup';\n self.rows[i].moveup_button.setAttribute('data-i',i);\n self.rows[i].moveup_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n var i = this.getAttribute('data-i')*1;\n\n if(i<=0) return;\n var rows = self.getValue();\n var tmp = rows[i-1];\n rows[i-1] = rows[i];\n rows[i] = tmp;\n\n self.setValue(rows);\n self.active_tab = self.rows[i-1].tab;\n self.refreshTabs();\n\n self.onChange(true);\n });\n \n if(controls_holder) {\n controls_holder.appendChild(self.rows[i].moveup_button);\n }\n }\n \n if(!self.hide_move_buttons) {\n self.rows[i].movedown_button = this.getButton('','movedown',this.translate('button_move_down_title'));\n self.rows[i].movedown_button.className += ' movedown';\n self.rows[i].movedown_button.setAttribute('data-i',i);\n self.rows[i].movedown_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n var i = this.getAttribute('data-i')*1;\n\n var rows = self.getValue();\n if(i>=rows.length-1) return;\n var tmp = rows[i+1];\n rows[i+1] = rows[i];\n rows[i] = tmp;\n\n self.setValue(rows);\n self.active_tab = self.rows[i+1].tab;\n self.refreshTabs();\n self.onChange(true);\n });\n \n if(controls_holder) {\n controls_holder.appendChild(self.rows[i].movedown_button);\n }\n }\n\n if(value) self.rows[i].setValue(value, initial);\n self.refreshTabs();\n },\n addControls: function() {\n var self = this;\n \n this.collapsed = false;\n this.toggle_button = this.getButton('','collapse',this.translate('button_collapse'));\n this.title_controls.appendChild(this.toggle_button);\n var row_holder_display = self.row_holder.style.display;\n var controls_display = self.controls.style.display;\n this.toggle_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n if(self.collapsed) {\n self.collapsed = false;\n if(self.panel) self.panel.style.display = '';\n self.row_holder.style.display = row_holder_display;\n if(self.tabs_holder) self.tabs_holder.style.display = '';\n self.controls.style.display = controls_display;\n self.setButtonText(this,'','collapse','Collapse');\n }\n else {\n self.collapsed = true;\n self.row_holder.style.display = 'none';\n if(self.tabs_holder) self.tabs_holder.style.display = 'none';\n self.controls.style.display = 'none';\n if(self.panel) self.panel.style.display = 'none';\n self.setButtonText(this,'','expand','Expand');\n }\n });\n\n // If it should start collapsed\n if(this.options.collapsed) {\n $trigger(this.toggle_button,'click');\n }\n \n // Collapse button disabled\n if(this.schema.options && typeof this.schema.options.disable_collapse !== \"undefined\") {\n if(this.schema.options.disable_collapse) this.toggle_button.style.display = 'none';\n }\n else if(this.jsoneditor.options.disable_collapse) {\n this.toggle_button.style.display = 'none';\n }\n \n // Add \"new row\" and \"delete last\" buttons below editor\n this.add_row_button = this.getButton(this.getItemTitle(),'add',this.translate('button_add_row_title',[this.getItemTitle()]));\n \n this.add_row_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n var i = self.rows.length;\n if(self.row_cache[i]) {\n self.rows[i] = self.row_cache[i];\n self.rows[i].setValue(self.rows[i].getDefault());\n self.rows[i].container.style.display = '';\n if(self.rows[i].tab) self.rows[i].tab.style.display = '';\n self.rows[i].register();\n }\n else {\n self.addRow();\n }\n self.active_tab = self.rows[i].tab;\n self.refreshTabs();\n self.refreshValue();\n self.onChange(true);\n });\n self.controls.appendChild(this.add_row_button);\n\n this.delete_last_row_button = this.getButton(this.translate('button_delete_last',[this.getItemTitle()]),'delete',this.translate('button_delete_last_title',[this.getItemTitle()]));\n this.delete_last_row_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n var rows = self.getValue();\n \n var new_active_tab = null;\n if(self.rows.length > 1 && self.rows[self.rows.length-1].tab === self.active_tab) new_active_tab = self.rows[self.rows.length-2].tab;\n \n rows.pop();\n self.setValue(rows);\n if(new_active_tab) {\n self.active_tab = new_active_tab;\n self.refreshTabs();\n }\n self.onChange(true);\n });\n self.controls.appendChild(this.delete_last_row_button);\n\n this.remove_all_rows_button = this.getButton(this.translate('button_delete_all'),'delete',this.translate('button_delete_all_title'));\n this.remove_all_rows_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n self.setValue([]);\n self.onChange(true);\n });\n self.controls.appendChild(this.remove_all_rows_button);\n\n if(self.tabs) {\n this.add_row_button.style.width = '100%';\n this.add_row_button.style.textAlign = 'left';\n this.add_row_button.style.marginBottom = '3px';\n \n this.delete_last_row_button.style.width = '100%';\n this.delete_last_row_button.style.textAlign = 'left';\n this.delete_last_row_button.style.marginBottom = '3px';\n \n this.remove_all_rows_button.style.width = '100%';\n this.remove_all_rows_button.style.textAlign = 'left';\n this.remove_all_rows_button.style.marginBottom = '3px';\n }\n },\n showValidationErrors: function(errors) {\n var self = this;\n\n // Get all the errors that pertain to this editor\n var my_errors = [];\n var other_errors = [];\n $each(errors, function(i,error) {\n if(error.path === self.path) {\n my_errors.push(error);\n }\n else {\n other_errors.push(error);\n }\n });\n\n // Show errors for this editor\n if(this.error_holder) {\n if(my_errors.length) {\n var message = [];\n this.error_holder.innerHTML = '';\n this.error_holder.style.display = '';\n $each(my_errors, function(i,error) {\n self.error_holder.appendChild(self.theme.getErrorMessage(error.message));\n });\n }\n // Hide error area\n else {\n this.error_holder.style.display = 'none';\n }\n }\n\n // Show errors for child editors\n $each(this.rows, function(i,row) {\n row.showValidationErrors(other_errors);\n });\n }\n});\n",
70
+ "JSONEditor.defaults.editors.table = JSONEditor.defaults.editors.array.extend({\n register: function() {\n this._super();\n if(this.rows) {\n for(var i=0; i<this.rows.length; i++) {\n this.rows[i].register();\n }\n }\n },\n unregister: function() {\n this._super();\n if(this.rows) {\n for(var i=0; i<this.rows.length; i++) {\n this.rows[i].unregister();\n }\n }\n },\n getNumColumns: function() {\n return Math.max(Math.min(12,this.width),3);\n },\n preBuild: function() {\n var item_schema = this.jsoneditor.expandRefs(this.schema.items || {});\n\n this.item_title = item_schema.title || 'row';\n this.item_default = item_schema[\"default\"] || null;\n this.item_has_child_editors = item_schema.properties || item_schema.items;\n this.width = 12;\n this._super();\n },\n build: function() {\n var self = this;\n this.table = this.theme.getTable();\n this.container.appendChild(this.table);\n this.thead = this.theme.getTableHead();\n this.table.appendChild(this.thead);\n this.header_row = this.theme.getTableRow();\n this.thead.appendChild(this.header_row);\n this.row_holder = this.theme.getTableBody();\n this.table.appendChild(this.row_holder);\n\n // Determine the default value of array element\n var tmp = this.getElementEditor(0,true);\n this.item_default = tmp.getDefault();\n this.width = tmp.getNumColumns() + 2;\n \n if(!this.options.compact) {\n this.title = this.theme.getHeader(this.getTitle());\n this.container.appendChild(this.title);\n this.title_controls = this.theme.getHeaderButtonHolder();\n this.title.appendChild(this.title_controls);\n if(this.schema.description) {\n this.description = this.theme.getDescription(this.schema.description);\n this.container.appendChild(this.description);\n }\n this.panel = this.theme.getIndentedPanel();\n this.container.appendChild(this.panel);\n this.error_holder = document.createElement('div');\n this.panel.appendChild(this.error_holder);\n }\n else {\n this.panel = document.createElement('div');\n this.container.appendChild(this.panel);\n }\n\n this.panel.appendChild(this.table);\n this.controls = this.theme.getButtonHolder();\n this.panel.appendChild(this.controls);\n\n if(this.item_has_child_editors) {\n var ce = tmp.getChildEditors();\n var order = tmp.property_order || Object.keys(ce);\n for(var i=0; i<order.length; i++) {\n var th = self.theme.getTableHeaderCell(ce[order[i]].getTitle());\n if(ce[order[i]].options.hidden) th.style.display = 'none';\n self.header_row.appendChild(th);\n }\n }\n else {\n self.header_row.appendChild(self.theme.getTableHeaderCell(this.item_title));\n }\n\n tmp.destroy();\n this.row_holder.innerHTML = '';\n\n // Row Controls column\n this.controls_header_cell = self.theme.getTableHeaderCell(\" \");\n self.header_row.appendChild(this.controls_header_cell);\n\n // Add controls\n this.addControls();\n },\n onChildEditorChange: function(editor) {\n this.refreshValue();\n this._super();\n },\n getItemDefault: function() {\n return $extend({},{\"default\":this.item_default})[\"default\"];\n },\n getItemTitle: function() {\n return this.item_title;\n },\n getElementEditor: function(i,ignore) {\n var schema_copy = $extend({},this.schema.items);\n var editor = this.jsoneditor.getEditorClass(schema_copy, this.jsoneditor);\n var row = this.row_holder.appendChild(this.theme.getTableRow());\n var holder = row;\n if(!this.item_has_child_editors) {\n holder = this.theme.getTableCell();\n row.appendChild(holder);\n }\n\n var ret = this.jsoneditor.createEditor(editor,{\n jsoneditor: this.jsoneditor,\n schema: schema_copy,\n container: holder,\n path: this.path+'.'+i,\n parent: this,\n compact: true,\n table_row: true\n });\n \n ret.preBuild();\n if(!ignore) {\n ret.build();\n ret.postBuild();\n\n ret.controls_cell = row.appendChild(this.theme.getTableCell());\n ret.row = row;\n ret.table_controls = this.theme.getButtonHolder();\n ret.controls_cell.appendChild(ret.table_controls);\n ret.table_controls.style.margin = 0;\n ret.table_controls.style.padding = 0;\n }\n \n return ret;\n },\n destroy: function() {\n this.innerHTML = '';\n if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);\n if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);\n if(this.row_holder && this.row_holder.parentNode) this.row_holder.parentNode.removeChild(this.row_holder);\n if(this.table && this.table.parentNode) this.table.parentNode.removeChild(this.table);\n if(this.panel && this.panel.parentNode) this.panel.parentNode.removeChild(this.panel);\n\n this.rows = this.title = this.description = this.row_holder = this.table = this.panel = null;\n\n this._super();\n },\n setValue: function(value, initial) {\n // Update the array's value, adding/removing rows when necessary\n value = value || [];\n\n // Make sure value has between minItems and maxItems items in it\n if(this.schema.minItems) {\n while(value.length < this.schema.minItems) {\n value.push(this.getItemDefault());\n }\n }\n if(this.schema.maxItems && value.length > this.schema.maxItems) {\n value = value.slice(0,this.schema.maxItems);\n }\n \n var serialized = JSON.stringify(value);\n if(serialized === this.serialized) return;\n\n var numrows_changed = false;\n\n var self = this;\n $each(value,function(i,val) {\n if(self.rows[i]) {\n // TODO: don't set the row's value if it hasn't changed\n self.rows[i].setValue(val);\n }\n else {\n self.addRow(val);\n numrows_changed = true;\n }\n });\n\n for(var j=value.length; j<self.rows.length; j++) {\n var holder = self.rows[j].container;\n if(!self.item_has_child_editors) {\n self.rows[j].row.parentNode.removeChild(self.rows[j].row);\n }\n self.rows[j].destroy();\n if(holder.parentNode) holder.parentNode.removeChild(holder);\n self.rows[j] = null;\n numrows_changed = true;\n }\n self.rows = self.rows.slice(0,value.length);\n\n self.refreshValue();\n if(numrows_changed || initial) self.refreshRowButtons();\n\n self.onChange();\n \n // TODO: sortable\n },\n refreshRowButtons: function() {\n var self = this;\n \n // If we currently have minItems items in the array\n var minItems = this.schema.minItems && this.schema.minItems >= this.rows.length;\n \n var need_row_buttons = false;\n $each(this.rows,function(i,editor) {\n // Hide the move down button for the last row\n if(editor.movedown_button) {\n if(i === self.rows.length - 1) {\n editor.movedown_button.style.display = 'none';\n }\n else {\n need_row_buttons = true;\n editor.movedown_button.style.display = '';\n }\n }\n\n // Hide the delete button if we have minItems items\n if(editor.delete_button) {\n if(minItems) {\n editor.delete_button.style.display = 'none';\n }\n else {\n need_row_buttons = true;\n editor.delete_button.style.display = '';\n }\n }\n \n if(editor.moveup_button) {\n need_row_buttons = true;\n }\n });\n \n // Show/hide controls column in table\n $each(this.rows,function(i,editor) {\n if(need_row_buttons) {\n editor.controls_cell.style.display = '';\n }\n else {\n editor.controls_cell.style.display = 'none';\n }\n });\n if(need_row_buttons) {\n this.controls_header_cell.style.display = '';\n }\n else {\n this.controls_header_cell.style.display = 'none';\n }\n \n var controls_needed = false;\n \n if(!this.value.length) {\n this.delete_last_row_button.style.display = 'none';\n this.remove_all_rows_button.style.display = 'none';\n this.table.style.display = 'none';\n }\n else if(this.value.length === 1 || this.hide_delete_buttons) {\n this.table.style.display = '';\n this.remove_all_rows_button.style.display = 'none';\n\n // If there are minItems items in the array, hide the delete button beneath the rows\n if(minItems || this.hide_delete_buttons) {\n this.delete_last_row_button.style.display = 'none';\n }\n else {\n this.delete_last_row_button.style.display = '';\n controls_needed = true;\n }\n }\n else {\n this.table.style.display = '';\n // If there are minItems items in the array, hide the delete button beneath the rows\n if(minItems || this.hide_delete_buttons) {\n this.delete_last_row_button.style.display = 'none';\n this.remove_all_rows_button.style.display = 'none';\n }\n else {\n this.delete_last_row_button.style.display = '';\n this.remove_all_rows_button.style.display = '';\n controls_needed = true;\n }\n }\n\n // If there are maxItems in the array, hide the add button beneath the rows\n if((this.schema.maxItems && this.schema.maxItems <= this.rows.length) || this.hide_add_button) {\n this.add_row_button.style.display = 'none';\n }\n else {\n this.add_row_button.style.display = '';\n controls_needed = true;\n }\n \n if(!controls_needed) {\n this.controls.style.display = 'none';\n }\n else {\n this.controls.style.display = '';\n }\n },\n refreshValue: function() {\n var self = this;\n this.value = [];\n\n $each(this.rows,function(i,editor) {\n // Get the value for this editor\n self.value[i] = editor.getValue();\n });\n this.serialized = JSON.stringify(this.value);\n },\n addRow: function(value) {\n var self = this;\n var i = this.rows.length;\n\n self.rows[i] = this.getElementEditor(i);\n\n var controls_holder = self.rows[i].table_controls;\n\n // Buttons to delete row, move row up, and move row down\n if(!this.hide_delete_buttons) {\n self.rows[i].delete_button = this.getButton('','delete',this.translate('button_delete_row_title_short'));\n self.rows[i].delete_button.className += ' delete';\n self.rows[i].delete_button.setAttribute('data-i',i);\n self.rows[i].delete_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n var i = this.getAttribute('data-i')*1;\n\n var value = self.getValue();\n\n var newval = [];\n $each(value,function(j,row) {\n if(j===i) return; // If this is the one we're deleting\n newval.push(row);\n });\n self.setValue(newval);\n self.onChange(true);\n });\n controls_holder.appendChild(self.rows[i].delete_button);\n }\n\n \n if(i && !this.hide_move_buttons) {\n self.rows[i].moveup_button = this.getButton('','moveup',this.translate('button_move_up_title'));\n self.rows[i].moveup_button.className += ' moveup';\n self.rows[i].moveup_button.setAttribute('data-i',i);\n self.rows[i].moveup_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n var i = this.getAttribute('data-i')*1;\n\n if(i<=0) return;\n var rows = self.getValue();\n var tmp = rows[i-1];\n rows[i-1] = rows[i];\n rows[i] = tmp;\n\n self.setValue(rows);\n self.onChange(true);\n });\n controls_holder.appendChild(self.rows[i].moveup_button);\n }\n \n if(!this.hide_move_buttons) {\n self.rows[i].movedown_button = this.getButton('','movedown',this.translate('button_move_down_title'));\n self.rows[i].movedown_button.className += ' movedown';\n self.rows[i].movedown_button.setAttribute('data-i',i);\n self.rows[i].movedown_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n var i = this.getAttribute('data-i')*1;\n var rows = self.getValue();\n if(i>=rows.length-1) return;\n var tmp = rows[i+1];\n rows[i+1] = rows[i];\n rows[i] = tmp;\n\n self.setValue(rows);\n self.onChange(true);\n });\n controls_holder.appendChild(self.rows[i].movedown_button);\n }\n\n if(value) self.rows[i].setValue(value);\n },\n addControls: function() {\n var self = this;\n\n this.collapsed = false;\n this.toggle_button = this.getButton('','collapse',this.translate('button_collapse'));\n if(this.title_controls) {\n this.title_controls.appendChild(this.toggle_button);\n this.toggle_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n if(self.collapsed) {\n self.collapsed = false;\n self.panel.style.display = '';\n self.setButtonText(this,'','collapse','Collapse');\n }\n else {\n self.collapsed = true;\n self.panel.style.display = 'none';\n self.setButtonText(this,'','expand','Expand');\n }\n });\n\n // If it should start collapsed\n if(this.options.collapsed) {\n $trigger(this.toggle_button,'click');\n }\n\n // Collapse button disabled\n if(this.schema.options && typeof this.schema.options.disable_collapse !== \"undefined\") {\n if(this.schema.options.disable_collapse) this.toggle_button.style.display = 'none';\n }\n else if(this.jsoneditor.options.disable_collapse) {\n this.toggle_button.style.display = 'none';\n }\n }\n\n // Add \"new row\" and \"delete last\" buttons below editor\n this.add_row_button = this.getButton(this.getItemTitle(),'add',this.translate('button_add_row_title',[this.getItemTitle()]));\n this.add_row_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n \n self.addRow();\n self.refreshValue();\n self.refreshRowButtons();\n self.onChange(true);\n });\n self.controls.appendChild(this.add_row_button);\n\n this.delete_last_row_button = this.getButton(this.translate('button_delete_last',[this.getItemTitle()]),'delete',this.translate('button_delete_last_title',[this.getItemTitle()]));\n this.delete_last_row_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n \n var rows = self.getValue();\n rows.pop();\n self.setValue(rows);\n self.onChange(true);\n });\n self.controls.appendChild(this.delete_last_row_button);\n\n this.remove_all_rows_button = this.getButton(this.translate('button_delete_all'),'delete',this.translate('button_delete_all_title'));\n this.remove_all_rows_button.addEventListener('click',function(e) {\n e.preventDefault();\n e.stopPropagation();\n \n self.setValue([]);\n self.onChange(true);\n });\n self.controls.appendChild(this.remove_all_rows_button);\n }\n});\n",
71
+ "// Multiple Editor (for when `type` is an array)\nJSONEditor.defaults.editors.multiple = JSONEditor.AbstractEditor.extend({\n register: function() {\n if(this.editors) {\n for(var i=0; i<this.editors.length; i++) {\n if(!this.editors[i]) continue;\n this.editors[i].unregister();\n }\n if(this.editors[this.type]) this.editors[this.type].register();\n }\n this._super();\n },\n unregister: function() {\n this._super();\n if(this.editors) {\n for(var i=0; i<this.editors.length; i++) {\n if(!this.editors[i]) continue;\n this.editors[i].unregister();\n }\n }\n },\n getNumColumns: function() {\n if(!this.editors[this.type]) return 4;\n return Math.max(this.editors[this.type].getNumColumns(),4);\n },\n enable: function() {\n if(this.editors) {\n for(var i=0; i<this.editors.length; i++) {\n if(!this.editors[i]) continue;\n this.editors[i].enable();\n }\n }\n this.switcher.disabled = false;\n this._super();\n },\n disable: function() {\n if(this.editors) {\n for(var i=0; i<this.editors.length; i++) {\n if(!this.editors[i]) continue;\n this.editors[i].disable();\n }\n }\n this.switcher.disabled = true;\n this._super();\n },\n switchEditor: function(i) {\n var self = this;\n\n if(!this.editors[i]) {\n this.buildChildEditor(i);\n }\n\n self.type = i;\n\n self.register();\n\n var current_value = self.getValue();\n\n $each(self.editors,function(type,editor) {\n if(!editor) return;\n if(self.type === type) {\n if(self.keep_values) editor.setValue(current_value,true);\n editor.container.style.display = '';\n }\n else editor.container.style.display = 'none';\n });\n self.refreshValue();\n self.refreshHeaderText();\n },\n buildChildEditor: function(i) {\n var self = this;\n var type = this.types[i];\n var holder = self.theme.getChildEditorHolder();\n self.editor_holder.appendChild(holder);\n\n var schema;\n\n if(typeof type === \"string\") {\n schema = $extend({},self.schema);\n schema.type = type;\n }\n else {\n schema = $extend({},self.schema,type);\n schema = self.jsoneditor.expandRefs(schema);\n\n // If we need to merge `required` arrays\n if(type.required && Array.isArray(type.required) && self.schema.required && Array.isArray(self.schema.required)) {\n schema.required = self.schema.required.concat(type.required);\n }\n }\n\n var editor = self.jsoneditor.getEditorClass(schema);\n\n self.editors[i] = self.jsoneditor.createEditor(editor,{\n jsoneditor: self.jsoneditor,\n schema: schema,\n container: holder,\n path: self.path,\n parent: self,\n required: true\n });\n self.editors[i].preBuild();\n self.editors[i].build();\n self.editors[i].postBuild();\n\n if(self.editors[i].header) self.editors[i].header.style.display = 'none';\n\n self.editors[i].option = self.switcher_options[i];\n\n holder.addEventListener('change_header_text',function() {\n self.refreshHeaderText();\n });\n\n if(i !== self.type) holder.style.display = 'none';\n },\n preBuild: function() {\n var self = this;\n\n this.types = [];\n this.type = 0;\n this.editors = [];\n this.validators = [];\n\n this.keep_values = true;\n if(typeof this.jsoneditor.options.keep_oneof_values !== \"undefined\") this.keep_values = this.jsoneditor.options.keep_oneof_values;\n if(typeof this.options.keep_oneof_values !== \"undefined\") this.keep_values = this.options.keep_oneof_values;\n\n if(this.schema.oneOf) {\n this.oneOf = true;\n this.types = this.schema.oneOf;\n $each(this.types,function(i,oneof) {\n //self.types[i] = self.jsoneditor.expandSchema(oneof);\n });\n delete this.schema.oneOf;\n }\n else {\n if(!this.schema.type || this.schema.type === \"any\") {\n this.types = ['string','number','integer','boolean','object','array','null'];\n\n // If any of these primitive types are disallowed\n if(this.schema.disallow) {\n var disallow = this.schema.disallow;\n if(typeof disallow !== 'object' || !(Array.isArray(disallow))) {\n disallow = [disallow];\n }\n var allowed_types = [];\n $each(this.types,function(i,type) {\n if(disallow.indexOf(type) === -1) allowed_types.push(type);\n });\n this.types = allowed_types;\n }\n }\n else if(Array.isArray(this.schema.type)) {\n this.types = this.schema.type;\n }\n else {\n this.types = [this.schema.type];\n }\n delete this.schema.type;\n }\n\n this.display_text = this.getDisplayText(this.types);\n },\n build: function() {\n var self = this;\n var container = this.container;\n\n this.header = this.label = this.theme.getFormInputLabel(this.getTitle());\n this.container.appendChild(this.header);\n\n this.switcher = this.theme.getSwitcher(this.display_text);\n container.appendChild(this.switcher);\n this.switcher.addEventListener('change',function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n self.switchEditor(self.display_text.indexOf(this.value));\n self.onChange(true);\n });\n\n this.editor_holder = document.createElement('div');\n container.appendChild(this.editor_holder);\n \n \n var validator_options = {};\n if(self.jsoneditor.options.custom_validators) {\n validator_options.custom_validators = self.jsoneditor.options.custom_validators;\n }\n\n this.switcher_options = this.theme.getSwitcherOptions(this.switcher);\n $each(this.types,function(i,type) {\n self.editors[i] = false;\n\n var schema;\n\n if(typeof type === \"string\") {\n schema = $extend({},self.schema);\n schema.type = type;\n }\n else {\n schema = $extend({},self.schema,type);\n\n // If we need to merge `required` arrays\n if(type.required && Array.isArray(type.required) && self.schema.required && Array.isArray(self.schema.required)) {\n schema.required = self.schema.required.concat(type.required);\n }\n }\n\n self.validators[i] = new JSONEditor.Validator(self.jsoneditor,schema,validator_options);\n });\n\n this.switchEditor(0);\n },\n onChildEditorChange: function(editor) {\n if(this.editors[this.type]) {\n this.refreshValue();\n this.refreshHeaderText();\n }\n\n this._super();\n },\n refreshHeaderText: function() {\n var display_text = this.getDisplayText(this.types);\n $each(this.switcher_options, function(i,option) {\n option.textContent = display_text[i];\n });\n },\n refreshValue: function() {\n this.value = this.editors[this.type].getValue();\n },\n setValue: function(val,initial) {\n // Determine type by getting the first one that validates\n var self = this;\n $each(this.validators, function(i,validator) {\n if(!validator.validate(val).length) {\n self.type = i;\n self.switcher.value = self.display_text[i];\n return false;\n }\n });\n\n this.switchEditor(this.type);\n\n this.editors[this.type].setValue(val,initial);\n\n this.refreshValue();\n self.onChange();\n },\n destroy: function() {\n $each(this.editors, function(type,editor) {\n if(editor) editor.destroy();\n });\n if(this.editor_holder && this.editor_holder.parentNode) this.editor_holder.parentNode.removeChild(this.editor_holder);\n if(this.switcher && this.switcher.parentNode) this.switcher.parentNode.removeChild(this.switcher);\n this._super();\n },\n showValidationErrors: function(errors) {\n var self = this;\n\n // oneOf error paths need to remove the oneOf[i] part before passing to child editors\n if(this.oneOf) {\n $each(this.editors,function(i,editor) {\n if(!editor) return;\n var check = self.path+'.oneOf['+i+']';\n var new_errors = [];\n $each(errors, function(j,error) {\n if(error.path.substr(0,check.length)===check) {\n var new_error = $extend({},error);\n new_error.path = self.path+new_error.path.substr(check.length);\n new_errors.push(new_error);\n }\n });\n\n editor.showValidationErrors(new_errors);\n });\n }\n else {\n $each(this.editors,function(type,editor) {\n if(!editor) return;\n editor.showValidationErrors(errors);\n });\n }\n }\n});\n",
72
+ "// Enum Editor (used for objects and arrays with enumerated values)\nJSONEditor.defaults.editors[\"enum\"] = JSONEditor.AbstractEditor.extend({\n getNumColumns: function() {\n return 4;\n },\n build: function() {\n var container = this.container;\n this.title = this.header = this.label = this.theme.getFormInputLabel(this.getTitle());\n this.container.appendChild(this.title);\n\n this.options.enum_titles = this.options.enum_titles || [];\n\n this[\"enum\"] = this.schema[\"enum\"];\n this.selected = 0;\n this.select_options = [];\n this.html_values = [];\n\n var self = this;\n for(var i=0; i<this[\"enum\"].length; i++) {\n this.select_options[i] = this.options.enum_titles[i] || \"Value \"+(i+1);\n this.html_values[i] = this.getHTML(this[\"enum\"][i]);\n }\n\n // Switcher\n this.switcher = this.theme.getSwitcher(this.select_options);\n this.container.appendChild(this.switcher);\n\n // Display area\n this.display_area = this.theme.getIndentedPanel();\n this.container.appendChild(this.display_area);\n\n if(this.options.hide_display) this.display_area.style.display = \"none\";\n\n this.switcher.addEventListener('change',function() {\n self.selected = self.select_options.indexOf(this.value);\n self.value = self[\"enum\"][self.selected];\n self.refreshValue();\n self.onChange(true);\n });\n this.value = this[\"enum\"][0];\n this.refreshValue();\n\n if(this[\"enum\"].length === 1) this.switcher.style.display = 'none';\n },\n refreshValue: function() {\n var self = this;\n self.selected = -1;\n var stringified = JSON.stringify(this.value);\n $each(this[\"enum\"], function(i, el) {\n if(stringified === JSON.stringify(el)) {\n self.selected = i;\n return false;\n }\n });\n\n if(self.selected<0) {\n self.setValue(self[\"enum\"][0]);\n return;\n }\n\n this.switcher.value = this.select_options[this.selected];\n this.display_area.innerHTML = this.html_values[this.selected];\n },\n enable: function() {\n if(!this.always_disabled) this.switcher.disabled = false;\n this._super();\n },\n disable: function() {\n this.switcher.disabled = true;\n this._super();\n },\n getHTML: function(el) {\n var self = this;\n\n if(el === null) {\n return '<em>null</em>';\n }\n // Array or Object\n else if(typeof el === \"object\") {\n // TODO: use theme\n var ret = '';\n\n $each(el,function(i,child) {\n var html = self.getHTML(child);\n\n // Add the keys to object children\n if(!(Array.isArray(el))) {\n // TODO: use theme\n html = '<div><em>'+i+'</em>: '+html+'</div>';\n }\n\n // TODO: use theme\n ret += '<li>'+html+'</li>';\n });\n\n if(Array.isArray(el)) ret = '<ol>'+ret+'</ol>';\n else ret = \"<ul style='margin-top:0;margin-bottom:0;padding-top:0;padding-bottom:0;'>\"+ret+'</ul>';\n\n return ret;\n }\n // Boolean\n else if(typeof el === \"boolean\") {\n return el? 'true' : 'false';\n }\n // String\n else if(typeof el === \"string\") {\n return el.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n }\n // Number\n else {\n return el;\n }\n },\n setValue: function(val) {\n if(this.value !== val) {\n this.value = val;\n this.refreshValue();\n this.onChange();\n }\n },\n destroy: function() {\n if(this.display_area && this.display_area.parentNode) this.display_area.parentNode.removeChild(this.display_area);\n if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);\n if(this.switcher && this.switcher.parentNode) this.switcher.parentNode.removeChild(this.switcher);\n\n this._super();\n }\n});\n",
73
+ "JSONEditor.defaults.editors.select = JSONEditor.AbstractEditor.extend({\n setValue: function(value,initial) {\n value = this.typecast(value||'');\n\n // Sanitize value before setting it\n var sanitized = value;\n if(this.enum_values.indexOf(sanitized) < 0) {\n sanitized = this.enum_values[0];\n }\n\n if(this.value === sanitized) {\n return;\n }\n\n this.input.value = this.enum_options[this.enum_values.indexOf(sanitized)];\n if(this.select2) this.select2.select2('val',this.input.value);\n this.value = sanitized;\n this.onChange();\n },\n register: function() {\n this._super();\n if(!this.input) return;\n this.input.setAttribute('name',this.formname);\n },\n unregister: function() {\n this._super();\n if(!this.input) return;\n this.input.removeAttribute('name');\n },\n getNumColumns: function() {\n if(!this.enum_options) return 3;\n var longest_text = this.getTitle().length;\n for(var i=0; i<this.enum_options.length; i++) {\n longest_text = Math.max(longest_text,this.enum_options[i].length+4);\n }\n return Math.min(12,Math.max(longest_text/7,2));\n },\n typecast: function(value) {\n if(this.schema.type === \"boolean\") {\n return !!value;\n }\n else if(this.schema.type === \"number\") {\n return 1*value;\n }\n else if(this.schema.type === \"integer\") {\n return Math.floor(value*1);\n }\n else {\n return \"\"+value;\n }\n },\n getValue: function() {\n return this.value;\n },\n preBuild: function() {\n var self = this;\n this.input_type = 'select';\n this.enum_options = [];\n this.enum_values = [];\n this.enum_display = [];\n\n // Enum options enumerated\n if(this.schema[\"enum\"]) {\n var display = this.schema.options && this.schema.options.enum_titles || [];\n \n $each(this.schema[\"enum\"],function(i,option) {\n self.enum_options[i] = \"\"+option;\n self.enum_display[i] = \"\"+(display[i] || option);\n self.enum_values[i] = self.typecast(option);\n });\n\n if(!this.isRequired()){\n self.enum_display.unshift(' ');\n self.enum_options.unshift('undefined');\n self.enum_values.unshift(undefined);\n }\n \n }\n // Boolean\n else if(this.schema.type === \"boolean\") {\n self.enum_display = this.schema.options && this.schema.options.enum_titles || ['true','false'];\n self.enum_options = ['1',''];\n self.enum_values = [true,false];\n \n if(!this.isRequired()){\n self.enum_display.unshift(' ');\n self.enum_options.unshift('undefined');\n self.enum_values.unshift(undefined);\n }\n \n }\n // Dynamic Enum\n else if(this.schema.enumSource) {\n this.enumSource = [];\n this.enum_display = [];\n this.enum_options = [];\n this.enum_values = [];\n \n // Shortcut declaration for using a single array\n if(!(Array.isArray(this.schema.enumSource))) {\n if(this.schema.enumValue) {\n this.enumSource = [\n {\n source: this.schema.enumSource,\n value: this.schema.enumValue\n }\n ];\n }\n else {\n this.enumSource = [\n {\n source: this.schema.enumSource\n }\n ];\n }\n }\n else {\n for(i=0; i<this.schema.enumSource.length; i++) {\n // Shorthand for watched variable\n if(typeof this.schema.enumSource[i] === \"string\") {\n this.enumSource[i] = {\n source: this.schema.enumSource[i]\n };\n }\n // Make a copy of the schema\n else if(!(Array.isArray(this.schema.enumSource[i]))) {\n this.enumSource[i] = $extend({},this.schema.enumSource[i]);\n }\n else {\n this.enumSource[i] = this.schema.enumSource[i];\n }\n }\n }\n \n // Now, enumSource is an array of sources\n // Walk through this array and fix up the values\n for(i=0; i<this.enumSource.length; i++) {\n if(this.enumSource[i].value) {\n this.enumSource[i].value = this.jsoneditor.compileTemplate(this.enumSource[i].value, this.template_engine);\n }\n if(this.enumSource[i].title) {\n this.enumSource[i].title = this.jsoneditor.compileTemplate(this.enumSource[i].title, this.template_engine);\n }\n if(this.enumSource[i].filter) {\n this.enumSource[i].filter = this.jsoneditor.compileTemplate(this.enumSource[i].filter, this.template_engine);\n }\n }\n }\n // Other, not supported\n else {\n throw \"'select' editor requires the enum property to be set.\";\n }\n },\n build: function() {\n var self = this;\n if(!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());\n if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);\n\n if(this.options.compact) this.container.className += ' compact';\n\n this.input = this.theme.getSelectInput(this.enum_options);\n this.theme.setSelectOptions(this.input,this.enum_options,this.enum_display);\n\n if(this.schema.readOnly || this.schema.readonly) {\n this.always_disabled = true;\n this.input.disabled = true;\n }\n\n this.input.addEventListener('change',function(e) {\n e.preventDefault();\n e.stopPropagation();\n self.onInputChange();\n });\n\n this.control = this.theme.getFormControl(this.label, this.input, this.description);\n this.container.appendChild(this.control);\n\n this.value = this.enum_values[0];\n },\n onInputChange: function() {\n var val = this.input.value;\n\n var new_val;\n // Invalid option, use first option instead\n if(this.enum_options.indexOf(val) === -1) {\n new_val = this.enum_values[0];\n }\n else {\n new_val = this.enum_values[this.enum_options.indexOf(val)];\n }\n\n // If valid hasn't changed\n if(new_val === this.value) return;\n\n // Store new value and propogate change event\n this.value = new_val;\n this.onChange(true);\n },\n setupSelect2: function() {\n // If the Select2 library is loaded use it when we have lots of items\n if(window.jQuery && window.jQuery.fn && window.jQuery.fn.select2 && (this.enum_options.length > 2 || (this.enum_options.length && this.enumSource))) {\n var options = $extend({},JSONEditor.plugins.select2);\n if(this.schema.options && this.schema.options.select2_options) options = $extend(options,this.schema.options.select2_options);\n this.select2 = window.jQuery(this.input).select2(options);\n var self = this;\n this.select2.on('select2-blur',function() {\n self.input.value = self.select2.select2('val');\n self.onInputChange();\n });\n this.select2.on('change',function() {\n self.input.value = self.select2.select2('val');\n self.onInputChange();\n });\n }\n else {\n this.select2 = null;\n }\n },\n postBuild: function() {\n this._super();\n this.theme.afterInputReady(this.input);\n this.setupSelect2();\n },\n onWatchedFieldChange: function() {\n var self = this, vars, j;\n \n // If this editor uses a dynamic select box\n if(this.enumSource) {\n vars = this.getWatchedFieldValues();\n var select_options = [];\n var select_titles = [];\n \n for(var i=0; i<this.enumSource.length; i++) {\n // Constant values\n if(Array.isArray(this.enumSource[i])) {\n select_options = select_options.concat(this.enumSource[i]);\n select_titles = select_titles.concat(this.enumSource[i]);\n }\n else {\n var items = [];\n // Static list of items\n if(Array.isArray(this.enumSource[i].source)) {\n items = this.enumSource[i].source;\n // A watched field\n } else {\n items = vars[this.enumSource[i].source];\n }\n \n if(items) {\n // Only use a predefined part of the array\n if(this.enumSource[i].slice) {\n items = Array.prototype.slice.apply(items,this.enumSource[i].slice);\n }\n // Filter the items\n if(this.enumSource[i].filter) {\n var new_items = [];\n for(j=0; j<items.length; j++) {\n if(this.enumSource[i].filter({i:j,item:items[j],watched:vars})) new_items.push(items[j]);\n }\n items = new_items;\n }\n \n var item_titles = [];\n var item_values = [];\n for(j=0; j<items.length; j++) {\n var item = items[j];\n \n // Rendered value\n if(this.enumSource[i].value) {\n item_values[j] = this.enumSource[i].value({\n i: j,\n item: item\n });\n }\n // Use value directly\n else {\n item_values[j] = items[j];\n }\n \n // Rendered title\n if(this.enumSource[i].title) {\n item_titles[j] = this.enumSource[i].title({\n i: j,\n item: item\n });\n }\n // Use value as the title also\n else {\n item_titles[j] = item_values[j];\n }\n }\n \n // TODO: sort\n \n select_options = select_options.concat(item_values);\n select_titles = select_titles.concat(item_titles);\n }\n }\n }\n \n var prev_value = this.value;\n \n this.theme.setSelectOptions(this.input, select_options, select_titles);\n this.enum_options = select_options;\n this.enum_display = select_titles;\n this.enum_values = select_options;\n \n if(this.select2) {\n this.select2.select2('destroy');\n }\n \n // If the previous value is still in the new select options, stick with it\n if(select_options.indexOf(prev_value) !== -1) {\n this.input.value = prev_value;\n this.value = prev_value;\n }\n // Otherwise, set the value to the first select option\n else {\n this.input.value = select_options[0];\n this.value = select_options[0] || \"\"; \n if(this.parent) this.parent.onChildEditorChange(this);\n else this.jsoneditor.onChange();\n this.jsoneditor.notifyWatchers(this.path);\n }\n \n this.setupSelect2();\n }\n\n this._super();\n },\n enable: function() {\n if(!this.always_disabled) {\n this.input.disabled = false;\n if(this.select2) this.select2.select2(\"enable\",true);\n }\n this._super();\n },\n disable: function() {\n this.input.disabled = true;\n if(this.select2) this.select2.select2(\"enable\",false);\n this._super();\n },\n destroy: function() {\n if(this.label && this.label.parentNode) this.label.parentNode.removeChild(this.label);\n if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);\n if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);\n if(this.select2) {\n this.select2.select2('destroy');\n this.select2 = null;\n }\n\n this._super();\n }\n});\n",
74
+ "JSONEditor.defaults.editors.selectize = JSONEditor.AbstractEditor.extend({\n setValue: function(value,initial) {\n value = this.typecast(value||'');\n\n // Sanitize value before setting it\n var sanitized = value;\n if(this.enum_values.indexOf(sanitized) < 0) {\n sanitized = this.enum_values[0];\n }\n\n if(this.value === sanitized) {\n return;\n }\n\n this.input.value = this.enum_options[this.enum_values.indexOf(sanitized)];\n\n if(this.selectize) {\n this.selectize[0].selectize.addItem(sanitized);\n }\n\n this.value = sanitized;\n this.onChange();\n },\n register: function() {\n this._super();\n if(!this.input) return;\n this.input.setAttribute('name',this.formname);\n },\n unregister: function() {\n this._super();\n if(!this.input) return;\n this.input.removeAttribute('name');\n },\n getNumColumns: function() {\n if(!this.enum_options) return 3;\n var longest_text = this.getTitle().length;\n for(var i=0; i<this.enum_options.length; i++) {\n longest_text = Math.max(longest_text,this.enum_options[i].length+4);\n }\n return Math.min(12,Math.max(longest_text/7,2));\n },\n typecast: function(value) {\n if(this.schema.type === \"boolean\") {\n return !!value;\n }\n else if(this.schema.type === \"number\") {\n return 1*value;\n }\n else if(this.schema.type === \"integer\") {\n return Math.floor(value*1);\n }\n else {\n return \"\"+value;\n }\n },\n getValue: function() {\n return this.value;\n },\n preBuild: function() {\n var self = this;\n this.input_type = 'select';\n this.enum_options = [];\n this.enum_values = [];\n this.enum_display = [];\n\n // Enum options enumerated\n if(this.schema.enum) {\n var display = this.schema.options && this.schema.options.enum_titles || [];\n\n $each(this.schema.enum,function(i,option) {\n self.enum_options[i] = \"\"+option;\n self.enum_display[i] = \"\"+(display[i] || option);\n self.enum_values[i] = self.typecast(option);\n });\n }\n // Boolean\n else if(this.schema.type === \"boolean\") {\n self.enum_display = this.schema.options && this.schema.options.enum_titles || ['true','false'];\n self.enum_options = ['1','0'];\n self.enum_values = [true,false];\n }\n // Dynamic Enum\n else if(this.schema.enumSource) {\n this.enumSource = [];\n this.enum_display = [];\n this.enum_options = [];\n this.enum_values = [];\n\n // Shortcut declaration for using a single array\n if(!(Array.isArray(this.schema.enumSource))) {\n if(this.schema.enumValue) {\n this.enumSource = [\n {\n source: this.schema.enumSource,\n value: this.schema.enumValue\n }\n ];\n }\n else {\n this.enumSource = [\n {\n source: this.schema.enumSource\n }\n ];\n }\n }\n else {\n for(i=0; i<this.schema.enumSource.length; i++) {\n // Shorthand for watched variable\n if(typeof this.schema.enumSource[i] === \"string\") {\n this.enumSource[i] = {\n source: this.schema.enumSource[i]\n };\n }\n // Make a copy of the schema\n else if(!(Array.isArray(this.schema.enumSource[i]))) {\n this.enumSource[i] = $extend({},this.schema.enumSource[i]);\n }\n else {\n this.enumSource[i] = this.schema.enumSource[i];\n }\n }\n }\n\n // Now, enumSource is an array of sources\n // Walk through this array and fix up the values\n for(i=0; i<this.enumSource.length; i++) {\n if(this.enumSource[i].value) {\n this.enumSource[i].value = this.jsoneditor.compileTemplate(this.enumSource[i].value, this.template_engine);\n }\n if(this.enumSource[i].title) {\n this.enumSource[i].title = this.jsoneditor.compileTemplate(this.enumSource[i].title, this.template_engine);\n }\n if(this.enumSource[i].filter) {\n this.enumSource[i].filter = this.jsoneditor.compileTemplate(this.enumSource[i].filter, this.template_engine);\n }\n }\n }\n // Other, not supported\n else {\n throw \"'select' editor requires the enum property to be set.\";\n }\n },\n build: function() {\n var self = this;\n if(!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());\n if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);\n\n if(this.options.compact) this.container.className += ' compact';\n\n this.input = this.theme.getSelectInput(this.enum_options);\n this.theme.setSelectOptions(this.input,this.enum_options,this.enum_display);\n\n if(this.schema.readOnly || this.schema.readonly) {\n this.always_disabled = true;\n this.input.disabled = true;\n }\n\n this.input.addEventListener('change',function(e) {\n e.preventDefault();\n e.stopPropagation();\n self.onInputChange();\n });\n\n this.control = this.theme.getFormControl(this.label, this.input, this.description);\n this.container.appendChild(this.control);\n\n this.value = this.enum_values[0];\n },\n onInputChange: function() {\n var val = this.input.value;\n\n var sanitized = val;\n if(this.enum_options.indexOf(val) === -1) {\n sanitized = this.enum_options[0];\n }\n\n this.value = this.enum_values[this.enum_options.indexOf(val)];\n this.onChange(true);\n },\n setupSelectize: function() {\n // If the Selectize library is loaded use it when we have lots of items\n var self = this;\n if(window.jQuery && window.jQuery.fn && window.jQuery.fn.selectize && (this.enum_options.length >= 2 || (this.enum_options.length && this.enumSource))) {\n var options = $extend({},JSONEditor.plugins.selectize);\n if(this.schema.options && this.schema.options.selectize_options) options = $extend(options,this.schema.options.selectize_options);\n this.selectize = window.jQuery(this.input).selectize($extend(options,\n {\n create: true,\n onChange : function() {\n self.onInputChange();\n }\n }));\n }\n else {\n this.selectize = null;\n }\n },\n postBuild: function() {\n this._super();\n this.theme.afterInputReady(this.input);\n this.setupSelectize();\n },\n onWatchedFieldChange: function() {\n var self = this, vars, j;\n\n // If this editor uses a dynamic select box\n if(this.enumSource) {\n vars = this.getWatchedFieldValues();\n var select_options = [];\n var select_titles = [];\n\n for(var i=0; i<this.enumSource.length; i++) {\n // Constant values\n if(Array.isArray(this.enumSource[i])) {\n select_options = select_options.concat(this.enumSource[i]);\n select_titles = select_titles.concat(this.enumSource[i]);\n }\n // A watched field\n else if(vars[this.enumSource[i].source]) {\n var items = vars[this.enumSource[i].source];\n\n // Only use a predefined part of the array\n if(this.enumSource[i].slice) {\n items = Array.prototype.slice.apply(items,this.enumSource[i].slice);\n }\n // Filter the items\n if(this.enumSource[i].filter) {\n var new_items = [];\n for(j=0; j<items.length; j++) {\n if(this.enumSource[i].filter({i:j,item:items[j]})) new_items.push(items[j]);\n }\n items = new_items;\n }\n\n var item_titles = [];\n var item_values = [];\n for(j=0; j<items.length; j++) {\n var item = items[j];\n\n // Rendered value\n if(this.enumSource[i].value) {\n item_values[j] = this.enumSource[i].value({\n i: j,\n item: item\n });\n }\n // Use value directly\n else {\n item_values[j] = items[j];\n }\n\n // Rendered title\n if(this.enumSource[i].title) {\n item_titles[j] = this.enumSource[i].title({\n i: j,\n item: item\n });\n }\n // Use value as the title also\n else {\n item_titles[j] = item_values[j];\n }\n }\n\n // TODO: sort\n\n select_options = select_options.concat(item_values);\n select_titles = select_titles.concat(item_titles);\n }\n }\n\n var prev_value = this.value;\n\n this.theme.setSelectOptions(this.input, select_options, select_titles);\n this.enum_options = select_options;\n this.enum_display = select_titles;\n this.enum_values = select_options;\n\n // If the previous value is still in the new select options, stick with it\n if(select_options.indexOf(prev_value) !== -1) {\n this.input.value = prev_value;\n this.value = prev_value;\n }\n\n // Otherwise, set the value to the first select option\n else {\n this.input.value = select_options[0];\n this.value = select_options[0] || \"\";\n if(this.parent) this.parent.onChildEditorChange(this);\n else this.jsoneditor.onChange();\n this.jsoneditor.notifyWatchers(this.path);\n }\n\n if(this.selectize) {\n // Update the Selectize options\n this.updateSelectizeOptions(select_options);\n }\n else {\n this.setupSelectize();\n }\n\n this._super();\n }\n },\n updateSelectizeOptions: function(select_options) {\n var selectized = this.selectize[0].selectize,\n self = this;\n\n selectized.off();\n selectized.clearOptions();\n for(var n in select_options) {\n selectized.addOption({value:select_options[n],text:select_options[n]});\n }\n selectized.addItem(this.value);\n selectized.on('change',function() {\n self.onInputChange();\n });\n },\n enable: function() {\n if(!this.always_disabled) {\n this.input.disabled = false;\n if(this.selectize) {\n this.selectize[0].selectize.unlock();\n }\n }\n this._super();\n },\n disable: function() {\n this.input.disabled = true;\n if(this.selectize) {\n this.selectize[0].selectize.lock();\n }\n this._super();\n },\n destroy: function() {\n if(this.label && this.label.parentNode) this.label.parentNode.removeChild(this.label);\n if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);\n if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);\n if(this.selectize) {\n this.selectize[0].selectize.destroy();\n this.selectize = null;\n }\n this._super();\n }\n});\n",
75
+ "JSONEditor.defaults.editors.multiselect = JSONEditor.AbstractEditor.extend({\n preBuild: function() {\n this._super();\n\n this.select_options = {};\n this.select_values = {};\n\n var items_schema = this.jsoneditor.expandRefs(this.schema.items || {});\n\n var e = items_schema[\"enum\"] || [];\n this.option_keys = [];\n for(i=0; i<e.length; i++) {\n // If the sanitized value is different from the enum value, don't include it\n if(this.sanitize(e[i]) !== e[i]) continue;\n\n this.option_keys.push(e[i]+\"\");\n this.select_values[e[i]+\"\"] = e[i];\n }\n },\n build: function() {\n var self = this, i;\n if(!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());\n if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);\n\n if((!this.schema.format && this.option_keys.length < 8) || this.schema.format === \"checkbox\") {\n this.input_type = 'checkboxes';\n\n this.inputs = {};\n this.controls = {};\n for(i=0; i<this.option_keys.length; i++) {\n this.inputs[this.option_keys[i]] = this.theme.getCheckbox();\n this.select_options[this.option_keys[i]] = this.inputs[this.option_keys[i]];\n var label = this.theme.getCheckboxLabel(this.option_keys[i]);\n this.controls[this.option_keys[i]] = this.theme.getFormControl(label, this.inputs[this.option_keys[i]]);\n }\n\n this.control = this.theme.getMultiCheckboxHolder(this.controls,this.label,this.description);\n }\n else {\n this.input_type = 'select';\n this.input = this.theme.getSelectInput(this.option_keys);\n this.input.multiple = true;\n this.input.size = Math.min(10,this.option_keys.length);\n\n for(i=0; i<this.option_keys.length; i++) {\n this.select_options[this.option_keys[i]] = this.input.children[i];\n }\n\n if(this.schema.readOnly || this.schema.readonly) {\n this.always_disabled = true;\n this.input.disabled = true;\n }\n\n this.control = this.theme.getFormControl(this.label, this.input, this.description);\n }\n\n this.container.appendChild(this.control);\n this.control.addEventListener('change',function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n var new_value = [];\n for(i = 0; i<self.option_keys.length; i++) {\n if(self.select_options[self.option_keys[i]].selected || self.select_options[self.option_keys[i]].checked) new_value.push(self.select_values[self.option_keys[i]]);\n }\n\n self.updateValue(new_value);\n self.onChange(true);\n });\n },\n setValue: function(value, initial) {\n var i;\n value = value || [];\n if(typeof value !== \"object\") value = [value];\n else if(!(Array.isArray(value))) value = [];\n\n // Make sure we are dealing with an array of strings so we can check for strict equality\n for(i=0; i<value.length; i++) {\n if(typeof value[i] !== \"string\") value[i] += \"\";\n }\n\n // Update selected status of options\n for(i in this.select_options) {\n if(!this.select_options.hasOwnProperty(i)) continue;\n\n this.select_options[i][this.input_type === \"select\"? \"selected\" : \"checked\"] = (value.indexOf(i) !== -1);\n }\n\n this.updateValue(value);\n this.onChange();\n },\n setupSelect2: function() {\n if(window.jQuery && window.jQuery.fn && window.jQuery.fn.select2) {\n var options = window.jQuery.extend({},JSONEditor.plugins.select2);\n if(this.schema.options && this.schema.options.select2_options) options = $extend(options,this.schema.options.select2_options);\n this.select2 = window.jQuery(this.input).select2(options);\n var self = this;\n this.select2.on('select2-blur',function() {\n var val =self.select2.select2('val');\n self.value = val;\n self.onChange(true);\n });\n }\n else {\n this.select2 = null;\n }\n },\n onInputChange: function() {\n this.value = this.input.value;\n this.onChange(true);\n },\n postBuild: function() {\n this._super();\n this.setupSelect2();\n },\n register: function() {\n this._super();\n if(!this.input) return;\n this.input.setAttribute('name',this.formname);\n },\n unregister: function() {\n this._super();\n if(!this.input) return;\n this.input.removeAttribute('name');\n },\n getNumColumns: function() {\n var longest_text = this.getTitle().length;\n for(var i in this.select_values) {\n if(!this.select_values.hasOwnProperty(i)) continue;\n longest_text = Math.max(longest_text,(this.select_values[i]+\"\").length+4);\n }\n\n return Math.min(12,Math.max(longest_text/7,2));\n },\n updateValue: function(value) {\n var changed = false;\n var new_value = [];\n for(var i=0; i<value.length; i++) {\n if(!this.select_options[value[i]+\"\"]) {\n changed = true;\n continue;\n }\n var sanitized = this.sanitize(this.select_values[value[i]]);\n new_value.push(sanitized);\n if(sanitized !== value[i]) changed = true;\n }\n this.value = new_value;\n if(this.select2) this.select2.select2('val',this.value);\n return changed;\n },\n sanitize: function(value) {\n if(this.schema.items.type === \"number\") {\n return 1*value;\n }\n else if(this.schema.items.type === \"integer\") {\n return Math.floor(value*1);\n }\n else {\n return \"\"+value;\n }\n },\n enable: function() {\n if(!this.always_disabled) {\n if(this.input) {\n this.input.disabled = false;\n }\n else if(this.inputs) {\n for(var i in this.inputs) {\n if(!this.inputs.hasOwnProperty(i)) continue;\n this.inputs[i].disabled = false;\n }\n }\n if(this.select2) this.select2.select2(\"enable\",true);\n }\n this._super();\n },\n disable: function() {\n if(this.input) {\n this.input.disabled = true;\n }\n else if(this.inputs) {\n for(var i in this.inputs) {\n if(!this.inputs.hasOwnProperty(i)) continue;\n this.inputs[i].disabled = true;\n }\n }\n if(this.select2) this.select2.select2(\"enable\",false);\n this._super();\n },\n destroy: function() {\n if(this.select2) {\n this.select2.select2('destroy');\n this.select2 = null;\n }\n this._super();\n }\n});\n",
76
+ "JSONEditor.defaults.editors.base64 = JSONEditor.AbstractEditor.extend({\n getNumColumns: function() {\n return 4;\n },\n build: function() { \n var self = this;\n this.title = this.header = this.label = this.theme.getFormInputLabel(this.getTitle());\n\n // Input that holds the base64 string\n this.input = this.theme.getFormInputField('hidden');\n this.container.appendChild(this.input);\n \n // Don't show uploader if this is readonly\n if(!this.schema.readOnly && !this.schema.readonly) {\n if(!window.FileReader) throw \"FileReader required for base64 editor\";\n \n // File uploader\n this.uploader = this.theme.getFormInputField('file');\n \n this.uploader.addEventListener('change',function(e) {\n e.preventDefault();\n e.stopPropagation();\n \n if(this.files && this.files.length) {\n var fr = new FileReader();\n fr.onload = function(evt) {\n self.value = evt.target.result;\n self.refreshPreview();\n self.onChange(true);\n fr = null;\n };\n fr.readAsDataURL(this.files[0]);\n }\n });\n }\n\n this.preview = this.theme.getFormInputDescription(this.schema.description);\n this.container.appendChild(this.preview);\n\n this.control = this.theme.getFormControl(this.label, this.uploader||this.input, this.preview);\n this.container.appendChild(this.control);\n },\n refreshPreview: function() {\n if(this.last_preview === this.value) return;\n this.last_preview = this.value;\n \n this.preview.innerHTML = '';\n \n if(!this.value) return;\n \n var mime = this.value.match(/^data:([^;,]+)[;,]/);\n if(mime) mime = mime[1];\n \n if(!mime) {\n this.preview.innerHTML = '<em>Invalid data URI</em>';\n }\n else {\n this.preview.innerHTML = '<strong>Type:</strong> '+mime+', <strong>Size:</strong> '+Math.floor((this.value.length-this.value.split(',')[0].length-1)/1.33333)+' bytes';\n if(mime.substr(0,5)===\"image\") {\n this.preview.innerHTML += '<br>';\n var img = document.createElement('img');\n img.style.maxWidth = '100%';\n img.style.maxHeight = '100px';\n img.src = this.value;\n this.preview.appendChild(img);\n }\n }\n },\n enable: function() {\n if(this.uploader) this.uploader.disabled = false;\n this._super();\n },\n disable: function() {\n if(this.uploader) this.uploader.disabled = true;\n this._super();\n },\n setValue: function(val) {\n if(this.value !== val) {\n this.value = val;\n this.input.value = this.value;\n this.refreshPreview();\n this.onChange();\n }\n },\n destroy: function() {\n if(this.preview && this.preview.parentNode) this.preview.parentNode.removeChild(this.preview);\n if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);\n if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);\n if(this.uploader && this.uploader.parentNode) this.uploader.parentNode.removeChild(this.uploader);\n\n this._super();\n }\n});\n",
77
+ "JSONEditor.defaults.editors.upload = JSONEditor.AbstractEditor.extend({\n getNumColumns: function() {\n return 4;\n },\n build: function() { \n var self = this;\n this.title = this.header = this.label = this.theme.getFormInputLabel(this.getTitle());\n\n // Input that holds the base64 string\n this.input = this.theme.getFormInputField('hidden');\n this.container.appendChild(this.input);\n \n // Don't show uploader if this is readonly\n if(!this.schema.readOnly && !this.schema.readonly) {\n\n if(!this.jsoneditor.options.upload) throw \"Upload handler required for upload editor\";\n\n // File uploader\n this.uploader = this.theme.getFormInputField('file');\n \n this.uploader.addEventListener('change',function(e) {\n e.preventDefault();\n e.stopPropagation();\n \n if(this.files && this.files.length) {\n var fr = new FileReader();\n fr.onload = function(evt) {\n self.preview_value = evt.target.result;\n self.refreshPreview();\n self.onChange(true);\n fr = null;\n };\n fr.readAsDataURL(this.files[0]);\n }\n });\n }\n\n var description = this.schema.description;\n if (!description) description = '';\n\n this.preview = this.theme.getFormInputDescription(description);\n this.container.appendChild(this.preview);\n\n this.control = this.theme.getFormControl(this.label, this.uploader||this.input, this.preview);\n this.container.appendChild(this.control);\n },\n refreshPreview: function() {\n if(this.last_preview === this.preview_value) return;\n this.last_preview = this.preview_value;\n\n this.preview.innerHTML = '';\n \n if(!this.preview_value) return;\n\n var self = this;\n\n var mime = this.preview_value.match(/^data:([^;,]+)[;,]/);\n if(mime) mime = mime[1];\n if(!mime) mime = 'unknown';\n\n var file = this.uploader.files[0];\n\n this.preview.innerHTML = '<strong>Type:</strong> '+mime+', <strong>Size:</strong> '+file.size+' bytes';\n if(mime.substr(0,5)===\"image\") {\n this.preview.innerHTML += '<br>';\n var img = document.createElement('img');\n img.style.maxWidth = '100%';\n img.style.maxHeight = '100px';\n img.src = this.preview_value;\n this.preview.appendChild(img);\n }\n\n this.preview.innerHTML += '<br>';\n var uploadButton = this.getButton('Upload', 'upload', 'Upload');\n this.preview.appendChild(uploadButton);\n uploadButton.addEventListener('click',function(event) {\n event.preventDefault();\n\n uploadButton.setAttribute(\"disabled\", \"disabled\");\n self.theme.removeInputError(self.uploader);\n\n if (self.theme.getProgressBar) {\n self.progressBar = self.theme.getProgressBar();\n self.preview.appendChild(self.progressBar);\n }\n\n self.jsoneditor.options.upload(self.path, file, {\n success: function(url) {\n self.setValue(url);\n\n if(self.parent) self.parent.onChildEditorChange(self);\n else self.jsoneditor.onChange();\n\n if (self.progressBar) self.preview.removeChild(self.progressBar);\n uploadButton.removeAttribute(\"disabled\");\n },\n failure: function(error) {\n self.theme.addInputError(self.uploader, error);\n if (self.progressBar) self.preview.removeChild(self.progressBar);\n uploadButton.removeAttribute(\"disabled\");\n },\n updateProgress: function(progress) {\n if (self.progressBar) {\n if (progress) self.theme.updateProgressBar(self.progressBar, progress);\n else self.theme.updateProgressBarUnknown(self.progressBar);\n }\n }\n });\n });\n },\n enable: function() {\n if(this.uploader) this.uploader.disabled = false;\n this._super();\n },\n disable: function() {\n if(this.uploader) this.uploader.disabled = true;\n this._super();\n },\n setValue: function(val) {\n if(this.value !== val) {\n this.value = val;\n this.input.value = this.value;\n this.onChange();\n }\n },\n destroy: function() {\n if(this.preview && this.preview.parentNode) this.preview.parentNode.removeChild(this.preview);\n if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);\n if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);\n if(this.uploader && this.uploader.parentNode) this.uploader.parentNode.removeChild(this.uploader);\n\n this._super();\n }\n});\n",
78
+ "JSONEditor.defaults.editors.checkbox = JSONEditor.AbstractEditor.extend({\n setValue: function(value,initial) {\n this.value = !!value;\n this.input.checked = this.value;\n this.onChange();\n },\n register: function() {\n this._super();\n if(!this.input) return;\n this.input.setAttribute('name',this.formname);\n },\n unregister: function() {\n this._super();\n if(!this.input) return;\n this.input.removeAttribute('name');\n },\n getNumColumns: function() {\n return Math.min(12,Math.max(this.getTitle().length/7,2));\n },\n build: function() {\n var self = this;\n if(!this.options.compact) {\n this.label = this.header = this.theme.getCheckboxLabel(this.getTitle());\n }\n if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);\n if(this.options.compact) this.container.className += ' compact';\n\n this.input = this.theme.getCheckbox();\n this.control = this.theme.getFormControl(this.label, this.input, this.description);\n\n if(this.schema.readOnly || this.schema.readonly) {\n this.always_disabled = true;\n this.input.disabled = true;\n }\n\n this.input.addEventListener('change',function(e) {\n e.preventDefault();\n e.stopPropagation();\n self.value = this.checked;\n self.onChange(true);\n });\n\n this.container.appendChild(this.control);\n },\n enable: function() {\n if(!this.always_disabled) {\n this.input.disabled = false;\n }\n this._super();\n },\n disable: function() {\n this.input.disabled = true;\n this._super();\n },\n destroy: function() {\n if(this.label && this.label.parentNode) this.label.parentNode.removeChild(this.label);\n if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);\n if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);\n this._super();\n }\n});\n",
79
+ "JSONEditor.defaults.editors.arraySelectize = JSONEditor.AbstractEditor.extend({\n build: function() {\n this.title = this.theme.getFormInputLabel(this.getTitle());\n\n this.title_controls = this.theme.getHeaderButtonHolder();\n this.title.appendChild(this.title_controls);\n this.error_holder = document.createElement('div');\n\n if(this.schema.description) {\n this.description = this.theme.getDescription(this.schema.description);\n }\n\n this.input = document.createElement('select');\n this.input.setAttribute('multiple', 'multiple');\n\n var group = this.theme.getFormControl(this.title, this.input, this.description);\n\n this.container.appendChild(group);\n this.container.appendChild(this.error_holder);\n\n window.jQuery(this.input).selectize({\n delimiter: false,\n createOnBlur: true,\n create: true\n });\n },\n postBuild: function() {\n var self = this;\n this.input.selectize.on('change', function(event) {\n self.refreshValue();\n self.onChange(true);\n });\n },\n destroy: function() {\n this.empty(true);\n if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);\n if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);\n if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);\n\n this._super();\n },\n empty: function(hard) {},\n setValue: function(value, initial) {\n var self = this;\n // Update the array's value, adding/removing rows when necessary\n value = value || [];\n if(!(Array.isArray(value))) value = [value];\n\n this.input.selectize.clearOptions();\n this.input.selectize.clear(true);\n\n value.forEach(function(item) {\n self.input.selectize.addOption({text: item, value: item});\n });\n this.input.selectize.setValue(value);\n\n this.refreshValue(initial);\n },\n refreshValue: function(force) {\n this.value = this.input.selectize.getValue();\n },\n showValidationErrors: function(errors) {\n var self = this;\n\n // Get all the errors that pertain to this editor\n var my_errors = [];\n var other_errors = [];\n $each(errors, function(i,error) {\n if(error.path === self.path) {\n my_errors.push(error);\n }\n else {\n other_errors.push(error);\n }\n });\n\n // Show errors for this editor\n if(this.error_holder) {\n\n if(my_errors.length) {\n var message = [];\n this.error_holder.innerHTML = '';\n this.error_holder.style.display = '';\n $each(my_errors, function(i,error) {\n self.error_holder.appendChild(self.theme.getErrorMessage(error.message));\n });\n }\n // Hide error area\n else {\n this.error_holder.style.display = 'none';\n }\n }\n }\n});\n",
80
+ "var matchKey = (function () {\n var elem = document.documentElement;\n\n if (elem.matches) return 'matches';\n else if (elem.webkitMatchesSelector) return 'webkitMatchesSelector';\n else if (elem.mozMatchesSelector) return 'mozMatchesSelector';\n else if (elem.msMatchesSelector) return 'msMatchesSelector';\n else if (elem.oMatchesSelector) return 'oMatchesSelector';\n})();\n\nJSONEditor.AbstractTheme = Class.extend({\n getContainer: function() {\n return document.createElement('div');\n },\n getFloatRightLinkHolder: function() {\n var el = document.createElement('div');\n el.style = el.style || {};\n el.style.cssFloat = 'right';\n el.style.marginLeft = '10px';\n return el;\n },\n getModal: function() {\n var el = document.createElement('div');\n el.style.backgroundColor = 'white';\n el.style.border = '1px solid black';\n el.style.boxShadow = '3px 3px black';\n el.style.position = 'absolute';\n el.style.zIndex = '10';\n el.style.display = 'none';\n return el;\n },\n getGridContainer: function() {\n var el = document.createElement('div');\n return el;\n },\n getGridRow: function() {\n var el = document.createElement('div');\n el.className = 'row';\n return el;\n },\n getGridColumn: function() {\n var el = document.createElement('div');\n return el;\n },\n setGridColumnSize: function(el,size) {\n\n },\n getLink: function(text) {\n var el = document.createElement('a');\n el.setAttribute('href','#');\n el.appendChild(document.createTextNode(text));\n return el;\n },\n disableHeader: function(header) {\n header.style.color = '#ccc';\n },\n disableLabel: function(label) {\n label.style.color = '#ccc';\n },\n enableHeader: function(header) {\n header.style.color = '';\n },\n enableLabel: function(label) {\n label.style.color = '';\n },\n getFormInputLabel: function(text) {\n var el = document.createElement('label');\n el.appendChild(document.createTextNode(text));\n return el;\n },\n getCheckboxLabel: function(text) {\n var el = this.getFormInputLabel(text);\n el.style.fontWeight = 'normal';\n return el;\n },\n getHeader: function(text) {\n var el = document.createElement('h3');\n if(typeof text === \"string\") {\n el.textContent = text;\n }\n else {\n el.appendChild(text);\n }\n\n return el;\n },\n getCheckbox: function() {\n var el = this.getFormInputField('checkbox');\n el.style.display = 'inline-block';\n el.style.width = 'auto';\n return el;\n },\n getMultiCheckboxHolder: function(controls,label,description) {\n var el = document.createElement('div');\n\n if(label) {\n label.style.display = 'block';\n el.appendChild(label);\n }\n\n for(var i in controls) {\n if(!controls.hasOwnProperty(i)) continue;\n controls[i].style.display = 'inline-block';\n controls[i].style.marginRight = '20px';\n el.appendChild(controls[i]);\n }\n\n if(description) el.appendChild(description);\n\n return el;\n },\n getSelectInput: function(options) {\n var select = document.createElement('select');\n if(options) this.setSelectOptions(select, options);\n return select;\n },\n getSwitcher: function(options) {\n var switcher = this.getSelectInput(options);\n switcher.style.backgroundColor = 'transparent';\n switcher.style.display = 'inline-block';\n switcher.style.fontStyle = 'italic';\n switcher.style.fontWeight = 'normal';\n switcher.style.height = 'auto';\n switcher.style.marginBottom = 0;\n switcher.style.marginLeft = '5px';\n switcher.style.padding = '0 0 0 3px';\n switcher.style.width = 'auto';\n return switcher;\n },\n getSwitcherOptions: function(switcher) {\n return switcher.getElementsByTagName('option');\n },\n setSwitcherOptions: function(switcher, options, titles) {\n this.setSelectOptions(switcher, options, titles);\n },\n setSelectOptions: function(select, options, titles) {\n titles = titles || [];\n select.innerHTML = '';\n for(var i=0; i<options.length; i++) {\n var option = document.createElement('option');\n option.setAttribute('value',options[i]);\n option.textContent = titles[i] || options[i];\n select.appendChild(option);\n }\n },\n getTextareaInput: function() {\n var el = document.createElement('textarea');\n el.style = el.style || {};\n el.style.width = '100%';\n el.style.height = '300px';\n el.style.boxSizing = 'border-box';\n return el;\n },\n getRangeInput: function(min,max,step) {\n var el = this.getFormInputField('range');\n el.setAttribute('min',min);\n el.setAttribute('max',max);\n el.setAttribute('step',step);\n return el;\n },\n getFormInputField: function(type) {\n var el = document.createElement('input');\n el.setAttribute('type',type);\n return el;\n },\n afterInputReady: function(input) {\n\n },\n getFormControl: function(label, input, description) {\n var el = document.createElement('div');\n el.className = 'form-control';\n if(label) el.appendChild(label);\n if(input.type === 'checkbox') {\n label.insertBefore(input,label.firstChild);\n }\n else {\n el.appendChild(input);\n }\n\n if(description) el.appendChild(description);\n return el;\n },\n getIndentedPanel: function() {\n var el = document.createElement('div');\n el.style = el.style || {};\n el.style.paddingLeft = '10px';\n el.style.marginLeft = '10px';\n el.style.borderLeft = '1px solid #ccc';\n return el;\n },\n getChildEditorHolder: function() {\n return document.createElement('div');\n },\n getDescription: function(text) {\n var el = document.createElement('p');\n el.innerHTML = text;\n return el;\n },\n getCheckboxDescription: function(text) {\n return this.getDescription(text);\n },\n getFormInputDescription: function(text) {\n return this.getDescription(text);\n },\n getHeaderButtonHolder: function() {\n return this.getButtonHolder();\n },\n getButtonHolder: function() {\n return document.createElement('div');\n },\n getButton: function(text, icon, title) {\n var el = document.createElement('button');\n el.type = 'button';\n this.setButtonText(el,text,icon,title);\n return el;\n },\n setButtonText: function(button, text, icon, title) {\n button.innerHTML = '';\n if(icon) {\n button.appendChild(icon);\n button.innerHTML += ' ';\n }\n button.appendChild(document.createTextNode(text));\n if(title) button.setAttribute('title',title);\n },\n getTable: function() {\n return document.createElement('table');\n },\n getTableRow: function() {\n return document.createElement('tr');\n },\n getTableHead: function() {\n return document.createElement('thead');\n },\n getTableBody: function() {\n return document.createElement('tbody');\n },\n getTableHeaderCell: function(text) {\n var el = document.createElement('th');\n el.textContent = text;\n return el;\n },\n getTableCell: function() {\n var el = document.createElement('td');\n return el;\n },\n getErrorMessage: function(text) {\n var el = document.createElement('p');\n el.style = el.style || {};\n el.style.color = 'red';\n el.appendChild(document.createTextNode(text));\n return el;\n },\n addInputError: function(input, text) {\n },\n removeInputError: function(input) {\n },\n addTableRowError: function(row) {\n },\n removeTableRowError: function(row) {\n },\n getTabHolder: function() {\n var el = document.createElement('div');\n el.innerHTML = \"<div style='float: left; width: 130px;' class='tabs'></div><div class='content' style='margin-left: 130px;'></div><div style='clear:both;'></div>\";\n return el;\n },\n applyStyles: function(el,styles) {\n el.style = el.style || {};\n for(var i in styles) {\n if(!styles.hasOwnProperty(i)) continue;\n el.style[i] = styles[i];\n }\n },\n closest: function(elem, selector) {\n while (elem && elem !== document) {\n if (matchKey) {\n if (elem[matchKey](selector)) {\n return elem;\n } else {\n elem = elem.parentNode;\n }\n }\n else {\n return false;\n }\n }\n return false;\n },\n getTab: function(span) {\n var el = document.createElement('div');\n el.appendChild(span);\n el.style = el.style || {};\n this.applyStyles(el,{\n border: '1px solid #ccc',\n borderWidth: '1px 0 1px 1px',\n textAlign: 'center',\n lineHeight: '30px',\n borderRadius: '5px',\n borderBottomRightRadius: 0,\n borderTopRightRadius: 0,\n fontWeight: 'bold',\n cursor: 'pointer'\n });\n return el;\n },\n getTabContentHolder: function(tab_holder) {\n return tab_holder.children[1];\n },\n getTabContent: function() {\n return this.getIndentedPanel();\n },\n markTabActive: function(tab) {\n this.applyStyles(tab,{\n opacity: 1,\n background: 'white'\n });\n },\n markTabInactive: function(tab) {\n this.applyStyles(tab,{\n opacity:0.5,\n background: ''\n });\n },\n addTab: function(holder, tab) {\n holder.children[0].appendChild(tab);\n },\n getBlockLink: function() {\n var link = document.createElement('a');\n link.style.display = 'block';\n return link;\n },\n getBlockLinkHolder: function() {\n var el = document.createElement('div');\n return el;\n },\n getLinksHolder: function() {\n var el = document.createElement('div');\n return el;\n },\n createMediaLink: function(holder,link,media) {\n holder.appendChild(link);\n media.style.width='100%';\n holder.appendChild(media);\n },\n createImageLink: function(holder,link,image) {\n holder.appendChild(link);\n link.appendChild(image);\n }\n});\n",
81
+ "JSONEditor.defaults.themes.bootstrap2 = JSONEditor.AbstractTheme.extend({\n getRangeInput: function(min, max, step) {\n // TODO: use bootstrap slider\n return this._super(min, max, step);\n },\n getGridContainer: function() {\n var el = document.createElement('div');\n el.className = 'container-fluid';\n return el;\n },\n getGridRow: function() {\n var el = document.createElement('div');\n el.className = 'row-fluid';\n return el;\n },\n getFormInputLabel: function(text) {\n var el = this._super(text);\n el.style.display = 'inline-block';\n el.style.fontWeight = 'bold';\n return el;\n },\n setGridColumnSize: function(el,size) {\n el.className = 'span'+size;\n },\n getSelectInput: function(options) {\n var input = this._super(options);\n input.style.width = 'auto';\n input.style.maxWidth = '98%';\n return input;\n },\n getFormInputField: function(type) {\n var el = this._super(type);\n el.style.width = '98%';\n return el;\n },\n afterInputReady: function(input) {\n if(input.controlgroup) return;\n input.controlgroup = this.closest(input,'.control-group');\n input.controls = this.closest(input,'.controls');\n if(this.closest(input,'.compact')) {\n input.controlgroup.className = input.controlgroup.className.replace(/control-group/g,'').replace(/[ ]{2,}/g,' ');\n input.controls.className = input.controlgroup.className.replace(/controls/g,'').replace(/[ ]{2,}/g,' ');\n input.style.marginBottom = 0;\n }\n\n // TODO: use bootstrap slider\n },\n getIndentedPanel: function() {\n var el = document.createElement('div');\n el.className = 'well well-small';\n el.style.paddingBottom = 0;\n return el;\n },\n getFormInputDescription: function(text) {\n var el = document.createElement('p');\n el.className = 'help-inline';\n el.textContent = text;\n return el;\n },\n getFormControl: function(label, input, description) {\n var ret = document.createElement('div');\n ret.className = 'control-group';\n\n var controls = document.createElement('div');\n controls.className = 'controls';\n\n if(label && input.getAttribute('type') === 'checkbox') {\n ret.appendChild(controls);\n label.className += ' checkbox';\n label.appendChild(input);\n controls.appendChild(label);\n controls.style.height = '30px';\n }\n else {\n if(label) {\n label.className += ' control-label';\n ret.appendChild(label);\n }\n controls.appendChild(input);\n ret.appendChild(controls);\n }\n\n if(description) controls.appendChild(description);\n\n return ret;\n },\n getHeaderButtonHolder: function() {\n var el = this.getButtonHolder();\n el.style.marginLeft = '10px';\n return el;\n },\n getButtonHolder: function() {\n var el = document.createElement('div');\n el.className = 'btn-group';\n return el;\n },\n getButton: function(text, icon, title) {\n var el = this._super(text, icon, title);\n el.className += ' btn btn-default';\n return el;\n },\n getTable: function() {\n var el = document.createElement('table');\n el.className = 'table table-bordered';\n el.style.width = 'auto';\n el.style.maxWidth = 'none';\n return el;\n },\n addInputError: function(input,text) {\n if(!input.controlgroup || !input.controls) return;\n input.controlgroup.className += ' error';\n if(!input.errmsg) {\n input.errmsg = document.createElement('p');\n input.errmsg.className = 'help-block errormsg';\n input.controls.appendChild(input.errmsg);\n }\n else {\n input.errmsg.style.display = '';\n }\n\n input.errmsg.textContent = text;\n },\n removeInputError: function(input) {\n if(!input.errmsg) return;\n input.errmsg.style.display = 'none';\n input.controlgroup.className = input.controlgroup.className.replace(/\\s?error/g,'');\n },\n getTabHolder: function() {\n var el = document.createElement('div');\n el.className = 'tabbable tabs-left';\n el.innerHTML = \"<ul class='nav nav-tabs span2' style='margin-right: 0;'></ul><div class='tab-content span10' style='overflow:visible;'></div>\";\n return el;\n },\n getTab: function(text) {\n var el = document.createElement('li');\n var a = document.createElement('a');\n a.setAttribute('href','#');\n a.appendChild(text);\n el.appendChild(a);\n return el;\n },\n getTabContentHolder: function(tab_holder) {\n return tab_holder.children[1];\n },\n getTabContent: function() {\n var el = document.createElement('div');\n el.className = 'tab-pane active';\n return el;\n },\n markTabActive: function(tab) {\n tab.className += ' active';\n },\n markTabInactive: function(tab) {\n tab.className = tab.className.replace(/\\s?active/g,'');\n },\n addTab: function(holder, tab) {\n holder.children[0].appendChild(tab);\n },\n getProgressBar: function() {\n var container = document.createElement('div');\n container.className = 'progress';\n\n var bar = document.createElement('div');\n bar.className = 'bar';\n bar.style.width = '0%';\n container.appendChild(bar);\n\n return container;\n },\n updateProgressBar: function(progressBar, progress) {\n if (!progressBar) return;\n\n progressBar.firstChild.style.width = progress + \"%\";\n },\n updateProgressBarUnknown: function(progressBar) {\n if (!progressBar) return;\n\n progressBar.className = 'progress progress-striped active';\n progressBar.firstChild.style.width = '100%';\n }\n});\n",
82
+ "JSONEditor.defaults.themes.bootstrap3 = JSONEditor.AbstractTheme.extend({\n getSelectInput: function(options) {\n var el = this._super(options);\n el.className += 'form-control';\n //el.style.width = 'auto';\n return el;\n },\n setGridColumnSize: function(el,size) {\n el.className = 'col-md-'+size;\n },\n afterInputReady: function(input) {\n if(input.controlgroup) return;\n input.controlgroup = this.closest(input,'.form-group');\n if(this.closest(input,'.compact')) {\n input.controlgroup.style.marginBottom = 0;\n }\n\n // TODO: use bootstrap slider\n },\n getTextareaInput: function() {\n var el = document.createElement('textarea');\n el.className = 'form-control';\n return el;\n },\n getRangeInput: function(min, max, step) {\n // TODO: use better slider\n return this._super(min, max, step);\n },\n getFormInputField: function(type) {\n var el = this._super(type);\n if(type !== 'checkbox') {\n el.className += 'form-control';\n }\n return el;\n },\n getFormControl: function(label, input, description) {\n var group = document.createElement('div');\n\n if(label && input.type === 'checkbox') {\n group.className += ' checkbox';\n label.appendChild(input);\n label.style.fontSize = '14px';\n group.style.marginTop = '0';\n group.appendChild(label);\n input.style.position = 'relative';\n input.style.cssFloat = 'left';\n } \n else {\n group.className += ' form-group';\n if(label) {\n label.className += ' control-label';\n group.appendChild(label);\n }\n group.appendChild(input);\n }\n\n if(description) group.appendChild(description);\n\n return group;\n },\n getIndentedPanel: function() {\n var el = document.createElement('div');\n el.className = 'well well-sm';\n el.style.paddingBottom = 0;\n return el;\n },\n getFormInputDescription: function(text) {\n var el = document.createElement('p');\n el.className = 'help-block';\n el.innerHTML = text;\n return el;\n },\n getHeaderButtonHolder: function() {\n var el = this.getButtonHolder();\n el.style.marginLeft = '10px';\n return el;\n },\n getButtonHolder: function() {\n var el = document.createElement('div');\n el.className = 'btn-group';\n return el;\n },\n getButton: function(text, icon, title) {\n var el = this._super(text, icon, title);\n el.className += 'btn btn-default';\n return el;\n },\n getTable: function() {\n var el = document.createElement('table');\n el.className = 'table table-bordered';\n el.style.width = 'auto';\n el.style.maxWidth = 'none';\n return el;\n },\n\n addInputError: function(input,text) {\n if(!input.controlgroup) return;\n input.controlgroup.className += ' has-error';\n if(!input.errmsg) {\n input.errmsg = document.createElement('p');\n input.errmsg.className = 'help-block errormsg';\n input.controlgroup.appendChild(input.errmsg);\n }\n else {\n input.errmsg.style.display = '';\n }\n\n input.errmsg.textContent = text;\n },\n removeInputError: function(input) {\n if(!input.errmsg) return;\n input.errmsg.style.display = 'none';\n input.controlgroup.className = input.controlgroup.className.replace(/\\s?has-error/g,'');\n },\n getTabHolder: function() {\n var el = document.createElement('div');\n el.innerHTML = \"<div class='tabs list-group col-md-2'></div><div class='col-md-10'></div>\";\n el.className = 'rows';\n return el;\n },\n getTab: function(text) {\n var el = document.createElement('a');\n el.className = 'list-group-item';\n el.setAttribute('href','#');\n el.appendChild(text);\n return el;\n },\n markTabActive: function(tab) {\n tab.className += ' active';\n },\n markTabInactive: function(tab) {\n tab.className = tab.className.replace(/\\s?active/g,'');\n },\n getProgressBar: function() {\n var min = 0, max = 100, start = 0;\n\n var container = document.createElement('div');\n container.className = 'progress';\n\n var bar = document.createElement('div');\n bar.className = 'progress-bar';\n bar.setAttribute('role', 'progressbar');\n bar.setAttribute('aria-valuenow', start);\n bar.setAttribute('aria-valuemin', min);\n bar.setAttribute('aria-valuenax', max);\n bar.innerHTML = start + \"%\";\n container.appendChild(bar);\n\n return container;\n },\n updateProgressBar: function(progressBar, progress) {\n if (!progressBar) return;\n\n var bar = progressBar.firstChild;\n var percentage = progress + \"%\";\n bar.setAttribute('aria-valuenow', progress);\n bar.style.width = percentage;\n bar.innerHTML = percentage;\n },\n updateProgressBarUnknown: function(progressBar) {\n if (!progressBar) return;\n\n var bar = progressBar.firstChild;\n progressBar.className = 'progress progress-striped active';\n bar.removeAttribute('aria-valuenow');\n bar.style.width = '100%';\n bar.innerHTML = '';\n }\n});\n",
83
+ "// Base Foundation theme\nJSONEditor.defaults.themes.foundation = JSONEditor.AbstractTheme.extend({\n getChildEditorHolder: function() {\n var el = document.createElement('div');\n el.style.marginBottom = '15px';\n return el;\n },\n getSelectInput: function(options) {\n var el = this._super(options);\n el.style.minWidth = 'none';\n el.style.padding = '5px';\n el.style.marginTop = '3px';\n return el;\n },\n getSwitcher: function(options) {\n var el = this._super(options);\n el.style.paddingRight = '8px';\n return el;\n },\n afterInputReady: function(input) {\n if(this.closest(input,'.compact')) {\n input.style.marginBottom = 0;\n }\n input.group = this.closest(input,'.form-control');\n },\n getFormInputLabel: function(text) {\n var el = this._super(text);\n el.style.display = 'inline-block';\n return el;\n },\n getFormInputField: function(type) {\n var el = this._super(type);\n el.style.width = '100%';\n el.style.marginBottom = type==='checkbox'? '0' : '12px';\n return el;\n },\n getFormInputDescription: function(text) {\n var el = document.createElement('p');\n el.textContent = text;\n el.style.marginTop = '-10px';\n el.style.fontStyle = 'italic';\n return el;\n },\n getIndentedPanel: function() {\n var el = document.createElement('div');\n el.className = 'panel';\n el.style.paddingBottom = 0;\n return el;\n },\n getHeaderButtonHolder: function() {\n var el = this.getButtonHolder();\n el.style.display = 'inline-block';\n el.style.marginLeft = '10px';\n el.style.verticalAlign = 'middle';\n return el;\n },\n getButtonHolder: function() {\n var el = document.createElement('div');\n el.className = 'button-group';\n return el;\n },\n getButton: function(text, icon, title) {\n var el = this._super(text, icon, title);\n el.className += ' small button';\n return el;\n },\n addInputError: function(input,text) {\n if(!input.group) return;\n input.group.className += ' error';\n \n if(!input.errmsg) {\n input.insertAdjacentHTML('afterend','<small class=\"error\"></small>');\n input.errmsg = input.parentNode.getElementsByClassName('error')[0];\n }\n else {\n input.errmsg.style.display = '';\n }\n \n input.errmsg.textContent = text;\n },\n removeInputError: function(input) {\n if(!input.errmsg) return;\n input.group.className = input.group.className.replace(/ error/g,'');\n input.errmsg.style.display = 'none';\n },\n getProgressBar: function() {\n var progressBar = document.createElement('div');\n progressBar.className = 'progress';\n\n var meter = document.createElement('span');\n meter.className = 'meter';\n meter.style.width = '0%';\n progressBar.appendChild(meter);\n return progressBar;\n },\n updateProgressBar: function(progressBar, progress) {\n if (!progressBar) return;\n progressBar.firstChild.style.width = progress + '%';\n },\n updateProgressBarUnknown: function(progressBar) {\n if (!progressBar) return;\n progressBar.firstChild.style.width = '100%';\n }\n});\n\n// Foundation 3 Specific Theme\nJSONEditor.defaults.themes.foundation3 = JSONEditor.defaults.themes.foundation.extend({\n getHeaderButtonHolder: function() {\n var el = this._super();\n el.style.fontSize = '.6em';\n return el;\n },\n getFormInputLabel: function(text) {\n var el = this._super(text);\n el.style.fontWeight = 'bold';\n return el;\n },\n getTabHolder: function() {\n var el = document.createElement('div');\n el.className = 'row';\n el.innerHTML = \"<dl class='tabs vertical two columns'></dl><div class='tabs-content ten columns'></div>\";\n return el;\n },\n setGridColumnSize: function(el,size) {\n var sizes = ['zero','one','two','three','four','five','six','seven','eight','nine','ten','eleven','twelve'];\n el.className = 'columns '+sizes[size];\n },\n getTab: function(text) {\n var el = document.createElement('dd');\n var a = document.createElement('a');\n a.setAttribute('href','#');\n a.appendChild(text);\n el.appendChild(a);\n return el;\n },\n getTabContentHolder: function(tab_holder) {\n return tab_holder.children[1];\n },\n getTabContent: function() {\n var el = document.createElement('div');\n el.className = 'content active';\n el.style.paddingLeft = '5px';\n return el;\n },\n markTabActive: function(tab) {\n tab.className += ' active';\n },\n markTabInactive: function(tab) {\n tab.className = tab.className.replace(/\\s*active/g,'');\n },\n addTab: function(holder, tab) {\n holder.children[0].appendChild(tab);\n }\n});\n\n// Foundation 4 Specific Theme\nJSONEditor.defaults.themes.foundation4 = JSONEditor.defaults.themes.foundation.extend({\n getHeaderButtonHolder: function() {\n var el = this._super();\n el.style.fontSize = '.6em';\n return el;\n },\n setGridColumnSize: function(el,size) {\n el.className = 'columns large-'+size;\n },\n getFormInputDescription: function(text) {\n var el = this._super(text);\n el.style.fontSize = '.8rem';\n return el;\n },\n getFormInputLabel: function(text) {\n var el = this._super(text);\n el.style.fontWeight = 'bold';\n return el;\n }\n});\n\n// Foundation 5 Specific Theme\nJSONEditor.defaults.themes.foundation5 = JSONEditor.defaults.themes.foundation.extend({\n getFormInputDescription: function(text) {\n var el = this._super(text);\n el.style.fontSize = '.8rem';\n return el;\n },\n setGridColumnSize: function(el,size) {\n el.className = 'columns medium-'+size;\n },\n getButton: function(text, icon, title) {\n var el = this._super(text,icon,title);\n el.className = el.className.replace(/\\s*small/g,'') + ' tiny';\n return el;\n },\n getTabHolder: function() {\n var el = document.createElement('div');\n el.innerHTML = \"<dl class='tabs vertical'></dl><div class='tabs-content vertical'></div>\";\n return el;\n },\n getTab: function(text) {\n var el = document.createElement('dd');\n var a = document.createElement('a');\n a.setAttribute('href','#');\n a.appendChild(text);\n el.appendChild(a);\n return el;\n },\n getTabContentHolder: function(tab_holder) {\n return tab_holder.children[1];\n },\n getTabContent: function() {\n var el = document.createElement('div');\n el.className = 'content active';\n el.style.paddingLeft = '5px';\n return el;\n },\n markTabActive: function(tab) {\n tab.className += ' active';\n },\n markTabInactive: function(tab) {\n tab.className = tab.className.replace(/\\s*active/g,'');\n },\n addTab: function(holder, tab) {\n holder.children[0].appendChild(tab);\n }\n});\n",
84
+ "JSONEditor.defaults.themes.html = JSONEditor.AbstractTheme.extend({\n getFormInputLabel: function(text) {\n var el = this._super(text);\n el.style.display = 'block';\n el.style.marginBottom = '3px';\n el.style.fontWeight = 'bold';\n return el;\n },\n getFormInputDescription: function(text) {\n var el = this._super(text);\n el.style.fontSize = '.8em';\n el.style.margin = 0;\n el.style.display = 'inline-block';\n el.style.fontStyle = 'italic';\n return el;\n },\n getIndentedPanel: function() {\n var el = this._super();\n el.style.border = '1px solid #ddd';\n el.style.padding = '5px';\n el.style.margin = '5px';\n el.style.borderRadius = '3px';\n return el;\n },\n getChildEditorHolder: function() {\n var el = this._super();\n el.style.marginBottom = '8px';\n return el;\n },\n getHeaderButtonHolder: function() {\n var el = this.getButtonHolder();\n el.style.display = 'inline-block';\n el.style.marginLeft = '10px';\n el.style.fontSize = '.8em';\n el.style.verticalAlign = 'middle';\n return el;\n },\n getTable: function() {\n var el = this._super();\n el.style.borderBottom = '1px solid #ccc';\n el.style.marginBottom = '5px';\n return el;\n },\n addInputError: function(input, text) {\n input.style.borderColor = 'red';\n \n if(!input.errmsg) {\n var group = this.closest(input,'.form-control');\n input.errmsg = document.createElement('div');\n input.errmsg.setAttribute('class','errmsg');\n input.errmsg.style = input.errmsg.style || {};\n input.errmsg.style.color = 'red';\n group.appendChild(input.errmsg);\n }\n else {\n input.errmsg.style.display = 'block';\n }\n \n input.errmsg.innerHTML = '';\n input.errmsg.appendChild(document.createTextNode(text));\n },\n removeInputError: function(input) {\n input.style.borderColor = '';\n if(input.errmsg) input.errmsg.style.display = 'none';\n },\n getProgressBar: function() {\n var max = 100, start = 0;\n\n var progressBar = document.createElement('progress');\n progressBar.setAttribute('max', max);\n progressBar.setAttribute('value', start);\n return progressBar;\n },\n updateProgressBar: function(progressBar, progress) {\n if (!progressBar) return;\n progressBar.setAttribute('value', progress);\n },\n updateProgressBarUnknown: function(progressBar) {\n if (!progressBar) return;\n progressBar.removeAttribute('value');\n }\n});\n",
85
+ "JSONEditor.defaults.themes.jqueryui = JSONEditor.AbstractTheme.extend({\n getTable: function() {\n var el = this._super();\n el.setAttribute('cellpadding',5);\n el.setAttribute('cellspacing',0);\n return el;\n },\n getTableHeaderCell: function(text) {\n var el = this._super(text);\n el.className = 'ui-state-active';\n el.style.fontWeight = 'bold';\n return el;\n },\n getTableCell: function() {\n var el = this._super();\n el.className = 'ui-widget-content';\n return el;\n },\n getHeaderButtonHolder: function() {\n var el = this.getButtonHolder();\n el.style.marginLeft = '10px';\n el.style.fontSize = '.6em';\n el.style.display = 'inline-block';\n return el;\n },\n getFormInputDescription: function(text) {\n var el = this.getDescription(text);\n el.style.marginLeft = '10px';\n el.style.display = 'inline-block';\n return el;\n },\n getFormControl: function(label, input, description) {\n var el = this._super(label,input,description);\n if(input.type === 'checkbox') {\n el.style.lineHeight = '25px';\n \n el.style.padding = '3px 0';\n }\n else {\n el.style.padding = '4px 0 8px 0';\n }\n return el;\n },\n getDescription: function(text) {\n var el = document.createElement('span');\n el.style.fontSize = '.8em';\n el.style.fontStyle = 'italic';\n el.textContent = text;\n return el;\n },\n getButtonHolder: function() {\n var el = document.createElement('div');\n el.className = 'ui-buttonset';\n el.style.fontSize = '.7em';\n return el;\n },\n getFormInputLabel: function(text) {\n var el = document.createElement('label');\n el.style.fontWeight = 'bold';\n el.style.display = 'block';\n el.textContent = text;\n return el;\n },\n getButton: function(text, icon, title) {\n var button = document.createElement(\"button\");\n button.className = 'ui-button ui-widget ui-state-default ui-corner-all';\n\n // Icon only\n if(icon && !text) {\n button.className += ' ui-button-icon-only';\n icon.className += ' ui-button-icon-primary ui-icon-primary';\n button.appendChild(icon);\n }\n // Icon and Text\n else if(icon) {\n button.className += ' ui-button-text-icon-primary';\n icon.className += ' ui-button-icon-primary ui-icon-primary';\n button.appendChild(icon);\n }\n // Text only\n else {\n button.className += ' ui-button-text-only';\n }\n\n var el = document.createElement('span');\n el.className = 'ui-button-text';\n el.textContent = text||title||\".\";\n button.appendChild(el);\n\n button.setAttribute('title',title);\n \n return button;\n },\n setButtonText: function(button,text, icon, title) {\n button.innerHTML = '';\n button.className = 'ui-button ui-widget ui-state-default ui-corner-all';\n\n // Icon only\n if(icon && !text) {\n button.className += ' ui-button-icon-only';\n icon.className += ' ui-button-icon-primary ui-icon-primary';\n button.appendChild(icon);\n }\n // Icon and Text\n else if(icon) {\n button.className += ' ui-button-text-icon-primary';\n icon.className += ' ui-button-icon-primary ui-icon-primary';\n button.appendChild(icon);\n }\n // Text only\n else {\n button.className += ' ui-button-text-only';\n }\n\n var el = document.createElement('span');\n el.className = 'ui-button-text';\n el.textContent = text||title||\".\";\n button.appendChild(el);\n\n button.setAttribute('title',title);\n },\n getIndentedPanel: function() {\n var el = document.createElement('div');\n el.className = 'ui-widget-content ui-corner-all';\n el.style.padding = '1em 1.4em';\n el.style.marginBottom = '20px';\n return el;\n },\n afterInputReady: function(input) {\n if(input.controls) return;\n input.controls = this.closest(input,'.form-control');\n },\n addInputError: function(input,text) {\n if(!input.controls) return;\n if(!input.errmsg) {\n input.errmsg = document.createElement('div');\n input.errmsg.className = 'ui-state-error';\n input.controls.appendChild(input.errmsg);\n }\n else {\n input.errmsg.style.display = '';\n }\n\n input.errmsg.textContent = text;\n },\n removeInputError: function(input) {\n if(!input.errmsg) return;\n input.errmsg.style.display = 'none';\n },\n markTabActive: function(tab) {\n tab.className = tab.className.replace(/\\s*ui-widget-header/g,'')+' ui-state-active';\n },\n markTabInactive: function(tab) {\n tab.className = tab.className.replace(/\\s*ui-state-active/g,'')+' ui-widget-header';\n }\n});\n",
86
+ "JSONEditor.AbstractIconLib = Class.extend({\n mapping: {\n collapse: '',\n expand: '',\n \"delete\": '',\n edit: '',\n add: '',\n cancel: '',\n save: '',\n moveup: '',\n movedown: ''\n },\n icon_prefix: '',\n getIconClass: function(key) {\n if(this.mapping[key]) return this.icon_prefix+this.mapping[key];\n else return null;\n },\n getIcon: function(key) {\n var iconclass = this.getIconClass(key);\n \n if(!iconclass) return null;\n \n var i = document.createElement('i');\n i.className = iconclass;\n return i;\n }\n});\n",
87
+ "JSONEditor.defaults.iconlibs.bootstrap2 = JSONEditor.AbstractIconLib.extend({\n mapping: {\n collapse: 'chevron-down',\n expand: 'chevron-up',\n \"delete\": 'trash',\n edit: 'pencil',\n add: 'plus',\n cancel: 'ban-circle',\n save: 'ok',\n moveup: 'arrow-up',\n movedown: 'arrow-down'\n },\n icon_prefix: 'icon-'\n});\n",
88
+ "JSONEditor.defaults.iconlibs.bootstrap3 = JSONEditor.AbstractIconLib.extend({\n mapping: {\n collapse: 'chevron-down',\n expand: 'chevron-right',\n \"delete\": 'remove',\n edit: 'pencil',\n add: 'plus',\n cancel: 'floppy-remove',\n save: 'floppy-saved',\n moveup: 'arrow-up',\n movedown: 'arrow-down'\n },\n icon_prefix: 'glyphicon glyphicon-'\n});\n",
89
+ "JSONEditor.defaults.iconlibs.fontawesome3 = JSONEditor.AbstractIconLib.extend({\n mapping: {\n collapse: 'chevron-down',\n expand: 'chevron-right',\n \"delete\": 'remove',\n edit: 'pencil',\n add: 'plus',\n cancel: 'ban-circle',\n save: 'save',\n moveup: 'arrow-up',\n movedown: 'arrow-down'\n },\n icon_prefix: 'icon-'\n});\n",
90
+ "JSONEditor.defaults.iconlibs.fontawesome4 = JSONEditor.AbstractIconLib.extend({\n mapping: {\n collapse: 'caret-square-o-down',\n expand: 'caret-square-o-right',\n \"delete\": 'times',\n edit: 'pencil',\n add: 'plus',\n cancel: 'ban',\n save: 'save',\n moveup: 'arrow-up',\n movedown: 'arrow-down'\n },\n icon_prefix: 'fa fa-'\n});\n",
91
+ "JSONEditor.defaults.iconlibs.foundation2 = JSONEditor.AbstractIconLib.extend({\n mapping: {\n collapse: 'minus',\n expand: 'plus',\n \"delete\": 'remove',\n edit: 'edit',\n add: 'add-doc',\n cancel: 'error',\n save: 'checkmark',\n moveup: 'up-arrow',\n movedown: 'down-arrow'\n },\n icon_prefix: 'foundicon-'\n});\n",
92
+ "JSONEditor.defaults.iconlibs.foundation3 = JSONEditor.AbstractIconLib.extend({\n mapping: {\n collapse: 'minus',\n expand: 'plus',\n \"delete\": 'x',\n edit: 'pencil',\n add: 'page-add',\n cancel: 'x-circle',\n save: 'save',\n moveup: 'arrow-up',\n movedown: 'arrow-down'\n },\n icon_prefix: 'fi-'\n});\n",
93
+ "JSONEditor.defaults.iconlibs.jqueryui = JSONEditor.AbstractIconLib.extend({\n mapping: {\n collapse: 'triangle-1-s',\n expand: 'triangle-1-e',\n \"delete\": 'trash',\n edit: 'pencil',\n add: 'plusthick',\n cancel: 'closethick',\n save: 'disk',\n moveup: 'arrowthick-1-n',\n movedown: 'arrowthick-1-s'\n },\n icon_prefix: 'ui-icon ui-icon-'\n});\n",
94
+ "JSONEditor.defaults.templates[\"default\"] = function() {\n return {\n compile: function(template) {\n var matches = template.match(/{{\\s*([a-zA-Z0-9\\-_ \\.]+)\\s*}}/g);\n var l = matches && matches.length;\n\n // Shortcut if the template contains no variables\n if(!l) return function() { return template; };\n\n // Pre-compute the search/replace functions\n // This drastically speeds up template execution\n var replacements = [];\n var get_replacement = function(i) {\n var p = matches[i].replace(/[{}]+/g,'').trim().split('.');\n var n = p.length;\n var func;\n \n if(n > 1) {\n var cur;\n func = function(vars) {\n cur = vars;\n for(i=0; i<n; i++) {\n cur = cur[p[i]];\n if(!cur) break;\n }\n return cur;\n };\n }\n else {\n p = p[0];\n func = function(vars) {\n return vars[p];\n };\n }\n \n replacements.push({\n s: matches[i],\n r: func\n });\n };\n for(var i=0; i<l; i++) {\n get_replacement(i);\n }\n\n // The compiled function\n return function(vars) {\n var ret = template+\"\";\n var r;\n for(i=0; i<l; i++) {\n r = replacements[i];\n ret = ret.replace(r.s, r.r(vars));\n }\n return ret;\n };\n }\n };\n};\n",
95
+ "JSONEditor.defaults.templates.ejs = function() {\n if(!window.EJS) return false;\n\n return {\n compile: function(template) {\n var compiled = new window.EJS({\n text: template\n });\n\n return function(context) {\n return compiled.render(context);\n };\n }\n };\n};\n",
96
+ "JSONEditor.defaults.templates.handlebars = function() {\n return window.Handlebars;\n};\n",
97
+ "JSONEditor.defaults.templates.hogan = function() {\n if(!window.Hogan) return false;\n\n return {\n compile: function(template) {\n var compiled = window.Hogan.compile(template);\n return function(context) {\n return compiled.render(context);\n };\n }\n };\n};\n",
98
+ "JSONEditor.defaults.templates.markup = function() {\n if(!window.Mark || !window.Mark.up) return false;\n\n return {\n compile: function(template) {\n return function(context) {\n return window.Mark.up(template,context);\n };\n }\n };\n};\n",
99
+ "JSONEditor.defaults.templates.mustache = function() {\n if(!window.Mustache) return false;\n\n return {\n compile: function(template) {\n return function(view) {\n return window.Mustache.render(template, view);\n };\n }\n };\n};\n",
100
+ "JSONEditor.defaults.templates.swig = function() {\n return window.swig;\n};\n",
101
+ "JSONEditor.defaults.templates.underscore = function() {\n if(!window._) return false;\n\n return {\n compile: function(template) {\n return function(context) {\n return window._.template(template, context);\n };\n }\n };\n};\n",
102
+ "// Set the default theme\nJSONEditor.defaults.theme = 'html';\n\n// Set the default template engine\nJSONEditor.defaults.template = 'default';\n\n// Default options when initializing JSON Editor\nJSONEditor.defaults.options = {};\n\n// String translate function\nJSONEditor.defaults.translate = function(key, variables) {\n var lang = JSONEditor.defaults.languages[JSONEditor.defaults.language];\n if(!lang) throw \"Unknown language \"+JSONEditor.defaults.language;\n \n var string = lang[key] || JSONEditor.defaults.languages[JSONEditor.defaults.default_language][key];\n \n if(typeof string === \"undefined\") throw \"Unknown translate string \"+key;\n \n if(variables) {\n for(var i=0; i<variables.length; i++) {\n string = string.replace(new RegExp('\\\\{\\\\{'+i+'}}','g'),variables[i]);\n }\n }\n \n return string;\n};\n\n// Translation strings and default languages\nJSONEditor.defaults.default_language = 'en';\nJSONEditor.defaults.language = JSONEditor.defaults.default_language;\nJSONEditor.defaults.languages.en = {\n /**\n * When a property is not set\n */\n error_notset: \"Property must be set\",\n /**\n * When a string must not be empty\n */\n error_notempty: \"Value required\",\n /**\n * When a value is not one of the enumerated values\n */\n error_enum: \"Value must be one of the enumerated values\",\n /**\n * When a value doesn't validate any schema of a 'anyOf' combination\n */\n error_anyOf: \"Value must validate against at least one of the provided schemas\",\n /**\n * When a value doesn't validate\n * @variables This key takes one variable: The number of schemas the value does not validate\n */\n error_oneOf: 'Value must validate against exactly one of the provided schemas. It currently validates against {{0}} of the schemas.',\n /**\n * When a value does not validate a 'not' schema\n */\n error_not: \"Value must not validate against the provided schema\",\n /**\n * When a value does not match any of the provided types\n */\n error_type_union: \"Value must be one of the provided types\",\n /**\n * When a value does not match the given type\n * @variables This key takes one variable: The type the value should be of\n */\n error_type: \"Value must be of type {{0}}\",\n /**\n * When the value validates one of the disallowed types\n */\n error_disallow_union: \"Value must not be one of the provided disallowed types\",\n /**\n * When the value validates a disallowed type\n * @variables This key takes one variable: The type the value should not be of\n */\n error_disallow: \"Value must not be of type {{0}}\",\n /**\n * When a value is not a multiple of or divisible by a given number\n * @variables This key takes one variable: The number mentioned above\n */\n error_multipleOf: \"Value must be a multiple of {{0}}\",\n /**\n * When a value is greater than it's supposed to be (exclusive)\n * @variables This key takes one variable: The maximum\n */\n error_maximum_excl: \"Value must be less than {{0}}\",\n /**\n * When a value is greater than it's supposed to be (inclusive\n * @variables This key takes one variable: The maximum\n */\n error_maximum_incl: \"Value must be at most {{0}}\",\n /**\n * When a value is lesser than it's supposed to be (exclusive)\n * @variables This key takes one variable: The minimum\n */\n error_minimum_excl: \"Value must be greater than {{0}}\",\n /**\n * When a value is lesser than it's supposed to be (inclusive)\n * @variables This key takes one variable: The minimum\n */\n error_minimum_incl: \"Value must be at least {{0}}\",\n /**\n * When a value have too many characters\n * @variables This key takes one variable: The maximum character count\n */\n error_maxLength: \"Value must be at most {{0}} characters long\",\n /**\n * When a value does not have enough characters\n * @variables This key takes one variable: The minimum character count\n */\n error_minLength: \"Value must be at least {{0}} characters long\",\n /**\n * When a value does not match a given pattern\n */\n error_pattern: \"Value must match the pattern {{0}}\",\n /**\n * When an array has additional items whereas it is not supposed to\n */\n error_additionalItems: \"No additional items allowed in this array\",\n /**\n * When there are to many items in an array\n * @variables This key takes one variable: The maximum item count\n */\n error_maxItems: \"Value must have at most {{0}} items\",\n /**\n * When there are not enough items in an array\n * @variables This key takes one variable: The minimum item count\n */\n error_minItems: \"Value must have at least {{0}} items\",\n /**\n * When an array is supposed to have unique items but has duplicates\n */\n error_uniqueItems: \"Array must have unique items\",\n /**\n * When there are too many properties in an object\n * @variables This key takes one variable: The maximum property count\n */\n error_maxProperties: \"Object must have at most {{0}} properties\",\n /**\n * When there are not enough properties in an object\n * @variables This key takes one variable: The minimum property count\n */\n error_minProperties: \"Object must have at least {{0}} properties\",\n /**\n * When a required property is not defined\n * @variables This key takes one variable: The name of the missing property\n */\n error_required: \"Object is missing the required property '{{0}}'\",\n /**\n * When there is an additional property is set whereas there should be none\n * @variables This key takes one variable: The name of the additional property\n */\n error_additional_properties: \"No additional properties allowed, but property {{0}} is set\",\n /**\n * When a dependency is not resolved\n * @variables This key takes one variable: The name of the missing property for the dependency\n */\n error_dependency: \"Must have property {{0}}\",\n /**\n * Text on Delete All buttons\n */\n button_delete_all: \"All\",\n /**\n * Title on Delete All buttons\n */\n button_delete_all_title: \"Delete All\",\n /**\n * Text on Delete Last buttons\n * @variable This key takes one variable: The title of object to delete\n */\n button_delete_last: \"Last {{0}}\",\n /**\n * Title on Delete Last buttons\n * @variable This key takes one variable: The title of object to delete\n */\n button_delete_last_title: \"Delete Last {{0}}\",\n /**\n * Title on Add Row buttons\n * @variable This key takes one variable: The title of object to add\n */\n button_add_row_title: \"Add {{0}}\",\n /**\n * Title on Move Down buttons\n */\n button_move_down_title: \"Move down\",\n /**\n * Title on Move Up buttons\n */\n button_move_up_title: \"Move up\",\n /**\n * Title on Delete Row buttons\n * @variable This key takes one variable: The title of object to delete\n */\n button_delete_row_title: \"Delete {{0}}\",\n /**\n * Title on Delete Row buttons, short version (no parameter with the object title)\n */\n button_delete_row_title_short: \"Delete\",\n /**\n * Title on Collapse buttons\n */\n button_collapse: \"Collapse\"\n};\n\n// Miscellaneous Plugin Settings\nJSONEditor.plugins = {\n ace: {\n theme: ''\n },\n epiceditor: {\n\n },\n sceditor: {\n\n },\n select2: {\n \n },\n selectize: {\n }\n};\n\n// Default per-editor options\nfor(var i in JSONEditor.defaults.editors) {\n if(!JSONEditor.defaults.editors.hasOwnProperty(i)) continue;\n JSONEditor.defaults.editors[i].options = JSONEditor.defaults.editors.options || {};\n}\n\n// Set the default resolvers\n// Use \"multiple\" as a fall back for everything\nJSONEditor.defaults.resolvers.unshift(function(schema) {\n if(typeof schema.type !== \"string\") return \"multiple\";\n});\n// If the type is not set but properties are defined, we can infer the type is actually object\nJSONEditor.defaults.resolvers.unshift(function(schema) {\n // If the schema is a simple type\n if(!schema.type && schema.properties ) return \"object\";\n});\n// If the type is set and it's a basic type, use the primitive editor\nJSONEditor.defaults.resolvers.unshift(function(schema) {\n // If the schema is a simple type\n if(typeof schema.type === \"string\") return schema.type;\n});\n// Boolean editors\nJSONEditor.defaults.resolvers.unshift(function(schema) {\n if(schema.type === 'boolean') {\n // If explicitly set to 'checkbox', use that\n if(schema.format === \"checkbox\" || (schema.options && schema.options.checkbox)) {\n return \"checkbox\";\n }\n // Otherwise, default to select menu\n return (JSONEditor.plugins.selectize.enable) ? 'selectize' : 'select';\n }\n});\n// Use the multiple editor for schemas where the `type` is set to \"any\"\nJSONEditor.defaults.resolvers.unshift(function(schema) {\n // If the schema can be of any type\n if(schema.type === \"any\") return \"multiple\";\n});\n// Editor for base64 encoded files\nJSONEditor.defaults.resolvers.unshift(function(schema) {\n // If the schema can be of any type\n if(schema.type === \"string\" && schema.media && schema.media.binaryEncoding===\"base64\") {\n return \"base64\";\n }\n});\n// Editor for uploading files\nJSONEditor.defaults.resolvers.unshift(function(schema) {\n if(schema.type === \"string\" && schema.format === \"url\" && schema.options && schema.options.upload === true) {\n if(window.FileReader) return \"upload\";\n }\n});\n// Use the table editor for arrays with the format set to `table`\nJSONEditor.defaults.resolvers.unshift(function(schema) {\n // Type `array` with format set to `table`\n if(schema.type == \"array\" && schema.format == \"table\") {\n return \"table\";\n }\n});\n// Use the `select` editor for dynamic enumSource enums\nJSONEditor.defaults.resolvers.unshift(function(schema) {\n if(schema.enumSource) return (JSONEditor.plugins.selectize.enable) ? 'selectize' : 'select';\n});\n// Use the `enum` or `select` editors for schemas with enumerated properties\nJSONEditor.defaults.resolvers.unshift(function(schema) {\n if(schema[\"enum\"]) {\n if(schema.type === \"array\" || schema.type === \"object\") {\n return \"enum\";\n }\n else if(schema.type === \"number\" || schema.type === \"integer\" || schema.type === \"string\") {\n return (JSONEditor.plugins.selectize.enable) ? 'selectize' : 'select';\n }\n }\n});\n// Specialized editors for arrays of strings\nJSONEditor.defaults.resolvers.unshift(function(schema) {\n if(schema.type === \"array\" && schema.items && !(Array.isArray(schema.items)) && schema.uniqueItems && ['string','number','integer'].indexOf(schema.items.type) >= 0) {\n // For enumerated strings, number, or integers\n if(schema.items.enum) {\n return 'multiselect';\n }\n // For non-enumerated strings (tag editor)\n else if(JSONEditor.plugins.selectize.enable && schema.items.type === \"string\") {\n return 'arraySelectize';\n }\n }\n});\n// Use the multiple editor for schemas with `oneOf` set\nJSONEditor.defaults.resolvers.unshift(function(schema) {\n // If this schema uses `oneOf`\n if(schema.oneOf) return \"multiple\";\n});\n",
103
+ "/**\n * This is a small wrapper for using JSON Editor like a typical jQuery plugin.\n */\n(function() {\n if(window.jQuery || window.Zepto) {\n var $ = window.jQuery || window.Zepto;\n $.jsoneditor = JSONEditor.defaults;\n \n $.fn.jsoneditor = function(options) {\n var self = this;\n var editor = this.data('jsoneditor');\n if(options === 'value') {\n if(!editor) throw \"Must initialize jsoneditor before getting/setting the value\";\n \n // Set value\n if(arguments.length > 1) {\n editor.setValue(arguments[1]);\n }\n // Get value\n else {\n return editor.getValue();\n }\n }\n else if(options === 'validate') {\n if(!editor) throw \"Must initialize jsoneditor before validating\";\n \n // Validate a specific value\n if(arguments.length > 1) {\n return editor.validate(arguments[1]);\n }\n // Validate current value\n else {\n return editor.validate();\n }\n }\n else if(options === 'destroy') {\n if(editor) {\n editor.destroy();\n this.data('jsoneditor',null);\n }\n }\n else {\n // Destroy first\n if(editor) {\n editor.destroy();\n }\n \n // Create editor\n editor = new JSONEditor(this.get(0),options);\n this.data('jsoneditor',editor);\n \n // Setup event listeners\n editor.on('change',function() {\n self.trigger('change');\n });\n editor.on('ready',function() {\n self.trigger('ready');\n });\n }\n \n return this;\n };\n }\n})();\n",
104
+ " window.JSONEditor = JSONEditor;\n})();\n"
105
+ ]
106
+ }