Merge "Fix check style issues"
authorSébastien Determe <sebastien.determe@intl.att.com>
Tue, 19 Mar 2019 14:11:32 +0000 (14:11 +0000)
committerGerrit Code Review <gerrit@onap.org>
Tue, 19 Mar 2019 14:11:32 +0000 (14:11 +0000)
29 files changed:
src/main/java/org/onap/clamp/clds/dao/CldsDao.java
src/main/java/org/onap/clamp/clds/model/CldsEvent.java
src/main/java/org/onap/clamp/clds/model/CldsModel.java
src/main/java/org/onap/clamp/clds/model/actions/ActionsHandler.java
src/main/java/org/onap/clamp/clds/sdc/controller/SdcSingleController.java
src/main/java/org/onap/clamp/clds/service/CldsService.java
src/main/java/org/onap/clamp/clds/tosca/JsonEditorSchemaConstants.java
src/main/java/org/onap/clamp/clds/tosca/ToscaYamlToJsonConvertor.java
src/main/java/org/onap/clamp/clds/util/drawing/AwtUtils.java
src/main/resources/META-INF/resources/designer/css/app.css
src/main/resources/META-INF/resources/designer/index.html
src/main/resources/META-INF/resources/designer/lib/jsoneditor.js
src/main/resources/META-INF/resources/designer/partials/portfolios/PolicyWindow_properties.html
src/main/resources/META-INF/resources/designer/scripts/ActivityModellingCtrl.js
src/main/resources/META-INF/resources/designer/scripts/ExportFileCtrl.js [deleted file]
src/main/resources/META-INF/resources/designer/scripts/ExportFileService.js [deleted file]
src/main/resources/META-INF/resources/designer/scripts/FileUploadCtrl.js [deleted file]
src/main/resources/META-INF/resources/designer/scripts/FileUploadService.js [deleted file]
src/main/resources/META-INF/resources/designer/scripts/ImportSchemaCtrl.js [deleted file]
src/main/resources/META-INF/resources/designer/scripts/OperationalPolicyCtrl.js [new file with mode: 0644]
src/main/resources/META-INF/resources/designer/scripts/OperationalPolicyService.js [moved from src/main/resources/META-INF/resources/designer/scripts/importSchemaService.js with 65% similarity]
src/main/resources/META-INF/resources/designer/scripts/ToscaModelCtrl.js
src/main/resources/META-INF/resources/designer/scripts/UpgradeSchemaCtrl.js [deleted file]
src/main/resources/META-INF/resources/designer/scripts/app.js
src/main/resources/META-INF/resources/designer/scripts/common_variables.js
src/main/resources/META-INF/resources/designer/scripts/propertyController.js
src/main/resources/META-INF/resources/designer/scripts/soapRequestService.js [deleted file]
src/test/java/org/onap/clamp/clds/it/CldsDaoItCase.java
src/test/resources/tosca/tosca_example.yaml

index eef6353..5da26b1 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP CLAMP
  * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights
  *                             reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -84,7 +84,7 @@ public class CldsDao {
     private static final String DATE_FORMAT = "MM-dd-yyyy HH:mm:ss";
 
     /**
-     * Log message when instantiating
+     * Log message when instantiating.
      */
     public CldsDao() {
         logger.info("CldsDao instantiating...");
@@ -92,6 +92,8 @@ public class CldsDao {
 
     /**
      * When dataSource is provided, instantiate spring jdbc objects.
+     *
+     * @param dataSource the data source
      */
     public void setDataSource(DataSource dataSource) {
         this.jdbcTemplateObject = new JdbcTemplate(dataSource);
@@ -114,18 +116,14 @@ public class CldsDao {
 
     /**
      * Get a model from the database given the model name.
+     *
+     * @param modelName the model name
+     * @return the model
      */
     public CldsModel getModel(String modelName) {
         return getModel(modelName, null);
     }
 
-    /**
-     * Get a model from the database given the controlNameUuid.
-     */
-    public CldsModel getModelByUuid(String controlNameUuid) {
-        return getModel(null, controlNameUuid);
-    }
-
     // Get a model from the database given the model name or a controlNameUuid.
     private CldsModel getModel(String modelName, String controlNameUuid) {
         CldsModel model = new CldsModel();
@@ -137,12 +135,22 @@ public class CldsDao {
         return model;
     }
 
+    /**
+     * Get a model from the database given the controlNameUuid.
+     *
+     * @param controlNameUuid the control name uuid
+     * @return the model by uuid
+     */
+    public CldsModel getModelByUuid(String controlNameUuid) {
+        return getModel(null, controlNameUuid);
+    }
     /**
      * Get a model and template information from the database given the model name.
      *
-     * @param modelName
-     * @return model
+     * @param modelName the model name
+     * @return model model template
      */
+
     public CldsModel getModelTemplate(String modelName) {
         CldsModel model = new CldsModel();
         model.setName(modelName);
@@ -171,9 +179,9 @@ public class CldsDao {
      * Update model in the database using parameter values and return updated model
      * object.
      *
-     * @param model
-     * @param userid
-     * @return
+     * @param model  the model
+     * @param userid the userid
+     * @return model
      */
     public CldsModel setModel(CldsModel model, String userid) {
         SqlParameterSource in = new MapSqlParameterSource().addValue("v_model_name", model.getName())
@@ -200,9 +208,8 @@ public class CldsDao {
      * Inserts new modelInstance in the database using parameter values and return
      * updated model object.
      *
-     * @param model
-     * @param modelInstancesList
-     * @return
+     * @param model              the model
+     * @param modelInstancesList the model instances list
      */
     public void insModelInstance(CldsModel model, List<CldsModelInstance> modelInstancesList) {
         // Delete all existing model instances for given controlNameUUID
@@ -234,11 +241,11 @@ public class CldsDao {
      * Insert an event in the database - require either modelName or
      * controlNamePrefix/controlNameUuid.
      *
-     * @param modelName
-     * @param controlNamePrefix
-     * @param controlNameUuid
-     * @param cldsEvent
-     * @return
+     * @param modelName         the model name
+     * @param controlNamePrefix the control name prefix
+     * @param controlNameUuid   the control name uuid
+     * @param cldsEvent         the clds event
+     * @return clds event
      */
     public CldsEvent insEvent(String modelName, String controlNamePrefix, String controlNameUuid, CldsEvent cldsEvent) {
         CldsEvent event = new CldsEvent();
@@ -261,8 +268,8 @@ public class CldsDao {
     /**
      * Update event with process instance id.
      *
-     * @param eventId
-     * @param processInstanceId
+     * @param eventId           the event id
+     * @param processInstanceId the process instance id
      */
     public void updEvent(String eventId, String processInstanceId) {
         SqlParameterSource in = new MapSqlParameterSource().addValue("v_event_id", eventId)
@@ -271,7 +278,7 @@ public class CldsDao {
     }
 
     /**
-     * Return list of model names
+     * Return list of model names.
      *
      * @return model names
      */
@@ -284,8 +291,8 @@ public class CldsDao {
      * Update template in the database using parameter values and return updated
      * template object.
      *
-     * @param template
-     * @param userid
+     * @param template the template
+     * @param userid   the userid
      */
     public void setTemplate(CldsTemplate template, String userid) {
         SqlParameterSource in = new MapSqlParameterSource().addValue("v_template_name", template.getName())
@@ -303,7 +310,7 @@ public class CldsDao {
     }
 
     /**
-     * Return list of template names
+     * Return list of template names.
      *
      * @return template names
      */
@@ -315,8 +322,8 @@ public class CldsDao {
     /**
      * Get a template from the database given the model name.
      *
-     * @param templateName
-     * @return model
+     * @param templateName the template name
+     * @return model template
      */
     public CldsTemplate getTemplate(String templateName) {
         CldsTemplate template = new CldsTemplate();
@@ -345,6 +352,9 @@ public class CldsDao {
         }
     }
 
+    /**
+     * Do health check.
+     */
     public void doHealthCheck() {
         jdbcTemplateObject.execute(HEALTHCHECK);
     }
@@ -356,7 +366,8 @@ public class CldsDao {
      */
     public List<CldsModelProp> getDeployedModelProperties() {
         List<CldsModelProp> cldsModelPropList = new ArrayList<>();
-        String modelsSql = "select m.model_id, m.model_name, mp.model_prop_id, mp.model_prop_text FROM model m, model_properties mp, event e "
+        String modelsSql = "select m.model_id, m.model_name, mp.model_prop_id, mp.model_prop_text FROM model m, "
+                + "model_properties mp, event e "
             + "WHERE m.model_prop_id = mp.model_prop_id and m.event_id = e.event_id and e.action_cd = 'DEPLOY'";
         List<Map<String, Object>> rows = jdbcTemplateObject.queryForList(modelsSql);
         CldsModelProp cldsModelProp = null;
@@ -383,10 +394,11 @@ public class CldsDao {
      *         TEMPLATE_NAME | Template used to generate the ClosedLoop model.
      *         ACTION_CD | Current state of the ClosedLoop in CLDS application.
      */
-    public List<CldsMonitoringDetails> getCLDSMonitoringDetails() {
+    public List<CldsMonitoringDetails> getCldsMonitoringDetails() {
         SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
         List<CldsMonitoringDetails> cldsMonitoringDetailsList = new ArrayList<>();
-        String modelsSql = "SELECT CONCAT(M.CONTROL_NAME_PREFIX, M.CONTROL_NAME_UUID) AS CLOSELOOP_NAME , M.MODEL_NAME, M.SERVICE_TYPE_ID, M.DEPLOYMENT_ID, T.TEMPLATE_NAME, E.ACTION_CD, E.USER_ID, E.TIMESTAMP "
+        String modelsSql = "SELECT CONCAT(M.CONTROL_NAME_PREFIX, M.CONTROL_NAME_UUID) AS CLOSELOOP_NAME , "
+            + "M.MODEL_NAME, M.SERVICE_TYPE_ID, M.DEPLOYMENT_ID, T.TEMPLATE_NAME, E.ACTION_CD, E.USER_ID, E.TIMESTAMP "
             + "FROM MODEL M, TEMPLATE T, EVENT E " + "WHERE M.TEMPLATE_ID = T.TEMPLATE_ID AND M.EVENT_ID = E.EVENT_ID "
             + "ORDER BY ACTION_CD";
         List<Map<String, Object>> rows = jdbcTemplateObject.queryForList(modelsSql);
@@ -409,7 +421,7 @@ public class CldsDao {
     /**
      * Method to delete model from database.
      *
-     * @param modelName
+     * @param modelName the model name
      */
     public void deleteModel(String modelName) {
         SqlParameterSource in = new MapSqlParameterSource().addValue("v_model_name", modelName);
@@ -440,7 +452,6 @@ public class CldsDao {
     /**
      * Method to retrieve a tosca models by Policy Type from database.
      *
-     * @param policyType
      * @return List of CldsToscaModel
      */
     public List<CldsToscaModel> getAllToscaModels() {
@@ -450,7 +461,7 @@ public class CldsDao {
     /**
      * Method to retrieve a tosca models by Policy Type from database.
      *
-     * @param policyType
+     * @param policyType the policy type
      * @return List of CldsToscaModel
      */
     public List<CldsToscaModel> getToscaModelByPolicyType(String policyType) {
@@ -460,7 +471,7 @@ public class CldsDao {
     /**
      * Method to retrieve a tosca models by toscaModelName, version from database.
      *
-     * @param policyType
+     * @param toscaModelName the tosca model name
      * @return List of CldsToscaModel
      */
     public List<CldsToscaModel> getToscaModelByName(String toscaModelName) {
@@ -473,12 +484,15 @@ public class CldsDao {
         SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
         List<CldsToscaModel> cldsToscaModels = new ArrayList<>();
 
-        String toscaModelSql = "SELECT tm.tosca_model_name, tm.tosca_model_id, tm.policy_type, tmr.tosca_model_revision_id, tmr.tosca_model_json, tmr.version, tmr.user_id, tmr.createdTimestamp, tmr.lastUpdatedTimestamp "
+        String toscaModelSql = "SELECT tm.tosca_model_name, tm.tosca_model_id, tm.policy_type, "
+            + "tmr.tosca_model_revision_id, tmr.tosca_model_json, tmr.version, tmr.user_id, tmr.createdTimestamp, "
+            + "tmr.lastUpdatedTimestamp "
             + ((toscaModelName != null) ? (", tmr.tosca_model_yaml ") : " ")
             + "FROM tosca_model tm, tosca_model_revision tmr WHERE tm.tosca_model_id = tmr.tosca_model_id "
             + ((toscaModelName != null) ? (" AND tm.tosca_model_name = '" + toscaModelName + "'") : " ")
             + ((policyType != null) ? (" AND tm.policy_type = '" + policyType + "'") : " ")
-            + "AND tmr.version = (select max(version) from tosca_model_revision st where tmr.tosca_model_id=st.tosca_model_id)";
+            + "AND tmr.version = (select max(version) from tosca_model_revision st "
+            + "where tmr.tosca_model_id=st.tosca_model_id)";
 
         List<Map<String, Object>> rows = jdbcTemplateObject.queryForList(toscaModelSql);
 
@@ -504,12 +518,11 @@ public class CldsDao {
     }
 
     /**
-     * Method to upload a new version of Tosca Model Yaml in Database
-     *
-     * @param cldsToscaModel
-     * @param userId
-     * @return CldsToscaModel
+     * Method to upload a new version of Tosca Model Yaml in Database.
      *
+     * @param cldsToscaModel the clds tosca model
+     * @param userId         the user id
+     * @return CldsToscaModel clds tosca model
      */
     public CldsToscaModel updateToscaModelWithNewVersion(CldsToscaModel cldsToscaModel, String userId) {
         SqlParameterSource in = new MapSqlParameterSource().addValue("v_tosca_model_id", cldsToscaModel.getId())
@@ -524,9 +537,9 @@ public class CldsDao {
     /**
      * Method to upload a new Tosca model Yaml in DB. Default version is 1.0
      *
-     * @param cldsToscaModel
-     * @param userId
-     * @return CldsToscaModel
+     * @param cldsToscaModel the clds tosca model
+     * @param userId         the user id
+     * @return CldsToscaModel clds tosca model
      */
     public CldsToscaModel insToscaModel(CldsToscaModel cldsToscaModel, String userId) {
         SqlParameterSource in = new MapSqlParameterSource()
@@ -543,9 +556,9 @@ public class CldsDao {
     }
 
     /**
-     * Method to insert a new Dictionary in Database
+     * Method to insert a new Dictionary in Database.
      *
-     * @param cldsDictionary
+     * @param cldsDictionary the clds dictionary
      */
     public void insDictionary(CldsDictionary cldsDictionary) {
         SqlParameterSource in = new MapSqlParameterSource()
@@ -556,11 +569,11 @@ public class CldsDao {
     }
 
     /**
-     * Method to update Dictionary with new info in Database
+     * Method to update Dictionary with new info in Database.
      *
-     * @param dictionaryId
-     * @param cldsDictionary
-     * @param userId
+     * @param dictionaryId   the dictionary id
+     * @param cldsDictionary the clds dictionary
+     * @param userId         the user id
      */
     public void updateDictionary(String dictionaryId, CldsDictionary cldsDictionary, String userId) {
 
@@ -571,16 +584,17 @@ public class CldsDao {
     }
 
     /**
-     * Method to get list of Dictionaries from the Database
+     * Method to get list of Dictionaries from the Database.
      *
-     * @param dictionaryId
-     * @param dictionaryName
-     * @return
+     * @param dictionaryId   the dictionary id
+     * @param dictionaryName the dictionary name
+     * @return dictionary
      */
     public List<CldsDictionary> getDictionary(String dictionaryId, String dictionaryName) {
         SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
         List<CldsDictionary> dictionaries = new ArrayList<>();
-        String dictionarySql = "SELECT dictionary_id, dictionary_name, created_by, modified_by, timestamp FROM dictionary"
+        String dictionarySql = "SELECT dictionary_id, dictionary_name, created_by, modified_by, "
+            + "timestamp FROM dictionary"
             + ((dictionaryId != null || dictionaryName != null)
                 ? (" WHERE " + ((dictionaryName != null) ? ("dictionary_name = '" + dictionaryName + "'") : "")
                     + ((dictionaryId != null && dictionaryName != null) ? (" AND ") : "")
@@ -604,10 +618,10 @@ public class CldsDao {
     }
 
     /**
-     * Method to insert a new Dictionary Element for given dictionary in Database
+     * Method to insert a new Dictionary Element for given dictionary in Database.
      *
-     * @param cldsDictionaryItem
-     * @param userId
+     * @param cldsDictionaryItem the clds dictionary item
+     * @param userId             the user id
      */
     public void insDictionarElements(CldsDictionaryItem cldsDictionaryItem, String userId) {
         SqlParameterSource in = new MapSqlParameterSource()
@@ -622,11 +636,11 @@ public class CldsDao {
 
     /**
      * Method to update Dictionary Elements with new info for a given dictionary in
-     * Database
+     * Database.
      *
-     * @param dictionaryElementId
-     * @param cldsDictionaryItem
-     * @param userId
+     * @param dictionaryElementId the dictionary element id
+     * @param cldsDictionaryItem  the clds dictionary item
+     * @param userId              the user id
      */
     public void updateDictionaryElements(String dictionaryElementId, CldsDictionaryItem cldsDictionaryItem,
         String userId) {
@@ -643,18 +657,20 @@ public class CldsDao {
 
     /**
      * Method to get list of all dictionary elements for a given dictionary in the
-     * Database
+     * Database.
      *
-     * @param dictionaryName
-     * @param dictionaryId
-     * @param dictElementShortName
-     * @return
+     * @param dictionaryName       the dictionary name
+     * @param dictionaryId         the dictionary id
+     * @param dictElementShortName the dict element short name
+     * @return dictionary elements
      */
     public List<CldsDictionaryItem> getDictionaryElements(String dictionaryName, String dictionaryId,
         String dictElementShortName) {
         SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
         List<CldsDictionaryItem> dictionaryItems = new ArrayList<>();
-        String dictionarySql = "SELECT de.dict_element_id, de.dictionary_id, de.dict_element_name, de.dict_element_short_name, de.dict_element_description, de.dict_element_type, de.created_by, de.modified_by, de.timestamp  "
+        String dictionarySql = "SELECT de.dict_element_id, de.dictionary_id, de.dict_element_name, "
+            + "de.dict_element_short_name, de.dict_element_description, de.dict_element_type, de.created_by, "
+            + "de.modified_by, de.timestamp  "
             + "FROM dictionary_elements de, dictionary d WHERE de.dictionary_id = d.dictionary_id "
             + ((dictionaryId != null) ? (" AND d.dictionary_id = '" + dictionaryId + "'") : "")
             + ((dictElementShortName != null) ? (" AND de.dict_element_short_name = '" + dictElementShortName + "'")
@@ -683,9 +699,9 @@ public class CldsDao {
 
     /**
      * Method to get Map of all dictionary elements with key as dictionary short
-     * name and value as the full name
+     * name and value as the full name.
      *
-     * @param dictionaryElementType
+     * @param dictionaryElementType the dictionary element type
      * @return Map of dictionary elements as key value pair
      */
     public Map<String, String> getDictionaryElementsByType(String dictionaryElementType) {
index b993c63..cc57f9e 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP CLAMP
  * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights
  *                             reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -29,31 +29,91 @@ import org.onap.clamp.clds.dao.CldsDao;
  * Represent a CLDS Event.
  */
 public class CldsEvent {
+    /**
+     * The constant ACTION_TEST.
+     */
     public static final String ACTION_TEST = "TEST";
+    /**
+     * The constant ACTION_CREATE.
+     */
     public static final String ACTION_CREATE = "CREATE";
+    /**
+     * The constant ACTION_MODIFY.
+     */
     public static final String ACTION_MODIFY = "MODIFY";
+    /**
+     * The constant ACTION_SUBMIT.
+     */
     public static final String ACTION_SUBMIT = "SUBMIT";
+    /**
+     * The constant ACTION_RESUBMIT.
+     */
     // an update before model is active
     public static final String ACTION_RESUBMIT = "RESUBMIT";
+    /**
+     * The constant ACTION_SUBMITDCAE.
+     */
     // For simplified models
     public static final String ACTION_SUBMITDCAE = "SUBMITDCAE";
+    /**
+     * The constant ACTION_SUBMITPOLICY.
+     */
     public static final String ACTION_SUBMITPOLICY = "SUBMITPOLICY";
+    /**
+     * The constant ACTION_DISTRIBUTE.
+     */
     // only from dcae
     public static final String ACTION_DISTRIBUTE = "DISTRIBUTE";
+    /**
+     * The constant ACTION_DEPLOY.
+     */
     // only from dcae
     public static final String ACTION_DEPLOY = "DEPLOY";
+    /**
+     * The constant ACTION_UNDEPLOY.
+     */
     // only from dcae
     public static final String ACTION_UNDEPLOY = "UNDEPLOY";
+    /**
+     * The constant ACTION_UPDATE.
+     */
     public static final String ACTION_UPDATE = "UPDATE";
+    /**
+     * The constant ACTION_DELETE.
+     */
     public static final String ACTION_DELETE = "DELETE";
+    /**
+     * The constant ACTION_STOP.
+     */
     public static final String ACTION_STOP = "STOP";
+    /**
+     * The constant ACTION_RESTART.
+     */
     public static final String ACTION_RESTART = "RESTART";
 
+    /**
+     * The constant ACTION_STATE_INITIATED.
+     */
     public static final String ACTION_STATE_INITIATED = "INITIATED";
+    /**
+     * The constant ACTION_STATE_SENT.
+     */
     public static final String ACTION_STATE_SENT = "SENT";
+    /**
+     * The constant ACTION_STATE_COMPLETED.
+     */
     public static final String ACTION_STATE_COMPLETED = "COMPLETED";
+    /**
+     * The constant ACTION_STATE_RECEIVED.
+     */
     public static final String ACTION_STATE_RECEIVED = "RECEIVED";
+    /**
+     * The constant ACTION_STATE_ERROR.
+     */
     public static final String ACTION_STATE_ERROR = "ERROR";
+    /**
+     * The constant ACTION_STATE_ANY.
+     */
     public static final String ACTION_STATE_ANY = null;
 
     private String id;
@@ -62,22 +122,34 @@ public class CldsEvent {
     private String processInstanceId;
     private String userid;
 
+    /**
+     * Gets id.
+     *
+     * @return the id
+     */
     public String getId() {
         return id;
     }
 
+    /**
+     * Sets id.
+     *
+     * @param id the id
+     */
     public void setId(String id) {
         this.id = id;
     }
 
     /**
-     * @param cldsDao
-     * @param controlName
-     * @param userid
-     * @param actionCd
-     * @param actionStateCd
-     * @param processInstanceId
-     * @return
+     * Ins event clds event.
+     *
+     * @param cldsDao           the clds dao
+     * @param controlName       the control name
+     * @param userid            the userid
+     * @param actionCd          the action cd
+     * @param actionStateCd     the action state cd
+     * @param processInstanceId the process instance id
+     * @return clds event
      */
     public static CldsEvent insEvent(CldsDao cldsDao, String controlName, String userid, String actionCd,
         String actionStateCd, String processInstanceId) {
@@ -89,13 +161,13 @@ public class CldsEvent {
      * Insert event using controlNameUuid to find the model. This method meant for
      * processing events from dcae.
      *
-     * @param cldsDao
-     * @param model
-     * @param userId
-     * @param actionCd
-     * @param actionStateCd
-     * @param processInstanceId
-     * @return
+     * @param cldsDao           the clds dao
+     * @param model             the model
+     * @param userId            the user id
+     * @param actionCd          the action cd
+     * @param actionStateCd     the action state cd
+     * @param processInstanceId the process instance id
+     * @return clds event
      */
     public static CldsEvent insEvent(CldsDao cldsDao, CldsModel model, String userId, String actionCd,
         String actionStateCd, String processInstanceId) {
@@ -112,8 +184,8 @@ public class CldsEvent {
      * Check if actionCd is equal to the supplied checkActionCd checkActionCd should
      * not be null.
      *
-     * @param checkActionCd
-     * @return
+     * @param checkActionCd the check action cd
+     * @return boolean
      */
     public boolean isActionCd(String checkActionCd) {
         if (actionCd == null) {
@@ -127,9 +199,9 @@ public class CldsEvent {
      * and checkActionStateCd. Treat checkActionStateCd == null as a wildcard
      * checkActionCd should not be null.
      *
-     * @param checkActionCd
-     * @param checkActionStateCd
-     * @return
+     * @param checkActionCd      the check action cd
+     * @param checkActionStateCd the check action state cd
+     * @return boolean
      */
     public boolean isActionAndStateCd(String checkActionCd, String checkActionStateCd) {
         if (actionCd == null) {
@@ -147,14 +219,16 @@ public class CldsEvent {
      * Check if actionStateCd is equal to the supplied checkActionStateCd.
      * checkActionCd should not be null.
      *
-     * @param checkActionStateCd
-     * @return
+     * @param checkActionStateCd the check action state cd
+     * @return boolean
      */
     public boolean isActionStateCd(String checkActionStateCd) {
         return !(checkActionStateCd == null || actionStateCd == null) && actionStateCd.equals(checkActionStateCd);
     }
 
     /**
+     * Gets action cd.
+     *
      * @return the actionCd
      */
     public String getActionCd() {
@@ -162,14 +236,17 @@ public class CldsEvent {
     }
 
     /**
-     * @param actionCd
-     *        the actionCd to set
+     * Sets action cd.
+     *
+     * @param actionCd the actionCd to set
      */
     public void setActionCd(String actionCd) {
         this.actionCd = actionCd;
     }
 
     /**
+     * Gets action state cd.
+     *
      * @return the actionStateCd
      */
     public String getActionStateCd() {
@@ -177,14 +254,17 @@ public class CldsEvent {
     }
 
     /**
-     * @param actionStateCd
-     *        the actionStateCd to set
+     * Sets action state cd.
+     *
+     * @param actionStateCd the actionStateCd to set
      */
     public void setActionStateCd(String actionStateCd) {
         this.actionStateCd = actionStateCd;
     }
 
     /**
+     * Gets process instance id.
+     *
      * @return the processInstanceId
      */
     public String getProcessInstanceId() {
@@ -192,14 +272,17 @@ public class CldsEvent {
     }
 
     /**
-     * @param processInstanceId
-     *        the processInstanceId to set
+     * Sets process instance id.
+     *
+     * @param processInstanceId the processInstanceId to set
      */
     public void setProcessInstanceId(String processInstanceId) {
         this.processInstanceId = processInstanceId;
     }
 
     /**
+     * Gets userid.
+     *
      * @return the userid
      */
     public String getUserid() {
@@ -207,8 +290,9 @@ public class CldsEvent {
     }
 
     /**
-     * @param userid
-     *        the userid to set
+     * Sets userid.
+     *
+     * @param userid the userid to set
      */
     public void setUserid(String userid) {
         this.userid = userid;
index 2c178eb..223d389 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP CLAMP
  * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights
  *                             reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -45,12 +45,33 @@ public class CldsModel {
 
     private static final EELFLogger logger = EELFManager.getInstance().getLogger(CldsModel.class);
     private static final int UUID_LENGTH = 36;
+    /**
+     * The constant STATUS_DESIGN.
+     */
     public static final String STATUS_DESIGN = "DESIGN";
+    /**
+     * The constant STATUS_DISTRIBUTED.
+     */
     public static final String STATUS_DISTRIBUTED = "DISTRIBUTED";
+    /**
+     * The constant STATUS_ACTIVE.
+     */
     public static final String STATUS_ACTIVE = "ACTIVE";
+    /**
+     * The constant STATUS_STOPPED.
+     */
     public static final String STATUS_STOPPED = "STOPPED";
+    /**
+     * The constant STATUS_DELETING.
+     */
     public static final String STATUS_DELETING = "DELETING";
+    /**
+     * The constant STATUS_ERROR.
+     */
     public static final String STATUS_ERROR = "ERROR";
+    /**
+     * The constant STATUS_UNKNOWN.
+     */
     public static final String STATUS_UNKNOWN = "UNKNOWN";
     private String id;
     private String templateId;
@@ -70,7 +91,7 @@ public class CldsModel {
     // This is a transient value used to return the failure message to UI
     private String errorMessageForUi;
     /**
-     * The service type Id received from DCAE by querying it
+     * The service type Id received from DCAE by querying it.
      */
     private String typeId;
     private String typeName;
@@ -81,10 +102,20 @@ public class CldsModel {
     private static StatusHandler statusHandler = new StatusHandlerImpl();
     private static ActionsHandler actionsHandler = new ActionsHandlerImpl();
 
+    /**
+     * Sets status handler.
+     *
+     * @param statHandler the stat handler
+     */
     public static synchronized void setStatusHandler(StatusHandler statHandler) {
         statusHandler = statHandler;
     }
 
+    /**
+     * Sets actions handler.
+     *
+     * @param cdHandler the cd handler
+     */
     public static synchronized void setActionsHandler(ActionsHandler cdHandler) {
         actionsHandler = cdHandler;
     }
@@ -98,6 +129,11 @@ public class CldsModel {
 
     /**
      * Retrieve from DB.
+     *
+     * @param cldsDao      the clds dao
+     * @param name         the name
+     * @param okIfNotFound the ok if not found
+     * @return the clds model
      */
     public static CldsModel retrieve(CldsDao cldsDao, String name, boolean okIfNotFound) {
         // get from db
@@ -110,6 +146,11 @@ public class CldsModel {
         return model;
     }
 
+    /**
+     * Can dcae inventory call boolean.
+     *
+     * @return the boolean
+     */
     public boolean canDcaeInventoryCall() {
         boolean canCall = false;
         /* Below checks the clds event is submit/resubmit/distribute */
@@ -122,6 +163,10 @@ public class CldsModel {
 
     /**
      * Save model to DB.
+     *
+     * @param cldsDao the clds dao
+     * @param userid  the userid
+     * @return the clds model
      */
     public CldsModel save(CldsDao cldsDao, String userid) {
         CldsModel cldsModel = cldsDao.setModel(this, userid);
@@ -131,7 +176,7 @@ public class CldsModel {
     }
 
     /**
-     * set the status in the model
+     * set the status in the model.
      */
     public void determineStatus() {
         status = statusHandler.determineStatusOnLastEvent(event);
@@ -151,6 +196,8 @@ public class CldsModel {
      * Validate requestedActionCd - determine permittedActionCd and then check if
      * contained in permittedActionCd Throw IllegalArgumentException if requested
      * actionCd is not permitted.
+     *
+     * @param requestedActionCd the requested action cd
      */
     public void validateAction(String requestedActionCd) {
         determinePermittedActionCd();
@@ -166,6 +213,9 @@ public class CldsModel {
      * controlNameUuid). No fields are populated other than controlNamePrefix and
      * controlNameUuid. Throws BadRequestException if length of given control name
      * is less than UUID_LENGTH.
+     *
+     * @param fullControlName the full control name
+     * @return the clds model
      */
     public static CldsModel createUsingControlName(String fullControlName) {
         if (fullControlName == null || fullControlName.length() < UUID_LENGTH) {
@@ -180,6 +230,8 @@ public class CldsModel {
     }
 
     /**
+     * Gets control name.
+     *
      * @return the controlName (controlNamePrefix + controlNameUuid)
      */
     public String getControlName() {
@@ -187,7 +239,12 @@ public class CldsModel {
     }
 
     /**
-     * To insert modelInstance to the database
+     * To insert modelInstance to the database.
+     *
+     * @param cldsDao   the clds dao
+     * @param dcaeEvent the dcae event
+     * @param userid    the userid
+     * @return the clds model
      */
     public static CldsModel insertModelInstance(CldsDao cldsDao, DcaeEvent dcaeEvent, String userid) {
         String controlName = dcaeEvent.getControlName();
@@ -205,6 +262,8 @@ public class CldsModel {
     }
 
     /**
+     * Gets name.
+     *
      * @return the name
      */
     public String getName() {
@@ -212,33 +271,53 @@ public class CldsModel {
     }
 
     /**
-     * @param name
-     *        the name to set
+     * Sets name.
+     *
+     * @param name the name to set
      */
     public void setName(String name) {
         this.name = name;
     }
 
     /**
+     * Gets type name.
+     *
      * @return the typeName
      */
     public String getTypeName() {
         return typeName;
     }
 
+    /**
+     * Sets type name.
+     *
+     * @param typeName the type name
+     */
     public void setTypeName(String typeName) {
         this.typeName = typeName;
     }
 
+    /**
+     * Gets template id.
+     *
+     * @return the template id
+     */
     public String getTemplateId() {
         return templateId;
     }
 
+    /**
+     * Sets template id.
+     *
+     * @param templateId the template id
+     */
     public void setTemplateId(String templateId) {
         this.templateId = templateId;
     }
 
     /**
+     * Gets control name prefix.
+     *
      * @return the controlNamePrefix
      */
     public String getControlNamePrefix() {
@@ -246,14 +325,17 @@ public class CldsModel {
     }
 
     /**
-     * @param controlNamePrefix
-     *        the controlNamePrefix to set
+     * Sets control name prefix.
+     *
+     * @param controlNamePrefix the controlNamePrefix to set
      */
     public void setControlNamePrefix(String controlNamePrefix) {
         this.controlNamePrefix = controlNamePrefix;
     }
 
     /**
+     * Gets control name uuid.
+     *
      * @return the controlNameUuid
      */
     public String getControlNameUuid() {
@@ -261,14 +343,17 @@ public class CldsModel {
     }
 
     /**
-     * @param controlNameUuid
-     *        the controlNameUuid to set
+     * Sets control name uuid.
+     *
+     * @param controlNameUuid the controlNameUuid to set
      */
     public void setControlNameUuid(String controlNameUuid) {
         this.controlNameUuid = controlNameUuid;
     }
 
     /**
+     * Gets prop text.
+     *
      * @return the propText
      */
     public String getPropText() {
@@ -276,45 +361,71 @@ public class CldsModel {
     }
 
     /**
-     * @param propText
-     *        the propText to set
+     * Sets prop text.
+     *
+     * @param propText the propText to set
      */
     public void setPropText(String propText) {
         this.propText = propText;
     }
 
     /**
+     * Gets event.
+     *
      * @return the event
      */
     public CldsEvent getEvent() {
         return event;
     }
 
+    /**
+     * Gets id.
+     *
+     * @return the id
+     */
     public String getId() {
         return id;
     }
 
+    /**
+     * Sets id.
+     *
+     * @param id the id
+     */
     public void setId(String id) {
         this.id = id;
     }
 
+    /**
+     * Gets template name.
+     *
+     * @return the template name
+     */
     public String getTemplateName() {
         return templateName;
     }
 
+    /**
+     * Sets template name.
+     *
+     * @param templateName the template name
+     */
     public void setTemplateName(String templateName) {
         this.templateName = templateName;
     }
 
     /**
-     * @param event
-     *        the event to set
+     * Sets event.
+     *
+     * @param event the event to set
      */
     public void setEvent(CldsEvent event) {
         this.event = event;
     }
 
     /**
+     * Gets status.
+     *
      * @return the status
      */
     public String getStatus() {
@@ -322,53 +433,109 @@ public class CldsModel {
     }
 
     /**
-     * @param status
-     *        the status to set
+     * Sets status.
+     *
+     * @param status the status to set
      */
     public void setStatus(String status) {
         this.status = status;
     }
 
+    /**
+     * Gets blueprint text.
+     *
+     * @return the blueprint text
+     */
     public String getBlueprintText() {
         return blueprintText;
     }
 
+    /**
+     * Sets blueprint text.
+     *
+     * @param blueprintText the blueprint text
+     */
     public void setBlueprintText(String blueprintText) {
         this.blueprintText = blueprintText;
     }
 
+    /**
+     * Gets bpmn text.
+     *
+     * @return the bpmn text
+     */
     public String getBpmnText() {
         return bpmnText;
     }
 
+    /**
+     * Sets bpmn text.
+     *
+     * @param bpmnText the bpmn text
+     */
     public void setBpmnText(String bpmnText) {
         this.bpmnText = bpmnText;
     }
 
+    /**
+     * Gets image text.
+     *
+     * @return the image text
+     */
     public String getImageText() {
         return imageText;
     }
 
+    /**
+     * Sets image text.
+     *
+     * @param imageText the image text
+     */
     public void setImageText(String imageText) {
         this.imageText = imageText;
     }
 
+    /**
+     * Gets doc text.
+     *
+     * @return the doc text
+     */
     public String getDocText() {
         return docText;
     }
 
+    /**
+     * Sets doc text.
+     *
+     * @param docText the doc text
+     */
     public void setDocText(String docText) {
         this.docText = docText;
     }
 
+    /**
+     * Gets type id.
+     *
+     * @return the type id
+     */
     public String getTypeId() {
         return typeId;
     }
 
+    /**
+     * Sets type id.
+     *
+     * @param typeId the type id
+     */
     public void setTypeId(String typeId) {
         this.typeId = typeId;
     }
 
+    /**
+     * Gets clds model instance list.
+     *
+     * @return the clds model instance list
+     */
     public List<CldsModelInstance> getCldsModelInstanceList() {
         if (cldsModelInstanceList == null) {
             cldsModelInstanceList = new ArrayList<>();
@@ -376,30 +543,65 @@ public class CldsModel {
         return cldsModelInstanceList;
     }
 
+    /**
+     * Gets deployment id.
+     *
+     * @return the deployment id
+     */
     public String getDeploymentId() {
         return deploymentId;
     }
 
+    /**
+     * Sets deployment id.
+     *
+     * @param deploymentId the deployment id
+     */
     public void setDeploymentId(String deploymentId) {
         this.deploymentId = deploymentId;
     }
 
+    /**
+     * Gets permitted action cd.
+     *
+     * @return the permitted action cd
+     */
     public List<String> getPermittedActionCd() {
         return permittedActionCd;
     }
 
+    /**
+     * Gets error message for ui.
+     *
+     * @return the error message for ui
+     */
     public String getErrorMessageForUi() {
         return errorMessageForUi;
     }
 
+    /**
+     * Sets error message for ui.
+     *
+     * @param errorMessageForUi the error message for ui
+     */
     public void setErrorMessageForUi(String errorMessageForUi) {
         this.errorMessageForUi = errorMessageForUi;
     }
 
+    /**
+     * Gets deployment status url.
+     *
+     * @return the deployment status url
+     */
     public String getDeploymentStatusUrl() {
         return deploymentStatusUrl;
     }
 
+    /**
+     * Sets deployment status url.
+     *
+     * @param deploymentStatusUrl the deployment status url
+     */
     public void setDeploymentStatusUrl(String deploymentStatusUrl) {
         this.deploymentStatusUrl = deploymentStatusUrl;
     }
index bafe48d..9aed447 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP CLAMP
  * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights
  *                             reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -68,68 +68,69 @@ public interface ActionsHandler {
         List<String> permittedActions;
         String actionCd = getCurrentActionCd(event);
         switch (actionCd) {
-        case CldsEvent.ACTION_CREATE:
-            permittedActions = Arrays.asList(CldsEvent.ACTION_SUBMIT, CldsEvent.ACTION_TEST, CldsEvent.ACTION_DELETE);
-            if (isTypeModel(propText, ModelType.SIMPLE_MODEL)) {
-                permittedActions = Arrays.asList(CldsEvent.ACTION_SUBMITDCAE, CldsEvent.ACTION_SUBMITPOLICY,
-                    CldsEvent.ACTION_TEST, CldsEvent.ACTION_DELETE);
-            }
-            break;
-        case CldsEvent.ACTION_SUBMIT:
-        case CldsEvent.ACTION_RESUBMIT:
-        case CldsEvent.ACTION_DISTRIBUTE:
-            permittedActions = Arrays.asList(CldsEvent.ACTION_DEPLOY, CldsEvent.ACTION_RESUBMIT,
-                CldsEvent.ACTION_DELETE);
-            if (isTypeModel(propText, ModelType.SIMPLE_MODEL)) {
-                permittedActions = Arrays.asList(CldsEvent.ACTION_DEPLOY, CldsEvent.ACTION_SUBMITDCAE,
-                    CldsEvent.ACTION_DELETE);
-            }
-            break;
-        case CldsEvent.ACTION_SUBMITDCAE:
-            permittedActions = Arrays.asList(CldsEvent.ACTION_SUBMITDCAE, CldsEvent.ACTION_DELETE);
-            break;
-        case CldsEvent.ACTION_SUBMITPOLICY:
-            permittedActions = Arrays.asList(CldsEvent.ACTION_UPDATE, CldsEvent.ACTION_STOP);
-            break;
-        case CldsEvent.ACTION_UNDEPLOY:
-            permittedActions = Arrays.asList(CldsEvent.ACTION_UPDATE, CldsEvent.ACTION_DEPLOY,
-                CldsEvent.ACTION_RESUBMIT, CldsEvent.ACTION_DELETE);
-            if (isTypeModel(propText, ModelType.SIMPLE_MODEL)) {
-                permittedActions = Arrays.asList(CldsEvent.ACTION_UPDATE, CldsEvent.ACTION_DEPLOY,
-                    CldsEvent.ACTION_SUBMITDCAE, CldsEvent.ACTION_DELETE);
-            }
-            break;
-        case CldsEvent.ACTION_DEPLOY:
-            permittedActions = Arrays.asList(CldsEvent.ACTION_UNDEPLOY, CldsEvent.ACTION_UPDATE, CldsEvent.ACTION_STOP);
-            break;
-        case CldsEvent.ACTION_RESTART:
-        case CldsEvent.ACTION_UPDATE:
-            permittedActions = Arrays.asList(CldsEvent.ACTION_DEPLOY, CldsEvent.ACTION_UPDATE, CldsEvent.ACTION_STOP,
-                CldsEvent.ACTION_UNDEPLOY);
-            if (isTypeModel(propText, ModelType.POLICY_MODEL)) {
+            case CldsEvent.ACTION_CREATE:
+                permittedActions = Arrays.asList(CldsEvent.ACTION_SUBMIT, CldsEvent.ACTION_TEST,
+                        CldsEvent.ACTION_DELETE);
+                if (isTypeModel(propText, ModelType.SIMPLE_MODEL)) {
+                    permittedActions = Arrays.asList(CldsEvent.ACTION_SUBMITDCAE, CldsEvent.ACTION_SUBMITPOLICY,
+                            CldsEvent.ACTION_TEST, CldsEvent.ACTION_DELETE);
+                }
+                break;
+            case CldsEvent.ACTION_SUBMIT:
+            case CldsEvent.ACTION_RESUBMIT:
+            case CldsEvent.ACTION_DISTRIBUTE:
+                permittedActions = Arrays.asList(CldsEvent.ACTION_DEPLOY, CldsEvent.ACTION_RESUBMIT,
+                        CldsEvent.ACTION_DELETE);
+                if (isTypeModel(propText, ModelType.SIMPLE_MODEL)) {
+                    permittedActions = Arrays.asList(CldsEvent.ACTION_DEPLOY, CldsEvent.ACTION_SUBMITDCAE,
+                            CldsEvent.ACTION_DELETE);
+                }
+                break;
+            case CldsEvent.ACTION_SUBMITDCAE:
+                permittedActions = Arrays.asList(CldsEvent.ACTION_SUBMITDCAE, CldsEvent.ACTION_DELETE);
+                break;
+            case CldsEvent.ACTION_SUBMITPOLICY:
                 permittedActions = Arrays.asList(CldsEvent.ACTION_UPDATE, CldsEvent.ACTION_STOP);
-            }
-            break;
-        case CldsEvent.ACTION_STOP:
-            permittedActions = Arrays.asList(CldsEvent.ACTION_UPDATE, CldsEvent.ACTION_RESTART,
-                CldsEvent.ACTION_UNDEPLOY);
-            if (isTypeModel(propText, ModelType.POLICY_MODEL)) {
+                break;
+            case CldsEvent.ACTION_UNDEPLOY:
+                permittedActions = Arrays.asList(CldsEvent.ACTION_UPDATE, CldsEvent.ACTION_DEPLOY,
+                        CldsEvent.ACTION_RESUBMIT, CldsEvent.ACTION_DELETE);
+                if (isTypeModel(propText, ModelType.SIMPLE_MODEL)) {
+                    permittedActions = Arrays.asList(CldsEvent.ACTION_UPDATE, CldsEvent.ACTION_DEPLOY,
+                            CldsEvent.ACTION_SUBMITDCAE, CldsEvent.ACTION_DELETE);
+                }
+                break;
+            case CldsEvent.ACTION_DEPLOY:
+                permittedActions = Arrays.asList(CldsEvent.ACTION_UNDEPLOY, CldsEvent.ACTION_UPDATE,
+                        CldsEvent.ACTION_STOP);
+                break;
+            case CldsEvent.ACTION_RESTART:
+            case CldsEvent.ACTION_UPDATE:
+                permittedActions = Arrays.asList(CldsEvent.ACTION_DEPLOY, CldsEvent.ACTION_UPDATE,
+                        CldsEvent.ACTION_STOP, CldsEvent.ACTION_UNDEPLOY);
+                if (isTypeModel(propText, ModelType.POLICY_MODEL)) {
+                    permittedActions = Arrays.asList(CldsEvent.ACTION_UPDATE, CldsEvent.ACTION_STOP);
+                }
+                break;
+            case CldsEvent.ACTION_STOP:
                 permittedActions = Arrays.asList(CldsEvent.ACTION_UPDATE, CldsEvent.ACTION_RESTART,
-                    CldsEvent.ACTION_DELETE);
-            }
-            break;
-        default:
-            getLogger().warn("Invalid current actionCd: " + actionCd);
-            permittedActions = Arrays.asList();
+                        CldsEvent.ACTION_UNDEPLOY);
+                if (isTypeModel(propText, ModelType.POLICY_MODEL)) {
+                    permittedActions = Arrays.asList(CldsEvent.ACTION_UPDATE, CldsEvent.ACTION_RESTART,
+                            CldsEvent.ACTION_DELETE);
+                }
+                break;
+            default:
+                getLogger().warn("Invalid current actionCd: " + actionCd);
+                permittedActions = Arrays.asList();
         }
         return permittedActions;
     }
 
     /**
-     * This method returns the action of the event or a default one if not found.
+     * This returns the action of the event or a default one if not found.
      *
-     * @param event
-     *        The last event
+     * @param event The last event
      * @return The action
      */
     default String getCurrentActionCd(CldsEvent event) {
@@ -157,8 +158,8 @@ public interface ActionsHandler {
                 JsonObject modelJson = JsonUtils.GSON.fromJson(propText, JsonObject.class);
                 JsonElement modelJsonOfType = modelJson.get(key.getType());
                 if (modelJsonOfType != null
-                    && modelJsonOfType.isJsonPrimitive()
-                    && modelJsonOfType.getAsJsonPrimitive().getAsBoolean()) {
+                        && modelJsonOfType.isJsonPrimitive()
+                        && modelJsonOfType.getAsJsonPrimitive().getAsBoolean()) {
                     result = true;
                 }
             }
index c9405d2..729ef49 100644 (file)
-/*-\r
- * ============LICENSE_START=======================================================\r
- * ONAP CLAMP\r
- * ================================================================================\r
- * Copyright (C) 2018 AT&T Intellectual Property. All rights\r
- *                             reserved.\r
- * ================================================================================\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * ============LICENSE_END============================================\r
- * Modifications copyright (c) 2018 Nokia\r
- * ===================================================================\r
- *\r
- */\r
-\r
-package org.onap.clamp.clds.sdc.controller;\r
-\r
-import com.att.eelf.configuration.EELFLogger;\r
-import com.att.eelf.configuration.EELFManager;\r
-\r
-import java.util.Date;\r
-import java.util.Map.Entry;\r
-import java.util.concurrent.ThreadLocalRandom;\r
-\r
-import org.onap.clamp.clds.config.ClampProperties;\r
-import org.onap.clamp.clds.config.sdc.SdcSingleControllerConfiguration;\r
-import org.onap.clamp.clds.exception.policy.PolicyModelException;\r
-import org.onap.clamp.clds.exception.sdc.controller.CsarHandlerException;\r
-import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;\r
-import org.onap.clamp.clds.exception.sdc.controller.SdcControllerException;\r
-import org.onap.clamp.clds.exception.sdc.controller.SdcDownloadException;\r
-import org.onap.clamp.clds.exception.sdc.controller.SdcParametersException;\r
-import org.onap.clamp.clds.sdc.controller.installer.BlueprintArtifact;\r
-import org.onap.clamp.clds.sdc.controller.installer.CsarHandler;\r
-import org.onap.clamp.clds.sdc.controller.installer.CsarInstaller;\r
-import org.onap.clamp.clds.util.LoggingUtils;\r
-import org.onap.sdc.api.IDistributionClient;\r
-import org.onap.sdc.api.consumer.IDistributionStatusMessage;\r
-import org.onap.sdc.api.consumer.INotificationCallback;\r
-import org.onap.sdc.api.notification.IArtifactInfo;\r
-import org.onap.sdc.api.notification.INotificationData;\r
-import org.onap.sdc.api.results.IDistributionClientDownloadResult;\r
-import org.onap.sdc.api.results.IDistributionClientResult;\r
-import org.onap.sdc.impl.DistributionClientFactory;\r
-import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;\r
-import org.onap.sdc.utils.DistributionActionResultEnum;\r
-import org.onap.sdc.utils.DistributionStatusEnum;\r
-\r
-/**\r
- * This class handles one sdc controller defined in the config.\r
- */\r
-public class SdcSingleController {\r
-\r
-    private static final EELFLogger logger = EELFManager.getInstance().getLogger(SdcSingleController.class);\r
-    private boolean isSdcClientAutoManaged = false;\r
-    private CsarInstaller csarInstaller;\r
-    private ClampProperties refProp;\r
-    public static final String CONFIG_SDC_FOLDER = "sdc.csarFolder";\r
-    private int nbOfNotificationsOngoing = 0;\r
-    private SdcSingleControllerStatus controllerStatus = SdcSingleControllerStatus.STOPPED;\r
-    private SdcSingleControllerConfiguration sdcConfig;\r
-    private IDistributionClient distributionClient;\r
-\r
-    /**\r
-     * Inner class for Notification callback\r
-     */\r
-    private final class SdcNotificationCallBack implements INotificationCallback {\r
-\r
-        private SdcSingleController sdcController;\r
-\r
-        SdcNotificationCallBack(SdcSingleController controller) {\r
-            sdcController = controller;\r
-        }\r
-\r
-        /**\r
-         * This method can be called multiple times at the same moment. The controller\r
-         * must be thread safe !\r
-         */\r
-        @Override\r
-        public void activateCallback(INotificationData iNotif) {\r
-            Date startTime = new Date();\r
-            logger.info("Receive a callback notification in SDC, nb of resources: " + iNotif.getResources().size());\r
-            sdcController.treatNotification(iNotif);\r
-            LoggingUtils.setTimeContext(startTime, new Date());\r
-            LoggingUtils.setResponseContext("0", "SDC Notification received and processed successfully",\r
-                this.getClass().getName());\r
-        }\r
-    }\r
-\r
-    public int getNbOfNotificationsOngoing() {\r
-        return nbOfNotificationsOngoing;\r
-    }\r
-\r
-    private void changeControllerStatusIdle() {\r
-        if (this.nbOfNotificationsOngoing > 1) {\r
-            --this.nbOfNotificationsOngoing;\r
-        } else {\r
-            this.nbOfNotificationsOngoing = 0;\r
-            this.controllerStatus = SdcSingleControllerStatus.IDLE;\r
-        }\r
-    }\r
-\r
-    protected final synchronized void changeControllerStatus(SdcSingleControllerStatus newControllerStatus) {\r
-        switch (newControllerStatus) {\r
-        case BUSY:\r
-            ++this.nbOfNotificationsOngoing;\r
-            this.controllerStatus = newControllerStatus;\r
-            break;\r
-        case IDLE:\r
-            this.changeControllerStatusIdle();\r
-            break;\r
-        default:\r
-            this.controllerStatus = newControllerStatus;\r
-            break;\r
-        }\r
-    }\r
-\r
-    public final synchronized SdcSingleControllerStatus getControllerStatus() {\r
-        return this.controllerStatus;\r
-    }\r
-\r
-    public SdcSingleController(ClampProperties clampProp, CsarInstaller csarInstaller,\r
-        SdcSingleControllerConfiguration sdcSingleConfig, IDistributionClient distributionClient) {\r
-        this.distributionClient = distributionClient;\r
-        isSdcClientAutoManaged = (distributionClient == null);\r
-        this.sdcConfig = sdcSingleConfig;\r
-        this.refProp = clampProp;\r
-        this.csarInstaller = csarInstaller;\r
-    }\r
-\r
-    /**\r
-     * This method initializes the SDC Controller and the SDC Client.\r
-     *\r
-     * @throws SdcControllerException\r
-     *         It throws an exception if the SDC Client cannot be instantiated or if\r
-     *         an init attempt is done when already initialized\r
-     * @throws SdcParametersException\r
-     *         If there is an issue with the parameters provided\r
-     */\r
-    public void initSdc() throws SdcControllerException {\r
-        logger.info("Attempt to initialize the SDC Controller: " + sdcConfig.getSdcControllerName());\r
-        if (this.getControllerStatus() != SdcSingleControllerStatus.STOPPED) {\r
-            throw new SdcControllerException("The controller is already initialized, call the closeSDC method first");\r
-        }\r
-        if (distributionClient == null) {\r
-            distributionClient = DistributionClientFactory.createDistributionClient();\r
-        }\r
-        IDistributionClientResult result = distributionClient.init(sdcConfig, new SdcNotificationCallBack(this));\r
-        if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {\r
-            logger.error("SDC distribution client init failed with reason:" + result.getDistributionMessageResult());\r
-            this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);\r
-            throw new SdcControllerException(\r
-                "Initialization of the SDC Controller failed with reason: " + result.getDistributionMessageResult());\r
-        }\r
-        logger.info("SDC Controller successfully initialized: " + sdcConfig.getSdcControllerName());\r
-        logger.info("Attempt to start the SDC Controller: " + sdcConfig.getSdcControllerName());\r
-        result = this.distributionClient.start();\r
-        if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {\r
-            logger.error("SDC distribution client start failed with reason:" + result.getDistributionMessageResult());\r
-            this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);\r
-            throw new SdcControllerException(\r
-                "Startup of the SDC Controller failed with reason: " + result.getDistributionMessageResult());\r
-        }\r
-        logger.info("SDC Controller successfully started: " + sdcConfig.getSdcControllerName());\r
-        this.changeControllerStatus(SdcSingleControllerStatus.IDLE);\r
-    }\r
-\r
-    /**\r
-     * This method closes the SDC Controller and the SDC Client.\r
-     *\r
-     * @throws SdcControllerException\r
-     *         It throws an exception if the SDC Client cannot be closed because\r
-     *         it's currently BUSY in processing notifications.\r
-     */\r
-    public void closeSdc() throws SdcControllerException {\r
-        if (this.getControllerStatus() == SdcSingleControllerStatus.BUSY) {\r
-            throw new SdcControllerException("Cannot close the SDC controller as it's currently in BUSY state");\r
-        }\r
-        if (this.distributionClient != null) {\r
-            this.distributionClient.stop();\r
-            // If auto managed we can set it to Null, SdcController controls it.\r
-            // In the other case the client of this class has specified it, so\r
-            // we can't reset it\r
-            if (isSdcClientAutoManaged) {\r
-                // Next init will initialize it with a new SDC Client\r
-                this.distributionClient = null;\r
-            }\r
-        }\r
-        this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);\r
-    }\r
-\r
-    private void sendAllNotificationForCsarHandler(INotificationData iNotif, CsarHandler csar,\r
-        NotificationType notificationType, DistributionStatusEnum distributionStatus, String errorMessage) {\r
-        if (csar != null) {\r
-            // Notify for the CSAR\r
-            this.sendSdcNotification(notificationType, csar.getArtifactElement().getArtifactURL(),\r
-                sdcConfig.getConsumerID(), iNotif.getDistributionID(), distributionStatus, errorMessage,\r
-                System.currentTimeMillis());\r
-            // Notify for all VF resources found\r
-            for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) {\r
-                // Normally always 1 artifact in resource for Clamp as we\r
-                // specified\r
-                // only VF_METADATA type\r
-                this.sendSdcNotification(notificationType,\r
-                    blueprint.getValue().getResourceAttached().getArtifacts().get(0).getArtifactURL(),\r
-                    sdcConfig.getConsumerID(), iNotif.getDistributionID(), distributionStatus, errorMessage,\r
-                    System.currentTimeMillis());\r
-            }\r
-        } else {\r
-            this.sendSdcNotification(notificationType, null, sdcConfig.getConsumerID(), iNotif.getDistributionID(),\r
-                distributionStatus, errorMessage, System.currentTimeMillis());\r
-        }\r
-    }\r
-\r
-    /**\r
-     * This method processes the notification received from Sdc.\r
-     *\r
-     * @param iNotif\r
-     *        The INotificationData\r
-     */\r
-    public void treatNotification(INotificationData iNotif) {\r
-        CsarHandler csar = null;\r
-        try {\r
-            // wait for a random time, so that 2 running Clamp will not treat\r
-            // the same Notification at the same time\r
-            Thread.sleep(ThreadLocalRandom.current().nextInt(1, 10) * 1000L);\r
-            logger.info("Notification received for service UUID:" + iNotif.getServiceUUID());\r
-            this.changeControllerStatus(SdcSingleControllerStatus.BUSY);\r
-            csar = new CsarHandler(iNotif, this.sdcConfig.getSdcControllerName(),\r
-                refProp.getStringValue(CONFIG_SDC_FOLDER));\r
-            csar.save(downloadTheArtifact(csar.getArtifactElement()));\r
-            if (csarInstaller.isCsarAlreadyDeployed(csar)) {\r
-                sendAllNotificationForCsarHandler(iNotif, csar, NotificationType.DOWNLOAD,\r
-                    DistributionStatusEnum.ALREADY_DOWNLOADED, null);\r
-                sendAllNotificationForCsarHandler(iNotif, csar, NotificationType.DEPLOY,\r
-                    DistributionStatusEnum.ALREADY_DEPLOYED, null);\r
-            } else {\r
-                sendAllNotificationForCsarHandler(iNotif, csar, NotificationType.DOWNLOAD,\r
-                    DistributionStatusEnum.DOWNLOAD_OK, null);\r
-                csarInstaller.installTheCsar(csar);\r
-                sendAllNotificationForCsarHandler(iNotif, csar, NotificationType.DEPLOY,\r
-                    DistributionStatusEnum.DEPLOY_OK, null);\r
-            }\r
-        } catch (SdcArtifactInstallerException | SdcToscaParserException e) {\r
-            logger.error("SdcArtifactInstallerException exception caught during the notification processing", e);\r
-            sendAllNotificationForCsarHandler(iNotif, csar, NotificationType.DEPLOY,\r
-                DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());\r
-        } catch (SdcDownloadException | CsarHandlerException e) {\r
-            logger.error("SdcDownloadException exception caught during the notification processing", e);\r
-            sendAllNotificationForCsarHandler(iNotif, csar, NotificationType.DOWNLOAD,\r
-                DistributionStatusEnum.DOWNLOAD_ERROR, e.getMessage());\r
-        } catch (PolicyModelException e) {\r
-            logger.error("PolicyModelException exception caught during the notification processing", e);\r
-            sendAllNotificationForCsarHandler(iNotif, csar, NotificationType.DEPLOY,\r
-                DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());\r
-        } catch (InterruptedException e) {\r
-            logger.error("Interrupt exception caught during the notification processing", e);\r
-            sendAllNotificationForCsarHandler(iNotif, csar, NotificationType.DEPLOY,\r
-                DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());\r
-            Thread.currentThread().interrupt();\r
-        } catch (RuntimeException e) {\r
-            logger.error("Unexpected exception caught during the notification processing", e);\r
-            sendAllNotificationForCsarHandler(iNotif, csar, NotificationType.DEPLOY,\r
-                DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());\r
-        }  finally {\r
-            this.changeControllerStatus(SdcSingleControllerStatus.IDLE);\r
-        }\r
-    }\r
-\r
-    private enum NotificationType {\r
-        DOWNLOAD, DEPLOY\r
-    }\r
-\r
-    private IDistributionClientDownloadResult downloadTheArtifact(IArtifactInfo artifact) throws SdcDownloadException {\r
-        logger.info(\r
-            "Trying to download the artifact : " + artifact.getArtifactURL() + " UUID: " + artifact.getArtifactUUID());\r
-        IDistributionClientDownloadResult downloadResult;\r
-        try {\r
-            downloadResult = distributionClient.download(artifact);\r
-            if (null == downloadResult) {\r
-                logger.info("downloadResult is Null for: " + artifact.getArtifactUUID());\r
-                return null;\r
-            }\r
-        } catch (RuntimeException e) {\r
-            throw new SdcDownloadException("Exception caught when downloading the artifact", e);\r
-        }\r
-        if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {\r
-            logger.info("Successfully downloaded the artifact " + artifact.getArtifactURL() + " UUID "\r
-                + artifact.getArtifactUUID() + "Size of payload " + downloadResult.getArtifactPayload().length);\r
-        } else {\r
-            throw new SdcDownloadException(\r
-                "Artifact " + artifact.getArtifactName() + " could not be downloaded from SDC URL "\r
-                    + artifact.getArtifactURL() + " UUID " + artifact.getArtifactUUID() + ")" + System.lineSeparator()\r
-                    + "Error message is " + downloadResult.getDistributionMessageResult() + System.lineSeparator());\r
-        }\r
-        return downloadResult;\r
-    }\r
-\r
-    private void sendSdcNotification(NotificationType notificationType, String artifactURL, String consumerID,\r
-        String distributionID, DistributionStatusEnum status, String errorReason, long timestamp) {\r
-        String event = "Sending " + notificationType.name() + "(" + status.name() + ")"\r
-            + " notification to SDC for artifact:" + artifactURL;\r
-        if (errorReason != null) {\r
-            event = event + "(" + errorReason + ")";\r
-        }\r
-        logger.info(event);\r
-        String action = "";\r
-        try {\r
-            IDistributionStatusMessage message = new DistributionStatusMessage(artifactURL, consumerID, distributionID,\r
-                status, timestamp);\r
-            switch (notificationType) {\r
-            case DOWNLOAD:\r
-                this.sendDownloadStatus(message, errorReason);\r
-                action = "sendDownloadStatus";\r
-                break;\r
-            case DEPLOY:\r
-                this.sendDeploymentStatus(message, errorReason);\r
-                action = "sendDeploymentdStatus";\r
-                break;\r
-            default:\r
-                break;\r
-            }\r
-        } catch (RuntimeException e) {\r
-            logger.warn("Unable to send the SDC Notification (" + action + ") due to an exception", e);\r
-        }\r
-        logger.info("SDC Notification sent successfully(" + action + ")");\r
-    }\r
-\r
-    private void sendDownloadStatus(IDistributionStatusMessage message, String errorReason) {\r
-        if (errorReason != null) {\r
-            this.distributionClient.sendDownloadStatus(message, errorReason);\r
-        } else {\r
-            this.distributionClient.sendDownloadStatus(message);\r
-        }\r
-    }\r
-\r
-    private void sendDeploymentStatus(IDistributionStatusMessage message, String errorReason) {\r
-        if (errorReason != null) {\r
-            this.distributionClient.sendDeploymentStatus(message, errorReason);\r
-        } else {\r
-            this.distributionClient.sendDeploymentStatus(message);\r
-        }\r
-    }\r
-}\r
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights
+ *                             reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * Modifications copyright (c) 2018 Nokia
+ * ===================================================================
+ *
+ */
+
+package org.onap.clamp.clds.sdc.controller;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import java.util.Date;
+import java.util.Map.Entry;
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.onap.clamp.clds.config.ClampProperties;
+import org.onap.clamp.clds.config.sdc.SdcSingleControllerConfiguration;
+import org.onap.clamp.clds.exception.policy.PolicyModelException;
+import org.onap.clamp.clds.exception.sdc.controller.CsarHandlerException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcControllerException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcDownloadException;
+import org.onap.clamp.clds.exception.sdc.controller.SdcParametersException;
+import org.onap.clamp.clds.sdc.controller.installer.BlueprintArtifact;
+import org.onap.clamp.clds.sdc.controller.installer.CsarHandler;
+import org.onap.clamp.clds.sdc.controller.installer.CsarInstaller;
+import org.onap.clamp.clds.util.LoggingUtils;
+import org.onap.sdc.api.IDistributionClient;
+import org.onap.sdc.api.consumer.IDistributionStatusMessage;
+import org.onap.sdc.api.consumer.INotificationCallback;
+import org.onap.sdc.api.notification.IArtifactInfo;
+import org.onap.sdc.api.notification.INotificationData;
+import org.onap.sdc.api.results.IDistributionClientDownloadResult;
+import org.onap.sdc.api.results.IDistributionClientResult;
+import org.onap.sdc.impl.DistributionClientFactory;
+import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;
+import org.onap.sdc.utils.DistributionActionResultEnum;
+import org.onap.sdc.utils.DistributionStatusEnum;
+
+/**
+ * This class handles one sdc controller defined in the config.
+ */
+public class SdcSingleController {
+
+    private static final EELFLogger logger = EELFManager.getInstance().getLogger(SdcSingleController.class);
+    private boolean isSdcClientAutoManaged = false;
+    private CsarInstaller csarInstaller;
+    private ClampProperties refProp;
+    /**
+     * The constant CONFIG_SDC_FOLDER.
+     */
+    public static final String CONFIG_SDC_FOLDER = "sdc.csarFolder";
+    private int nbOfNotificationsOngoing = 0;
+    private SdcSingleControllerStatus controllerStatus = SdcSingleControllerStatus.STOPPED;
+    private SdcSingleControllerConfiguration sdcConfig;
+    private IDistributionClient distributionClient;
+
+    /**
+     * Inner class for Notification callback.
+     */
+    private final class SdcNotificationCallBack implements INotificationCallback {
+
+        private SdcSingleController sdcController;
+
+        /**
+         * Instantiates a new Sdc notification call back.
+         *
+         * @param controller the controller
+         */
+        SdcNotificationCallBack(SdcSingleController controller) {
+            sdcController = controller;
+        }
+
+        /**
+         * This method can be called multiple times at the same moment. The controller
+         * must be thread safe !
+         */
+        @Override
+        public void activateCallback(INotificationData notificationData) {
+            Date startTime = new Date();
+            logger.info("Receive a callback notification in SDC, nb of resources: "
+                    + notificationData.getResources().size());
+            sdcController.treatNotification(notificationData);
+            LoggingUtils.setTimeContext(startTime, new Date());
+            LoggingUtils.setResponseContext("0", "SDC Notification received and processed successfully",
+                    this.getClass().getName());
+        }
+    }
+
+    /**
+     * Gets nb of notifications ongoing.
+     *
+     * @return the nb of notifications ongoing
+     */
+    public int getNbOfNotificationsOngoing() {
+        return nbOfNotificationsOngoing;
+    }
+
+    private void changeControllerStatusIdle() {
+        if (this.nbOfNotificationsOngoing > 1) {
+            --this.nbOfNotificationsOngoing;
+        } else {
+            this.nbOfNotificationsOngoing = 0;
+            this.controllerStatus = SdcSingleControllerStatus.IDLE;
+        }
+    }
+
+    /**
+     * Change controller status.
+     *
+     * @param newControllerStatus the new controller status
+     */
+    protected final synchronized void changeControllerStatus(SdcSingleControllerStatus newControllerStatus) {
+        switch (newControllerStatus) {
+            case BUSY:
+                ++this.nbOfNotificationsOngoing;
+                this.controllerStatus = newControllerStatus;
+                break;
+            case IDLE:
+                this.changeControllerStatusIdle();
+                break;
+            default:
+                this.controllerStatus = newControllerStatus;
+                break;
+        }
+    }
+
+    /**
+     * Gets controller status.
+     *
+     * @return the controller status
+     */
+    public final synchronized SdcSingleControllerStatus getControllerStatus() {
+        return this.controllerStatus;
+    }
+
+    /**
+     * Instantiates a new Sdc single controller.
+     *
+     * @param clampProp          the clamp prop
+     * @param csarInstaller      the csar installer
+     * @param sdcSingleConfig    the sdc single config
+     * @param distributionClient the distribution client
+     */
+    public SdcSingleController(ClampProperties clampProp, CsarInstaller csarInstaller,
+                               SdcSingleControllerConfiguration sdcSingleConfig,
+                               IDistributionClient distributionClient) {
+        this.distributionClient = distributionClient;
+        isSdcClientAutoManaged = (distributionClient == null);
+        this.sdcConfig = sdcSingleConfig;
+        this.refProp = clampProp;
+        this.csarInstaller = csarInstaller;
+    }
+
+    /**
+     * This method initializes the SDC Controller and the SDC Client.
+     *
+     * @throws SdcControllerException It throws an exception if the SDC Client cannot be instantiated or if
+     *                                an init attempt is done when already initialized
+     */
+    public void initSdc() throws SdcControllerException {
+        logger.info("Attempt to initialize the SDC Controller: " + sdcConfig.getSdcControllerName());
+        if (this.getControllerStatus() != SdcSingleControllerStatus.STOPPED) {
+            throw new SdcControllerException("The controller is already initialized, call the closeSDC method first");
+        }
+        if (distributionClient == null) {
+            distributionClient = DistributionClientFactory.createDistributionClient();
+        }
+        IDistributionClientResult result = distributionClient.init(sdcConfig,
+                new SdcNotificationCallBack(this));
+        if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+            logger.error("SDC distribution client init failed with reason:" + result.getDistributionMessageResult());
+            this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);
+            throw new SdcControllerException(
+                    "Initialization of the SDC Controller failed with reason: "
+                            + result.getDistributionMessageResult());
+        }
+        logger.info("SDC Controller successfully initialized: " + sdcConfig.getSdcControllerName());
+        logger.info("Attempt to start the SDC Controller: " + sdcConfig.getSdcControllerName());
+        result = this.distributionClient.start();
+        if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+            logger.error("SDC distribution client start failed with reason:" + result.getDistributionMessageResult());
+            this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);
+            throw new SdcControllerException(
+                    "Startup of the SDC Controller failed with reason: " + result.getDistributionMessageResult());
+        }
+        logger.info("SDC Controller successfully started: " + sdcConfig.getSdcControllerName());
+        this.changeControllerStatus(SdcSingleControllerStatus.IDLE);
+    }
+
+    /**
+    * This method closes the SDC Controller and the SDC Client.
+    *
+    * @throws SdcControllerException It throws an exception if the SDC Client cannot be closed because
+    *                                it's currently BUSY in processing notifications.
+    */
+    public void closeSdc() throws SdcControllerException {
+        if (this.getControllerStatus() == SdcSingleControllerStatus.BUSY) {
+            throw new SdcControllerException("Cannot close the SDC controller as it's currently in BUSY state");
+        }
+        if (this.distributionClient != null) {
+            this.distributionClient.stop();
+            // If auto managed we can set it to Null, SdcController controls it.
+            // In the other case the client of this class has specified it, so
+            // we can't reset it
+            if (isSdcClientAutoManaged) {
+                // Next init will initialize it with a new SDC Client
+                this.distributionClient = null;
+            }
+        }
+        this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);
+    }
+
+    private void sendAllNotificationForCsarHandler(INotificationData notificationData, CsarHandler csar,
+                                                   NotificationType notificationType,
+                                                   DistributionStatusEnum distributionStatus, String errorMessage) {
+        if (csar != null) {
+            // Notify for the CSAR
+            this.sendSdcNotification(notificationType, csar.getArtifactElement().getArtifactURL(),
+                    sdcConfig.getConsumerID(), notificationData.getDistributionID(), distributionStatus, errorMessage,
+                    System.currentTimeMillis());
+            // Notify for all VF resources found
+            for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) {
+                // Normally always 1 artifact in resource for Clamp as we
+                // specified
+                // only VF_METADATA type
+                this.sendSdcNotification(notificationType,
+                        blueprint.getValue().getResourceAttached().getArtifacts().get(0).getArtifactURL(),
+                        sdcConfig.getConsumerID(), notificationData.getDistributionID(), distributionStatus,
+                        errorMessage,
+                        System.currentTimeMillis());
+            }
+        } else {
+            this.sendSdcNotification(notificationType, null, sdcConfig.getConsumerID(),
+                    notificationData.getDistributionID(),
+                    distributionStatus, errorMessage, System.currentTimeMillis());
+        }
+    }
+
+    /**
+     * This method processes the notification received from Sdc.
+     *
+     * @param notificationData The INotificationData
+     */
+    public void treatNotification(INotificationData notificationData) {
+        CsarHandler csar = null;
+        try {
+            // wait for a random time, so that 2 running Clamp will not treat
+            // the same Notification at the same time
+            Thread.sleep(ThreadLocalRandom.current().nextInt(1, 10) * 1000L);
+            logger.info("Notification received for service UUID:" + notificationData.getServiceUUID());
+            this.changeControllerStatus(SdcSingleControllerStatus.BUSY);
+            csar = new CsarHandler(notificationData, this.sdcConfig.getSdcControllerName(),
+                    refProp.getStringValue(CONFIG_SDC_FOLDER));
+            csar.save(downloadTheArtifact(csar.getArtifactElement()));
+            if (csarInstaller.isCsarAlreadyDeployed(csar)) {
+                sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD,
+                        DistributionStatusEnum.ALREADY_DOWNLOADED, null);
+                sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+                        DistributionStatusEnum.ALREADY_DEPLOYED, null);
+            } else {
+                sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD,
+                        DistributionStatusEnum.DOWNLOAD_OK, null);
+                csarInstaller.installTheCsar(csar);
+                sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+                        DistributionStatusEnum.DEPLOY_OK, null);
+            }
+        } catch (SdcArtifactInstallerException | SdcToscaParserException e) {
+            logger.error("SdcArtifactInstallerException exception caught during the notification processing", e);
+            sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+                    DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+        } catch (SdcDownloadException | CsarHandlerException e) {
+            logger.error("SdcDownloadException exception caught during the notification processing", e);
+            sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD,
+                    DistributionStatusEnum.DOWNLOAD_ERROR, e.getMessage());
+        } catch (PolicyModelException e) {
+            logger.error("PolicyModelException exception caught during the notification processing", e);
+            sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+                    DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+        } catch (InterruptedException e) {
+            logger.error("Interrupt exception caught during the notification processing", e);
+            sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+                    DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+            Thread.currentThread().interrupt();
+        } catch (RuntimeException e) {
+            logger.error("Unexpected exception caught during the notification processing", e);
+            sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+                    DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+        }  finally {
+            this.changeControllerStatus(SdcSingleControllerStatus.IDLE);
+        }
+    }
+
+    private enum NotificationType {
+        /**
+         * Download notification type.
+         */
+        DOWNLOAD,
+        /**
+         * Deploy notification type.
+         */
+        DEPLOY
+    }
+
+    private IDistributionClientDownloadResult downloadTheArtifact(IArtifactInfo artifact) throws SdcDownloadException {
+        logger.info(
+                "Trying to download the artifact : " + artifact.getArtifactURL() + " UUID: "
+                        + artifact.getArtifactUUID());
+        IDistributionClientDownloadResult downloadResult;
+        try {
+            downloadResult = distributionClient.download(artifact);
+            if (null == downloadResult) {
+                logger.info("downloadResult is Null for: " + artifact.getArtifactUUID());
+                return null;
+            }
+        } catch (RuntimeException e) {
+            throw new SdcDownloadException("Exception caught when downloading the artifact", e);
+        }
+        if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {
+            logger.info("Successfully downloaded the artifact " + artifact.getArtifactURL() + " UUID "
+                    + artifact.getArtifactUUID() + "Size of payload " + downloadResult.getArtifactPayload().length);
+        } else {
+            throw new SdcDownloadException(
+                    "Artifact " + artifact.getArtifactName() + " could not be downloaded from SDC URL "
+                            + artifact.getArtifactURL() + " UUID " + artifact.getArtifactUUID() + ")"
+                            + System.lineSeparator()
+                            + "Error message is " + downloadResult.getDistributionMessageResult()
+                            + System.lineSeparator());
+        }
+        return downloadResult;
+    }
+
+    private void sendSdcNotification(NotificationType notificationType, String artifactUrl, String consumerID,
+                                     String distributionID, DistributionStatusEnum status, String errorReason,
+                                     long timestamp) {
+        String event = "Sending " + notificationType.name() + "(" + status.name() + ")"
+                + " notification to SDC for artifact:" + artifactUrl;
+        if (errorReason != null) {
+            event = event + "(" + errorReason + ")";
+        }
+        logger.info(event);
+        String action = "";
+        try {
+            IDistributionStatusMessage message = new DistributionStatusMessage(artifactUrl, consumerID, distributionID,
+                    status, timestamp);
+            switch (notificationType) {
+                case DOWNLOAD:
+                    this.sendDownloadStatus(message, errorReason);
+                    action = "sendDownloadStatus";
+                    break;
+                case DEPLOY:
+                    this.sendDeploymentStatus(message, errorReason);
+                    action = "sendDeploymentdStatus";
+                    break;
+                default:
+                    break;
+            }
+        } catch (RuntimeException e) {
+            logger.warn("Unable to send the SDC Notification (" + action + ") due to an exception", e);
+        }
+        logger.info("SDC Notification sent successfully(" + action + ")");
+    }
+
+    private void sendDownloadStatus(IDistributionStatusMessage message, String errorReason) {
+        if (errorReason != null) {
+            this.distributionClient.sendDownloadStatus(message, errorReason);
+        } else {
+            this.distributionClient.sendDownloadStatus(message);
+        }
+    }
+
+    private void sendDeploymentStatus(IDistributionStatusMessage message, String errorReason) {
+        if (errorReason != null) {
+            this.distributionClient.sendDeploymentStatus(message, errorReason);
+        } else {
+            this.distributionClient.sendDeploymentStatus(message);
+        }
+    }
+}
index e3a379b..b9cce08 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP CLAMP
  * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights
  *                             reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -81,23 +81,53 @@ import org.springframework.web.client.HttpClientErrorException;
 @Component
 public class CldsService extends SecureServiceBase {
 
+    /**
+     * The constant LIST_OF_SDC_SERVICE_INFO_TYPE.
+     */
     public static final Type LIST_OF_SDC_SERVICE_INFO_TYPE = new TypeToken<List<SdcServiceInfo>>() {
     }.getType();
     @Produce(uri = "direct:processSubmit")
     private CamelProxy camelProxy;
+    /**
+     * The constant securityLogger.
+     */
     protected static final EELFLogger securityLogger = EELFManager.getInstance().getSecurityLogger();
+    /**
+     * The constant logger.
+     */
     protected static final EELFLogger logger = EELFManager.getInstance().getLogger(CldsService.class);
 
+    /**
+     * The constant GLOBAL_PROPERTIES_KEY.
+     */
     public static final String GLOBAL_PROPERTIES_KEY = "files.globalProperties";
     private final String cldsPermissionTypeClManage;
     private final String cldsPermissionTypeClEvent;
     private final String cldsPermissionTypeFilterVf;
     private final String cldsPermissionInstance;
+    /**
+     * The Permission read cl.
+     */
     final SecureServicePermission permissionReadCl;
+    /**
+     * The Permission update cl.
+     */
     final SecureServicePermission permissionUpdateCl;
+    /**
+     * The Permission read template.
+     */
     final SecureServicePermission permissionReadTemplate;
+    /**
+     * The Permission update template.
+     */
     final SecureServicePermission permissionUpdateTemplate;
+    /**
+     * The Permission read tosca.
+     */
     final SecureServicePermission permissionReadTosca;
+    /**
+     * The Permission update tosca.
+     */
     final SecureServicePermission permissionUpdateTosca;
 
     private final CldsDao cldsDao;
@@ -110,17 +140,40 @@ public class CldsService extends SecureServiceBase {
     @Autowired
     private HttpServletRequest request;
 
+    /**
+     * Instantiates a new Clds service.
+     *
+     * @param cldsDao                    the clds dao
+     * @param cldsBpmnTransformer        the clds bpmn transformer
+     * @param refProp                    the ref prop
+     * @param dcaeDispatcherServices     the dcae dispatcher services
+     * @param dcaeInventoryServices      the dcae inventory services
+     * @param cldsPersmissionTypeCl      the clds persmission type cl
+     * @param cldsPermissionTypeClManage the clds permission type cl manage
+     * @param cldsPermissionTypeClEvent  the clds permission type cl event
+     * @param cldsPermissionTypeFilterVf the clds permission type filter vf
+     * @param cldsPermissionTypeTemplate the clds permission type template
+     * @param cldsPermissionTypeTosca    the clds permission type tosca
+     * @param cldsPermissionInstance     the clds permission instance
+     */
     @Autowired
     public CldsService(CldsDao cldsDao, XslTransformer cldsBpmnTransformer, ClampProperties refProp,
         DcaeDispatcherServices dcaeDispatcherServices,
         DcaeInventoryServices dcaeInventoryServices,
-        @Value("${clamp.config.security.permission.type.cl:permission-type-cl}") String cldsPersmissionTypeCl,
-        @Value("${clamp.config.security.permission.type.cl.manage:permission-type-cl-manage}") String cldsPermissionTypeClManage,
-        @Value("${clamp.config.security.permission.type.cl.event:permission-type-cl-event}") String cldsPermissionTypeClEvent,
-        @Value("${clamp.config.security.permission.type.filter.vf:permission-type-filter-vf}") String cldsPermissionTypeFilterVf,
-        @Value("${clamp.config.security.permission.type.template:permission-type-template}") String cldsPermissionTypeTemplate,
-        @Value("${clamp.config.security.permission.type.tosca:permission-type-tosca}") String cldsPermissionTypeTosca,
-        @Value("${clamp.config.security.permission.instance:dev}") String cldsPermissionInstance) {
+        @Value("${clamp.config.security.permission.type.cl:permission-type-cl}")
+                                   String cldsPersmissionTypeCl,
+        @Value("${clamp.config.security.permission.type.cl.manage:permission-type-cl-manage}")
+                                   String cldsPermissionTypeClManage,
+        @Value("${clamp.config.security.permission.type.cl.event:permission-type-cl-event}")
+                                   String cldsPermissionTypeClEvent,
+        @Value("${clamp.config.security.permission.type.filter.vf:permission-type-filter-vf}")
+                                   String cldsPermissionTypeFilterVf,
+        @Value("${clamp.config.security.permission.type.template:permission-type-template}")
+                                   String cldsPermissionTypeTemplate,
+        @Value("${clamp.config.security.permission.type.tosca:permission-type-tosca}")
+                                   String cldsPermissionTypeTosca,
+        @Value("${clamp.config.security.permission.instance:dev}")
+                                   String cldsPermissionInstance) {
         this.cldsDao = cldsDao;
         this.cldsBpmnTransformer = cldsBpmnTransformer;
         this.refProp = refProp;
@@ -141,8 +194,9 @@ public class CldsService extends SecureServiceBase {
             "update");
     }
 
-    /*
-     * @return list of CLDS-Monitoring-Details: CLOSELOOP_NAME | Close loop name
+    /**
+     * Gets clds details.
+     * list of CLDS-Monitoring-Details: CLOSELOOP_NAME | Close loop name
      * used in the CLDS application (prefix: ClosedLoop- + unique ClosedLoop ID)
      * MODEL_NAME | Model Name in CLDS application SERVICE_TYPE_ID | TypeId returned
      * from the DCAE application when the ClosedLoop is submitted
@@ -150,11 +204,12 @@ public class CldsService extends SecureServiceBase {
      * generated when the ClosedLoop is deployed in DCAE. TEMPLATE_NAME | Template
      * used to generate the ClosedLoop model. ACTION_CD | Current state of the
      * ClosedLoop in CLDS application.
+     * @return the clds details
      */
     public List<CldsMonitoringDetails> getCldsDetails() {
         util.entering(request, "CldsService: GET model details");
         Date startTime = new Date();
-        List<CldsMonitoringDetails> cldsMonitoringDetailsList = cldsDao.getCLDSMonitoringDetails();
+        List<CldsMonitoringDetails> cldsMonitoringDetailsList = cldsDao.getCldsMonitoringDetails();
         // audit log
         LoggingUtils.setTimeContext(startTime, new Date());
         auditLogger.info("GET cldsDetails completed");
@@ -162,9 +217,11 @@ public class CldsService extends SecureServiceBase {
         return cldsMonitoringDetailsList;
     }
 
-    /*
+    /**
+     * Gets clds info.
      * CLDS IFO service will return 3 things 1. User Name 2. CLDS code version that
      * is currently installed from pom.xml file 3. User permissions
+     * @return the clds info
      */
     public CldsInfo getCldsInfo() {
         util.entering(request, "CldsService: GET cldsInfo");
@@ -186,7 +243,7 @@ public class CldsService extends SecureServiceBase {
      * This is subset of the json getModel. This is only expected to be used for
      * testing purposes, not by the UI.
      *
-     * @param modelName
+     * @param modelName the model name
      * @return bpmn xml text - content of bpmn given name
      */
     public String getBpmnXml(String modelName) {
@@ -207,7 +264,7 @@ public class CldsService extends SecureServiceBase {
      * This is subset of the json getModel. This is only expected to be used for
      * testing purposes, not by the UI.
      *
-     * @param modelName
+     * @param modelName the model name
      * @return image xml text - content of image given name
      */
     public String getImageXml(String modelName) {
@@ -226,7 +283,7 @@ public class CldsService extends SecureServiceBase {
     /**
      * REST service that retrieves a CLDS model by name from the database.
      *
-     * @param modelName
+     * @param modelName the model name
      * @return clds model - clds model for the given model name
      */
     public CldsModel getModel(String modelName) {
@@ -266,7 +323,9 @@ public class CldsService extends SecureServiceBase {
     /**
      * REST service that saves a CLDS model by name in the database.
      *
-     * @param modelName
+     * @param modelName the model name
+     * @param cldsModel the clds model
+     * @return the clds model
      */
     public CldsModel putModel(String modelName, CldsModel cldsModel) {
         util.entering(request, "CldsService: PUT model");
@@ -322,19 +381,13 @@ public class CldsService extends SecureServiceBase {
     /**
      * REST service that saves and processes an action for a CLDS model by name.
      *
-     * @param action
-     * @param modelName
-     * @param test
-     * @param model
-     * @return
-     * @throws TransformerException
-     *         In case of issues when doing the XSLT of the BPMN flow
-     * @throws ParseException
-     *         In case of issues when parsing the JSON
-     * @throws GeneralSecurityException
-     *         In case of issues when decrypting the password
-     * @throws DecoderException
-     *         In case of issues with the Hex String decoding
+     * @param action    the action
+     * @param modelName the model name
+     * @param test      the test
+     * @param model     the model
+     * @return response entity
+     * @throws TransformerException In case of issues when doing the XSLT of the BPMN flow
+     * @throws ParseException       In case of issues when parsing the JSON
      */
     public ResponseEntity<?> putModelAndProcessAction(String action, String modelName, String test, CldsModel model)
         throws TransformerException, ParseException {
@@ -418,8 +471,9 @@ public class CldsService extends SecureServiceBase {
     /**
      * REST service that accepts events for a model.
      *
-     * @param test
-     * @param dcaeEvent
+     * @param test      the test
+     * @param dcaeEvent the dcae event
+     * @return the string
      */
     public String postDcaeEvent(String test, DcaeEvent dcaeEvent) {
         util.entering(request, "CldsService: Post dcae event");
@@ -462,10 +516,10 @@ public class CldsService extends SecureServiceBase {
     }
 
     /**
-     * REST service that retrieves total properties required by UI
+     * REST service that retrieves total properties required by UI.
      *
-     * @throws IOException
-     *         In case of issues
+     * @return the sdc properties
+     * @throws IOException In case of issues
      */
     public String getSdcProperties() throws IOException {
         return refProp.getJsonTemplate(GLOBAL_PROPERTIES_KEY).toString();
@@ -476,9 +530,8 @@ public class CldsService extends SecureServiceBase {
      * Determine if the user is authorized for a particular VF by its invariant
      * UUID.
      *
-     * @param vfInvariantUuid
-     * @throws NotAuthorizedException
-     * @return
+     * @param vfInvariantUuid the vf invariant uuid
+     * @return boolean or throws NotAuthorizedException
      */
     public boolean isAuthorizedForVf(String vfInvariantUuid) {
         if (cldsPermissionTypeFilterVf != null && !cldsPermissionTypeFilterVf.isEmpty()) {
@@ -497,7 +550,7 @@ public class CldsService extends SecureServiceBase {
      * Determine if the user is authorized for a particular VF by its invariant
      * UUID. If not authorized, then NotAuthorizedException is thrown.
      *
-     * @param model
+     * @param model The clds model
      * @return
      */
     private boolean isAuthorizedForVf(CldsModel model) {
@@ -510,6 +563,13 @@ public class CldsService extends SecureServiceBase {
         }
     }
 
+    /**
+     * Deploy model response entity.
+     *
+     * @param modelName the model name
+     * @param model     the model
+     * @return the response entity
+     */
     public ResponseEntity<CldsModel> deployModel(String modelName, CldsModel model) {
         util.entering(request, "CldsService: Deploy model");
         Date startTime = new Date();
@@ -559,6 +619,13 @@ public class CldsService extends SecureServiceBase {
         }
     }
 
+    /**
+     * Un deploy model response entity.
+     *
+     * @param modelName the model name
+     * @param model     the model
+     * @return the response entity
+     */
     public ResponseEntity<CldsModel> unDeployModel(String modelName, CldsModel model) {
         util.entering(request, "CldsService: Undeploy model");
         Date startTime = new Date();
@@ -642,6 +709,11 @@ public class CldsService extends SecureServiceBase {
         }
     }
 
+    /**
+     * Sets logging util.
+     *
+     * @param utilP the util p
+     */
     // Created for the integration test
     public void setLoggingUtil(LoggingUtils utilP) {
         util = utilP;
index 58a2f6f..fdc9423 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP CLAMP
  * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights
  *                             reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * limitations under the License.
  * ============LICENSE_END============================================
  * ===================================================================
- * 
+ *
  */
 
 package org.onap.clamp.clds.tosca;
 
 public class JsonEditorSchemaConstants {
-       
-       //Data types in JSON Schema
-       public static final String TYPE_OBJECT = "object";
-       public static final String TYPE_ARRAY = "array";
-       public static final String TYPE_STRING = "string";
-       public static final String TYPE_INTEGER = "integer";
-       
-       //Key elements in JSON Schema
-       public static final String TYPE = "type";
-       public static final String TITLE = "title";
-       public static final String REQUIRED = "required";
-       public static final String DEFAULT = "default";
-       public static final String ENUM = "enum";
-       public static final String ENUM_TITLES = "enum_titles";
-       public static final String OPTIONS = "options";
-       public static final String FORMAT = "format";
-       public static final String ITEMS = "items";
-       public static final String PROPERTIES = "properties";
-       public static final String PROPERTY_ORDER = "propertyOrder";
-       
-       public static final String MINIMUM = "minimum";
-       public static final String MAXIMUM = "maximum";
-       public static final String MIN_LENGTH = "minLength";
-       public static final String MAX_LENGTH = "maxLength";
-       public static final String EXCLUSIVE_MINIMUM = "exclusiveMinimum";
-       public static final String EXCLUSIVE_MAXIMUM = "exclusiveMaximum";
-       
-       public static final String CUSTOM_KEY_FORMAT = "format";
-       public static final String CUSTOM_KEY_FORMAT_TABS_TOP = "tabs-top";
-       public static final String FORMAT_SELECT = "select";
-       public static final String UNIQUE_ITEMS = "uniqueItems";
-       public static final String TRUE = "true";
-       public static final String QSSCHEMA = "qschema";
-       public static final String TYPE_QBLDR = "qbldr";
-       
-       public static final String ID = "id";
-       public static final String LABEL = "label";
-       public static final String OPERATORS = "operators";
-       public static final String FILTERS = "filters";
-       
-       public static final String SCHEMA = "schema";
-       public static final String CURRENT_VALUES = "currentValues";
-       
-       
-       
-       
-       
-       
-       
-       
-       
+
+    //Data types in JSON Schema
+    public static final String TYPE_OBJECT = "object";
+    public static final String TYPE_ARRAY = "array";
+    public static final String TYPE_STRING = "string";
+    public static final String TYPE_INTEGER = "integer";
+
+    //Key elements in JSON Schema
+    public static final String TYPE = "type";
+    public static final String TITLE = "title";
+    public static final String REQUIRED = "required";
+    public static final String DEFAULT = "default";
+    public static final String ENUM = "enum";
+    public static final String ENUM_TITLES = "enum_titles";
+    public static final String OPTIONS = "options";
+    public static final String FORMAT = "format";
+    public static final String ITEMS = "items";
+    public static final String PROPERTIES = "properties";
+    public static final String PROPERTY_ORDER = "propertyOrder";
+
+    public static final String MINIMUM = "minimum";
+    public static final String MAXIMUM = "maximum";
+    public static final String MIN_LENGTH = "minLength";
+    public static final String MAX_LENGTH = "maxLength";
+    public static final String EXCLUSIVE_MINIMUM = "exclusiveMinimum";
+    public static final String EXCLUSIVE_MAXIMUM = "exclusiveMaximum";
+
+    public static final String CUSTOM_KEY_FORMAT = "format";
+    public static final String CUSTOM_KEY_FORMAT_TABS_TOP = "tabs-top";
+    public static final String FORMAT_SELECT = "select";
+    public static final String UNIQUE_ITEMS = "uniqueItems";
+    public static final String TRUE = "true";
+    public static final String QSSCHEMA = "qschema";
+    public static final String TYPE_QBLDR = "qbldr";
+
+    public static final String ID = "id";
+    public static final String LABEL = "label";
+    public static final String OPERATORS = "operators";
+    public static final String FILTERS = "filters";
+
+    public static final String SCHEMA = "schema";
+    public static final String CURRENT_VALUES = "currentValues";
+
+
 }
index 8a172ab..16a817e 100644 (file)
@@ -109,19 +109,12 @@ public class ToscaYamlToJsonConvertor {
         LinkedHashMap<String, Object> dataNodes) {
         map.entrySet().stream().forEach(n -> {
             if (n.getKey().contains(ToscaSchemaConstants.NODE_TYPES) && n.getValue() instanceof Map) {
-
                 parseNodeAndDataType((LinkedHashMap<String, Object>) n.getValue(), nodeTypes, dataNodes);
-
             } else if (n.getKey().contains(ToscaSchemaConstants.DATA_TYPES) && n.getValue() instanceof Map) {
-
                 parseNodeAndDataType((LinkedHashMap<String, Object>) n.getValue(), nodeTypes, dataNodes);
-
             } else if (n.getKey().contains(ToscaSchemaConstants.POLICY_NODE)) {
-
                 nodeTypes.put(n.getKey(), n.getValue());
-
             } else if (n.getKey().contains(ToscaSchemaConstants.POLICY_DATA)) {
-
                 dataNodes.put(n.getKey(), n.getValue());
             }
 
@@ -149,7 +142,7 @@ public class ToscaYamlToJsonConvertor {
                                         .getValue();
                                     if (parentPropertiesMap.containsKey(ToscaSchemaConstants.TYPE)
                                         && ((String) parentPropertiesMap.get(ToscaSchemaConstants.TYPE))
-                                            .contains(ToscaSchemaConstants.TYPE_LIST)
+                                            .contains(ToscaSchemaConstants.TYPE_MAP)
                                         && parentPropertiesMap.containsKey(ToscaSchemaConstants.ENTRY_SCHEMA)) {
                                         parentPropertiesMap = (LinkedHashMap<String, Object>) parentPropertiesMap
                                             .get(ToscaSchemaConstants.ENTRY_SCHEMA);
index f746ab1..e9e589e 100755 (executable)
@@ -17,6 +17,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * ============LICENSE_END============================================
+ * Modifications copyright (c) 2019 AT&T.
  * ===================================================================
  *
  */
@@ -33,39 +34,39 @@ import java.awt.Rectangle;
 public class AwtUtils {
     private static final int ARROW_W = 4;
     private static final int ARROW_H = 2;
-    private static final  int FONT_SIZE = 12;
-    private static final  int FONT_STYLE = Font.PLAIN;
+    private static final int FONT_SIZE = 12;
+    private static final int FONT_STYLE = Font.PLAIN;
     private static final String FONT_FACE = "SansSerif";
-    private static final Color TRANSPARENT = new Color(0.0f, 0.0f,0.0f,0.0f);
+    private static final Color TRANSPARENT = new Color(0.0f, 0.0f, 0.0f, 0.0f);
 
-    static void rectWithText(Graphics2D g2d, String text, Point p, int w, int h) {
-        Rectangle rect = new Rectangle(p.x, p.y, w, h);
+    static void rectWithText(Graphics2D g2d, String text, Point point, int width, int height) {
+        Rectangle rect = new Rectangle(point.x, point.y, width, height);
         g2d.draw(rect);
         Color oldColor = g2d.getColor();
         g2d.setColor(TRANSPARENT);
         g2d.fill(rect);
         g2d.setColor(oldColor);
-        addText(g2d, text, p.x+w/2, p.y+h/2);
+        addText(g2d, text, point.x + width / 2, point.y + height / 2);
     }
 
     static void drawArrow(Graphics2D g2d, Point from, Point to, int lineThickness) {
         int x2 = to.x - lineThickness;
-        g2d.drawLine(from.x, from.y, x2-lineThickness, to.y);
-        g2d.drawPolygon(new int[] {x2-ARROW_W, x2-ARROW_W, x2},new int[] {to.y- ARROW_H, to.y+ ARROW_H, to.y},3);
-        g2d.fillPolygon(new int[] {x2-ARROW_W, x2-ARROW_W, x2},new int[] {to.y- ARROW_H, to.y+ ARROW_H, to.y},3);
+        g2d.drawLine(from.x, from.y, x2 - lineThickness, to.y);
+        g2d.drawPolygon(new int[]{x2 - ARROW_W, x2 - ARROW_W, x2}, new int[]{to.y - ARROW_H, to.y + ARROW_H, to.y}, 3);
+        g2d.fillPolygon(new int[]{x2 - ARROW_W, x2 - ARROW_W, x2}, new int[]{to.y - ARROW_H, to.y + ARROW_H, to.y}, 3);
     }
 
-    private static void addText(Graphics2D g2d, String text, int x, int y) {
-        Font f = new Font(FONT_FACE, FONT_STYLE, FONT_SIZE);
-        g2d.setFont(f);
+    private static void addText(Graphics2D g2d, String text, int abs, int ord) {
+        Font font = new Font(FONT_FACE, FONT_STYLE, FONT_SIZE);
+        g2d.setFont(font);
 
         FontMetrics fm1 = g2d.getFontMetrics();
         int w1 = fm1.stringWidth(text);
-        int x1 = x - (w1 / 2);
+        int x1 = abs - (w1 / 2);
 
-        g2d.setFont(f);
+        g2d.setFont(font);
         g2d.setColor(Color.BLACK);
-        g2d.drawString(text, x1, y);
+        g2d.drawString(text, x1, ord);
     }
 
 }
index 34842ef..d9d7fd1 100644 (file)
@@ -126,18 +126,6 @@ svg:not(:root) {
        z-index:100000; /*a number that's more than the modal box*/
        
 } /* '' */
-.upgrade-schema:before{ 
-       content: url('../images/UpgradeSchema.png'); 
-       position:relative; /*or absolute*/
-       z-index:100000; /*a number that's more than the modal box*/     
-       opacity:0.5;
-       cursor: none;
-} /* '' */
-.upgradeSchema:before{ 
-       content: url('../images/UpgradeSchema.png'); 
-       position:relative; /*or absolute*/
-       z-index:100000; /*a number that's more than the modal box*/     
-} /* '' */
 .set-default-values:before{ 
        content: url('../images/SetDefaultValues.png'); 
        position:relative; /*or absolute*/
index ec13e2a..62672d2 100644 (file)
@@ -34,7 +34,7 @@
 <html lang="en" ng-app="clds-app">
 
 <head>
-<meta charset="utf-8"/>
+<meta charset="utf-8" />
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1">
@@ -47,7 +47,7 @@
 
 <!-- bootstrap css and plugins -->
 <link rel="stylesheet" type="text/css" href="css/bootstrap.css">
+
 
 <!-- DataTables CSS -->
 <link href="css/jquery.dataTables.css" rel="stylesheet">
        <div ng-controller="dialogCtrl" style="display: none;">
                <div class="row">
                        <div class="col-md-12">
-                               <button class="btn btn-danger" ng-click="launch('error')" style="display:none">Error
-                                       Dialog</button>
-                               <button class="btn btn-primary" ng-click="launch('wait')" style="display:none">Wait
-                                       Dialog</button>
-                               <button class="btn btn-primary" ng-click="launch('customwait')" style="display:none">"Custom"
-                                       Wait Dialog</button>
-                               <button class="btn btn-default" ng-click="launch('notify')" style="display:none">Notify
-                                       Dialog</button>
-                               <button class="btn btn-success" ng-click="launch('confirm')" style="display:none">Confirm
-                                       Dialog</button>
+                               <button class="btn btn-danger" ng-click="launch('error')"
+                                       style="display: none">Error Dialog</button>
+                               <button class="btn btn-primary" ng-click="launch('wait')"
+                                       style="display: none">Wait Dialog</button>
+                               <button class="btn btn-primary" ng-click="launch('customwait')"
+                                       style="display: none">"Custom" Wait Dialog</button>
+                               <button class="btn btn-default" ng-click="launch('notify')"
+                                       style="display: none">Notify Dialog</button>
+                               <button class="btn btn-success" ng-click="launch('confirm')"
+                                       style="display: none">Confirm Dialog</button>
                        </div>
                </div>
        </div>
@@ -95,8 +95,8 @@
 
        <!-- TOSCA Model Driven Dymamic UI Support -->
        <script src="lib/jsoneditor.js"></script>
-       <script src="lib/query-builder.standalone.js"></script>
-       
+       <script src="lib/query-builder.standalone.js"></script>
+
        <script src="lib/angular.min.js"></script>
        <script src="lib/angular-cookies.min.js"></script>
 
        <script src="scripts/route_ctrl.js"></script>
        <script src="scripts/authcontroller.js"></script>
        <script src="scripts/query_params_handler_ctrl.js"></script>
-       
-        <script src="scripts/under_construction_ctrl.js"></script> 
-        
-       
+
+       <script src="scripts/under_construction_ctrl.js"></script>
+
+
 
        <script src="scripts/DashboardCtrl.js"></script>
 
-       <!--    File Upload start -->
-       <script src="scripts/FileUploadService.js"></script>
-       <script src="scripts/FileUploadCtrl.js"></script>
-       <!--    File Upload end -->
-
-       
-       <!--    Export File  start -->
-       <script src="scripts/ExportFileService.js"></script>
-       <script src="scripts/ExportFileCtrl.js"></script>
-       <!--    Export File end -->
-       
-       
-       
        <!--  Activity Modelling start -->
        <script src="scripts/ActivityModellingCtrl.js"></script>
        <!--  Activity Modelling end -->
-       
+
        <!--    dialog box ctl start -->
        <script type="text/javascript" src="scripts/common_variables.js"></script>
        <!-- <script src="scripts/ImportProjectCtrl.js"></script> -->
-     <script src="scripts/CldsOpenModelCtrl.js"></script>
-     <script src="scripts/CldsModelService.js"></script>
-     
-     <script src="scripts/ImportSchemaCtrl.js"></script>
-     
-     <script src="scripts/importSchemaService.js"></script>
-     
-     <script src="scripts/UpgradeSchemaCtrl.js"></script>
-     
-     <script src="scripts/soapRequestService.js"></script>
-    
-     <script src="scripts/dataFactory.js"></script>
-     
-     <script src="scripts/textAreaCtrl.js"></script>
-     
-     <script src="scripts/userPreferencesService.js"></script>
-
-     <script src="scripts/DeploymentCtrl.js"></script>
-     <script src="scripts/ExtraUserInfoCtrl.js"></script>
-     <script src="scripts/ExtraUserInfoService.js"></script>     
-     <script src="scripts/saveConfirmationModalPopUpCtrl.js"></script>
-     <script src="scripts/GlobalPropertiesCtrl.js"></script>
-     <script src="scripts/AlertService.js"></script>
-     <script src="scripts/ToscaModelCtrl.js"></script>
-     <script src="scripts/ToscaModelService.js"></script>
-
-    <!--    dialog box ctl end -->
-    <script src="scripts/aOnBoot.js"></script>
-    <script src="scripts/propertyController.js"></script>
-    <script src="scripts/menuHandler.js"></script>
-        
-</body>
+       <script src="scripts/CldsOpenModelCtrl.js"></script>
+       <script src="scripts/CldsModelService.js"></script>
+
+       <script src="scripts/OperationalPolicyCtrl.js"></script>
+       <script src="scripts/OperationalPolicyService.js"></script>
+
+       <script src="scripts/dataFactory.js"></script>
+
+       <script src="scripts/textAreaCtrl.js"></script>
+
+       <script src="scripts/userPreferencesService.js"></script>
+
+       <script src="scripts/DeploymentCtrl.js"></script>
+       <script src="scripts/ExtraUserInfoCtrl.js"></script>
+       <script src="scripts/ExtraUserInfoService.js"></script>
+       <script src="scripts/saveConfirmationModalPopUpCtrl.js"></script>
+       <script src="scripts/GlobalPropertiesCtrl.js"></script>
+       <script src="scripts/AlertService.js"></script>
+       <script src="scripts/ToscaModelCtrl.js"></script>
+       <script src="scripts/ToscaModelService.js"></script>
+
+       <!--    dialog box ctl end -->
+       <script src="scripts/aOnBoot.js"></script>
+       <script src="scripts/propertyController.js"></script>
+       <script src="scripts/menuHandler.js"></script>
+
+</body>
\ No newline at end of file
index 2966fac..3d89905 100644 (file)
 /**
  * @name JSON Editor
  * @description JSON Schema Based Editor
- * Deprecation notice
- * This repo is no longer maintained (see also https://github.com/jdorn/json-editor/issues/800)
- * Development is continued at https://github.com/json-editor/json-editor
- * For details please visit https://github.com/json-editor/json-editor/issues/5
- * @version 1.1.0-beta.2
+ * This library is the continuation of jdorn's great work (see also https://github.com/jdorn/json-editor/issues/800)
+ * @version 1.3.5
  * @author Jeremy Dorn
  * @see https://github.com/jdorn/json-editor/
  * @see https://github.com/json-editor/json-editor
  * @license MIT
  * @example see README.md and docs/ for requirements, examples and usage info
  */
-
-(function() {
-
-/*jshint loopfunc: true */
-/* Simple JavaScript Inheritance
- * By John Resig http://ejohn.org/
- * MIT Licensed.
- */
-// Inspired by base2 and Prototype
-var Class;
-(function(){
-  var initializing = false, fnTest = /xyz/.test(function(){window.postMessage("xyz");}) ? /\b_super\b/ : /.*/;
-  // The base Class implementation (does nothing)
-  Class = function(){};
-  // Create a new Class that inherits from this class
-  Class.extend = function extend(prop) {
-    var _super = this.prototype;
-   
-    // Instantiate a base class (but only create the instance,
-    // don't run the init constructor)
-    initializing = true;
-    var prototype = new this();
-    initializing = false;
-   
-    // Copy the properties over onto the new prototype
-    for (var name in prop) {
-      // Check if we're overwriting an existing function
-      prototype[name] = typeof prop[name] == "function" &&
-        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
-        (function(name, fn){
-          return function() {
-            var tmp = this._super;
-           
-            // Add a new ._super() method that is the same method
-            // but on the super-class
-            this._super = _super[name];
-           
-            // The method only need to be bound temporarily, so we
-            // remove it when we're done executing
-            var ret = fn.apply(this, arguments);        
-            this._super = tmp;
-           
-            return ret;
-          };
-        })(name, prop[name]) :
-        prop[name];
-    }
-   
-    // The dummy class constructor
-    function Class() {
-      // All construction is actually done in the init method
-      if ( !initializing && this.init )
-        this.init.apply(this, arguments);
-    }
-   
-    // Populate our constructed prototype object
-    Class.prototype = prototype;
-   
-    // Enforce the constructor to be what we expect
-    Class.prototype.constructor = Class;
-    // And make this class extendable
-    Class.extend = extend;
-   
-    return Class;
-  };
-  
-  return Class;
-})();
-
-// CustomEvent constructor polyfill
-// From MDN
-(function () {
-  function CustomEvent ( event, params ) {
-    params = params || { bubbles: false, cancelable: false, detail: undefined };
-    var evt = document.createEvent( 'CustomEvent' );
-    evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
-    return evt;
-  }
-
-  CustomEvent.prototype = window.Event.prototype;
-
-  window.CustomEvent = CustomEvent;
-})();
-
-// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
-// MIT license
-(function() {
-    var lastTime = 0;
-    var vendors = ['ms', 'moz', 'webkit', 'o'];
-    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
-        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
-        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || 
-                                      window[vendors[x]+'CancelRequestAnimationFrame'];
-    }
-    if (!window.requestAnimationFrame)
-        window.requestAnimationFrame = function(callback, element) {
-            var currTime = new Date().getTime();
-            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
-            var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
-              timeToCall);
-            lastTime = currTime + timeToCall;
-            return id;
-        };
-    if (!window.cancelAnimationFrame)
-        window.cancelAnimationFrame = function(id) {
-            clearTimeout(id);
-        };
-}());
-
-// Array.isArray polyfill
-// From MDN
-(function() {
-       if(!Array.isArray) {
-         Array.isArray = function(arg) {
-               return Object.prototype.toString.call(arg) === '[object Array]';
-         };
-       }
-}());
-/**
- * Taken from jQuery 2.1.3
- *
- * @param obj
- * @returns {boolean}
- */
-var $isplainobject = function( obj ) {
-  // Not plain objects:
-  // - Any object or value whose internal [[Class]] property is not "[object Object]"
-  // - DOM nodes
-  // - window
-  if (typeof obj !== "object" || obj.nodeType || (obj !== null && obj === obj.window)) {
-    return false;
-  }
-
-  if (obj.constructor && !Object.prototype.hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf")) {
-    return false;
-  }
-
-  // If the function hasn't returned already, we're confident that
-  // |obj| is a plain object, created by {} or constructed with new Object
-  return true;
-};
-
-var $extend = function(destination) {
-  var source, i,property;
-  for(i=1; i<arguments.length; i++) {
-    source = arguments[i];
-    for (property in source) {
-      if(!source.hasOwnProperty(property)) continue;
-      if(source[property] && $isplainobject(source[property])) {
-        if(!destination.hasOwnProperty(property)) destination[property] = {};
-        $extend(destination[property], source[property]);
-      }
-      else {
-        destination[property] = source[property];
-      }
-    }
-  }
-  return destination;
-};
-
-var $each = function(obj,callback) {
-  if(!obj || typeof obj !== "object") return;
-  var i;
-  if(Array.isArray(obj) || (typeof obj.length === 'number' && obj.length > 0 && (obj.length - 1) in obj)) {
-    for(i=0; i<obj.length; i++) {
-      if(callback(i,obj[i])===false) return;
-    }
-  }
-  else {
-    if (Object.keys) {
-      var keys = Object.keys(obj);
-      for(i=0; i<keys.length; i++) {
-        if(callback(keys[i],obj[keys[i]])===false) return;
-      }
-    }
-    else {
-      for(i in obj) {
-        if(!obj.hasOwnProperty(i)) continue;
-        if(callback(i,obj[i])===false) return;
-      }
-    }
-  }
-};
-
-var $trigger = function(el,event) {
-  var e = document.createEvent('HTMLEvents');
-  e.initEvent(event, true, true);
-  el.dispatchEvent(e);
-};
-var $triggerc = function(el,event) {
-  var e = new CustomEvent(event,{
-    bubbles: true,
-    cancelable: true
-  });
-
-  el.dispatchEvent(e);
-};
-
-var JSONEditor = function(element,options) {
-  if (!(element instanceof Element)) {
-    throw new Error('element should be an instance of Element');
-  }
-  options = $extend({},JSONEditor.defaults.options,options||{});
-  this.element = element;
-  this.options = options;
-  this.init();
-};
-JSONEditor.prototype = {
-  // necessary since we remove the ctor property by doing a literal assignment. Without this
-  // the $isplainobject function will think that this is a plain object.
-  constructor: JSONEditor,
-  init: function() {
-    var self = this;
-    
-    this.ready = false;
-    this.copyClipboard = null;
-
-    var theme_class = JSONEditor.defaults.themes[this.options.theme || JSONEditor.defaults.theme];
-    if(!theme_class) throw "Unknown theme " + (this.options.theme || JSONEditor.defaults.theme);
-    
-    this.schema = this.options.schema;
-    this.theme = new theme_class();
-    this.template = this.options.template;
-    this.refs = this.options.refs || {};
-    this.uuid = 0;
-    this.__data = {};
-    
-    var icon_class = JSONEditor.defaults.iconlibs[this.options.iconlib || JSONEditor.defaults.iconlib];
-    if(icon_class) this.iconlib = new icon_class();
-
-    this.root_container = this.theme.getContainer();
-    this.element.appendChild(this.root_container);
-    
-    this.translate = this.options.translate || JSONEditor.defaults.translate;
-
-    // Fetch all external refs via ajax
-    this._loadExternalRefs(this.schema, function() {
-      self._getDefinitions(self.schema);
-      
-      // Validator options
-      var validator_options = {};
-      if(self.options.custom_validators) {
-        validator_options.custom_validators = self.options.custom_validators;
-      }
-      self.validator = new JSONEditor.Validator(self,null,validator_options);
-      
-      // Create the root editor
-      var schema = self.expandRefs(self.schema);
-      var editor_class = self.getEditorClass(schema);
-      self.root = self.createEditor(editor_class, {
-        jsoneditor: self,
-        schema: schema,
-        required: true,
-        container: self.root_container
-      });
-      
-      self.root.preBuild();
-      self.root.build();
-      self.root.postBuild();
-
-      // Starting data
-      if(self.options.hasOwnProperty('startval')) self.root.setValue(self.options.startval, true);
-
-      self.validation_results = self.validator.validate(self.root.getValue());
-      self.root.showValidationErrors(self.validation_results);
-      self.ready = true;
-
-      // Fire ready event asynchronously
-      window.requestAnimationFrame(function() {
-        if(!self.ready) return;
-        self.validation_results = self.validator.validate(self.root.getValue());
-        self.root.showValidationErrors(self.validation_results);
-        self.trigger('ready');
-        self.trigger('change');
-      });
-    });
-  },
-  getValue: function() {
-    if(!this.ready) throw "JSON Editor not ready yet.  Listen for 'ready' event before getting the value";
-
-    return this.root.getValue();
-  },
-  setValue: function(value) {
-    if(!this.ready) throw "JSON Editor not ready yet.  Listen for 'ready' event before setting the value";
-
-    this.root.setValue(value);
-    return this;
-  },
-  validate: function(value) {
-    if(!this.ready) throw "JSON Editor not ready yet.  Listen for 'ready' event before validating";
-    
-    // Custom value
-    if(arguments.length === 1) {
-      return this.validator.validate(value);
-    }
-    // Current value (use cached result)
-    else {
-      return this.validation_results;
-    }
-  },
-  destroy: function() {
-    if(this.destroyed) return;
-    if(!this.ready) return;
-    
-    this.schema = null;
-    this.options = null;
-    this.root.destroy();
-    this.root = null;
-    this.root_container = null;
-    this.validator = null;
-    this.validation_results = null;
-    this.theme = null;
-    this.iconlib = null;
-    this.template = null;
-    this.__data = null;
-    this.ready = false;
-    this.element.innerHTML = '';
-    
-    this.destroyed = true;
-  },
-  on: function(event, callback) {
-    this.callbacks = this.callbacks || {};
-    this.callbacks[event] = this.callbacks[event] || [];
-    this.callbacks[event].push(callback);
-    
-    return this;
-  },
-  off: function(event, callback) {
-    // Specific callback
-    if(event && callback) {
-      this.callbacks = this.callbacks || {};
-      this.callbacks[event] = this.callbacks[event] || [];
-      var newcallbacks = [];
-      for(var i=0; i<this.callbacks[event].length; i++) {
-        if(this.callbacks[event][i]===callback) continue;
-        newcallbacks.push(this.callbacks[event][i]);
-      }
-      this.callbacks[event] = newcallbacks;
-    }
-    // All callbacks for a specific event
-    else if(event) {
-      this.callbacks = this.callbacks || {};
-      this.callbacks[event] = [];
-    }
-    // All callbacks for all events
-    else {
-      this.callbacks = {};
-    }
-    
-    return this;
-  },
-  trigger: function(event) {
-    if(this.callbacks && this.callbacks[event] && this.callbacks[event].length) {
-      for(var i=0; i<this.callbacks[event].length; i++) {
-        this.callbacks[event][i].apply(this, []);
-      }
-    }
-    
-    return this;
-  },
-  setOption: function(option, value) {
-    if(option === "show_errors") {
-      this.options.show_errors = value;
-      this.onChange();
-    }
-    // Only the `show_errors` option is supported for now
-    else {
-      throw "Option "+option+" must be set during instantiation and cannot be changed later";
-    }
-    
-    return this;
-  },
-  getEditorClass: function(schema) {
-    var classname;
-
-    schema = this.expandSchema(schema);
-
-    $each(JSONEditor.defaults.resolvers,function(i,resolver) {
-      var tmp = resolver(schema);
-      if(tmp) {
-        if(JSONEditor.defaults.editors[tmp]) {
-          classname = tmp;
-          return false;
-        }
-      }
-    });
-
-    if(!classname) throw "Unknown editor for schema "+JSON.stringify(schema);
-    if(!JSONEditor.defaults.editors[classname]) throw "Unknown editor "+classname;
-
-    return JSONEditor.defaults.editors[classname];
-  },
-  createEditor: function(editor_class, options) {
-    options = $extend({},editor_class.options||{},options);
-    return new editor_class(options);
-  },
-  onChange: function() {
-    if(!this.ready) return;
-    
-    if(this.firing_change) return;
-    this.firing_change = true;
-    
-    var self = this;
-    
-    window.requestAnimationFrame(function() {
-      self.firing_change = false;
-      if(!self.ready) return;
-
-      // Validate and cache results
-      self.validation_results = self.validator.validate(self.root.getValue());
-      
-      if(self.options.show_errors !== "never") {
-        self.root.showValidationErrors(self.validation_results);
-      }
-      else {
-        self.root.showValidationErrors([]);
-      }
-      
-      // Fire change event
-      self.trigger('change');
-    });
-    
-    return this;
-  },
-  compileTemplate: function(template, name) {
-    name = name || JSONEditor.defaults.template;
-
-    var engine;
-
-    // Specifying a preset engine
-    if(typeof name === 'string') {
-      if(!JSONEditor.defaults.templates[name]) throw "Unknown template engine "+name;
-      engine = JSONEditor.defaults.templates[name]();
-
-      if(!engine) throw "Template engine "+name+" missing required library.";
-    }
-    // Specifying a custom engine
-    else {
-      engine = name;
-    }
-
-    if(!engine) throw "No template engine set";
-    if(!engine.compile) throw "Invalid template engine set";
-
-    return engine.compile(template);
-  },
-  _data: function(el,key,value) {
-    // Setting data
-    if(arguments.length === 3) {
-      var uuid;
-      if(el.hasAttribute('data-jsoneditor-'+key)) {
-        uuid = el.getAttribute('data-jsoneditor-'+key);
-      }
-      else {
-        uuid = this.uuid++;
-        el.setAttribute('data-jsoneditor-'+key,uuid);
-      }
-
-      this.__data[uuid] = value;
-    }
-    // Getting data
-    else {
-      // No data stored
-      if(!el.hasAttribute('data-jsoneditor-'+key)) return null;
-      
-      return this.__data[el.getAttribute('data-jsoneditor-'+key)];
-    }
-  },
-  registerEditor: function(editor) {
-    this.editors = this.editors || {};
-    this.editors[editor.path] = editor;
-    return this;
-  },
-  unregisterEditor: function(editor) {
-    this.editors = this.editors || {};
-    this.editors[editor.path] = null;
-    return this;
-  },
-  getEditor: function(path) {
-    if(!this.editors) return;
-    return this.editors[path];
-  },
-  watch: function(path,callback) {
-    this.watchlist = this.watchlist || {};
-    this.watchlist[path] = this.watchlist[path] || [];
-    this.watchlist[path].push(callback);
-    
-    return this;
-  },
-  unwatch: function(path,callback) {
-    if(!this.watchlist || !this.watchlist[path]) return this;
-    // If removing all callbacks for a path
-    if(!callback) {
-      this.watchlist[path] = null;
-      return this;
-    }
-    
-    var newlist = [];
-    for(var i=0; i<this.watchlist[path].length; i++) {
-      if(this.watchlist[path][i] === callback) continue;
-      else newlist.push(this.watchlist[path][i]);
-    }
-    this.watchlist[path] = newlist.length? newlist : null;
-    return this;
-  },
-  notifyWatchers: function(path) {
-    if(!this.watchlist || !this.watchlist[path]) return this;
-    for(var i=0; i<this.watchlist[path].length; i++) {
-      this.watchlist[path][i]();
-    }
-  },
-  isEnabled: function() {
-    return !this.root || this.root.isEnabled();
-  },
-  enable: function() {
-    this.root.enable();
-  },
-  disable: function() {
-    this.root.disable();
-  },
-  _getDefinitions: function(schema,path) {
-    path = path || '#/definitions/';
-    if(schema.definitions) {
-      for(var i in schema.definitions) {
-        if(!schema.definitions.hasOwnProperty(i)) continue;
-        this.refs[path+i] = schema.definitions[i];
-        if(schema.definitions[i].definitions) {
-          this._getDefinitions(schema.definitions[i],path+i+'/definitions/');
-        }
-      }
-    }
-  },
-  _getExternalRefs: function(schema) {
-    var refs = {};
-    var merge_refs = function(newrefs) {
-      for(var i in newrefs) {
-        if(newrefs.hasOwnProperty(i)) {
-          refs[i] = true;
-        }
-      }
-    };
-    
-    if(schema.$ref && typeof schema.$ref !== "object" && schema.$ref.substr(0,1) !== "#" && !this.refs[schema.$ref]) {
-      refs[schema.$ref] = true;
-    }
-    
-    for(var i in schema) {
-      if(!schema.hasOwnProperty(i)) continue;
-      if(schema[i] && typeof schema[i] === "object" && Array.isArray(schema[i])) {
-        for(var j=0; j<schema[i].length; j++) {
-          if(schema[i][j] && typeof schema[i][j]==="object") {
-            merge_refs(this._getExternalRefs(schema[i][j]));
-          }
-        }
-      }
-      else if(schema[i] && typeof schema[i] === "object") {
-        merge_refs(this._getExternalRefs(schema[i]));
-      }
-    }
-    
-    return refs;
-  },
-  _loadExternalRefs: function(schema, callback) {
-    var self = this;
-    var refs = this._getExternalRefs(schema);
-    
-    var done = 0, waiting = 0, callback_fired = false;
-    
-    $each(refs,function(url) {
-      if(self.refs[url]) return;
-      if(!self.options.ajax) throw "Must set ajax option to true to load external ref "+url;
-      self.refs[url] = 'loading';
-      waiting++;
-
-      var fetchUrl=url;
-      if( self.options.ajaxBase && self.options.ajaxBase!=url.substr(0,self.options.ajaxBase.length) && "http"!=url.substr(0,4)) fetchUrl=self.options.ajaxBase+url;
-
-      var r = new XMLHttpRequest(); 
-      r.open("GET", fetchUrl, true);
-      if(self.options.ajaxCredentials) r.withCredentials=self.options.ajaxCredentials;
-      r.onreadystatechange = function () {
-        if (r.readyState != 4) return; 
-        // Request succeeded
-        if(r.status === 200) {
-          var response;
-          try {
-            response = JSON.parse(r.responseText);
-          }
-          catch(e) {
-            window.console.log(e);
-            throw "Failed to parse external ref "+fetchUrl;
-          }
-          if(!response || typeof response !== "object") throw "External ref does not contain a valid schema - "+fetchUrl;
-          
-          self.refs[url] = response;
-          self._loadExternalRefs(response,function() {
-            done++;
-            if(done >= waiting && !callback_fired) {
-              callback_fired = true;
-              callback();
-            }
-          });
-        }
-        // Request failed
-        else {
-          window.console.log(r);
-          throw "Failed to fetch ref via ajax- "+url;
-        }
-      };
-      r.send();
-    });
-    
-    if(!waiting) {
-      callback();
-    }
-  },
-  expandRefs: function(schema) {
-    schema = $extend({},schema);
-    
-    while (schema.$ref) {
-      var ref = schema.$ref;
-      delete schema.$ref;
-      
-      if(!this.refs[ref]) ref = decodeURIComponent(ref);
-      
-      schema = this.extendSchemas(schema,this.refs[ref]);
-    }
-    return schema;
-  },
-  expandSchema: function(schema) {
-    var self = this;
-    var extended = $extend({},schema);
-    var i;
-
-    // Version 3 `type`
-    if(typeof schema.type === 'object') {
-      // Array of types
-      if(Array.isArray(schema.type)) {
-        $each(schema.type, function(key,value) {
-          // Schema
-          if(typeof value === 'object') {
-            schema.type[key] = self.expandSchema(value);
-          }
-        });
-      }
-      // Schema
-      else {
-        schema.type = self.expandSchema(schema.type);
-      }
-    }
-    // Version 3 `disallow`
-    if(typeof schema.disallow === 'object') {
-      // Array of types
-      if(Array.isArray(schema.disallow)) {
-        $each(schema.disallow, function(key,value) {
-          // Schema
-          if(typeof value === 'object') {
-            schema.disallow[key] = self.expandSchema(value);
-          }
-        });
-      }
-      // Schema
-      else {
-        schema.disallow = self.expandSchema(schema.disallow);
-      }
-    }
-    // Version 4 `anyOf`
-    if(schema.anyOf) {
-      $each(schema.anyOf, function(key,value) {
-        schema.anyOf[key] = self.expandSchema(value);
-      });
-    }
-    // Version 4 `dependencies` (schema dependencies)
-    if(schema.dependencies) {
-      $each(schema.dependencies,function(key,value) {
-        if(typeof value === "object" && !(Array.isArray(value))) {
-          schema.dependencies[key] = self.expandSchema(value);
-        }
-      });
-    }
-    // Version 4 `not`
-    if(schema.not) {
-      schema.not = this.expandSchema(schema.not);
-    }
-    
-    // allOf schemas should be merged into the parent
-    if(schema.allOf) {
-      for(i=0; i<schema.allOf.length; i++) {
-        extended = this.extendSchemas(extended,this.expandSchema(schema.allOf[i]));
-      }
-      delete extended.allOf;
-    }
-    // extends schemas should be merged into parent
-    if(schema["extends"]) {
-      // If extends is a schema
-      if(!(Array.isArray(schema["extends"]))) {
-        extended = this.extendSchemas(extended,this.expandSchema(schema["extends"]));
-      }
-      // If extends is an array of schemas
-      else {
-        for(i=0; i<schema["extends"].length; i++) {
-          extended = this.extendSchemas(extended,this.expandSchema(schema["extends"][i]));
-        }
-      }
-      delete extended["extends"];
-    }
-    // parent should be merged into oneOf schemas
-    if(schema.oneOf) {
-      var tmp = $extend({},extended);
-      delete tmp.oneOf;
-      for(i=0; i<schema.oneOf.length; i++) {
-        extended.oneOf[i] = this.extendSchemas(this.expandSchema(schema.oneOf[i]),tmp);
-      }
-    }
-    
-    return this.expandRefs(extended);
-  },
-  extendSchemas: function(obj1, obj2) {
-    obj1 = $extend({},obj1);
-    obj2 = $extend({},obj2);
-
-    var self = this;
-    var extended = {};
-    $each(obj1, function(prop,val) {
-      // If this key is also defined in obj2, merge them
-      if(typeof obj2[prop] !== "undefined") {
-        // Required and defaultProperties arrays should be unioned together
-        if((prop === 'required'||prop === 'defaultProperties') && typeof val === "object" && Array.isArray(val)) {
-          // Union arrays and unique
-          extended[prop] = val.concat(obj2[prop]).reduce(function(p, c) {
-            if (p.indexOf(c) < 0) p.push(c);
-            return p;
-          }, []);
-        }
-        // Type should be intersected and is either an array or string
-        else if(prop === 'type' && (typeof val === "string" || Array.isArray(val))) {
-          // Make sure we're dealing with arrays
-          if(typeof val === "string") val = [val];
-          if(typeof obj2.type === "string") obj2.type = [obj2.type];
-
-          // If type is only defined in the first schema, keep it
-          if(!obj2.type || !obj2.type.length) {
-            extended.type = val;
-          }
-          // If type is defined in both schemas, do an intersect
-          else {
-            extended.type = val.filter(function(n) {
-              return obj2.type.indexOf(n) !== -1;
-            });
-          }
-
-          // If there's only 1 type and it's a primitive, use a string instead of array
-          if(extended.type.length === 1 && typeof extended.type[0] === "string") {
-            extended.type = extended.type[0];
-          }
-          // Remove the type property if it's empty
-          else if(extended.type.length === 0) {
-            delete extended.type;
-          }
-        }
-        // All other arrays should be intersected (enum, etc.)
-        else if(typeof val === "object" && Array.isArray(val)){
-          extended[prop] = val.filter(function(n) {
-            return obj2[prop].indexOf(n) !== -1;
-          });
-        }
-        // Objects should be recursively merged
-        else if(typeof val === "object" && val !== null) {
-          extended[prop] = self.extendSchemas(val,obj2[prop]);
-        }
-        // Otherwise, use the first value
-        else {
-          extended[prop] = val;
-        }
-      }
-      // Otherwise, just use the one in obj1
-      else {
-        extended[prop] = val;
-      }
-    });
-    // Properties in obj2 that aren't in obj1
-    $each(obj2, function(prop,val) {
-      if(typeof obj1[prop] === "undefined") {
-        extended[prop] = val;
-      }
-    });
-
-    return extended;
-  },
-  setCopyClipboardContents: function(value) {
-    this.copyClipboard = value;
-  },
-  getCopyClipboardContents: function() {
-    return this.copyClipboard;
-  }
-};
-
-JSONEditor.defaults = {
-  themes: {},
-  templates: {},
-  iconlibs: {},
-  editors: {},
-  languages: {},
-  resolvers: [],
-  custom_validators: []
-};
-
-JSONEditor.Validator = Class.extend({
-  init: function(jsoneditor,schema,options) {
-    this.jsoneditor = jsoneditor;
-    this.schema = schema || this.jsoneditor.schema;
-    this.options = options || {};
-    this.translate = this.jsoneditor.translate || JSONEditor.defaults.translate;
-  },
-  validate: function(value) {
-    return this._validateSchema(this.schema, value);
-  },
-  _validateSchema: function(schema,value,path) {
-    var self = this;
-    var errors = [];
-    var valid, i, j;
-    var stringified = JSON.stringify(value);
-
-    path = path || 'root';
-
-    // Work on a copy of the schema
-    schema = $extend({},this.jsoneditor.expandRefs(schema));
-
-    /*
-     * Type Agnostic Validation
-     */
-
-    // Version 3 `required` and `required_by_default`
-    if(typeof value === "undefined" || value === null) {
-      if((typeof schema.required !== "undefined" && schema.required === true) || (typeof schema.required === "undefined" && this.jsoneditor.options.required_by_default === true)) {
-        errors.push({
-          path: path,
-          property: 'required',
-          message: this.translate("error_notset", [schema.title ? schema.title : path.split('-').pop().trim()])
-        });
-      }
-
-      return errors;
-    }
-
-    // `enum`
-    if(schema["enum"]) {
-      valid = false;
-      for(i=0; i<schema["enum"].length; i++) {
-        if(stringified === JSON.stringify(schema["enum"][i])) valid = true;
-      }
-      if(!valid) {
-        errors.push({
-          path: path,
-          property: 'enum',
-          message: this.translate("error_enum", [schema.title ? schema.title : path.split('-').pop().trim()])
-        });
-      }
-    }
-
-    // `extends` (version 3)
-    if(schema["extends"]) {
-      for(i=0; i<schema["extends"].length; i++) {
-        errors = errors.concat(this._validateSchema(schema["extends"][i],value,path));
-      }
-    }
-
-    // `allOf`
-    if(schema.allOf) {
-      for(i=0; i<schema.allOf.length; i++) {
-        errors = errors.concat(this._validateSchema(schema.allOf[i],value,path));
-      }
-    }
-
-    // `anyOf`
-    if(schema.anyOf) {
-      valid = false;
-      for(i=0; i<schema.anyOf.length; i++) {
-        if(!this._validateSchema(schema.anyOf[i],value,path).length) {
-          valid = true;
-          break;
-        }
-      }
-      if(!valid) {
-        errors.push({
-          path: path,
-          property: 'anyOf',
-          message: this.translate('error_anyOf')
-        });
-      }
-    }
-
-    // `oneOf`
-    if(schema.oneOf) {
-      valid = 0;
-      var oneof_errors = [];
-      for(i=0; i<schema.oneOf.length; i++) {
-        // Set the error paths to be path.oneOf[i].rest.of.path
-        var tmp = this._validateSchema(schema.oneOf[i],value,path);
-        if(!tmp.length) {
-          valid++;
-        }
-
-        for(j=0; j<tmp.length; j++) {
-          tmp[j].path = path+'.oneOf['+i+']'+tmp[j].path.substr(path.length);
-        }
-        oneof_errors = oneof_errors.concat(tmp);
-
-      }
-      if(valid !== 1) {
-        errors.push({
-          path: path,
-          property: 'oneOf',
-          message: this.translate('error_oneOf', [valid])
-        });
-        errors = errors.concat(oneof_errors);
-      }
-    }
-
-    // `not`
-    if(schema.not) {
-      if(!this._validateSchema(schema.not,value,path).length) {
-        errors.push({
-          path: path,
-          property: 'not',
-          message: this.translate('error_not')
-        });
-      }
-    }
-
-    // `type` (both Version 3 and Version 4 support)
-    if(schema.type) {
-      // Union type
-      if(Array.isArray(schema.type)) {
-        valid = false;
-        for(i=0;i<schema.type.length;i++) {
-          if(this._checkType(schema.type[i], value)) {
-            valid = true;
-            break;
-          }
-        }
-        if(!valid) {
-          errors.push({
-            path: path,
-            property: 'type',
-            message: this.translate('error_type_union')
-          });
-        }
-      }
-      // Simple type
-      else {
-        if(!this._checkType(schema.type, value)) {
-          errors.push({
-            path: path,
-            property: 'type',
-            message: this.translate('error_type', [schema.type])
-          });
-        }
-      }
-    }
-
-
-    // `disallow` (version 3)
-    if(schema.disallow) {
-      // Union type
-      if(Array.isArray(schema.disallow)) {
-        valid = true;
-        for(i=0;i<schema.disallow.length;i++) {
-          if(this._checkType(schema.disallow[i], value)) {
-            valid = false;
-            break;
-          }
-        }
-        if(!valid) {
-          errors.push({
-            path: path,
-            property: 'disallow',
-            message: this.translate('error_disallow_union')
-          });
-        }
-      }
-      // Simple type
-      else {
-        if(this._checkType(schema.disallow, value)) {
-          errors.push({
-            path: path,
-            property: 'disallow',
-            message: this.translate('error_disallow', [schema.disallow])
-          });
-        }
-      }
-    }
-
-    /*
-     * Type Specific Validation
-     */
-
-    // Number Specific Validation
-    if(typeof value === "number") {
-      // `multipleOf` and `divisibleBy`
-      if(schema.multipleOf || schema.divisibleBy) {
-        var divisor = schema.multipleOf || schema.divisibleBy;
-        // Vanilla JS, prone to floating point rounding errors (e.g. 1.14 / .01 == 113.99999)
-        valid = (value/divisor === Math.floor(value/divisor));
-
-        // Use math.js is available
-        if(window.math) {
-          valid = window.math.mod(window.math.bignumber(value), window.math.bignumber(divisor)).equals(0);
-        }
-        // Use decimal.js is available
-        else if(window.Decimal) {
-          valid = (new window.Decimal(value)).mod(new window.Decimal(divisor)).equals(0);
-        }
-
-        if(!valid) {
-          errors.push({
-            path: path,
-            property: schema.multipleOf? 'multipleOf' : 'divisibleBy',
-            message: this.translate('error_multipleOf', [divisor])
-          });
-        }
-      }
-
-      // `maximum`
-      if(schema.hasOwnProperty('maximum')) {
-        // Vanilla JS, prone to floating point rounding errors (e.g. .999999999999999 == 1)
-        valid = schema.exclusiveMaximum? (value < schema.maximum) : (value <= schema.maximum);
-
-        // Use math.js is available
-        if(window.math) {
-          valid = window.math[schema.exclusiveMaximum?'smaller':'smallerEq'](
-            window.math.bignumber(value),
-            window.math.bignumber(schema.maximum)
-          );
-        }
-        // Use Decimal.js if available
-        else if(window.Decimal) {
-          valid = (new window.Decimal(value))[schema.exclusiveMaximum?'lt':'lte'](new window.Decimal(schema.maximum));
-        }
-
-        if(!valid) {
-          errors.push({
-            path: path,
-            property: 'maximum',
-            message: this.translate(
-              (schema.exclusiveMaximum?'error_maximum_excl':'error_maximum_incl'),
-              [schema.title ? schema.title : path.split('-').pop().trim(), schema.maximum]
-            )
-          });
-        }
-      }
-
-      // `minimum`
-      if(schema.hasOwnProperty('minimum')) {
-        // Vanilla JS, prone to floating point rounding errors (e.g. .999999999999999 == 1)
-        valid = schema.exclusiveMinimum? (value > schema.minimum) : (value >= schema.minimum);
-
-        // Use math.js is available
-        if(window.math) {
-          valid = window.math[schema.exclusiveMinimum?'larger':'largerEq'](
-            window.math.bignumber(value),
-            window.math.bignumber(schema.minimum)
-          );
-        }
-        // Use Decimal.js if available
-        else if(window.Decimal) {
-          valid = (new window.Decimal(value))[schema.exclusiveMinimum?'gt':'gte'](new window.Decimal(schema.minimum));
-        }
-
-        if(!valid) {
-          errors.push({
-            path: path,
-            property: 'minimum',
-            message: this.translate(
-              (schema.exclusiveMinimum?'error_minimum_excl':'error_minimum_incl'),
-              [schema.title ? schema.title : path.split('-').pop().trim(), schema.minimum]
-            )
-          });
-        }
-      }
-    }
-    // String specific validation
-    else if(typeof value === "string") {
-      // `maxLength`
-      if(schema.maxLength) {
-        if((value+"").length > schema.maxLength) {
-          errors.push({
-            path: path,
-            property: 'maxLength',
-            message: this.translate('error_maxLength', 
-                       [schema.title ? schema.title : path.split('-').pop().trim(), schema.maxLength])
-          });
-        }
-      }
-
-      // `minLength` -- Commented because we are validating required field. 
-      if(schema.minLength) {
-        if((value+"").length < schema.minLength) {
-          errors.push({
-            path: path,
-            property: 'minLength',
-            message: this.translate((schema.minLength===1?'error_notempty':'error_minLength'), 
-                       [schema.title ? schema.title : path.split('-').pop().trim(), schema.minLength])
-          });
-        }
-      }
-
-      // `pattern`
-      if(schema.pattern) {
-        if(!(new RegExp(schema.pattern)).test(value)) {
-          errors.push({
-            path: path,
-            property: 'pattern',
-            message: this.translate('error_pattern', 
-                       [schema.title ? schema.title : path.split('-').pop().trim(), schema.pattern])
-          });
-        }
-      }
-    }
-    // Array specific validation
-    else if(typeof value === "object" && value !== null && Array.isArray(value)) {
-      // `items` and `additionalItems`
-      if(schema.items) {
-        // `items` is an array
-        if(Array.isArray(schema.items)) {
-          for(i=0; i<value.length; i++) {
-            // If this item has a specific schema tied to it
-            // Validate against it
-            if(schema.items[i]) {
-              errors = errors.concat(this._validateSchema(schema.items[i],value[i],path+'.'+i));
-            }
-            // If all additional items are allowed
-            else if(schema.additionalItems === true) {
-              break;
-            }
-            // If additional items is a schema
-            // TODO: Incompatibility between version 3 and 4 of the spec
-            else if(schema.additionalItems) {
-              errors = errors.concat(this._validateSchema(schema.additionalItems,value[i],path+'.'+i));
-            }
-            // If no additional items are allowed
-            else if(schema.additionalItems === false) {
-              errors.push({
-                path: path,
-                property: 'additionalItems',
-                message: this.translate('error_additionalItems')
-              });
-              break;
-            }
-            // Default for `additionalItems` is an empty schema
-            else {
-              break;
-            }
-          }
-        }
-        // `items` is a schema
-        else {
-          // Each item in the array must validate against the schema
-          for(i=0; i<value.length; i++) {
-            errors = errors.concat(this._validateSchema(schema.items,value[i],path+'.'+i));
-          }
-        }
-      }
-
-      // `maxItems`
-      if(schema.maxItems) {
-        if(value.length > schema.maxItems) {
-          errors.push({
-            path: path,
-            property: 'maxItems',
-            message: this.translate('error_maxItems', [schema.maxItems])
-          });
-        }
-      }
-
-      // `minItems`
-      if(schema.minItems) {
-        if(value.length < schema.minItems) {
-          errors.push({
-            path: path,
-            property: 'minItems',
-            message: this.translate('error_minItems', [schema.minItems])
-          });
-        }
-      }
-
-      // `uniqueItems`
-      if(schema.uniqueItems) {
-        var seen = {};
-        for(i=0; i<value.length; i++) {
-          valid = JSON.stringify(value[i]);
-          if(seen[valid]) {
-            errors.push({
-              path: path,
-              property: 'uniqueItems',
-              message: this.translate('error_uniqueItems', 
-                               [schema.title ? schema.title : path.split('-').pop().trim()])
-            });
-            break;
-          }
-          seen[valid] = true;
-        }
-      }
-    }
-    // Object specific validation
-    else if(typeof value === "object" && value !== null) {
-      // `maxProperties`
-      if(schema.maxProperties) {
-        valid = 0;
-        for(i in value) {
-          if(!value.hasOwnProperty(i)) continue;
-          valid++;
-        }
-        if(valid > schema.maxProperties) {
-          errors.push({
-            path: path,
-            property: 'maxProperties',
-            message: this.translate('error_maxProperties', [schema.maxProperties])
-          });
-        }
-      }
-
-      // `minProperties`
-      if(schema.minProperties) {
-        valid = 0;
-        for(i in value) {
-          if(!value.hasOwnProperty(i)) continue;
-          valid++;
-        }
-        if(valid < schema.minProperties) {
-          errors.push({
-            path: path,
-            property: 'minProperties',
-            message: this.translate('error_minProperties', [schema.minProperties])
-          });
-        }
-      }
-
-      // Version 4 `required`
-      if(typeof schema.required !== "undefined" && Array.isArray(schema.required)) {
-        for(i=0; i<schema.required.length; i++) {
-          // Arrays are the only missing "required" thing we report in the "object" 
-          // level control group error message area; all others appear in their own form control 
-          // control message area.
-          if((typeof value[schema.required[i]] === "undefined") ||
-                (Array.isArray(value[schema.required[i]]) && value[schema.required[i]].length == 0)) {
-            var parm_name;
-            if(typeof schema.properties[schema.required[i]].title !== "undefined") {
-              parm_name = schema.properties[schema.required[i]].title;
-            } 
-            else {
-              parm_name = schema.required[i];
-            }
-            errors.push({
-              path: path,
-              property: 'required',
-              message: this.translate('error_required', [parm_name])
-            });
-          }
-        }
-      }
-
-      // `properties`
-      var validated_properties = {};
-      if(schema.properties) {
-        if(typeof schema.required !== "undefined" && Array.isArray(schema.required)) {
-          for(i=0; i<schema.required.length; i++) {
-            var property = schema.required[i];
-            validated_properties[property] = true;
-            errors = errors.concat(this._validateSchema(schema.properties[property],value[property],path+'.'+property));
-          }
-        }
-
-        // If an optional property is not an object and is not empty, we must run validation
-        // on it as the user may have entered some data into it.
-
-        for(i in schema.properties) {
-          if(!schema.properties.hasOwnProperty(i) || validated_properties[i] === true) continue;
-          if((typeof value[i] !== "object" && typeof value[i] !== "undefined" && value[i] !== null) ||
-             (schema.properties[i].type === "array" && Array.isArray(value[i]) && value[i].length > 0)) {
-                 
-            errors = errors.concat(this._validateSchema(schema.properties[i],value[i],path+'.'+i));
-          }
-          validated_properties[i] = true;
-        }
-      }
-
-      // `patternProperties`
-      if(schema.patternProperties) {
-        for(i in schema.patternProperties) {
-          if(!schema.patternProperties.hasOwnProperty(i)) continue;
-          var regex = new RegExp(i);
-
-          // Check which properties match
-          for(j in value) {
-            if(!value.hasOwnProperty(j)) continue;
-            if(regex.test(j)) {
-              validated_properties[j] = true;
-              errors = errors.concat(this._validateSchema(schema.patternProperties[i],value[j],path+'.'+j));
-            }
-          }
-        }
-      }
-
-      // The no_additional_properties option currently doesn't work with extended schemas that use oneOf or anyOf
-      if(typeof schema.additionalProperties === "undefined" && this.jsoneditor.options.no_additional_properties && !schema.oneOf && !schema.anyOf) {
-        schema.additionalProperties = false;
-      }
-
-      // `additionalProperties`
-      if(typeof schema.additionalProperties !== "undefined") {
-        for(i in value) {
-          if(!value.hasOwnProperty(i)) continue;
-          if(!validated_properties[i]) {
-            // No extra properties allowed
-            if(!schema.additionalProperties) {
-              errors.push({
-                path: path,
-                property: 'additionalProperties',
-                message: this.translate('error_additional_properties', [i])
-              });
-              break;
-            }
-            // Allowed
-            else if(schema.additionalProperties === true) {
-              break;
-            }
-            // Must match schema
-            // TODO: incompatibility between version 3 and 4 of the spec
-            else {
-              errors = errors.concat(this._validateSchema(schema.additionalProperties,value[i],path+'.'+i));
-            }
-          }
-        }
-      }
-
-      // `dependencies`
-      if(schema.dependencies) {
-        for(i in schema.dependencies) {
-          if(!schema.dependencies.hasOwnProperty(i)) continue;
-
-          // Doesn't need to meet the dependency
-          if(typeof value[i] === "undefined") continue;
-
-          // Property dependency
-          if(Array.isArray(schema.dependencies[i])) {
-            for(j=0; j<schema.dependencies[i].length; j++) {
-              if(typeof value[schema.dependencies[i][j]] === "undefined") {
-                errors.push({
-                  path: path,
-                  property: 'dependencies',
-                  message: this.translate('error_dependency', [schema.dependencies[i][j]])
-                });
-              }
-            }
-          }
-          // Schema dependency
-          else {
-            errors = errors.concat(this._validateSchema(schema.dependencies[i],value,path));
-          }
-        }
-      }
-    }
-
-    // Custom type validation (global)
-    $each(JSONEditor.defaults.custom_validators,function(i,validator) {
-      errors = errors.concat(validator.call(self,schema,value,path));
-    });
-    // Custom type validation (instance specific)
-    if(this.options.custom_validators) {
-      $each(this.options.custom_validators,function(i,validator) {
-        errors = errors.concat(validator.call(self,schema,value,path));
-      });
-    }
-
-    return errors;
-  },
-  _checkType: function(type, value) {
-    // Simple types
-    if(typeof type === "string") {
-      if(type==="string") return typeof value === "string";
-      else if(type==="number") return typeof value === "number";
-      else if(type==="qbldr") return typeof value === "string";
-      else if(type==="integer") return typeof value === "number" && value === Math.floor(value);
-      else if(type==="boolean") return typeof value === "boolean";
-      else if(type==="array") return Array.isArray(value);
-      else if(type === "object") return value !== null && !(Array.isArray(value)) && typeof value === "object";
-      else if(type === "null") return value === null;
-      else return true;
-    }
-    // Schema
-    else {
-      return !this._validateSchema(type,value).length;
-    }
-  }
-});
-
-/**
- * All editors should extend from this class
- */
-JSONEditor.AbstractEditor = Class.extend({
-  onChildEditorChange: function(editor) {
-    this.onChange(true);
-  },
-  notify: function() {
-    if(this.path) this.jsoneditor.notifyWatchers(this.path);
-  },
-  change: function() {
-    if(this.parent) this.parent.onChildEditorChange(this);
-    else if(this.jsoneditor) this.jsoneditor.onChange();
-  },
-  onChange: function(bubble) {
-    this.notify();
-    if(this.watch_listener) this.watch_listener();
-    if(bubble) this.change();
-  },
-  register: function() {
-    this.jsoneditor.registerEditor(this);
-    this.onChange();
-  },
-  unregister: function() {
-    if(!this.jsoneditor) return;
-    this.jsoneditor.unregisterEditor(this);
-  },
-  getNumColumns: function() {
-    return 12;
-  },
-  init: function(options) {
-    this.jsoneditor = options.jsoneditor;
-    
-    this.theme = this.jsoneditor.theme;
-    this.template_engine = this.jsoneditor.template;
-    this.iconlib = this.jsoneditor.iconlib;
-    
-    this.translate = this.jsoneditor.translate || JSONEditor.defaults.translate;
-
-    this.original_schema = options.schema;
-    this.schema = this.jsoneditor.expandSchema(this.original_schema);
-
-    this.options = $extend({}, (this.options || {}), (this.schema.options || {}), (options.schema.options || {}), options);
-
-    if(!options.path && !this.schema.id) this.schema.id = 'root';
-    this.path = options.path || 'root';
-    this.formname = options.formname || this.path.replace(/\.([^.]+)/g,'[$1]');
-    if(this.jsoneditor.options.form_name_root) this.formname = this.formname.replace(/^root\[/,this.jsoneditor.options.form_name_root+'[');
-    this.key = this.path.split('.').pop();
-    this.parent = options.parent;
-    
-    this.link_watchers = [];
-    
-    if(options.container) this.setContainer(options.container);
-    this.registerDependencies();
-  },
-  registerDependencies: function() {
-    this.dependenciesFulfilled = true;
-    var deps = this.options.dependencies;
-    if (!deps) {
-      return;
-    }
-    
-    var self = this;
-    Object.keys(deps).forEach(function(dependency) {
-      var path = self.path.split('.');
-      path[path.length - 1] = dependency;
-      path = path.join('.');
-      var choices = deps[dependency];
-      self.jsoneditor.watch(path, function() {
-        self.checkDependency(path, choices);
-      });
-    });
-  },
-  checkDependency: function(path, choices) {
-    var wrapper = this.control || this.container;
-    if (this.path === path || !wrapper) {
-      return;
-    }
-    
-    var self = this;
-    var editor = this.jsoneditor.getEditor(path);
-    var value = editor ? editor.getValue() : undefined;
-    var previousStatus = this.dependenciesFulfilled;
-    this.dependenciesFulfilled = false;
-    
-    if (!editor || !editor.dependenciesFulfilled) {
-      this.dependenciesFulfilled = false;
-    } else if (Array.isArray(choices)) {
-      choices.some(function(choice) {
-        if (value === choice) {
-          self.dependenciesFulfilled = true;
-          return true;
-        }
-      });
-    } else if (typeof choices === 'object') {
-      if (typeof value !== 'object') {
-        this.dependenciesFulfilled = choices === value;
-      } else {
-        Object.keys(choices).some(function(key) {
-          if (!choices.hasOwnProperty(key)) {
-            return false;
-          }
-          if (!value.hasOwnProperty(key) || choices[key] !== value[key]) {
-            self.dependenciesFulfilled = false;
-            return true;
-          }
-          self.dependenciesFulfilled = true;
-        });
-      }
-    } else if (typeof choices === 'string' || typeof choices === 'number') {
-      this.dependenciesFulfilled = value === choices;
-    } else if (typeof choices === 'boolean') {
-      if (choices) {
-        this.dependenciesFulfilled = value && value.length > 0;
-      } else {
-        this.dependenciesFulfilled = !value || value.length === 0;
-      }
-    }
-    
-    if (this.dependenciesFulfilled !== previousStatus) {
-      this.notify();
-    }
-    
-    if (this.dependenciesFulfilled) {
-      wrapper.style.display = 'block';
-    } else {
-      wrapper.style.display = 'none';
-    }
-  },
-  setContainer: function(container) {
-    this.container = container;
-    if(this.schema.id) this.container.setAttribute('data-schemaid',this.schema.id);
-    if(this.schema.type && typeof this.schema.type === "string") this.container.setAttribute('data-schematype',this.schema.type);
-    this.container.setAttribute('data-schemapath',this.path);
-    this.container.style.padding = '4px';
-  },
-  
-  preBuild: function() {
-
-  },
-  build: function() {
-    
-  },
-  postBuild: function() {
-    this.setupWatchListeners();
-    this.addLinks();
-    this.setValue(this.getDefault(), true);
-    this.updateHeaderText();
-    this.register();
-    this.onWatchedFieldChange();
-  },
-  
-  setupWatchListeners: function() {
-    var self = this;
-    
-    // Watched fields
-    this.watched = {};
-    if(this.schema.vars) this.schema.watch = this.schema.vars;
-    this.watched_values = {};
-    this.watch_listener = function() {
-      if(self.refreshWatchedFieldValues()) {
-        self.onWatchedFieldChange();
-      }
-    };
-    
-    if(this.schema.hasOwnProperty('watch')) {
-      var path,path_parts,first,root,adjusted_path;
-
-      for(var name in this.schema.watch) {
-        if(!this.schema.watch.hasOwnProperty(name)) continue;
-        path = this.schema.watch[name];
-
-        if(Array.isArray(path)) {
-          if(path.length<2) continue;
-          path_parts = [path[0]].concat(path[1].split('.'));
-        }
-        else {
-          path_parts = path.split('.');
-          if(!self.theme.closest(self.container,'[data-schemaid="'+path_parts[0]+'"]')) path_parts.unshift('#');
-        }
-        first = path_parts.shift();
-
-        if(first === '#') first = self.jsoneditor.schema.id || 'root';
-
-        // Find the root node for this template variable
-        root = self.theme.closest(self.container,'[data-schemaid="'+first+'"]');
-        if(!root) throw "Could not find ancestor node with id "+first;
-
-        // Keep track of the root node and path for use when rendering the template
-        adjusted_path = root.getAttribute('data-schemapath') + '.' + path_parts.join('.');
-        
-        self.jsoneditor.watch(adjusted_path,self.watch_listener);
-        
-        self.watched[name] = adjusted_path;
-      }
-    }
-    
-    // Dynamic header
-    if(this.schema.headerTemplate) {
-      this.header_template = this.jsoneditor.compileTemplate(this.schema.headerTemplate, this.template_engine);
-    }
-  },
-  
-  addLinks: function() {
-    // Add links
-    if(!this.no_link_holder) {
-      this.link_holder = this.theme.getLinksHolder();
-      this.container.appendChild(this.link_holder);
-      if(this.schema.links) {
-        for(var i=0; i<this.schema.links.length; i++) {
-          this.addLink(this.getLink(this.schema.links[i]));
-        }
-      }
-    }
-  },
-  
-  
-  getButton: function(text, icon, title) {
-    var btnClass = 'json-editor-btn-'+icon;
-    if(!this.iconlib) icon = null;
-    else icon = this.iconlib.getIcon(icon);
-    
-    if(!icon && title) {
-      text = title;
-      title = null;
-    }
-    
-    var btn = this.theme.getButton(text, icon, title);
-    btn.className += ' ' + btnClass + ' ';
-    return btn;
-  },
-  setButtonText: function(button, text, icon, title) {
-    if(!this.iconlib) icon = null;
-    else icon = this.iconlib.getIcon(icon);
-    
-    if(!icon && title) {
-      text = title;
-      title = null;
-    }
-    
-    return this.theme.setButtonText(button, text, icon, title);
-  },
-  addLink: function(link) {
-    if(this.link_holder) this.link_holder.appendChild(link);
-  },
-  getLink: function(data) {
-    var holder, link;
-        
-    // Get mime type of the link
-    var mime = data.mediaType || 'application/javascript';
-    var type = mime.split('/')[0];
-    
-    // Template to generate the link href
-    var href = this.jsoneditor.compileTemplate(data.href,this.template_engine);
-    var relTemplate = this.jsoneditor.compileTemplate(data.rel ? data.rel : data.href,this.template_engine);
-    
-    // Template to generate the link's download attribute
-    var download = null;
-    if(data.download) download = data.download;
-
-    if(download && download !== true) {
-      download = this.jsoneditor.compileTemplate(download, this.template_engine);
-    }
-
-    // Image links
-    if(type === 'image') {
-      holder = this.theme.getBlockLinkHolder();
-      link = document.createElement('a');
-      link.setAttribute('target','_blank');
-      var image = document.createElement('img');
-      
-      this.theme.createImageLink(holder,link,image);
-    
-      // When a watched field changes, update the url  
-      this.link_watchers.push(function(vars) {
-        var url = href(vars);
-        var rel = relTemplate(vars);
-        link.setAttribute('href',url);
-        link.setAttribute('title',rel || url);
-        image.setAttribute('src',url);
-      });
-    }
-    // Audio/Video links
-    else if(['audio','video'].indexOf(type) >=0) {
-      holder = this.theme.getBlockLinkHolder();
-      
-      link = this.theme.getBlockLink();
-      link.setAttribute('target','_blank');
-      
-      var media = document.createElement(type);
-      media.setAttribute('controls','controls');
-      
-      this.theme.createMediaLink(holder,link,media);
-      
-      // When a watched field changes, update the url  
-      this.link_watchers.push(function(vars) {
-        var url = href(vars);
-        var rel = relTemplate(vars);
-        link.setAttribute('href',url);
-        link.textContent = rel || url;
-        media.setAttribute('src',url);
-      });
-    }
-    // Text links
-    else {
-      link = holder = this.theme.getBlockLink();
-      holder.setAttribute('target','_blank');
-      holder.textContent = data.rel;
-
-      // When a watched field changes, update the url
-      this.link_watchers.push(function(vars) {
-        var url = href(vars);
-        var rel = relTemplate(vars);
-        holder.setAttribute('href',url);
-        holder.textContent = rel || url;
-      });
-    }
-
-    if(download && link) {
-      if(download === true) {
-        link.setAttribute('download','');
-      }
-      else {
-        this.link_watchers.push(function(vars) {
-          link.setAttribute('download',download(vars));
-        });
-      }
-    }
-    
-    if(data.class) link.className = link.className + ' ' + data.class;
-
-    return holder;
-  },
-  refreshWatchedFieldValues: function() {
-    if(!this.watched_values) return;
-    var watched = {};
-    var changed = false;
-    var self = this;
-    
-    if(this.watched) {
-      var val,editor;
-      for(var name in this.watched) {
-        if(!this.watched.hasOwnProperty(name)) continue;
-        editor = self.jsoneditor.getEditor(this.watched[name]);
-        val = editor? editor.getValue() : null;
-        if(self.watched_values[name] !== val) changed = true;
-        watched[name] = val;
-      }
-    }
-    
-    watched.self = this.getValue();
-    if(this.watched_values.self !== watched.self) changed = true;
-    
-    this.watched_values = watched;
-    
-    return changed;
-  },
-  getWatchedFieldValues: function() {
-    return this.watched_values;
-  },
-  updateHeaderText: function() {
-    if(this.header) {
-      // If the header has children, only update the text node's value
-      if(this.header.children.length) {
-        for(var i=0; i<this.header.childNodes.length; i++) {
-          if(this.header.childNodes[i].nodeType===3) {
-            this.header.childNodes[i].nodeValue = this.getHeaderText();
-            break;
-          }
-        }
-      }
-      // Otherwise, just update the entire node
-      else {
-        this.header.textContent = this.getHeaderText();
-      }
-    }
-  },
-  getHeaderText: function(title_only) {
-    if(this.header_text) return this.header_text;
-    else if(title_only) return this.schema.title;
-    else return this.getTitle();
-  },
-  onWatchedFieldChange: function() {
-    var vars;
-    if(this.header_template) {      
-      vars = $extend(this.getWatchedFieldValues(),{
-        key: this.key,
-        i: this.key,
-        i0: (this.key*1),
-        i1: (this.key*1+1),
-        title: this.getTitle()
-      });
-      var header_text = this.header_template(vars);
-      
-      if(header_text !== this.header_text) {
-        this.header_text = header_text;
-        this.updateHeaderText();
-        this.notify();
-        //this.fireChangeHeaderEvent();
-      }
-    }
-    if(this.link_watchers.length) {
-      vars = this.getWatchedFieldValues();
-      for(var i=0; i<this.link_watchers.length; i++) {
-        this.link_watchers[i](vars);
-      }
-    }
-  },
-  setValue: function(value) {
-    this.value = value;
-  },
-  getValue: function() {
-    if (!this.dependenciesFulfilled) {
-      return undefined;
-    }
-    return this.value;
-  },
-  refreshValue: function() {
-
-  },
-  getChildEditors: function() {
-    return false;
-  },
-  destroy: function() {
-    var self = this;
-    this.unregister(this);
-    $each(this.watched,function(name,adjusted_path) {
-      self.jsoneditor.unwatch(adjusted_path,self.watch_listener);
-    });
-    this.watched = null;
-    this.watched_values = null;
-    this.watch_listener = null;
-    this.header_text = null;
-    this.header_template = null;
-    this.value = null;
-    if(this.container && this.container.parentNode) this.container.parentNode.removeChild(this.container);
-    this.container = null;
-    this.jsoneditor = null;
-    this.schema = null;
-    this.path = null;
-    this.key = null;
-    this.parent = null;
-  },
-  getDefault: function() {
-    if (typeof this.schema["default"] !== 'undefined') {
-      return this.schema["default"];
-    }
-
-    if (typeof this.schema["enum"] !== 'undefined') {
-      return this.schema["enum"][0];
-    }
-    
-    var type = this.schema.type || this.schema.oneOf;
-    if(type && Array.isArray(type)) type = type[0];
-    if(type && typeof type === "object") type = type.type;
-    if(type && Array.isArray(type)) type = type[0];
-    
-    if(typeof type === "string") {
-      if(type === "number") return 0.0;
-      if(type === "boolean") return false;
-      if(type === "integer") return 0;
-      if(type === "string") return "";
-      if(type === "object") return {};
-      if(type === "array") return [];
-    }
-    
-    return null;
-  },
-  getTitle: function() {
-    return this.schema.title || this.key;
-  },
-  enable: function() {
-    this.disabled = false;
-  },
-  disable: function() {
-    this.disabled = true;
-  },
-  isEnabled: function() {
-    return !this.disabled;
-  },
-  isRequired: function() {
-    if(typeof this.schema.required === "boolean") return this.schema.required;
-    else if(this.parent && this.parent.schema && Array.isArray(this.parent.schema.required)) return this.parent.schema.required.indexOf(this.key) > -1;
-    else if(this.jsoneditor.options.required_by_default) return true;
-    else return false;
-  },  
-  getDisplayText: function(arr) {
-    var disp = [];
-    var used = {};
-    
-    // Determine how many times each attribute name is used.
-    // This helps us pick the most distinct display text for the schemas.
-    $each(arr,function(i,el) {
-      if(el.title) {
-        used[el.title] = used[el.title] || 0;
-        used[el.title]++;
-      }
-      if(el.description) {
-        used[el.description] = used[el.description] || 0;
-        used[el.description]++;
-      }
-      if(el.format) {
-        used[el.format] = used[el.format] || 0;
-        used[el.format]++;
-      }
-      if(el.type) {
-        used[el.type] = used[el.type] || 0;
-        used[el.type]++;
-      }
-    });
-    
-    // Determine display text for each element of the array
-    $each(arr,function(i,el)  {
-      var name;
-      
-      // If it's a simple string
-      if(typeof el === "string") name = el;
-      // Object
-      else if(el.title && used[el.title]<=1) name = el.title;
-      else if(el.format && used[el.format]<=1) name = el.format;
-      else if(el.type && used[el.type]<=1) name = el.type;
-      else if(el.description && used[el.description]<=1) name = el.descripton;
-      else if(el.title) name = el.title;
-      else if(el.format) name = el.format;
-      else if(el.type) name = el.type;
-      else if(el.description) name = el.description;
-      else if(JSON.stringify(el).length < 50) name = JSON.stringify(el);
-      else name = "type";
-      
-      disp.push(name);
-    });
-    
-    // Replace identical display text with "text 1", "text 2", etc.
-    var inc = {};
-    $each(disp,function(i,name) {
-      inc[name] = inc[name] || 0;
-      inc[name]++;
-      
-      if(used[name] > 1) disp[i] = name + " " + inc[name];
-    });
-    
-    return disp;
-  },
-  getOption: function(key) {
-    try {
-      throw "getOption is deprecated";
-    }
-    catch(e) {
-      window.console.error(e);
-    }
-    
-    return this.options[key];
-  },
-  showValidationErrors: function(errors) {
-
-  }
-});
-
-JSONEditor.defaults.editors["null"] = JSONEditor.AbstractEditor.extend({
-  getValue: function() {
-    if (!this.dependenciesFulfilled) {
-      return undefined;
-    }
-    return null;
-  },
-  setValue: function() {
-    this.onChange();
-  },
-  getNumColumns: function() {
-    return 2;
-  }
-});
-
-JSONEditor.defaults.editors.qbldr = JSONEditor.AbstractEditor.extend({
-  register: function() {
-       this._super();
-       if(!this.input) return;
-       this.input.setAttribute('name',this.formname);
-  },
-  unregister: function() {
-       this._super();
-       if(!this.input) return;
-       this.input.removeAttribute('name');
-  },
-  setValue: function(value, initial) {
-       var self = this;
-           
-       if(typeof value === "undefined" || typeof this.jqbldrId === "undefined" || value === this.value) {
-         return;
-       }
-
-    if ((initial === true) && (value !== "") && (value !== null)) {
-         $(this.jqbldrId).queryBuilder('off','rulesChanged');
-         $(this.jqbldrId).queryBuilder('setRulesFromSQL', value);
-         var filter_result = $(this.jqbldrId).queryBuilder('getSQL');
-         value = filter_result === null ? null : filter_result.sql;
-         $(this.jqbldrId).queryBuilder('on', 'rulesChanged', this.qbldrRulesChangedCb.bind(this));
-    }
-    
-       this.input.value = value;  
-       this.value = value;
-
-       // Bubble this setValue to parents if the value changed
-       this.onChange(true);
-  },
-  getValue: function() {
-       var self = this;
-
-       if (this.value === "" || this.value === null) { 
-         return undefined; 
-       } else { 
-         return this.value;
-       }
-  },
-  
-  getNumColumns: function() {   
-    return 12;
-  },
-  
-  qbldrRulesChangedCb: function(eventObj) {
-    var self = this;
-
-    $(this.jqbldrId).queryBuilder('off','rulesChanged');
-
-    var filter_result = $(this.jqbldrId).queryBuilder('getSQL');
-    
-    if (filter_result !== null) {
-       this.setValue(filter_result.sql);
-    }
-
-    $(this.jqbldrId).queryBuilder('on', 'rulesChanged', this.qbldrRulesChangedCb.bind(this));
-
-    return;
-  },
-  preBuild: function() {
-    var self = this;
-    this._super();
-  },
-  build: function() {
-    var self = this;
-    
-    this.qschema = this.schema.qschema;
-    this.qbldrId = this.path;
-    this.jqbldrId = '#' + this.qbldrId;
-    this.jqbldrId = this.jqbldrId.replace(/\./g,'\\.');
-
-    this.qgrid = this.theme.getGridContainer();
-    this.qgrid.style.padding = '4px';
-    this.qgrid.style.border = '1px solid #e3e3e3';
-
-    this.gridrow1 = this.theme.getGridRow();
-    this.gridrow1.style.padding = '4px';
-    
-    this.gridrow2 = this.theme.getGridRow();
-    this.gridrow2.style.padding = '4px';
-    
-    this.title = this.getTitle();
-    this.label = this.theme.getFormInputLabel(this.title);
-
-    this.input = this.theme.getTextareaInput();
-    this.input.disabled = 'true';
-
-    this.control = this.theme.getFormControl(this.label, this.input, this.description);
-    
-    this.gridrow2.setAttribute('id',this.qbldrId);
-    
-    this.container.appendChild(this.qgrid);  // attach the grid to container
-
-    this.qgrid.appendChild(this.gridrow1);   // attach gridrow1 to grid
-    this.gridrow1.appendChild(this.control); // attach control form to gridrow1
-    
-    this.qgrid.appendChild(this.gridrow2);
-    
-    var options = { conditions: [ 'AND', 'OR'], sort_filters: true };
-    
-    $.extend(this.qschema, options);
-    
-    $(this.jqbldrId).queryBuilder(this.qschema);
-    
-    //$(this.jqbldrId).queryBuilder('on', 'rulesChanged', this.qbldrRulesChangedCb.bind(this));
-    //$(this.jqbldrId).queryBuilder('on', 'afterUpdateRuleValue', this.qbldrRulesChangedCb.bind(this));
-    $(this.jqbldrId).queryBuilder('on', 'rulesChanged', this.qbldrRulesChangedCb.bind(this));
-  },
-  enable: function() {
-    this._super();
-  },
-  disable: function() {
-    this._super();
-  },
-  afterInputReady: function() {
-    var self = this, options;
-    self.theme.afterInputReady(self.input);
-  },
-  refreshValue: function() {
-    this.value = this.input.value;
-    if(typeof this.value !== "string") this.value = '';
-  },
-  destroy: function() {
-       var self = this;
-    this._super();
-  },
-  /**
-   * This is overridden in derivative editors
-   */
-  sanitize: function(value) {
-    return value;
-  },
-  /**
-   * Re-calculates the value if needed
-   */
-  onWatchedFieldChange: function() {    
-    var self = this, vars, j;
-    
-    this._super();
-  },
-  showValidationErrors: function(errors) {
-    var self = this;
-
-    if(this.jsoneditor.options.show_errors === "always") {}
-    else if(this.previous_error_setting===this.jsoneditor.options.show_errors) return;
-    
-    this.previous_error_setting = this.jsoneditor.options.show_errors;
-
-    var messages = [];
-    $each(errors,function(i,error) {
-      if(error.path === self.path) {
-        messages.push(error.message);
-      }
-    });
-
-    this.input.controlgroup = this.control;
-
-    if(messages.length) {
-      this.theme.addInputError(this.input, messages.join('. ')+'.');
-    }
-    else {
-      this.theme.removeInputError(this.input);
-    }
-  }
-});
-
-JSONEditor.defaults.editors.string = JSONEditor.AbstractEditor.extend({
-  register: function() {
-    this._super();
-    if(!this.input) return;
-    this.input.setAttribute('name',this.formname);
-  },
-  unregister: function() {
-    this._super();
-    if(!this.input) return;
-    this.input.removeAttribute('name');
-  },
-  setValue: function(value,initial,from_template) {
-    var self = this;
-    
-    if(this.template && !from_template) {
-      return;
-    }
-    
-    if(value === null || typeof value === 'undefined') value = "";
-    else if(typeof value === "object") value = JSON.stringify(value);
-    else if(typeof value !== "string") value = ""+value;
-    
-    if(value === this.serialized) return;
-
-    // Sanitize value before setting it
-    var sanitized = this.sanitize(value);
-
-    if(this.input.value === sanitized) {
-      return;
-    }
-
-    this.input.value = sanitized;
-    
-    // If using SCEditor, update the WYSIWYG
-    if(this.sceditor_instance) {
-      this.sceditor_instance.val(sanitized);
-    }
-    else if(this.SimpleMDE) {
-      this.SimpleMDE.value(sanitized);
-    }
-    else if(this.ace_editor) {
-      this.ace_editor.setValue(sanitized);
-    }
-    
-    var changed = from_template || this.getValue() !== value;
-    
-    this.refreshValue();
-    
-    if(initial) this.is_dirty = false;
-    else if(this.jsoneditor.options.show_errors === "change") this.is_dirty = true;
-    
-    if(this.adjust_height) this.adjust_height(this.input);
-
-    // Bubble this setValue to parents if the value changed
-    this.onChange(changed);
-  },
-  getNumColumns: function() {
-    var min = Math.ceil(Math.max(this.getTitle().length,this.schema.maxLength||0,this.schema.minLength||0)/5);
-    var num;
-    
-    if(this.input_type === 'textarea') num = 6;
-    else if(['text','email'].indexOf(this.input_type) >= 0) num = 4;
-    else num = 2;
-    
-    return Math.min(12,Math.max(min,num));
-  },
-  build: function() {
-    var self = this, i;
-    if(!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
-    if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);
-    if(this.options.infoText) this.infoButton = this.theme.getInfoButton(this.options.infoText);
-
-    this.format = this.schema.format;
-    if(!this.format && this.schema.media && this.schema.media.type) {
-      this.format = this.schema.media.type.replace(/(^(application|text)\/(x-)?(script\.)?)|(-source$)/g,'');
-    }
-    if(!this.format && this.options.default_format) {
-      this.format = this.options.default_format;
-    }
-    if(this.options.format) {
-      this.format = this.options.format;
-    }
-
-    // Specific format
-    if(this.format) {
-      // Text Area
-      if(this.format === 'textarea') {
-        this.input_type = 'textarea';
-        this.input = this.theme.getTextareaInput();
-      }
-      // Range Input
-      else if(this.format === 'range') {
-        this.input_type = 'range';
-        var min = this.schema.minimum || 0;
-        var max = this.schema.maximum || Math.max(100,min+1);
-        var step = 1;
-        if(this.schema.multipleOf) {
-          if(min%this.schema.multipleOf) min = Math.ceil(min/this.schema.multipleOf)*this.schema.multipleOf;
-          if(max%this.schema.multipleOf) max = Math.floor(max/this.schema.multipleOf)*this.schema.multipleOf;
-          step = this.schema.multipleOf;
-        }
-
-        this.input = this.theme.getRangeInput(min,max,step);
-      }
-      // Source Code
-      else if([
-          'actionscript',
-          'batchfile',
-          'bbcode',
-          'c',
-          'c++',
-          'cpp',
-          'coffee',
-          'csharp',
-          'css',
-          'dart',
-          'django',
-          'ejs',
-          'erlang',
-          'golang',
-          'groovy',
-          'handlebars',
-          'haskell',
-          'haxe',
-          'html',
-          'ini',
-          'jade',
-          'java',
-          'javascript',
-          'json',
-          'less',
-          'lisp',
-          'lua',
-          'makefile',
-          'markdown',
-          'matlab',
-          'mysql',
-          'objectivec',
-          'pascal',
-          'perl',
-          'pgsql',
-          'php',
-          'python',
-          'r',
-          'ruby',
-          'sass',
-          'scala',
-          'scss',
-          'smarty',
-          'sql',
-          'stylus',
-          'svg',
-          'twig',
-          'vbscript',
-          'xml',
-          'yaml'
-        ].indexOf(this.format) >= 0
-      ) {
-        this.input_type = this.format;
-        this.source_code = true;
-        
-        this.input = this.theme.getTextareaInput();
-      }
-      // HTML5 Input type
-      else {
-        this.input_type = this.format;
-        this.input = this.theme.getFormInputField(this.input_type);
-      }
-    }
-    // Normal text input
-    else {
-      this.input_type = 'text';
-      this.input = this.theme.getFormInputField(this.input_type);
-    }
-    
-    // minLength, maxLength, and pattern
-    if(typeof this.schema.maxLength !== "undefined") this.input.setAttribute('maxlength',this.schema.maxLength);
-    if(typeof this.schema.pattern !== "undefined") this.input.setAttribute('pattern',this.schema.pattern);
-    else if(typeof this.schema.minLength !== "undefined") this.input.setAttribute('pattern','.{'+this.schema.minLength+',}');
-
-    if(this.options.compact) {
-      this.container.className += ' compact';
-    }
-    else {
-      if(this.options.input_width) this.input.style.width = this.options.input_width;
-    }
-
-    if(this.schema.readOnly || this.schema.readonly || this.schema.template) {
-      this.always_disabled = true;
-      this.input.disabled = true;
-    }
-
-    this.input
-      .addEventListener('change',function(e) {        
-        e.preventDefault();
-        e.stopPropagation();
-        
-        // Don't allow changing if this field is a template
-        if(self.schema.template) {
-          this.value = self.value;
-          return;
-        }
-
-        var val = this.value;
-        
-        // sanitize value
-        var sanitized = self.sanitize(val);
-        if(val !== sanitized) {
-          this.value = sanitized;
-        }
-        
-        self.is_dirty = true;
-
-        self.refreshValue();
-        self.onChange(true);
-      });
-      
-    if(this.options.input_height) this.input.style.height = this.options.input_height;
-    if(this.options.expand_height) {
-      this.adjust_height = function(el) {
-        if(!el) return;
-        var i, ch=el.offsetHeight;
-        // Input too short
-        if(el.offsetHeight < el.scrollHeight) {
-          i=0;
-          while(el.offsetHeight < el.scrollHeight+3) {
-            if(i>100) break;
-            i++;
-            ch++;
-            el.style.height = ch+'px';
-          }
-        }
-        else {
-          i=0;
-          while(el.offsetHeight >= el.scrollHeight+3) {
-            if(i>100) break;
-            i++;
-            ch--;
-            el.style.height = ch+'px';
-          }
-          el.style.height = (ch+1)+'px';
-        }
-      };
-      
-      this.input.addEventListener('keyup',function(e) {
-        self.adjust_height(this);
-      });
-      this.input.addEventListener('change',function(e) {
-        self.adjust_height(this);
-      });
-      this.adjust_height();
-    }
-
-    if(this.format) this.input.setAttribute('data-schemaformat',this.format);
-
-    this.control = this.theme.getFormControl(this.label, this.input, this.description, this.infoButton);
-    this.container.appendChild(this.control);
-
-    // Any special formatting that needs to happen after the input is added to the dom
-    window.requestAnimationFrame(function() {
-      // Skip in case the input is only a temporary editor,
-      // otherwise, in the case of an ace_editor creation,
-      // it will generate an error trying to append it to the missing parentNode
-      if(self.input.parentNode) self.afterInputReady();
-      if(self.adjust_height) self.adjust_height(self.input);
-    });
-
-    // Compile and store the template
-    if(this.schema.template) {
-      this.template = this.jsoneditor.compileTemplate(this.schema.template, this.template_engine);
-      this.refreshValue();
-    }
-    else {
-      this.refreshValue();
-    }
-  },
-  enable: function() {
-    if(!this.always_disabled) {
-      this.input.disabled = false;
-      // TODO: WYSIWYG and Markdown editors
-      this._super();
-    }
-  },
-  disable: function(always_disabled) {
-    if(always_disabled) this.always_disabled = true;
-    this.input.disabled = true;
-    // TODO: WYSIWYG and Markdown editors
-    this._super();
-  },
-  afterInputReady: function() {
-    var self = this, options;
-    
-    // Code editor
-    if(this.source_code) {      
-      // WYSIWYG html and bbcode editor
-      if(this.options.wysiwyg && 
-        ['html','bbcode'].indexOf(this.input_type) >= 0 && 
-        window.jQuery && window.jQuery.fn && window.jQuery.fn.sceditor
-      ) {
-        options = $extend({},{
-          plugins: self.input_type==='html'? 'xhtml' : 'bbcode',
-          emoticonsEnabled: false,
-          width: '100%',
-          height: 300
-        },JSONEditor.plugins.sceditor,self.options.sceditor_options||{});
-        
-        window.jQuery(self.input).sceditor(options);
-        
-        self.sceditor_instance = window.jQuery(self.input).sceditor('instance');
-        
-        self.sceditor_instance.blur(function() {
-          // Get editor's value
-          var val = window.jQuery("<div>"+self.sceditor_instance.val()+"</div>");
-          // Remove sceditor spans/divs
-          window.jQuery('#sceditor-start-marker,#sceditor-end-marker,.sceditor-nlf',val).remove();
-          // Set the value and update
-          self.input.value = val.html();
-          self.value = self.input.value;
-          self.is_dirty = true;
-          self.onChange(true);
-        });
-      }
-      // SimpleMDE for markdown (if it's loaded)
-      else if (this.input_type === 'markdown' && window.SimpleMDE) {
-        options = $extend({},JSONEditor.plugins.SimpleMDE,{
-          element: this.input
-        });
-
-        this.SimpleMDE = new window.SimpleMDE((options));
-
-        this.SimpleMDE.codemirror.on("change",function() {
-          self.value = self.SimpleMDE.value();
-          self.is_dirty = true;
-          self.onChange(true);
-        });
-      }
-      // ACE editor for everything else
-      else if(window.ace) {
-        var mode = this.input_type;
-        // aliases for c/cpp
-        if(mode === 'cpp' || mode === 'c++' || mode === 'c') {
-          mode = 'c_cpp';
-        }
-        
-        this.ace_container = document.createElement('div');
-        this.ace_container.style.width = '100%';
-        this.ace_container.style.position = 'relative';
-        this.ace_container.style.height = '400px';
-        this.input.parentNode.insertBefore(this.ace_container,this.input);
-        this.input.style.display = 'none';
-        this.ace_editor = window.ace.edit(this.ace_container);
-        
-        this.ace_editor.setValue(this.getValue());
-
-        // The theme
-        if(JSONEditor.plugins.ace.theme) this.ace_editor.setTheme('ace/theme/'+JSONEditor.plugins.ace.theme);
-        // The mode
-        this.ace_editor.getSession().setMode('ace/mode/' + this.schema.format);
-
-        // Listen for changes
-        this.ace_editor.on('change',function() {
-          var val = self.ace_editor.getValue();
-          self.input.value = val;
-          self.refreshValue();
-          self.is_dirty = true;
-          self.onChange(true);
-        });
-      }
-    }
-    
-    self.theme.afterInputReady(self.input);
-  },
-  refreshValue: function() {
-    this.value = this.input.value;
-    if(typeof this.value !== "string") this.value = '';
-    this.serialized = this.value;
-  },
-  destroy: function() {
-    // If using SCEditor, destroy the editor instance
-    if(this.sceditor_instance) {
-      this.sceditor_instance.destroy();
-    }
-    else if(this.SimpleMDE) {
-      this.SimpleMDE.destroy();
-    }
-    else if(this.ace_editor) {
-      this.ace_editor.destroy();
-    }
-    
-    
-    this.template = null;
-    if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);
-    if(this.label && this.label.parentNode) this.label.parentNode.removeChild(this.label);
-    if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);
-
-    this._super();
-  },
-  /**
-   * This is overridden in derivative editors
-   */
-  sanitize: function(value) {
-    return value;
-  },
-  /**
-   * Re-calculates the value if needed
-   */
-  onWatchedFieldChange: function() {    
-    var self = this, vars, j;
-    
-    // If this editor needs to be rendered by a macro template
-    if(this.template) {
-      vars = this.getWatchedFieldValues();
-      this.setValue(this.template(vars),false,true);
-    }
-    
-    this._super();
-  },
-  showValidationErrors: function(errors) {
-    var self = this;
-    
-    if(this.jsoneditor.options.show_errors === "always") {}
-    else if(!this.is_dirty && this.previous_error_setting===this.jsoneditor.options.show_errors) return;
-    
-    this.previous_error_setting = this.jsoneditor.options.show_errors;
-
-    var messages = [];
-    $each(errors,function(i,error) {
-      if(error.path === self.path) {
-        messages.push(error.message);
-      }
-    });
-
-    this.input.controlgroup = this.control;
-    
-    if(messages.length) {
-      this.theme.addInputError(this.input, messages.join('. ')+'.');
-    }
-    else {
-      this.theme.removeInputError(this.input);
-    }
-  }
-});
-
-/**
- * Created by Mehmet Baker on 12.04.2017
- */
-JSONEditor.defaults.editors.hidden = JSONEditor.AbstractEditor.extend({
-  register: function () {
-    this._super();
-    if (!this.input) return;
-    this.input.setAttribute('name', this.formname);
-  },
-  unregister: function () {
-    this._super();
-    if (!this.input) return;
-    this.input.removeAttribute('name');
-  },
-  setValue: function (value, initial, from_template) {
-    var self = this;
-
-    if(this.template && !from_template) {
-      return;
-    }
-
-    if(value === null || typeof value === 'undefined') value = "";
-    else if(typeof value === "object") value = JSON.stringify(value);
-    else if(typeof value !== "string") value = ""+value;
-
-    if(value === this.serialized) return;
-
-    // Sanitize value before setting it
-    var sanitized = this.sanitize(value);
-
-    if(this.input.value === sanitized) {
-      return;
-    }
-
-    this.input.value = sanitized;
-
-    var changed = from_template || this.getValue() !== value;
-
-    this.refreshValue();
-
-    if(initial) this.is_dirty = false;
-    else if(this.jsoneditor.options.show_errors === "change") this.is_dirty = true;
-
-    if(this.adjust_height) this.adjust_height(this.input);
-
-    // Bubble this setValue to parents if the value changed
-    this.onChange(changed);
-  },
-  getNumColumns: function () {
-    return 2;
-  },
-  enable: function () {
-    this._super();
-  },
-  disable: function () {
-    this._super();
-  },
-  refreshValue: function () {
-    this.value = this.input.value;
-    if (typeof this.value !== "string") this.value = '';
-    this.serialized = this.value;
-  },
-  destroy: function () {
-    this.template = null;
-    if (this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);
-    if (this.label && this.label.parentNode) this.label.parentNode.removeChild(this.label);
-    if (this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);
-
-    this._super();
-  },
-  /**
-   * This is overridden in derivative editors
-   */
-  sanitize: function (value) {
-    return value;
-  },
-  /**
-   * Re-calculates the value if needed
-   */
-  onWatchedFieldChange: function () {
-    var self = this, vars, j;
-
-    // If this editor needs to be rendered by a macro template
-    if (this.template) {
-      vars = this.getWatchedFieldValues();
-      this.setValue(this.template(vars), false, true);
-    }
-
-    this._super();
-  },
-  build: function () {
-    var self = this;
-
-    this.format = this.schema.format;
-    if (!this.format && this.options.default_format) {
-      this.format = this.options.default_format;
-    }
-    if (this.options.format) {
-      this.format = this.options.format;
-    }
-
-    this.input_type = 'hidden';
-    this.input = this.theme.getFormInputField(this.input_type);
-
-    if (this.format) this.input.setAttribute('data-schemaformat', this.format);
-
-    this.container.appendChild(this.input);
-
-    // Compile and store the template
-    if (this.schema.template) {
-      this.template = this.jsoneditor.compileTemplate(this.schema.template, this.template_engine);
-      this.refreshValue();
-    }
-    else {
-      this.refreshValue();
-    }
-  }
-});
-JSONEditor.defaults.editors.number = JSONEditor.defaults.editors.string.extend({
-  build: function() {
-    this._super();
-
-    if (typeof this.schema.minimum !== "undefined") {
-      var minimum = this.schema.minimum;
-
-      if (typeof this.schema.exclusiveMinimum !== "undefined") {
-        minimum += 1;
-      }
-
-      this.input.setAttribute("min", minimum);
-    }
-
-    if (typeof this.schema.maximum !== "undefined") {
-      var maximum = this.schema.maximum;
-
-      if (typeof this.schema.exclusiveMaximum !== "undefined") {
-        maximum -= 1;
-      }
-
-      this.input.setAttribute("max", maximum);
-    }
-
-    if (typeof this.schema.step !== "undefined") {
-      var step = this.schema.step || 1;
-      this.input.setAttribute("step", step);
-    }
-
-  },
-  sanitize: function(value) {
-    return (value+"").replace(/[^0-9\.\-eE]/g,'');
-  },
-  getNumColumns: function() {
-    return 2;
-  },
-  getValue: function() {
-    if (!this.dependenciesFulfilled) {
-      return undefined;
-    }
-    return this.value===''?undefined:this.value*1;
-  }
-});
-
-JSONEditor.defaults.editors.integer = JSONEditor.defaults.editors.number.extend({
-  sanitize: function(value) {
-    value = value + "";
-    return value.replace(/[^0-9\-]/g,'');
-  },
-  getNumColumns: function() {
-    return 2;
-  }
-});
-
-JSONEditor.defaults.editors.rating = JSONEditor.defaults.editors.integer.extend({
-  build: function() {
-    var self = this, i;
-    if(!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
-    if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);
-
-    // Dynamically add the required CSS the first time this editor is used
-    var styleId = 'json-editor-style-rating';
-    var styles = document.getElementById(styleId);
-    if (!styles) {
-      var style = document.createElement('style');
-      style.id = styleId;
-      style.type = 'text/css';
-      style.innerHTML =
-        '      .rating-container {' +
-        '        display: inline-block;' +
-        '        clear: both;' +
-        '      }' +
-        '      ' +
-        '      .rating {' +
-        '        float:left;' +
-        '      }' +
-        '      ' +
-        '      /* :not(:checked) is a filter, so that browsers that don’t support :checked don’t' +
-        '         follow these rules. Every browser that supports :checked also supports :not(), so' +
-        '         it doesn’t make the test unnecessarily selective */' +
-        '      .rating:not(:checked) > input {' +
-        '        position:absolute;' +
-        '        top:-9999px;' +
-        '        clip:rect(0,0,0,0);' +
-        '      }' +
-        '      ' +
-        '      .rating:not(:checked) > label {' +
-        '        float:right;' +
-        '        width:1em;' +
-        '        padding:0 .1em;' +
-        '        overflow:hidden;' +
-        '        white-space:nowrap;' +
-        '        cursor:pointer;' +
-        '        color:#ddd;' +
-        '      }' +
-        '      ' +
-        '      .rating:not(:checked) > label:before {' +
-        '        content: \'★ \';' +
-        '      }' +
-        '      ' +
-        '      .rating > input:checked ~ label {' +
-        '        color: #FFB200;' +
-        '      }' +
-        '      ' +
-        '      .rating:not([readOnly]):not(:checked) > label:hover,' +
-        '      .rating:not([readOnly]):not(:checked) > label:hover ~ label {' +
-        '        color: #FFDA00;' +
-        '      }' +
-        '      ' +
-        '      .rating:not([readOnly]) > input:checked + label:hover,' +
-        '      .rating:not([readOnly]) > input:checked + label:hover ~ label,' +
-        '      .rating:not([readOnly]) > input:checked ~ label:hover,' +
-        '      .rating:not([readOnly]) > input:checked ~ label:hover ~ label,' +
-        '      .rating:not([readOnly]) > label:hover ~ input:checked ~ label {' +
-        '        color: #FF8C0D;' +
-        '      }' +
-        '      ' +
-        '      .rating:not([readOnly])  > label:active {' +
-        '        position:relative;' +
-        '        top:2px;' +
-        '        left:2px;' +
-        '      }';
-      document.getElementsByTagName('head')[0].appendChild(style);
-    }
-
-    this.input = this.theme.getFormInputField('hidden');
-    this.container.appendChild(this.input);
-
-    // Required to keep height
-    var ratingContainer = document.createElement('div');
-    ratingContainer.className = 'rating-container';
-
-    // Contains options for rating
-    var group = document.createElement('div');
-    group.setAttribute('name', this.formname);
-    group.className = 'rating';
-    ratingContainer.appendChild(group);
-
-    if(this.options.compact) this.container.setAttribute('class',this.container.getAttribute('class')+' compact');
-
-    var max = this.schema.maximum ? this.schema.maximum : 5;
-    if (this.schema.exclusiveMaximum) max--;
-
-    this.inputs = [];
-    for(i=max; i>0; i--) {
-      var id = this.formname + i;
-      var radioInput = this.theme.getFormInputField('radio');
-      radioInput.setAttribute('id', id);
-      radioInput.setAttribute('value', i);
-      radioInput.setAttribute('name', this.formname);
-      group.appendChild(radioInput);
-      this.inputs.push(radioInput);
-
-      var label = document.createElement('label');
-      label.setAttribute('for', id);
-      label.appendChild(document.createTextNode(i + (i == 1 ? ' star' : ' stars')));
-      group.appendChild(label);
-    }
-
-    if(this.schema.readOnly || this.schema.readonly) {
-      this.always_disabled = true;
-      $each(this.inputs,function(i,input) {
-        group.setAttribute("readOnly", "readOnly");
-        input.disabled = true;
-      });
-    }
-
-    ratingContainer
-      .addEventListener('change',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-
-        self.input.value = e.srcElement.value;
-
-        self.is_dirty = true;
-
-        self.refreshValue();
-        self.watch_listener();
-        self.jsoneditor.notifyWatchers(self.path);
-        if(self.parent) self.parent.onChildEditorChange(self);
-        else self.jsoneditor.onChange();
-      });
-
-    this.control = this.theme.getFormControl(this.label, ratingContainer, this.description);
-    this.container.appendChild(this.control);
-
-    this.refreshValue();
-  },
-  setValue: function(val) {
-    var sanitized = this.sanitize(val);
-    if(this.value === sanitized) {
-      return;
-    }
-    var self = this;
-    $each(this.inputs,function(i,input) {
-      if (input.value === sanitized) {
-        input.checked = true;
-        self.value = sanitized;
-        self.input.value = self.value;
-        self.watch_listener();
-        self.jsoneditor.notifyWatchers(self.path);
-        return false;
-      }
-    });
-  }
-});
-
-JSONEditor.defaults.editors.object = JSONEditor.AbstractEditor.extend({
-  getDefault: function() {
-    return $extend({},this.schema["default"] || {});
-  },
-  getChildEditors: function() {
-    return this.editors;
-  },
-  register: function() {
-    this._super();
-    if(this.editors) {
-      for(var i in this.editors) {
-        if(!this.editors.hasOwnProperty(i)) continue;
-        this.editors[i].register();
-      }
-    }
-  },
-  unregister: function() {
-    this._super();
-    if(this.editors) {
-      for(var i in this.editors) {
-        if(!this.editors.hasOwnProperty(i)) continue;
-        this.editors[i].unregister();
-      }
-    }
-  },
-  getNumColumns: function() {
-    return Math.max(Math.min(12,this.maxwidth),3);
-  },
-  enable: function() {
-    if(!this.always_disabled) {
-      if(this.editjson_button) this.editjson_button.disabled = false;
-      if(this.addproperty_button) this.addproperty_button.disabled = false;
-
-      this._super();
-      if(this.editors) {
-        for(var i in this.editors) {
-          if(!this.editors.hasOwnProperty(i)) continue;
-          this.editors[i].enable();
-        }
-      }
-    }
-  },
-  disable: function(always_disabled) {
-    if(always_disabled) this.always_disabled = true;
-    if(this.editjson_button) this.editjson_button.disabled = true;
-    if(this.addproperty_button) this.addproperty_button.disabled = true;
-    this.hideEditJSON();
-
-    this._super();
-    if(this.editors) {
-      for(var i in this.editors) {
-        if(!this.editors.hasOwnProperty(i)) continue;
-        this.editors[i].disable(always_disabled);
-      }
-    }
-  },
-  layoutEditors: function() {
-    var self = this, i, j;
-
-    if(!this.row_container) return;
-
-    // Sort editors by propertyOrder
-    this.property_order = Object.keys(this.editors);
-    this.property_order = this.property_order.sort(function(a,b) {
-      var ordera = self.editors[a].schema.propertyOrder;
-      var orderb = self.editors[b].schema.propertyOrder;
-      if(typeof ordera !== "number") ordera = 1000;
-      if(typeof orderb !== "number") orderb = 1000;
-
-      return ordera - orderb;
-    });
-
-    var container = document.createElement('div');
-    var isCategoriesFormat = (this.format === 'categories');
-
-    if(this.format === 'grid') {
-      var rows = [];
-      $each(this.property_order, function(j,key) {
-        var editor = self.editors[key];
-        if(editor.property_removed) return;
-        var found = false;
-        var width = editor.options.hidden? 0 : (editor.options.grid_columns || editor.getNumColumns());
-        var height = editor.options.hidden? 0 : editor.container.offsetHeight;
-        // See if the editor will fit in any of the existing rows first
-        for(var i=0; i<rows.length; i++) {
-          // If the editor will fit in the row horizontally
-          if(rows[i].width + width <= 12) {
-            // If the editor is close to the other elements in height
-            // i.e. Don't put a really tall editor in an otherwise short row or vice versa
-            if(!height || (rows[i].minh*0.5 < height && rows[i].maxh*2 > height)) {
-              found = i;
-            }
-          }
-        }
-
-        // If there isn't a spot in any of the existing rows, start a new row
-        if(found === false) {
-          rows.push({
-            width: 0,
-            minh: 999999,
-            maxh: 0,
-            editors: []
-          });
-          found = rows.length-1;
-        }
-
-        rows[found].editors.push({
-          key: key,
-          //editor: editor,
-          width: width,
-          height: height
-        });
-        rows[found].width += width;
-        rows[found].minh = Math.min(rows[found].minh,height);
-        rows[found].maxh = Math.max(rows[found].maxh,height);
-      });
-
-      // Make almost full rows width 12
-      // Do this by increasing all editors' sizes proprotionately
-      // Any left over space goes to the biggest editor
-      // Don't touch rows with a width of 6 or less
-      for(i=0; i<rows.length; i++) {
-        if(rows[i].width < 12) {
-          var biggest = false;
-          var new_width = 0;
-          for(j=0; j<rows[i].editors.length; j++) {
-            if(biggest === false) biggest = j;
-            else if(rows[i].editors[j].width > rows[i].editors[biggest].width) biggest = j;
-            rows[i].editors[j].width *= 12/rows[i].width;
-            rows[i].editors[j].width = Math.floor(rows[i].editors[j].width);
-            new_width += rows[i].editors[j].width;
-          }
-          if(new_width < 12) rows[i].editors[biggest].width += 12-new_width;
-          rows[i].width = 12;
-        }
-      }
-
-      // layout hasn't changed
-      if(this.layout === JSON.stringify(rows)) return false;
-      this.layout = JSON.stringify(rows);
-
-      // Layout the form
-      for(i=0; i<rows.length; i++) {
-        var row = this.theme.getGridRow();
-        container.appendChild(row);
-        for(j=0; j<rows[i].editors.length; j++) {
-          var key = rows[i].editors[j].key;
-          var editor = this.editors[key];
-
-          if(editor.options.hidden) editor.container.style.display = 'none';
-          else this.theme.setGridColumnSize(editor.container,rows[i].editors[j].width);
-          row.appendChild(editor.container);
-        }
-      }
-    }
-    // Normal layout
-    else if(isCategoriesFormat) {
-      //A container for properties not object nor arrays
-      var containerSimple = document.createElement('div');
-      //This will be the place to (re)build tabs and panes
-      //tabs_holder has 2 childs, [0]: ul.nav.nav-tabs and [1]: div.tab-content
-      var newTabs_holder = this.theme.getTopTabHolder(this.schema.title);
-      //child [1] of previous, stores panes
-      var newTabPanesContainer = this.theme.getTopTabContentHolder(newTabs_holder);
-
-      $each(this.property_order, function(i,key){
-        var editor = self.editors[key];
-        if(editor.property_removed) return;
-        var aPane = self.theme.getTabContent();
-        var isObjOrArray = editor.schema && (editor.schema.type === "object" || editor.schema.type === "array");
-        //mark the pane
-        aPane.isObjOrArray = isObjOrArray;
-        var gridRow = self.theme.getGridRow();
-
-        //this happens with added properties, they don't have a tab
-        if(!editor.tab){
-          //Pass the pane which holds the editor
-          if(typeof self.basicPane === 'undefined'){
-            //There is no basicPane yet, so aPane will be it
-            self.addRow(editor,newTabs_holder, aPane);
-          }
-          else {
-            self.addRow(editor,newTabs_holder, self.basicPane);
-          }
-        }
-
-        aPane.id = editor.tab_text.textContent;
-
-        //For simple properties, add them on the same panel (Basic)
-        if(!isObjOrArray){
-          containerSimple.appendChild(gridRow);
-          //There is already some panes
-          if(newTabPanesContainer.childElementCount > 0){
-            //If first pane is object or array, insert before a simple pane
-            if(newTabPanesContainer.firstChild.isObjOrArray){
-              //Append pane for simple properties
-              aPane.appendChild(containerSimple);
-              newTabPanesContainer.insertBefore(aPane,newTabPanesContainer.firstChild);
-              //Add "Basic" tab
-              self.theme.insertBasicTopTab(editor.tab,newTabs_holder);
-              //newTabs_holder.firstChild.insertBefore(editor.tab,newTabs_holder.firstChild.firstChild);
-              //Update the basicPane
-              editor.basicPane = aPane;
-            }
-            else {
-              //We already have a first "Basic" pane, just add the new property to it, so
-              //do nothing;
-            }
-          }
-          //There is no pane, so add the first (simple) pane
-          else {
-            //Append pane for simple properties
-            aPane.appendChild(containerSimple);
-            newTabPanesContainer.appendChild(aPane);
-            //Add "Basic" tab
-            //newTabs_holder.firstChild.appendChild(editor.tab);
-            self.theme.addTopTab(newTabs_holder,editor.tab);
-            //Update the basicPane
-            editor.basicPane = aPane;
-          }
-        }
-        //Objects and arrays earn it's own panes
-        else {
-          aPane.appendChild(gridRow);
-          newTabPanesContainer.appendChild(aPane);
-          //newTabs_holder.firstChild.appendChild(editor.tab);
-          self.theme.addTopTab(newTabs_holder,editor.tab);
-        }
-
-        if(editor.options.hidden) editor.container.style.display = 'none';
-        else self.theme.setGridColumnSize(editor.container,12);
-        //Now, add the property editor to the row
-        gridRow.appendChild(editor.container);
-        //Update the container (same as self.rows[x].container)
-        editor.container = aPane;
-
-      });
-
-      //Erase old panes
-      while (this.tabPanesContainer.firstChild) {
-        this.tabPanesContainer.removeChild(this.tabPanesContainer.firstChild);
-      }
-
-      //Erase old tabs and set the new ones
-      var parentTabs_holder = this.tabs_holder.parentNode;
-      parentTabs_holder.removeChild(parentTabs_holder.firstChild);
-      parentTabs_holder.appendChild(newTabs_holder);
-
-      this.tabPanesContainer = newTabPanesContainer;
-      this.tabs_holder = newTabs_holder;
-
-      //Activate the first tab
-      var firstTab = this.theme.getFirstTab(this.tabs_holder);
-      if(firstTab){
-        $trigger(firstTab,'click');
-      }
-      return;
-    }
-    // !isCategoriesFormat
-    else {
-      $each(this.property_order, function(i,key) {
-        var editor = self.editors[key];
-        if(editor.property_removed) return;
-        var row = self.theme.getGridRow();
-        container.appendChild(row);
-
-        if(editor.options.hidden) editor.container.style.display = 'none';
-        else self.theme.setGridColumnSize(editor.container,12);
-        row.appendChild(editor.container);
-      });
-    }
-    //for grid and normal layout
-    while (this.row_container.firstChild) {
-      this.row_container.removeChild(this.row_container.firstChild);
-    }
-    this.row_container.appendChild(container);
-  },
-  getPropertySchema: function(key) {
-    // Schema declared directly in properties
-    var schema = this.schema.properties[key] || {};
-    schema = $extend({},schema);
-    var matched = this.schema.properties[key]? true : false;
-
-    // Any matching patternProperties should be merged in
-    if(this.schema.patternProperties) {
-      for(var i in this.schema.patternProperties) {
-        if(!this.schema.patternProperties.hasOwnProperty(i)) continue;
-        var regex = new RegExp(i);
-        if(regex.test(key)) {
-          schema.allOf = schema.allOf || [];
-          schema.allOf.push(this.schema.patternProperties[i]);
-          matched = true;
-        }
-      }
-    }
-
-    // Hasn't matched other rules, use additionalProperties schema
-    if(!matched && this.schema.additionalProperties && typeof this.schema.additionalProperties === "object") {
-      schema = $extend({},this.schema.additionalProperties);
-    }
-
-    return schema;
-  },
-  preBuild: function() {
-    this._super();
-
-    this.editors = {};
-    this.cached_editors = {};
-    var self = this;
-
-    this.format = this.options.layout || this.options.object_layout || this.schema.format || this.jsoneditor.options.object_layout || 'normal';
-
-    this.schema.properties = this.schema.properties || {};
-
-    this.minwidth = 0;
-    this.maxwidth = 0;
-
-    // If the object should be rendered as a table row
-    if(this.options.table_row) {
-      $each(this.schema.properties, function(key,schema) {
-        var editor = self.jsoneditor.getEditorClass(schema);
-        self.editors[key] = self.jsoneditor.createEditor(editor,{
-          jsoneditor: self.jsoneditor,
-          schema: schema,
-          path: self.path+'.'+key,
-          parent: self,
-          compact: true,
-          required: true
-        });
-        self.editors[key].preBuild();
-
-        var width = self.editors[key].options.hidden? 0 : (self.editors[key].options.grid_columns || self.editors[key].getNumColumns());
-
-        self.minwidth += width;
-        self.maxwidth += width;
-      });
-      this.no_link_holder = true;
-    }
-    // If the object should be rendered as a table
-    else if(this.options.table) {
-      // TODO: table display format
-      throw "Not supported yet";
-    }
-    // If the object should be rendered as a div
-    else {
-      if(!this.schema.defaultProperties) {
-        if(this.jsoneditor.options.display_required_only || this.options.display_required_only) {
-          this.schema.defaultProperties = [];
-          $each(this.schema.properties, function(k,s) {
-            if(self.isRequired({key: k, schema: s})) {
-              self.schema.defaultProperties.push(k);
-            }
-          });
-        }
-        else {
-          self.schema.defaultProperties = Object.keys(self.schema.properties);
-        }
-      }
-
-      // Increase the grid width to account for padding
-      self.maxwidth += 1;
-
-      $each(this.schema.defaultProperties, function(i,key) {
-        self.addObjectProperty(key, true);
-
-        if(self.editors[key]) {
-          self.minwidth = Math.max(self.minwidth,(self.editors[key].options.grid_columns || self.editors[key].getNumColumns()));
-          self.maxwidth += (self.editors[key].options.grid_columns || self.editors[key].getNumColumns());
-        }
-      });
-    }
-
-    // Sort editors by propertyOrder
-    this.property_order = Object.keys(this.editors);
-    this.property_order = this.property_order.sort(function(a,b) {
-      var ordera = self.editors[a].schema.propertyOrder;
-      var orderb = self.editors[b].schema.propertyOrder;
-      if(typeof ordera !== "number") ordera = 1000;
-      if(typeof orderb !== "number") orderb = 1000;
-
-      return ordera - orderb;
-    });
-  },
-  //"Borrow" from arrays code
-  addTab: function(idx){
-      var self = this;
-      var isObjOrArray = self.rows[idx].schema && (self.rows[idx].schema.type === "object" || self.rows[idx].schema.type === "array");
-      if(self.tabs_holder) {
-        self.rows[idx].tab_text = document.createElement('span');
-
-        if(!isObjOrArray){
-          self.rows[idx].tab_text.textContent = (typeof self.schema.basicCategoryTitle === 'undefined') ? "Basic" : self.schema.basicCategoryTitle;
-        } else {
-          self.rows[idx].tab_text.textContent = self.rows[idx].getHeaderText();
-        }
-        self.rows[idx].tab = self.theme.getTopTab(self.rows[idx].tab_text,self.rows[idx].tab_text.textContent);
-        self.rows[idx].tab.addEventListener('click', function(e) {
-          self.active_tab = self.rows[idx].tab;
-          self.refreshTabs();
-          e.preventDefault();
-          e.stopPropagation();
-        });
-
-      }
-
-    },
-  addRow: function(editor, tabHolder, holder) {
-    var self = this;
-    var rowsLen = this.rows.length;
-    var isObjOrArray = editor.schema.type === "object" || editor.schema.type === "array";
-
-    //Add a row
-    self.rows[rowsLen] = editor;
-    //container stores the editor corresponding pane to set the display style when refreshing Tabs
-    self.rows[rowsLen].container = holder;
-
-    if(!isObjOrArray){
-
-      //This is the first simple property to be added,
-      //add a ("Basic") tab for it and save it's row number
-      if(typeof self.basicTab === "undefined"){
-        self.addTab(rowsLen);
-        //Store the index row of the first simple property added
-        self.basicTab = rowsLen;
-        self.basicPane = holder;
-        self.theme.addTopTab(tabHolder, self.rows[rowsLen].tab);
-      }
-
-      else {
-        //Any other simple property gets the same tab (and the same pane) as the first one,
-        //so, when 'click' event is fired from a row, it gets the correct ("Basic") tab
-        self.rows[rowsLen].tab = self.rows[self.basicTab].tab;
-        self.rows[rowsLen].tab_text = self.rows[self.basicTab].tab_text;
-        self.rows[rowsLen].container = self.rows[self.basicTab].container;
-      }
-    }
-    else {
-      self.addTab(rowsLen);
-      self.theme.addTopTab(tabHolder, self.rows[rowsLen].tab);
-    }
-  },
-  //Mark the active tab and make visible the corresponding pane, hide others
-  refreshTabs: function(refresh_headers) {
-    var self = this;
-    var basicTabPresent = typeof self.basicTab !== 'undefined';
-    var basicTabRefreshed = false;
-
-    $each(this.rows, function(i,row) {
-      //If it's an orphan row (some property which has been deleted), return
-      if(!row.tab || !row.container || !row.container.parentNode) return;
-
-      if(basicTabPresent && row.tab == self.rows[self.basicTab].tab && basicTabRefreshed) return;
-
-      if(refresh_headers) {
-        row.tab_text.textContent = row.getHeaderText();
-      }
-      else {
-        //All rows of simple properties point to the same tab, so refresh just once
-        if(basicTabPresent && row.tab == self.rows[self.basicTab].tab) basicTabRefreshed = true;
-
-        if(row.tab === self.active_tab) {
-          self.theme.markTabActive(row);
-        }
-        else {
-          self.theme.markTabInactive(row);
-        }
-      }
-    });
-  },
-  build: function() {
-    var self = this;
-
-    var isCategoriesFormat = (this.format === 'categories');
-    this.rows=[];
-    this.active_tab = null;
-
-    // If the object should be rendered as a table row
-    if(this.options.table_row) {
-      this.editor_holder = this.container;
-      $each(this.editors, function(key,editor) {
-        var holder = self.theme.getTableCell();
-        self.editor_holder.appendChild(holder);
-
-        editor.setContainer(holder);
-        editor.build();
-        editor.postBuild();
-
-        if(self.editors[key].options.hidden) {
-          holder.style.display = 'none';
-        }
-        if(self.editors[key].options.input_width) {
-          holder.style.width = self.editors[key].options.input_width;
-        }
-      });
-    }
-    // If the object should be rendered as a table
-    else if(this.options.table) {
-      // TODO: table display format
-      throw "Not supported yet";
-    }
-    // If the object should be rendered as a div
-    else {
-      this.header = document.createElement('span');
-      this.header.textContent = this.getTitle();
-      this.title = this.theme.getHeader(this.header);
-      this.container.appendChild(this.title);
-      this.container.style.position = 'relative';
-
-      // Edit JSON modal
-      this.editjson_holder = this.theme.getModal();
-      this.editjson_textarea = this.theme.getTextareaInput();
-      this.editjson_textarea.style.height = '170px';
-      this.editjson_textarea.style.width = '300px';
-      this.editjson_textarea.style.display = 'block';
-      this.editjson_save = this.getButton('Save','save','Save');
-      this.editjson_save.addEventListener('click',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-        self.saveJSON();
-      });
-      this.editjson_cancel = this.getButton('Cancel','cancel','Cancel');
-      this.editjson_cancel.addEventListener('click',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-        self.hideEditJSON();
-      });
-      this.editjson_holder.appendChild(this.editjson_textarea);
-      this.editjson_holder.appendChild(this.editjson_save);
-      this.editjson_holder.appendChild(this.editjson_cancel);
-
-      // Manage Properties modal
-      this.addproperty_holder = this.theme.getModal();
-      this.addproperty_list = document.createElement('div');
-      this.addproperty_list.style.width = '295px';
-      this.addproperty_list.style.maxHeight = '160px';
-      this.addproperty_list.style.padding = '5px 0';
-      this.addproperty_list.style.overflowY = 'auto';
-      this.addproperty_list.style.overflowX = 'hidden';
-      this.addproperty_list.style.paddingLeft = '5px';
-      this.addproperty_list.setAttribute('class', 'property-selector');
-      this.addproperty_add = this.getButton('add','add','add');
-      this.addproperty_input = this.theme.getFormInputField('text');
-      this.addproperty_input.setAttribute('placeholder','Property name...');
-      this.addproperty_input.style.width = '220px';
-      this.addproperty_input.style.marginBottom = '0';
-      this.addproperty_input.style.display = 'inline-block';
-      this.addproperty_add.addEventListener('click',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-        if(self.addproperty_input.value) {
-          if(self.editors[self.addproperty_input.value]) {
-            window.alert('there is already a property with that name');
-            return;
-          }
-
-          self.addObjectProperty(self.addproperty_input.value);
-          if(self.editors[self.addproperty_input.value]) {
-            self.editors[self.addproperty_input.value].disable();
-          }
-          self.onChange(true);
-        }
-      });
-      this.addproperty_holder.appendChild(this.addproperty_list);
-      this.addproperty_holder.appendChild(this.addproperty_input);
-      this.addproperty_holder.appendChild(this.addproperty_add);
-      var spacer = document.createElement('div');
-      spacer.style.clear = 'both';
-      this.addproperty_holder.appendChild(spacer);
-
-
-      // Description
-      if(this.schema.description) {
-        this.description = this.theme.getDescription(this.schema.description);
-        this.container.appendChild(this.description);
-      }
-
-      // Validation error placeholder area
-      this.error_holder = document.createElement('div');
-      this.container.appendChild(this.error_holder);
-
-      // Container for child editor area
-      this.editor_holder = this.theme.getIndentedPanel();
-      this.container.appendChild(this.editor_holder);
-
-      // Container for rows of child editors
-      this.row_container = this.theme.getGridContainer();
-
-      if(isCategoriesFormat) {
-        this.tabs_holder = this.theme.getTopTabHolder(this.schema.title);
-        this.tabPanesContainer = this.theme.getTopTabContentHolder(this.tabs_holder);
-        this.editor_holder.appendChild(this.tabs_holder);
-      }
-      else {
-        this.tabs_holder = this.theme.getTabHolder(this.schema.title);
-        this.tabPanesContainer = this.theme.getTabContentHolder(this.tabs_holder);
-        this.editor_holder.appendChild(this.row_container);
-      }
-
-      $each(this.editors, function(key,editor) {
-        var aPane = self.theme.getTabContent();
-        var holder = self.theme.getGridColumn();
-        var isObjOrArray = (editor.schema && (editor.schema.type === 'object' || editor.schema.type === 'array')) ? true : false;
-        aPane.isObjOrArray = isObjOrArray;
-
-        if(isCategoriesFormat){
-          if(isObjOrArray) {
-            var single_row_container = self.theme.getGridContainer();
-            single_row_container.appendChild(holder);
-            aPane.appendChild(single_row_container);
-            self.tabPanesContainer.appendChild(aPane);
-            self.row_container = single_row_container;
-          }
-          else {
-            if(typeof self.row_container_basic === 'undefined'){
-              self.row_container_basic = self.theme.getGridContainer();
-              aPane.appendChild(self.row_container_basic);
-              if(self.tabPanesContainer.childElementCount == 0){
-                self.tabPanesContainer.appendChild(aPane);
-              }
-              else {
-                self.tabPanesContainer.insertBefore(aPane,self.tabPanesContainer.childNodes[1]);
-              }
-            }
-            self.row_container_basic.appendChild(holder);
-          }
-
-          self.addRow(editor,self.tabs_holder,aPane);
-
-          aPane.id = editor.schema.title; //editor.schema.path//tab_text.textContent
-
-        }
-        else {
-          self.row_container.appendChild(holder);
-        }
-
-        editor.setContainer(holder);
-        editor.build();
-        editor.postBuild();
-      });
-
-      if(this.rows[0]){
-        $trigger(this.rows[0].tab,'click');
-      }
-
-      // Control buttons
-      this.title_controls = this.theme.getHeaderButtonHolder();
-      this.editjson_controls = this.theme.getHeaderButtonHolder();
-      this.addproperty_controls = this.theme.getHeaderButtonHolder();
-      this.title.appendChild(this.title_controls);
-      this.title.appendChild(this.editjson_controls);
-      this.title.appendChild(this.addproperty_controls);
-
-      // Show/Hide button
-      this.collapsed = false;
-      this.toggle_button = this.getButton('', 'collapse', this.translate('button_collapse'));
-      this.title_controls.appendChild(this.toggle_button);
-      this.toggle_button.addEventListener('click',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-        if(self.collapsed) {
-          self.editor_holder.style.display = '';
-          self.collapsed = false;
-          self.setButtonText(self.toggle_button,'','collapse',self.translate('button_collapse'));
-        }
-        else {
-          self.editor_holder.style.display = 'none';
-          self.collapsed = true;
-          self.setButtonText(self.toggle_button,'','expand',self.translate('button_expand'));
-        }
-      });
-
-      // If it should start collapsed
-      if(this.options.collapsed) {
-        $trigger(this.toggle_button,'click');
-      }
-
-      // Collapse button disabled
-      if(this.schema.options && typeof this.schema.options.disable_collapse !== "undefined") {
-        if(this.schema.options.disable_collapse) this.toggle_button.style.display = 'none';
-      }
-      else if(this.jsoneditor.options.disable_collapse) {
-        this.toggle_button.style.display = 'none';
-      }
-
-      // Edit JSON Button
-      this.editjson_button = this.getButton('JSON','edit','Edit JSON');
-      this.editjson_button.addEventListener('click',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-        self.toggleEditJSON();
-      });
-      this.editjson_controls.appendChild(this.editjson_button);
-      this.editjson_controls.appendChild(this.editjson_holder);
-
-      // Edit JSON Buttton disabled
-      if(this.schema.options && typeof this.schema.options.disable_edit_json !== "undefined") {
-        if(this.schema.options.disable_edit_json) this.editjson_button.style.display = 'none';
-      }
-      else if(this.jsoneditor.options.disable_edit_json) {
-        this.editjson_button.style.display = 'none';
-      }
-
-      // Object Properties Button
-      this.addproperty_button = this.getButton('Properties','edit','Object Properties');
-      this.addproperty_button.addEventListener('click',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-        self.toggleAddProperty();
-      });
-      this.addproperty_controls.appendChild(this.addproperty_button);
-      this.addproperty_controls.appendChild(this.addproperty_holder);
-      this.refreshAddProperties();
-    }
-
-    // Fix table cell ordering
-    if(this.options.table_row) {
-      this.editor_holder = this.container;
-      $each(this.property_order,function(i,key) {
-        self.editor_holder.appendChild(self.editors[key].container);
-      });
-    }
-    // Layout object editors in grid if needed
-    else {
-      // Initial layout
-      this.layoutEditors();
-      // Do it again now that we know the approximate heights of elements
-      this.layoutEditors();
-    }
-  },
-  showEditJSON: function() {
-    if(!this.editjson_holder) return;
-    this.hideAddProperty();
-
-    // Position the form directly beneath the button
-    // TODO: edge detection
-    this.editjson_holder.style.left = this.editjson_button.offsetLeft+"px";
-    this.editjson_holder.style.top = this.editjson_button.offsetTop + this.editjson_button.offsetHeight+"px";
-
-    // Start the textarea with the current value
-    this.editjson_textarea.value = JSON.stringify(this.getValue(),null,2);
-
-    // Disable the rest of the form while editing JSON
-    this.disable();
-
-    this.editjson_holder.style.display = '';
-    this.editjson_button.disabled = false;
-    this.editing_json = true;
-  },
-  hideEditJSON: function() {
-    if(!this.editjson_holder) return;
-    if(!this.editing_json) return;
-
-    this.editjson_holder.style.display = 'none';
-    this.enable();
-    this.editing_json = false;
-  },
-  saveJSON: function() {
-    if(!this.editjson_holder) return;
-
-    try {
-      var json = JSON.parse(this.editjson_textarea.value);
-      this.setValue(json);
-      this.hideEditJSON();
-    }
-    catch(e) {
-      window.alert('invalid JSON');
-      throw e;
-    }
-  },
-  toggleEditJSON: function() {
-    if(this.editing_json) this.hideEditJSON();
-    else this.showEditJSON();
-  },
-  insertPropertyControlUsingPropertyOrder: function (property, control, container) {
-    var propertyOrder;
-    if (this.schema.properties[property])
-      propertyOrder = this.schema.properties[property].propertyOrder;
-    if (typeof propertyOrder !== "number") propertyOrder = 1000;
-    control.propertyOrder = propertyOrder;
-
-    for (var i = 0; i < container.childNodes.length; i++) {
-      var child = container.childNodes[i];
-      if (control.propertyOrder < child.propertyOrder) {
-        this.addproperty_list.insertBefore(control, child);
-        control = null;
-        break;
-      }
-    }
-    if (control) {
-      this.addproperty_list.appendChild(control);
-    }
-  },
-  addPropertyCheckbox: function(key) {
-    var self = this;
-    var checkbox, label, labelText, control;
-
-    checkbox = self.theme.getCheckbox();
-    checkbox.style.width = 'auto';
-
-    if (this.schema.properties[key] && this.schema.properties[key].title)
-      labelText = this.schema.properties[key].title;
-    else
-      labelText = key;
-
-    label = self.theme.getCheckboxLabel(labelText);
-
-    control = self.theme.getFormControl(label,checkbox);
-    control.style.paddingBottom = control.style.marginBottom = control.style.paddingTop = control.style.marginTop = 0;
-    control.style.height = 'auto';
-    //control.style.overflowY = 'hidden';
-
-    this.insertPropertyControlUsingPropertyOrder(key, control, this.addproperty_list);
-
-    checkbox.checked = key in this.editors;
-    checkbox.addEventListener('change',function() {
-      if(checkbox.checked) {
-        self.addObjectProperty(key);
-      }
-      else {
-        self.removeObjectProperty(key);
-      }
-      self.onChange(true);
-    });
-    self.addproperty_checkboxes[key] = checkbox;
-
-    return checkbox;
-  },
-  showAddProperty: function() {
-    if(!this.addproperty_holder) return;
-    this.hideEditJSON();
-
-    // Position the form directly beneath the button
-    // TODO: edge detection
-    this.addproperty_holder.style.left = this.addproperty_button.offsetLeft+"px";
-    this.addproperty_holder.style.top = this.addproperty_button.offsetTop + this.addproperty_button.offsetHeight+"px";
-
-    // Disable the rest of the form while editing JSON
-    this.disable();
-
-    this.adding_property = true;
-    this.addproperty_button.disabled = false;
-    this.addproperty_holder.style.display = '';
-    this.refreshAddProperties();
-  },
-  hideAddProperty: function() {
-    if(!this.addproperty_holder) return;
-    if(!this.adding_property) return;
-
-    this.addproperty_holder.style.display = 'none';
-    this.enable();
-
-    this.adding_property = false;
-  },
-  toggleAddProperty: function() {
-    if(this.adding_property) this.hideAddProperty();
-    else this.showAddProperty();
-  },
-  removeObjectProperty: function(property) {
-    if(this.editors[property]) {
-      this.editors[property].unregister();
-      delete this.editors[property];
-
-      this.refreshValue();
-      this.layoutEditors();
-    }
-  },
-  addObjectProperty: function(name, prebuild_only) {
-    var self = this;
-
-    // Property is already added
-    if(this.editors[name]) return;
-
-    // Property was added before and is cached
-    if(this.cached_editors[name]) {
-      this.editors[name] = this.cached_editors[name];
-      if(prebuild_only) return;
-      this.editors[name].register();
-    }
-    // New property
-    else {
-      if(!this.canHaveAdditionalProperties() && (!this.schema.properties || !this.schema.properties[name])) {
-        return;
-      }
-
-      var schema = self.getPropertySchema(name);
-      if(typeof schema.propertyOrder !== 'number'){
-        // if the propertyOrder undefined, then set a smart default value.
-        schema.propertyOrder = Object.keys(self.editors).length + 1000;
-      }
-
-
-      // Add the property
-      var editor = self.jsoneditor.getEditorClass(schema);
-
-      self.editors[name] = self.jsoneditor.createEditor(editor,{
-        jsoneditor: self.jsoneditor,
-        schema: schema,
-        path: self.path+'.'+name,
-        parent: self
-      });
-      self.editors[name].preBuild();
-
-      if(!prebuild_only) {
-        var holder = self.theme.getChildEditorHolder();
-        self.editor_holder.appendChild(holder);
-        self.editors[name].setContainer(holder);
-        self.editors[name].build();
-        self.editors[name].postBuild();
-      }
-
-      self.cached_editors[name] = self.editors[name];
-    }
-
-    // If we're only prebuilding the editors, don't refresh values
-    if(!prebuild_only) {
-      self.refreshValue();
-      self.layoutEditors();
-    }
-  },
-  onChildEditorChange: function(editor) {
-    this.refreshValue();
-    this._super(editor);
-  },
-  canHaveAdditionalProperties: function() {
-    if (typeof this.schema.additionalProperties === "boolean") {//# sourceMappingURL=jsoneditor.js.map
-      return this.schema.additionalProperties;
-    }
-    return !this.jsoneditor.options.no_additional_properties;
-  },
-  destroy: function() {
-    $each(this.cached_editors, function(i,el) {
-      el.destroy();
-    });
-    if(this.editor_holder) this.editor_holder.innerHTML = '';
-    if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);
-    if(this.error_holder && this.error_holder.parentNode) this.error_holder.parentNode.removeChild(this.error_holder);
-
-    this.editors = null;
-    this.cached_editors = null;
-    if(this.editor_holder && this.editor_holder.parentNode) this.editor_holder.parentNode.removeChild(this.editor_holder);
-    this.editor_holder = null;
-
-    this._super();
-  },
-  getValue: function() {
-    if (!this.dependenciesFulfilled) {
-      return undefined;
-    }
-    var result = this._super();
-    if(this.jsoneditor.options.remove_empty_properties || this.options.remove_empty_properties) {
-      for (var i in result) {
-        if (result.hasOwnProperty(i)) {
-          if ((typeof result[i] === 'undefined' || result[i] === '') || 
-              (Object.keys(result[i]).length == 0 && result[i].constructor == Object) ||
-              (Array.isArray(result[i]) && result[i].length == 0)) {
-              delete result[i];
-          }
-        }
-      }
-    }
-
-    return result;
-  },
-  refreshValue: function() {
-    this.value = {};
-    var self = this;
-
-    for(var i in this.editors) {
-      if(!this.editors.hasOwnProperty(i)) continue;
-      this.value[i] = this.editors[i].getValue();
-    }
-
-    if(this.adding_property) this.refreshAddProperties();
-  },
-  refreshAddProperties: function() {
-    if(this.options.disable_properties || (this.options.disable_properties !== false && this.jsoneditor.options.disable_properties)) {
-      this.addproperty_controls.style.display = 'none';
-      return;
-    }
-
-    var can_add = false, can_remove = false, num_props = 0, i, show_modal = false;
-
-    // Get number of editors
-    for(i in this.editors) {
-      if(!this.editors.hasOwnProperty(i)) continue;
-      num_props++;
-    }
-
-    // Determine if we can add back removed properties
-    can_add = this.canHaveAdditionalProperties() && !(typeof this.schema.maxProperties !== "undefined" && num_props >= this.schema.maxProperties);
-
-    if(this.addproperty_checkboxes) {
-      this.addproperty_list.innerHTML = '';
-    }
-    this.addproperty_checkboxes = {};
-
-    // Check for which editors can't be removed or added back
-    for(i in this.cached_editors) {
-      if(!this.cached_editors.hasOwnProperty(i)) continue;
-
-      this.addPropertyCheckbox(i);
-
-      if(this.isRequired(this.cached_editors[i]) && i in this.editors) {
-        this.addproperty_checkboxes[i].disabled = true;
-      }
-
-      if(typeof this.schema.minProperties !== "undefined" && num_props <= this.schema.minProperties) {
-        this.addproperty_checkboxes[i].disabled = this.addproperty_checkboxes[i].checked;
-        if(!this.addproperty_checkboxes[i].checked) show_modal = true;
-      }
-      else if(!(i in this.editors)) {
-        if(!can_add  && !this.schema.properties.hasOwnProperty(i)) {
-          this.addproperty_checkboxes[i].disabled = true;
-        }
-        else {
-          this.addproperty_checkboxes[i].disabled = false;
-          show_modal = true;
-        }
-      }
-      else {
-        show_modal = true;
-        can_remove = true;
-      }
-    }
-
-    if(this.canHaveAdditionalProperties()) {
-      show_modal = true;
-    }
-
-    // Additional addproperty checkboxes not tied to a current editor
-    for(i in this.schema.properties) {
-      if(!this.schema.properties.hasOwnProperty(i)) continue;
-      if(this.cached_editors[i]) continue;
-      show_modal = true;
-      this.addPropertyCheckbox(i);
-    }
-
-    // If no editors can be added or removed, hide the modal button
-    if(!show_modal) {
-      this.hideAddProperty();
-      this.addproperty_controls.style.display = 'none';
-    }
-    // If additional properties are disabled
-    else if(!this.canHaveAdditionalProperties()) {
-      this.addproperty_add.style.display = 'none';
-      this.addproperty_input.style.display = 'none';
-    }
-    // If no new properties can be added
-    else if(!can_add) {
-      this.addproperty_add.disabled = true;
-    }
-    // If new properties can be added
-    else {
-      this.addproperty_add.disabled = false;
-    }
-  },
-  isRequired: function(editor) {
-    if(typeof editor.schema.required === "boolean") return editor.schema.required;
-    else if(Array.isArray(this.schema.required)) return this.schema.required.indexOf(editor.key) > -1;
-    else if(this.jsoneditor.options.required_by_default) return true;
-    else return false;
-  },
-  setValue: function(value, initial) {
-    var self = this;
-    value = value || {};
-
-    if(typeof value !== "object" || Array.isArray(value)) value = {};
-
-    // First, set the values for all of the defined properties
-    $each(this.cached_editors, function(i,editor) {
-      // Value explicitly set
-      if(typeof value[i] !== "undefined") {
-        self.addObjectProperty(i);
-        editor.setValue(value[i],initial);
-      }
-      // Otherwise, remove value unless this is the initial set or it's required
-      else if(!initial && !self.isRequired(editor)) {
-        self.removeObjectProperty(i);
-      }
-      // Otherwise, set the value to the default
-      else {
-        editor.setValue(editor.getDefault(),initial);
-      }
-    });
-
-    $each(value, function(i,val) {
-      if(!self.cached_editors[i]) {
-        self.addObjectProperty(i);
-        if(self.editors[i]) self.editors[i].setValue(val,initial);
-      }
-    });
-
-    this.refreshValue();
-    this.layoutEditors();
-    this.onChange();
-  },
-  showValidationErrors: function(errors) {
-    var self = this;
-
-    // Get all the errors that pertain to this editor
-    var my_errors = [];
-    var other_errors = [];
-    $each(errors, function(i,error) {
-      if(error.path === self.path) {
-        my_errors.push(error);
-      }
-      else {
-        other_errors.push(error);
-      }
-    });
-
-    // Show errors for this editor
-    if(this.error_holder) {
-      if(my_errors.length) {
-        var message = [];
-        this.error_holder.innerHTML = '';
-        this.error_holder.style.display = '';
-        $each(my_errors, function(i,error) {
-          self.error_holder.appendChild(self.theme.getErrorMessage(error.message));
-        });
-      }
-      // Hide error area
-      else {
-        this.error_holder.style.display = 'none';
-      }
-    }
-
-    // Show error for the table row if this is inside a table
-    if(this.options.table_row) {
-      if(my_errors.length) {
-        this.theme.addTableRowError(this.container);
-      }
-      else {
-        this.theme.removeTableRowError(this.container);
-      }
-    }
-
-    // Show errors for child editors
-    $each(this.editors, function(i,editor) {
-      editor.showValidationErrors(other_errors);
-    });
-  }
-});
-
-JSONEditor.defaults.editors.array = JSONEditor.AbstractEditor.extend({
-  getDefault: function() {
-    return this.schema["default"] || [];
-  },
-  register: function() {
-    this._super();
-    if(this.rows) {
-      for(var i=0; i<this.rows.length; i++) {
-        this.rows[i].register();
-      }
-    }
-  },
-  unregister: function() {
-    this._super();
-    if(this.rows) {
-      for(var i=0; i<this.rows.length; i++) {
-        this.rows[i].unregister();
-      }
-    }
-  },
-  getNumColumns: function() {
-    var info = this.getItemInfo(0);
-    // Tabs require extra horizontal space
-    if(this.tabs_holder && this.schema.format !== 'tabs-top') {
-      return Math.max(Math.min(12,info.width+2),4);
-    }
-    else {
-      return info.width;
-    }
-  },
-  enable: function() {
-    if(!this.always_disabled) {
-      if(this.add_row_button) this.add_row_button.disabled = false;
-      if(this.remove_all_rows_button) this.remove_all_rows_button.disabled = false;
-      if(this.delete_last_row_button) this.delete_last_row_button.disabled = false;
-
-      if(this.rows) {
-        for(var i=0; i<this.rows.length; i++) {
-          this.rows[i].enable();
-
-          if(this.rows[i].moveup_button) this.rows[i].moveup_button.disabled = false;
-          if(this.rows[i].movedown_button) this.rows[i].movedown_button.disabled = false;
-          if(this.rows[i].delete_button) this.rows[i].delete_button.disabled = false;
-        }
-      }
-      this._super();
-    }
-  },
-  disable: function(always_disabled) {
-    if(always_disabled) this.always_disabled = true;
-    if(this.add_row_button) this.add_row_button.disabled = true;
-    if(this.remove_all_rows_button) this.remove_all_rows_button.disabled = true;
-    if(this.delete_last_row_button) this.delete_last_row_button.disabled = true;
-
-    if(this.rows) {
-      for(var i=0; i<this.rows.length; i++) {
-        this.rows[i].disable(always_disabled);
-
-        if(this.rows[i].moveup_button) this.rows[i].moveup_button.disabled = true;
-        if(this.rows[i].movedown_button) this.rows[i].movedown_button.disabled = true;
-        if(this.rows[i].delete_button) this.rows[i].delete_button.disabled = true;
-      }
-    }
-    this._super();
-  },
-  preBuild: function() {
-    this._super();
-
-    this.rows = [];
-    this.row_cache = [];
-
-    this.hide_delete_buttons = this.options.disable_array_delete || this.jsoneditor.options.disable_array_delete;
-    this.hide_delete_all_rows_buttons = this.hide_delete_buttons || this.options.disable_array_delete_all_rows || this.jsoneditor.options.disable_array_delete_all_rows;
-    this.hide_delete_last_row_buttons = this.hide_delete_buttons || this.options.disable_array_delete_last_row || this.jsoneditor.options.disable_array_delete_last_row;
-    this.hide_move_buttons = this.options.disable_array_reorder || this.jsoneditor.options.disable_array_reorder;
-    this.hide_add_button = this.options.disable_array_add || this.jsoneditor.options.disable_array_add;
-       this.show_copy_button = this.options.enable_array_copy || this.jsoneditor.options.enable_array_copy;
-  },
-  build: function() {
-    var self = this;
-
-    if(!this.options.compact) {
-      this.header = document.createElement('span');
-      this.header.textContent = this.getTitle();
-      this.title = this.theme.getHeader(this.header);
-      this.container.appendChild(this.title);
-      this.title_controls = this.theme.getHeaderButtonHolder();
-      this.title.appendChild(this.title_controls);
-      if(this.schema.description) {
-        this.description = this.theme.getDescription(this.schema.description);
-        this.container.appendChild(this.description);
-      }
-      this.error_holder = document.createElement('div');
-      this.container.appendChild(this.error_holder);
-
-      if(this.schema.format === 'tabs-top') {
-        this.controls = this.theme.getHeaderButtonHolder();
-        this.title.appendChild(this.controls);
-        this.tabs_holder = this.theme.getTopTabHolder(this.getItemTitle());
-        this.container.appendChild(this.tabs_holder);
-        this.row_holder = this.theme.getTopTabContentHolder(this.tabs_holder);
-
-        this.active_tab = null;
-      }
-      else if(this.schema.format === 'tabs') {
-        this.controls = this.theme.getHeaderButtonHolder();
-        this.title.appendChild(this.controls);
-        this.tabs_holder = this.theme.getTabHolder(this.getItemTitle());
-        this.container.appendChild(this.tabs_holder);
-        this.row_holder = this.theme.getTabContentHolder(this.tabs_holder);
-
-        this.active_tab = null;
-      }
-      else {
-        this.panel = this.theme.getIndentedPanel();
-        this.container.appendChild(this.panel);
-        this.row_holder = document.createElement('div');
-        this.panel.appendChild(this.row_holder);
-        this.controls = this.theme.getButtonHolder();
-        this.panel.appendChild(this.controls);
-      }
-    }
-    else {
-        this.panel = this.theme.getIndentedPanel();
-        this.container.appendChild(this.panel);
-        this.controls = this.theme.getButtonHolder();
-        this.panel.appendChild(this.controls);
-        this.row_holder = document.createElement('div');
-        this.panel.appendChild(this.row_holder);
-    }
-
-    // Add controls
-    this.addControls();
-  },
-  onChildEditorChange: function(editor) {
-    this.refreshValue();
-    this.refreshTabs(true);
-    this._super(editor);
-  },
-  getItemTitle: function() {
-    if(!this.item_title) {
-      if(this.schema.items && !Array.isArray(this.schema.items)) {
-        var tmp = this.jsoneditor.expandRefs(this.schema.items);
-        this.item_title = tmp.title || 'item';
-      }
-      else {
-        this.item_title = 'item';
-      }
-    }
-    return this.item_title;
-  },
-  getItemSchema: function(i) {
-    if(Array.isArray(this.schema.items)) {
-      if(i >= this.schema.items.length) {
-        if(this.schema.additionalItems===true) {
-          return {};
-        }
-        else if(this.schema.additionalItems) {
-          return $extend({},this.schema.additionalItems);
-        }
-      }
-      else {
-        return $extend({},this.schema.items[i]);
-      }
-    }
-    else if(this.schema.items) {
-      return $extend({},this.schema.items);
-    }
-    else {
-      return {};
-    }
-  },
-  getItemInfo: function(i) {
-    var schema = this.getItemSchema(i);
-
-    // Check if it's cached
-    this.item_info = this.item_info || {};
-    var stringified = JSON.stringify(schema);
-    if(typeof this.item_info[stringified] !== "undefined") return this.item_info[stringified];
-
-    // Get the schema for this item
-    schema = this.jsoneditor.expandRefs(schema);
-
-    this.item_info[stringified] = {
-      title: schema.title || "item",
-      'default': schema["default"],
-      width: 12,
-      child_editors: schema.properties || schema.items
-    };
-
-    return this.item_info[stringified];
-  },
-  getElementEditor: function(i) {
-    var item_info = this.getItemInfo(i);
-    var schema = this.getItemSchema(i);
-    schema = this.jsoneditor.expandRefs(schema);
-    schema.title = item_info.title+' '+(i+1);
-
-    var editor = this.jsoneditor.getEditorClass(schema);
-
-    var holder;
-    if(this.tabs_holder) {
-      if(this.schema.format === 'tabs-top') {
-        holder = this.theme.getTopTabContent();
-      }
-      else {
-        holder = this.theme.getTabContent();
-      }
-      holder.id = this.path+'.'+i;
-    }
-    else if(item_info.child_editors) {
-      holder = this.theme.getChildEditorHolder();
-    }
-    else {
-      holder = this.theme.getIndentedPanel();
-    }
-
-    this.row_holder.appendChild(holder);
-
-    var ret = this.jsoneditor.createEditor(editor,{
-      jsoneditor: this.jsoneditor,
-      schema: schema,
-      container: holder,
-      path: this.path+'.'+i,
-      parent: this,
-      required: true
-    });
-    ret.preBuild();
-    ret.build();
-    ret.postBuild();
-
-    if(!ret.title_controls) {
-      ret.array_controls = this.theme.getButtonHolder();
-      holder.appendChild(ret.array_controls);
-    }
-
-    return ret;
-  },
-  destroy: function() {
-    this.empty(true);
-    if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);
-    if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);
-    if(this.row_holder && this.row_holder.parentNode) this.row_holder.parentNode.removeChild(this.row_holder);
-    if(this.controls && this.controls.parentNode) this.controls.parentNode.removeChild(this.controls);
-    if(this.panel && this.panel.parentNode) this.panel.parentNode.removeChild(this.panel);
-
-    this.rows = this.row_cache = this.title = this.description = this.row_holder = this.panel = this.controls = null;
-
-    this._super();
-  },
-  empty: function(hard) {
-    if(!this.rows) return;
-    var self = this;
-    $each(this.rows,function(i,row) {
-      if(hard) {
-        if(row.tab && row.tab.parentNode) row.tab.parentNode.removeChild(row.tab);
-        self.destroyRow(row,true);
-        self.row_cache[i] = null;
-      }
-      self.rows[i] = null;
-    });
-    self.rows = [];
-    if(hard) self.row_cache = [];
-  },
-  destroyRow: function(row,hard) {
-    var holder = row.container;
-    if(hard) {
-      row.destroy();
-      if(holder.parentNode) holder.parentNode.removeChild(holder);
-      if(row.tab && row.tab.parentNode) row.tab.parentNode.removeChild(row.tab);
-    }
-    else {
-      if(row.tab) row.tab.style.display = 'none';
-      holder.style.display = 'none';
-      row.unregister();
-    }
-  },
-  getMax: function() {
-    if((Array.isArray(this.schema.items)) && this.schema.additionalItems === false) {
-      return Math.min(this.schema.items.length,this.schema.maxItems || Infinity);
-    }
-    else {
-      return this.schema.maxItems || Infinity;
-    }
-  },
-  refreshTabs: function(refresh_headers) {
-    var self = this;
-    $each(this.rows, function(i,row) {
-      if(!row.tab) return;
-
-      if(refresh_headers) {
-        row.tab_text.textContent = row.getHeaderText();
-      }
-      else {
-        if(row.tab === self.active_tab) {
-          self.theme.markTabActive(row);
-        }
-        else {
-          self.theme.markTabInactive(row);
-        }
-      }
-    });
-  },
-  setValue: function(value, initial) {
-    // Update the array's value, adding/removing rows when necessary
-    value = value || [];
-
-    if(!(Array.isArray(value))) value = [value];
-
-    var serialized = JSON.stringify(value);
-    if(serialized === this.serialized) return;
-
-    // Make sure value has between minItems and maxItems items in it
-    if(this.schema.minItems) {
-      while(value.length < this.schema.minItems) {
-        value.push(this.getItemInfo(value.length)["default"]);
-      }
-    }
-    if(this.getMax() && value.length > this.getMax()) {
-      value = value.slice(0,this.getMax());
-    }
-
-    var self = this;
-    $each(value,function(i,val) {
-      if(self.rows[i]) {
-        // TODO: don't set the row's value if it hasn't changed
-        self.rows[i].setValue(val,initial);
-      }
-      else if(self.row_cache[i]) {
-        self.rows[i] = self.row_cache[i];
-        self.rows[i].setValue(val,initial);
-        self.rows[i].container.style.display = '';
-        if(self.rows[i].tab) self.rows[i].tab.style.display = '';
-        self.rows[i].register();
-      }
-      else {
-        self.addRow(val,initial);
-      }
-    });
-
-    for(var j=value.length; j<self.rows.length; j++) {
-      self.destroyRow(self.rows[j]);
-      self.rows[j] = null;
-    }
-    self.rows = self.rows.slice(0,value.length);
-
-    // Set the active tab
-    var new_active_tab = null;
-    $each(self.rows, function(i,row) {
-      if(row.tab === self.active_tab) {
-        new_active_tab = row.tab;
-        return false;
-      }
-    });
-    if(!new_active_tab && self.rows.length) new_active_tab = self.rows[0].tab;
-
-    self.active_tab = new_active_tab;
-
-    self.refreshValue(initial);
-    self.refreshTabs(true);
-    self.refreshTabs();
-
-    self.onChange();
-
-    // TODO: sortable
-  },
-  refreshValue: function(force) {
-    var self = this;
-    var oldi = this.value? this.value.length : 0;
-    this.value = [];
-
-    $each(this.rows,function(i,editor) {
-      // Get the value for this editor
-      self.value[i] = editor.getValue();
-    });
-
-    if(oldi !== this.value.length || force) {
-      // If we currently have minItems items in the array
-      var minItems = this.schema.minItems && this.schema.minItems >= this.rows.length;
-
-      $each(this.rows,function(i,editor) {
-        // Hide the move down button for the last row
-        if(editor.movedown_button) {
-          if(i === self.rows.length - 1) {
-            editor.movedown_button.style.display = 'none';
-          }
-          else {
-            editor.movedown_button.style.display = '';
-          }
-        }
-
-        // Hide the delete button if we have minItems items
-        if(editor.delete_button) {
-          if(minItems) {
-            editor.delete_button.style.display = 'none';
-          }
-          else {
-            editor.delete_button.style.display = '';
-          }
-        }
-
-        // Get the value for this editor
-        self.value[i] = editor.getValue();
-      });
-
-      var controls_needed = false;
-
-      if(!this.value.length) {
-        this.delete_last_row_button.style.display = 'none';
-        this.remove_all_rows_button.style.display = 'none';
-      }
-      else if(this.value.length === 1) {
-        this.remove_all_rows_button.style.display = 'none';
-
-        // If there are minItems items in the array, or configured to hide the delete_last_row button, hide the delete button beneath the rows
-        if(minItems || this.hide_delete_last_row_buttons) {
-          this.delete_last_row_button.style.display = 'none';
-        }
-        else {
-          this.delete_last_row_button.style.display = '';
-          controls_needed = true;
-        }
-      }
-      else {
-        if(minItems || this.hide_delete_last_row_buttons) {
-          this.delete_last_row_button.style.display = 'none';
-        }
-        else {
-          this.delete_last_row_button.style.display = '';
-          controls_needed = true;
-        }
-
-        if(minItems || this.hide_delete_all_rows_buttons) {
-          this.remove_all_rows_button.style.display = 'none';
-        }
-        else {
-          this.remove_all_rows_button.style.display = '';
-          controls_needed = true;
-        }
-      }
-
-      // If there are maxItems in the array, hide the add button beneath the rows
-      if((this.getMax() && this.getMax() <= this.rows.length) || this.hide_add_button){
-        this.add_row_button.style.display = 'none';
-      }
-      else {
-        this.add_row_button.style.display = '';
-        controls_needed = true;
-      }
-
-      if(!this.collapsed && controls_needed) {
-        this.controls.style.display = 'inline-block';
-      }
-      else {
-        this.controls.style.display = 'none';
-      }
-    }
-  },
-  addRow: function(value, initial) {
-    var self = this;
-    var i = this.rows.length;
-
-    self.rows[i] = this.getElementEditor(i);
-    self.row_cache[i] = self.rows[i];
-
-    if(self.tabs_holder) {
-      self.rows[i].tab_text = document.createElement('span');
-      self.rows[i].tab_text.textContent = self.rows[i].getHeaderText();
-      if(self.schema.format === 'tabs-top'){
-        self.rows[i].tab = self.theme.getTopTab(self.rows[i].tab_text,self.rows[i].path);
-        self.theme.addTopTab(self.tabs_holder, self.rows[i].tab);
-      }
-      else {
-        self.rows[i].tab = self.theme.getTab(self.rows[i].tab_text,self.rows[i].path);
-        self.theme.addTab(self.tabs_holder, self.rows[i].tab);
-      }
-      self.rows[i].tab.addEventListener('click', function(e) {
-        self.active_tab = self.rows[i].tab;
-        self.refreshTabs();
-        e.preventDefault();
-        e.stopPropagation();
-      });
-
-    }
-
-    var controls_holder = self.rows[i].title_controls || self.rows[i].array_controls;
-
-    // Buttons to delete row, move row up, and move row down
-    if(!self.hide_delete_buttons) {
-      self.rows[i].delete_button = this.getButton(self.getItemTitle(),'delete',this.translate('button_delete_row_title',[self.getItemTitle()]));
-      self.rows[i].delete_button.className += ' delete';
-      self.rows[i].delete_button.setAttribute('data-i',i);
-      self.rows[i].delete_button.addEventListener('click',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-
-        if (self.jsoneditor.options.prompt_before_delete === true) {
-          if (confirm("Confirm to remove.") === false) {
-            return false;
-          }
-        }
-
-        var i = this.getAttribute('data-i')*1;
-
-        var value = self.getValue();
-
-        var newval = [];
-        var new_active_tab = null;
-        $each(value,function(j,row) {
-          if(j===i) {
-            // If the one we're deleting is the active tab
-            if(self.rows[j].tab === self.active_tab) {
-              // Make the next tab active if there is one
-              // Note: the next tab is going to be the current tab after deletion
-              if(self.rows[j+1]) new_active_tab = self.rows[j].tab;
-              // Otherwise, make the previous tab active if there is one
-              else if(j) new_active_tab = self.rows[j-1].tab;
-            }
-
-            return; // If this is the one we're deleting
-          }
-          newval.push(row);
-        });
-        self.setValue(newval);
-        if(new_active_tab) {
-          self.active_tab = new_active_tab;
-          self.refreshTabs();
-        }
-
-        self.onChange(true);
-      });
-
-      if(controls_holder) {
-        controls_holder.appendChild(self.rows[i].delete_button);
-      }
-    }
-
-       //Button to copy an array element and add it as last element
-       if(self.show_copy_button){
-        self.rows[i].copy_button = this.getButton(self.getItemTitle(),'copy','Copy '+self.getItemTitle());
-        self.rows[i].copy_button.className += ' copy';
-        self.rows[i].copy_button.setAttribute('data-i',i);
-        self.rows[i].copy_button.addEventListener('click',function(e) {
-            var value = self.getValue();
-            e.preventDefault();
-            e.stopPropagation();
-            var i = this.getAttribute('data-i')*1;
-
-            $each(value,function(j,row) {
-              if(j===i) {
-                value.push(row);
-                return;
-              }
-            });
-
-            self.setValue(value);
-            self.refreshValue(true);
-            self.onChange(true);
-
-        });
-
-        controls_holder.appendChild(self.rows[i].copy_button);
-    }
-
-
-    if(i && !self.hide_move_buttons) {
-      self.rows[i].moveup_button = this.getButton('','moveup',this.translate('button_move_up_title'));
-      self.rows[i].moveup_button.className += ' moveup';
-      self.rows[i].moveup_button.setAttribute('data-i',i);
-      self.rows[i].moveup_button.addEventListener('click',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-        var i = this.getAttribute('data-i')*1;
-
-        if(i<=0) return;
-        var rows = self.getValue();
-        var tmp = rows[i-1];
-        rows[i-1] = rows[i];
-        rows[i] = tmp;
-
-        self.setValue(rows);
-        self.active_tab = self.rows[i-1].tab;
-        self.refreshTabs();
-
-        self.onChange(true);
-      });
-
-      if(controls_holder) {
-        controls_holder.appendChild(self.rows[i].moveup_button);
-      }
-    }
-
-    if(!self.hide_move_buttons) {
-      self.rows[i].movedown_button = this.getButton('','movedown',this.translate('button_move_down_title'));
-      self.rows[i].movedown_button.className += ' movedown';
-      self.rows[i].movedown_button.setAttribute('data-i',i);
-      self.rows[i].movedown_button.addEventListener('click',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-        var i = this.getAttribute('data-i')*1;
-
-        var rows = self.getValue();
-        if(i>=rows.length-1) return;
-        var tmp = rows[i+1];
-        rows[i+1] = rows[i];
-        rows[i] = tmp;
-
-        self.setValue(rows);
-        self.active_tab = self.rows[i+1].tab;
-        self.refreshTabs();
-        self.onChange(true);
-      });
-
-      if(controls_holder) {
-        controls_holder.appendChild(self.rows[i].movedown_button);
-      }
-    }
-
-    if(value) self.rows[i].setValue(value, initial);
-    self.refreshTabs();
-  },
-  addControls: function() {
-    var self = this;
-
-    this.collapsed = false;
-    this.toggle_button = this.getButton('','collapse',this.translate('button_collapse'));
-    this.title_controls.appendChild(this.toggle_button);
-    var row_holder_display = self.row_holder.style.display;
-    var controls_display = self.controls.style.display;
-    this.toggle_button.addEventListener('click',function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-      if(self.collapsed) {
-        self.collapsed = false;
-        if(self.panel) self.panel.style.display = '';
-        self.row_holder.style.display = row_holder_display;
-        if(self.tabs_holder) self.tabs_holder.style.display = '';
-        self.controls.style.display = controls_display;
-        self.setButtonText(this,'','collapse',self.translate('button_collapse'));
-      }
-      else {
-        self.collapsed = true;
-        self.row_holder.style.display = 'none';
-        if(self.tabs_holder) self.tabs_holder.style.display = 'none';
-        self.controls.style.display = 'none';
-        if(self.panel) self.panel.style.display = 'none';
-        self.setButtonText(this,'','expand',self.translate('button_expand'));
-      }
-    });
-
-    // If it should start collapsed
-    if(this.options.collapsed) {
-      $trigger(this.toggle_button,'click');
-    }
-
-    // Collapse button disabled
-    if(this.schema.options && typeof this.schema.options.disable_collapse !== "undefined") {
-      if(this.schema.options.disable_collapse) this.toggle_button.style.display = 'none';
-    }
-    else if(this.jsoneditor.options.disable_collapse) {
-      this.toggle_button.style.display = 'none';
-    }
-
-    // Add "new row" and "delete last" buttons below editor
-    this.add_row_button = this.getButton(this.getItemTitle(),'add',this.translate('button_add_row_title',[this.getItemTitle()]));
-
-    this.add_row_button.addEventListener('click',function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-      var i = self.rows.length;
-      if(self.row_cache[i]) {
-        self.rows[i] = self.row_cache[i];
-        self.rows[i].setValue(self.rows[i].getDefault(), true);
-        self.rows[i].container.style.display = '';
-        if(self.rows[i].tab) self.rows[i].tab.style.display = '';
-        self.rows[i].register();
-      }
-      else {
-        self.addRow();
-      }
-      self.active_tab = self.rows[i].tab;
-      self.refreshTabs();
-      self.refreshValue();
-      self.onChange(true);
-    });
-    self.controls.appendChild(this.add_row_button);
-
-    this.delete_last_row_button = this.getButton(this.translate('button_delete_last',[this.getItemTitle()]),'delete',this.translate('button_delete_last_title',[this.getItemTitle()]));
-    this.delete_last_row_button.addEventListener('click',function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-
-      if (self.jsoneditor.options.prompt_before_delete === true) {
-        if (confirm("Confirm to remove.") === false) {
-          return false;
-        }
-      }
-
-      var rows = self.getValue();
-
-      var new_active_tab = null;
-      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;
-
-      rows.pop();
-      self.setValue(rows);
-      if(new_active_tab) {
-        self.active_tab = new_active_tab;
-        self.refreshTabs();
-      }
-      self.onChange(true);
-    });
-    self.controls.appendChild(this.delete_last_row_button);
-
-    this.remove_all_rows_button = this.getButton(this.translate('button_delete_all'),'delete',this.translate('button_delete_all_title'));
-    this.remove_all_rows_button.addEventListener('click',function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-
-      if (self.jsoneditor.options.prompt_before_delete === true) {
-        if (confirm("Confirm to remove.") === false) {
-          return false;
-        }
-      }
-
-      self.setValue([]);
-      self.onChange(true);
-    });
-    self.controls.appendChild(this.remove_all_rows_button);
-
-    if(self.tabs) {
-      this.add_row_button.style.width = '100%';
-      this.add_row_button.style.textAlign = 'left';
-      this.add_row_button.style.marginBottom = '3px';
-
-      this.delete_last_row_button.style.width = '100%';
-      this.delete_last_row_button.style.textAlign = 'left';
-      this.delete_last_row_button.style.marginBottom = '3px';
-
-      this.remove_all_rows_button.style.width = '100%';
-      this.remove_all_rows_button.style.textAlign = 'left';
-      this.remove_all_rows_button.style.marginBottom = '3px';
-    }
-  },
-  showValidationErrors: function(errors) {
-    var self = this;
-
-    // Get all the errors that pertain to this editor
-    var my_errors = [];
-    var other_errors = [];
-    $each(errors, function(i,error) {
-      if(error.path === self.path) {
-        my_errors.push(error);
-      }
-      else {
-        other_errors.push(error);
-      }
-    });
-
-    // Show errors for this editor
-    if(this.error_holder) {
-      if(my_errors.length) {
-        var message = [];
-        this.error_holder.innerHTML = '';
-        this.error_holder.style.display = '';
-        $each(my_errors, function(i,error) {
-          self.error_holder.appendChild(self.theme.getErrorMessage(error.message));
-        });
-      }
-      // Hide error area
-      else {
-        this.error_holder.style.display = 'none';
-      }
-    }
-
-    // Show errors for child editors
-    $each(this.rows, function(i,row) {
-      row.showValidationErrors(other_errors);
-    });
-  }
-});
-
-JSONEditor.defaults.editors.table = JSONEditor.defaults.editors.array.extend({
-  register: function() {
-    this._super();
-    if(this.rows) {
-      for(var i=0; i<this.rows.length; i++) {
-        this.rows[i].register();
-      }
-    }
-  },
-  unregister: function() {
-    this._super();
-    if(this.rows) {
-      for(var i=0; i<this.rows.length; i++) {
-        this.rows[i].unregister();
-      }
-    }
-  },
-  getNumColumns: function() {
-    return Math.max(Math.min(12,this.width),3);
-  },
-  preBuild: function() {
-    var item_schema = this.jsoneditor.expandRefs(this.schema.items || {});
-
-    this.item_title = item_schema.title || 'row';
-    this.item_default = item_schema["default"] || null;
-    this.item_has_child_editors = item_schema.properties || item_schema.items;
-    this.width = 12;
-    this._super();
-  },
-  build: function() {
-    var self = this;
-    this.table = this.theme.getTable();
-    this.container.appendChild(this.table);
-    this.thead = this.theme.getTableHead();
-    this.table.appendChild(this.thead);
-    this.header_row = this.theme.getTableRow();
-    this.thead.appendChild(this.header_row);
-    this.row_holder = this.theme.getTableBody();
-    this.table.appendChild(this.row_holder);
-
-    // Determine the default value of array element
-    var tmp = this.getElementEditor(0,true);
-    this.item_default = tmp.getDefault();
-    this.width = tmp.getNumColumns() + 2;
-
-    if(!this.options.compact) {
-      this.title = this.theme.getHeader(this.getTitle());
-      this.container.appendChild(this.title);
-      this.title_controls = this.theme.getHeaderButtonHolder();
-      this.title.appendChild(this.title_controls);
-      if(this.schema.description) {
-        this.description = this.theme.getDescription(this.schema.description);
-        this.container.appendChild(this.description);
-      }
-      this.panel = this.theme.getIndentedPanel();
-      this.container.appendChild(this.panel);
-      this.error_holder = document.createElement('div');
-      this.panel.appendChild(this.error_holder);
-    }
-    else {
-      this.panel = document.createElement('div');
-      this.container.appendChild(this.panel);
-    }
-
-    this.panel.appendChild(this.table);
-    this.controls = this.theme.getButtonHolder();
-    this.panel.appendChild(this.controls);
-
-    if(this.item_has_child_editors) {
-      var ce = tmp.getChildEditors();
-      var order = tmp.property_order || Object.keys(ce);
-      for(var i=0; i<order.length; i++) {
-        var th = self.theme.getTableHeaderCell(ce[order[i]].getTitle());
-        if(ce[order[i]].options.hidden) th.style.display = 'none';
-        self.header_row.appendChild(th);
-      }
-    }
-    else {
-      self.header_row.appendChild(self.theme.getTableHeaderCell(this.item_title));
-    }
-
-    tmp.destroy();
-    this.row_holder.innerHTML = '';
-
-    // Row Controls column
-    this.controls_header_cell = self.theme.getTableHeaderCell(" ");
-    self.header_row.appendChild(this.controls_header_cell);
-
-    // Add controls
-    this.addControls();
-  },
-  onChildEditorChange: function(editor) {
-    this.refreshValue();
-    this._super();
-  },
-  getItemDefault: function() {
-    return $extend({},{"default":this.item_default})["default"];
-  },
-  getItemTitle: function() {
-    return this.item_title;
-  },
-  getElementEditor: function(i,ignore) {
-    var schema_copy = $extend({},this.schema.items);
-    var editor = this.jsoneditor.getEditorClass(schema_copy, this.jsoneditor);
-    var row = this.row_holder.appendChild(this.theme.getTableRow());
-    var holder = row;
-    if(!this.item_has_child_editors) {
-      holder = this.theme.getTableCell();
-      row.appendChild(holder);
-    }
-
-    var ret = this.jsoneditor.createEditor(editor,{
-      jsoneditor: this.jsoneditor,
-      schema: schema_copy,
-      container: holder,
-      path: this.path+'.'+i,
-      parent: this,
-      compact: true,
-      table_row: true
-    });
-
-    ret.preBuild();
-    if(!ignore) {
-      ret.build();
-      ret.postBuild();
-
-      ret.controls_cell = row.appendChild(this.theme.getTableCell());
-      ret.row = row;
-      ret.table_controls = this.theme.getButtonHolder();
-      ret.controls_cell.appendChild(ret.table_controls);
-      ret.table_controls.style.margin = 0;
-      ret.table_controls.style.padding = 0;
-    }
-
-    return ret;
-  },
-  destroy: function() {
-    this.innerHTML = '';
-    if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);
-    if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);
-    if(this.row_holder && this.row_holder.parentNode) this.row_holder.parentNode.removeChild(this.row_holder);
-    if(this.table && this.table.parentNode) this.table.parentNode.removeChild(this.table);
-    if(this.panel && this.panel.parentNode) this.panel.parentNode.removeChild(this.panel);
-
-    this.rows = this.title = this.description = this.row_holder = this.table = this.panel = null;
-
-    this._super();
-  },
-  setValue: function(value, initial) {
-    // Update the array's value, adding/removing rows when necessary
-    value = value || [];
-
-    // Make sure value has between minItems and maxItems items in it
-    if(this.schema.minItems) {
-      while(value.length < this.schema.minItems) {
-        value.push(this.getItemDefault());
-      }
-    }
-    if(this.schema.maxItems && value.length > this.schema.maxItems) {
-      value = value.slice(0,this.schema.maxItems);
-    }
-
-    var serialized = JSON.stringify(value);
-    if(serialized === this.serialized) return;
-
-    var numrows_changed = false;
-
-    var self = this;
-    $each(value,function(i,val) {
-      if(self.rows[i]) {
-        // TODO: don't set the row's value if it hasn't changed
-        self.rows[i].setValue(val);
-      }
-      else {
-        self.addRow(val);
-        numrows_changed = true;
-      }
-    });
-
-    for(var j=value.length; j<self.rows.length; j++) {
-      var holder = self.rows[j].container;
-      if(!self.item_has_child_editors) {
-        self.rows[j].row.parentNode.removeChild(self.rows[j].row);
-      }
-      self.rows[j].destroy();
-      if(holder.parentNode) holder.parentNode.removeChild(holder);
-      self.rows[j] = null;
-      numrows_changed = true;
-    }
-    self.rows = self.rows.slice(0,value.length);
-
-    self.refreshValue();
-    if(numrows_changed || initial) self.refreshRowButtons();
-
-    self.onChange();
-
-    // TODO: sortable
-  },
-  refreshRowButtons: function() {
-    var self = this;
-
-    // If we currently have minItems items in the array
-    var minItems = this.schema.minItems && this.schema.minItems >= this.rows.length;
-
-    var need_row_buttons = false;
-    $each(this.rows,function(i,editor) {
-      // Hide the move down button for the last row
-      if(editor.movedown_button) {
-        if(i === self.rows.length - 1) {
-          editor.movedown_button.style.display = 'none';
-        }
-        else {
-          need_row_buttons = true;
-          editor.movedown_button.style.display = '';
-        }
-      }
-
-      // Hide the delete button if we have minItems items
-      if(editor.delete_button) {
-        if(minItems) {
-          editor.delete_button.style.display = 'none';
-        }
-        else {
-          need_row_buttons = true;
-          editor.delete_button.style.display = '';
-        }
-      }
-
-      if(editor.moveup_button) {
-        need_row_buttons = true;
-      }
-    });
-
-    // Show/hide controls column in table
-    $each(this.rows,function(i,editor) {
-      if(need_row_buttons) {
-        editor.controls_cell.style.display = '';
-      }
-      else {
-        editor.controls_cell.style.display = 'none';
-      }
-    });
-    if(need_row_buttons) {
-      this.controls_header_cell.style.display = '';
-    }
-    else {
-      this.controls_header_cell.style.display = 'none';
-    }
-
-    var controls_needed = false;
-
-    if(!this.value.length) {
-      this.delete_last_row_button.style.display = 'none';
-      this.remove_all_rows_button.style.display = 'none';
-      this.table.style.display = 'none';
-    }
-    else if(this.value.length === 1) {
-      this.table.style.display = '';
-      this.remove_all_rows_button.style.display = 'none';
-
-      // If there are minItems items in the array, or configured to hide the delete_last_row button, hide the delete button beneath the rows
-      if(minItems || this.hide_delete_last_row_buttons) {
-        this.delete_last_row_button.style.display = 'none';
-      }
-      else {
-        this.delete_last_row_button.style.display = '';
-        controls_needed = true;
-      }
-    }
-    else {
-      this.table.style.display = '';
-
-      if(minItems || this.hide_delete_last_row_buttons) {
-        this.delete_last_row_button.style.display = 'none';
-      }
-      else {
-        this.delete_last_row_button.style.display = '';
-        controls_needed = true;
-      }
-
-      if(minItems || this.hide_delete_all_rows_buttons) {
-        this.remove_all_rows_button.style.display = 'none';
-      }
-      else {
-        this.remove_all_rows_button.style.display = '';
-        controls_needed = true;
-      }
-    }
-
-    // If there are maxItems in the array, hide the add button beneath the rows
-    if((this.schema.maxItems && this.schema.maxItems <= this.rows.length) || this.hide_add_button) {
-      this.add_row_button.style.display = 'none';
-    }
-    else {
-      this.add_row_button.style.display = '';
-      controls_needed = true;
-    }
-
-    if(!controls_needed) {
-      this.controls.style.display = 'none';
-    }
-    else {
-      this.controls.style.display = '';
-    }
-  },
-  refreshValue: function() {
-    var self = this;
-    this.value = [];
-
-    $each(this.rows,function(i,editor) {
-      // Get the value for this editor
-      self.value[i] = editor.getValue();
-    });
-    this.serialized = JSON.stringify(this.value);
-  },
-  addRow: function(value) {
-    var self = this;
-    var i = this.rows.length;
-
-    self.rows[i] = this.getElementEditor(i);
-
-    var controls_holder = self.rows[i].table_controls;
-
-    // Buttons to delete row, move row up, and move row down
-    if(!this.hide_delete_buttons) {
-      self.rows[i].delete_button = this.getButton('','delete',this.translate('button_delete_row_title_short'));
-      self.rows[i].delete_button.className += ' delete';
-      self.rows[i].delete_button.setAttribute('data-i',i);
-      self.rows[i].delete_button.addEventListener('click',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-        var i = this.getAttribute('data-i')*1;
-
-        var value = self.getValue();
-
-        var newval = [];
-        $each(value,function(j,row) {
-          if(j===i) return; // If this is the one we're deleting
-          newval.push(row);
-        });
-        self.setValue(newval);
-        self.onChange(true);
-      });
-      controls_holder.appendChild(self.rows[i].delete_button);
-    }
-
-
-    if(i && !this.hide_move_buttons) {
-      self.rows[i].moveup_button = this.getButton('','moveup',this.translate('button_move_up_title'));
-      self.rows[i].moveup_button.className += ' moveup';
-      self.rows[i].moveup_button.setAttribute('data-i',i);
-      self.rows[i].moveup_button.addEventListener('click',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-        var i = this.getAttribute('data-i')*1;
-
-        if(i<=0) return;
-        var rows = self.getValue();
-        var tmp = rows[i-1];
-        rows[i-1] = rows[i];
-        rows[i] = tmp;
-
-        self.setValue(rows);
-        self.onChange(true);
-      });
-      controls_holder.appendChild(self.rows[i].moveup_button);
-    }
-
-    if(!this.hide_move_buttons) {
-      self.rows[i].movedown_button = this.getButton('','movedown',this.translate('button_move_down_title'));
-      self.rows[i].movedown_button.className += ' movedown';
-      self.rows[i].movedown_button.setAttribute('data-i',i);
-      self.rows[i].movedown_button.addEventListener('click',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-        var i = this.getAttribute('data-i')*1;
-        var rows = self.getValue();
-        if(i>=rows.length-1) return;
-        var tmp = rows[i+1];
-        rows[i+1] = rows[i];
-        rows[i] = tmp;
-
-        self.setValue(rows);
-        self.onChange(true);
-      });
-      controls_holder.appendChild(self.rows[i].movedown_button);
-    }
-
-    if(value) self.rows[i].setValue(value);
-  },
-  addControls: function() {
-    var self = this;
-
-    this.collapsed = false;
-    this.toggle_button = this.getButton('','collapse',this.translate('button_collapse'));
-    if(this.title_controls) {
-      this.title_controls.appendChild(this.toggle_button);
-      this.toggle_button.addEventListener('click',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-
-        if(self.collapsed) {
-          self.collapsed = false;
-          self.panel.style.display = '';
-          self.setButtonText(this,'','collapse',self.translate('button_collapse'));
-        }
-        else {
-          self.collapsed = true;
-          self.panel.style.display = 'none';
-          self.setButtonText(this,'','expand',self.translate('button_expand'));
-        }
-      });
-
-      // If it should start collapsed
-      if(this.options.collapsed) {
-        $trigger(this.toggle_button,'click');
-      }
-
-      // Collapse button disabled
-      if(this.schema.options && typeof this.schema.options.disable_collapse !== "undefined") {
-        if(this.schema.options.disable_collapse) this.toggle_button.style.display = 'none';
-      }
-      else if(this.jsoneditor.options.disable_collapse) {
-        this.toggle_button.style.display = 'none';
-      }
-    }
-
-    // Add "new row" and "delete last" buttons below editor
-    this.add_row_button = this.getButton(this.getItemTitle(),'add',this.translate('button_add_row_title',[this.getItemTitle()]));
-    this.add_row_button.addEventListener('click',function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-
-      self.addRow();
-      self.refreshValue();
-      self.refreshRowButtons();
-      self.onChange(true);
-    });
-    self.controls.appendChild(this.add_row_button);
-
-    this.delete_last_row_button = this.getButton(this.translate('button_delete_last',[this.getItemTitle()]),'delete',this.translate('button_delete_last_title',[this.getItemTitle()]));
-    this.delete_last_row_button.addEventListener('click',function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-
-      var rows = self.getValue();
-      rows.pop();
-      self.setValue(rows);
-      self.onChange(true);
-    });
-    self.controls.appendChild(this.delete_last_row_button);
-
-    this.remove_all_rows_button = this.getButton(this.translate('button_delete_all'),'delete',this.translate('button_delete_all_title'));
-    this.remove_all_rows_button.addEventListener('click',function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-
-      self.setValue([]);
-      self.onChange(true);
-    });
-    self.controls.appendChild(this.remove_all_rows_button);
-  }
-});
-
-// Multiple Editor (for when `type` is an array, also when `oneOf` is present)
-JSONEditor.defaults.editors.multiple = JSONEditor.AbstractEditor.extend({
-  register: function() {
-    if(this.editors) {
-      for(var i=0; i<this.editors.length; i++) {
-        if(!this.editors[i]) continue;
-        this.editors[i].unregister();
-      }
-      if(this.editors[this.type]) this.editors[this.type].register();
-    }
-    this._super();
-  },
-  unregister: function() {
-    this._super();
-    if(this.editors) {
-      for(var i=0; i<this.editors.length; i++) {
-        if(!this.editors[i]) continue;
-        this.editors[i].unregister();
-      }
-    }
-  },
-  getNumColumns: function() {
-    if(!this.editors[this.type]) return 4;
-    return Math.max(this.editors[this.type].getNumColumns(),4);
-  },
-  enable: function() {
-    if(!this.always_disabled) {
-      if(this.editors) {
-        for(var i=0; i<this.editors.length; i++) {
-          if(!this.editors[i]) continue;
-          this.editors[i].enable();
-        }
-      }
-      this.switcher.disabled = false;
-      this._super();
-    }
-  },
-  disable: function(always_disabled) {
-    if(always_disabled) this.always_disabled = true;
-    if(this.editors) {
-      for(var i=0; i<this.editors.length; i++) {
-        if(!this.editors[i]) continue;
-        this.editors[i].disable(always_disabled);
-      }
-    }
-    this.switcher.disabled = true;
-    this._super();
-  },
-  switchEditor: function(i) {
-    var self = this;
-
-    if(!this.editors[i]) {
-      this.buildChildEditor(i);
-    }
-    
-    var current_value = self.getValue();
-
-    self.type = i;
-
-    self.register();
-
-    $each(self.editors,function(type,editor) {
-      if(!editor) return;
-      if(self.type === type) {
-        if(self.keep_values) editor.setValue(current_value,true);
-        editor.container.style.display = '';
-      }
-      else editor.container.style.display = 'none';
-    });
-    self.refreshValue();
-    self.refreshHeaderText();
-  },
-  buildChildEditor: function(i) {
-    var self = this;
-    var type = this.types[i];
-    var holder = self.theme.getChildEditorHolder();
-    self.editor_holder.appendChild(holder);
-
-    var schema;
-
-    if(typeof type === "string") {
-      schema = $extend({},self.schema);
-      schema.type = type;
-    }
-    else {
-      schema = $extend({},self.schema,type);
-      schema = self.jsoneditor.expandRefs(schema);
-
-      // If we need to merge `required` arrays
-      if(type && type.required && Array.isArray(type.required) && self.schema.required && Array.isArray(self.schema.required)) {
-        schema.required = self.schema.required.concat(type.required);
-      }
-    }
-
-    var editor = self.jsoneditor.getEditorClass(schema);
-
-    self.editors[i] = self.jsoneditor.createEditor(editor,{
-      jsoneditor: self.jsoneditor,
-      schema: schema,
-      container: holder,
-      path: self.path,
-      parent: self,
-      required: true
-    });
-    self.editors[i].preBuild();
-    self.editors[i].build();
-    self.editors[i].postBuild();
-
-    if(self.editors[i].header) self.editors[i].header.style.display = 'none';
-
-    self.editors[i].option = self.switcher_options[i];
-
-    holder.addEventListener('change_header_text',function() {
-      self.refreshHeaderText();
-    });
-
-    if(i !== self.type) holder.style.display = 'none';
-  },
-  preBuild: function() {
-    var self = this;
-
-    this.types = [];
-    this.type = 0;
-    this.editors = [];
-    this.validators = [];
-
-    this.keep_values = true;
-    if(typeof this.jsoneditor.options.keep_oneof_values !== "undefined") this.keep_values = this.jsoneditor.options.keep_oneof_values;
-    if(typeof this.options.keep_oneof_values !== "undefined") this.keep_values = this.options.keep_oneof_values;
-
-    if(this.schema.oneOf) {
-      this.oneOf = true;
-      this.types = this.schema.oneOf;
-      delete this.schema.oneOf;
-    }
-    else if(this.schema.anyOf) {
-      this.anyOf = true;
-      this.types = this.schema.anyOf;
-      delete this.schema.anyOf;
-    }
-    else {
-      if(!this.schema.type || this.schema.type === "any") {
-        this.types = ['string','number','integer','boolean','object','array','null'];
-
-        // If any of these primitive types are disallowed
-        if(this.schema.disallow) {
-          var disallow = this.schema.disallow;
-          if(typeof disallow !== 'object' || !(Array.isArray(disallow))) {
-            disallow = [disallow];
-          }
-          var allowed_types = [];
-          $each(this.types,function(i,type) {
-            if(disallow.indexOf(type) === -1) allowed_types.push(type);
-          });
-          this.types = allowed_types;
-        }
-      }
-      else if(Array.isArray(this.schema.type)) {
-        this.types = this.schema.type;
-      }
-      else {
-        this.types = [this.schema.type];
-      }
-      delete this.schema.type;
-    }
-
-    this.display_text = this.getDisplayText(this.types);
-  },
-  build: function() {
-    var self = this;
-    var container = this.container;
-
-    this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
-    this.container.appendChild(this.header);
-
-    this.switcher = this.theme.getSwitcher(this.display_text);
-    container.appendChild(this.switcher);
-    this.switcher.addEventListener('change',function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-
-      self.switchEditor(self.display_text.indexOf(this.value));
-      self.onChange(true);
-    });
-
-    this.editor_holder = document.createElement('div');
-    container.appendChild(this.editor_holder);
-    
-      
-    var validator_options = {};
-    if(self.jsoneditor.options.custom_validators) {
-      validator_options.custom_validators = self.jsoneditor.options.custom_validators;
-    }
-
-    this.switcher_options = this.theme.getSwitcherOptions(this.switcher);
-    $each(this.types,function(i,type) {
-      self.editors[i] = false;
-
-      var schema;
-
-      if(typeof type === "string") {
-        schema = $extend({},self.schema);
-        schema.type = type;
-      }
-      else {
-        schema = $extend({},self.schema,type);
-
-        // If we need to merge `required` arrays
-        if(type.required && Array.isArray(type.required) && self.schema.required && Array.isArray(self.schema.required)) {
-          schema.required = self.schema.required.concat(type.required);
-        }
-      }
-
-      self.validators[i] = new JSONEditor.Validator(self.jsoneditor,schema,validator_options);
-    });
-
-    this.switchEditor(0);
-  },
-  onChildEditorChange: function(editor) {
-    if(this.editors[this.type]) {
-      this.refreshValue();
-      this.refreshHeaderText();
-    }
-
-    this._super();
-  },
-  refreshHeaderText: function() {
-    var display_text = this.getDisplayText(this.types);
-    $each(this.switcher_options, function(i,option) {
-      option.textContent = display_text[i];
-    });
-  },
-  refreshValue: function() {
-    this.value = this.editors[this.type].getValue();
-  },
-  setValue: function(val,initial) {
-    // Determine type by getting the first one that validates
-    var self = this;
-    var prev_type = this.type;
-    $each(this.validators, function(i,validator) {
-      if(!validator.validate(val).length) {
-        self.type = i;
-        self.switcher.value = self.display_text[i];
-        return false;
-      }
-    });
-
-    var type_changed = this.type != prev_type;
-    if (type_changed) {
-       this.switchEditor(this.type);
-    }
-
-    this.editors[this.type].setValue(val,initial);
-
-    this.refreshValue();
-    self.onChange(type_changed);
-  },
-  destroy: function() {
-    $each(this.editors, function(type,editor) {
-      if(editor) editor.destroy();
-    });
-    if(this.editor_holder && this.editor_holder.parentNode) this.editor_holder.parentNode.removeChild(this.editor_holder);
-    if(this.switcher && this.switcher.parentNode) this.switcher.parentNode.removeChild(this.switcher);
-    this._super();
-  },
-  showValidationErrors: function(errors) {
-    var self = this;
-
-    // oneOf and anyOf error paths need to remove the oneOf[i] part before passing to child editors
-    if(this.oneOf || this.anyOf) {
-      var check_part = this.oneOf? 'oneOf' : 'anyOf';
-      $each(this.editors,function(i,editor) {
-        if(!editor) return;
-        var check = self.path+'.'+check_part+'['+i+']';
-        var new_errors = [];
-        $each(errors, function(j,error) {
-          if(error.path.substr(0,check.length)===check) {
-            var new_error = $extend({},error);
-            new_error.path = self.path+new_error.path.substr(check.length);
-            new_errors.push(new_error);
-          }
-        });
-
-        editor.showValidationErrors(new_errors);
-      });
-    }
-    else {
-      $each(this.editors,function(type,editor) {
-        if(!editor) return;
-        editor.showValidationErrors(errors);
-      });
-    }
-  }
-});
-
-// Enum Editor (used for objects and arrays with enumerated values)
-JSONEditor.defaults.editors["enum"] = JSONEditor.AbstractEditor.extend({
-  getNumColumns: function() {
-    return 4;
-  },
-  build: function() {
-    var container = this.container;
-    this.title = this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
-    this.container.appendChild(this.title);
-
-    this.options.enum_titles = this.options.enum_titles || [];
-
-    this["enum"] = this.schema["enum"];
-    this.selected = 0;
-    this.select_options = [];
-    this.html_values = [];
-
-    var self = this;
-    for(var i=0; i<this["enum"].length; i++) {
-      this.select_options[i] = this.options.enum_titles[i] || "Value "+(i+1);
-      this.html_values[i] = this.getHTML(this["enum"][i]);
-    }
-
-    // Switcher
-    this.switcher = this.theme.getSwitcher(this.select_options);
-    this.container.appendChild(this.switcher);
-
-    // Display area
-    this.display_area = this.theme.getIndentedPanel();
-    this.container.appendChild(this.display_area);
-
-    if(this.options.hide_display) this.display_area.style.display = "none";
-
-    this.switcher.addEventListener('change',function() {
-      self.selected = self.select_options.indexOf(this.value);
-      self.value = self["enum"][self.selected];
-      self.refreshValue();
-      self.onChange(true);
-    });
-    this.value = this["enum"][0];
-    this.refreshValue();
-
-    if(this["enum"].length === 1) this.switcher.style.display = 'none';
-  },
-  refreshValue: function() {
-    var self = this;
-    self.selected = -1;
-    var stringified = JSON.stringify(this.value);
-    $each(this["enum"], function(i, el) {
-      if(stringified === JSON.stringify(el)) {
-        self.selected = i;
-        return false;
-      }
-    });
-
-    if(self.selected<0) {
-      self.setValue(self["enum"][0]);
-      return;
-    }
-
-    this.switcher.value = this.select_options[this.selected];
-    this.display_area.innerHTML = this.html_values[this.selected];
-  },
-  enable: function() {
-    if(!this.always_disabled) {
-      this.switcher.disabled = false;
-      this._super();
-    }
-  },
-  disable: function(always_disabled) {
-    if(always_disabled) this.always_disabled = true;
-    this.switcher.disabled = true;
-    this._super();
-  },
-  getHTML: function(el) {
-    var self = this;
-
-    if(el === null) {
-      return '<em>null</em>';
-    }
-    // Array or Object
-    else if(typeof el === "object") {
-      // TODO: use theme
-      var ret = '';
-
-      $each(el,function(i,child) {
-        var html = self.getHTML(child);
-
-        // Add the keys to object children
-        if(!(Array.isArray(el))) {
-          // TODO: use theme
-          html = '<div><em>'+i+'</em>: '+html+'</div>';
-        }
-
-        // TODO: use theme
-        ret += '<li>'+html+'</li>';
-      });
-
-      if(Array.isArray(el)) ret = '<ol>'+ret+'</ol>';
-      else ret = "<ul style='margin-top:0;margin-bottom:0;padding-top:0;padding-bottom:0;'>"+ret+'</ul>';
-
-      return ret;
-    }
-    // Boolean
-    else if(typeof el === "boolean") {
-      return el? 'true' : 'false';
-    }
-    // String
-    else if(typeof el === "string") {
-      return el.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
-    }
-    // Number
-    else {
-      return el;
-    }
-  },
-  setValue: function(val) {
-    if(this.value !== val) {
-      this.value = val;
-      this.refreshValue();
-      this.onChange();
-    }
-  },
-  destroy: function() {
-    if(this.display_area && this.display_area.parentNode) this.display_area.parentNode.removeChild(this.display_area);
-    if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);
-    if(this.switcher && this.switcher.parentNode) this.switcher.parentNode.removeChild(this.switcher);
-
-    this._super();
-  }
-});
-
-JSONEditor.defaults.editors.select = JSONEditor.AbstractEditor.extend({
-  setValue: function(value,initial) {
-    value = this.typecast(value||'');
-
-    // Sanitize value before setting it
-    var sanitized = value;
-    if(this.enum_values.indexOf(sanitized) < 0) {
-      sanitized = this.enum_values[0];
-    }
-
-    if(this.value === sanitized) {
-      return;
-    }
-
-    this.input.value = this.enum_options[this.enum_values.indexOf(sanitized)];
-    if(this.select2) {
-      if(this.select2v4)
-        this.select2.val(this.input.value).trigger("change"); 
-      else
-        this.select2.select2('val',this.input.value);
-    }
-    this.value = sanitized;
-    this.onChange();
-    this.change();
-  },
-  register: function() {
-    this._super();
-    if(!this.input) return;
-    this.input.setAttribute('name',this.formname);
-  },
-  unregister: function() {
-    this._super();
-    if(!this.input) return;
-    this.input.removeAttribute('name');
-  },
-  getNumColumns: function() {
-    if(!this.enum_options) return 3;
-    var longest_text = this.getTitle().length;
-    for(var i=0; i<this.enum_options.length; i++) {
-      longest_text = Math.max(longest_text,this.enum_options[i].length+4);
-    }
-    return Math.min(12,Math.max(longest_text/7,2));
-  },
-  typecast: function(value) {
-    if(this.schema.type === "boolean") {
-      return !!value;
-    }
-    else if(this.schema.type === "number") {
-      return 1*value;
-    }
-    else if(this.schema.type === "integer") {
-      return Math.floor(value*1);
-    }
-    else {
-      return ""+value;
-    }
-  },
-  getValue: function() {
-    if (!this.dependenciesFulfilled) {
-      return undefined;
-    }
-    return this.typecast(this.value);
-  },
-  preBuild: function() {
-    var self = this;
-    this.input_type = 'select';
-    this.enum_options = [];
-    this.enum_values = [];
-    this.enum_display = [];
-    var i;
-
-    // Enum options enumerated
-    if(this.schema["enum"]) {
-      var display = this.schema.options && this.schema.options.enum_titles || [];
-
-      $each(this.schema["enum"],function(i,option) {
-        self.enum_options[i] = ""+option;
-        self.enum_display[i] = ""+(display[i] || option);
-        self.enum_values[i] = self.typecast(option);
-      });
-
-      if(!this.isRequired()){
-        self.enum_display.unshift(' ');
-        self.enum_options.unshift('undefined');
-        self.enum_values.unshift(undefined);
-      }
-
-    }
-    // Boolean
-    else if(this.schema.type === "boolean") {
-      self.enum_display = this.schema.options && this.schema.options.enum_titles || ['true','false'];
-      self.enum_options = ['1',''];
-      self.enum_values = [true,false];
-
-      if(!this.isRequired()){
-        self.enum_display.unshift(' ');
-        self.enum_options.unshift('undefined');
-        self.enum_values.unshift(undefined);
-      }
-
-    }
-    // Dynamic Enum
-    else if(this.schema.enumSource) {
-      this.enumSource = [];
-      this.enum_display = [];
-      this.enum_options = [];
-      this.enum_values = [];
-
-      // Shortcut declaration for using a single array
-      if(!(Array.isArray(this.schema.enumSource))) {
-        if(this.schema.enumValue) {
-          this.enumSource = [
-            {
-              source: this.schema.enumSource,
-              value: this.schema.enumValue
-            }
-          ];
-        }
-        else {
-          this.enumSource = [
-            {
-              source: this.schema.enumSource
-            }
-          ];
-        }
-      }
-      else {
-        for(i=0; i<this.schema.enumSource.length; i++) {
-          // Shorthand for watched variable
-          if(typeof this.schema.enumSource[i] === "string") {
-            this.enumSource[i] = {
-              source: this.schema.enumSource[i]
-            };
-          }
-          // Make a copy of the schema
-          else if(!(Array.isArray(this.schema.enumSource[i]))) {
-            this.enumSource[i] = $extend({},this.schema.enumSource[i]);
-          }
-          else {
-            this.enumSource[i] = this.schema.enumSource[i];
-          }
-        }
-      }
-
-      // Now, enumSource is an array of sources
-      // Walk through this array and fix up the values
-      for(i=0; i<this.enumSource.length; i++) {
-        if(this.enumSource[i].value) {
-          this.enumSource[i].value = this.jsoneditor.compileTemplate(this.enumSource[i].value, this.template_engine);
-        }
-        if(this.enumSource[i].title) {
-          this.enumSource[i].title = this.jsoneditor.compileTemplate(this.enumSource[i].title, this.template_engine);
-        }
-        if(this.enumSource[i].filter) {
-          this.enumSource[i].filter = this.jsoneditor.compileTemplate(this.enumSource[i].filter, this.template_engine);
-        }
-      }
-    }
-    // Other, not supported
-    else {
-      throw "'select' editor requires the enum property to be set.";
-    }
-  },
-  build: function() {
-    var self = this;
-    if(!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
-    if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);
-    if(this.options.infoText) this.infoButton = this.theme.getInfoButton(this.options.infoText);
-    if(this.options.compact) this.container.className += ' compact';
-
-    this.input = this.theme.getSelectInput(this.enum_options);
-    this.theme.setSelectOptions(this.input,this.enum_options,this.enum_display);
-
-    if(this.schema.readOnly || this.schema.readonly) {
-      this.always_disabled = true;
-      this.input.disabled = true;
-    }
-
-    this.input.addEventListener('change',function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-      self.onInputChange();
-    });
-
-    this.control = this.theme.getFormControl(this.label, this.input, this.description, this.infoButton);
-    this.input.controlgroup = this.control;
-    this.container.appendChild(this.control);
-
-    this.value = this.enum_values[0];
-  },
-  onInputChange: function() {
-    var val = this.typecast(this.input.value);
-
-    var new_val;
-    // Invalid option, use first option instead
-    if(this.enum_options.indexOf(val) === -1) {
-      new_val = this.enum_values[0];
-    }
-    else {
-      new_val = this.enum_values[this.enum_options.indexOf(val)];
-    }
-
-    // If valid hasn't changed
-    if(new_val === this.value) return;
-
-    // Store new value and propogate change event
-    this.value = new_val;
-    this.onChange(true);
-  },
-  setupSelect2: function() {
-    // If the Select2 library is loaded use it when we have lots of items
-    if(window.jQuery && window.jQuery.fn && window.jQuery.fn.select2 && (this.enum_options.length > 2 || (this.enum_options.length && this.enumSource))) {
-      var options = $extend({},JSONEditor.plugins.select2);
-      if(this.schema.options && this.schema.options.select2_options) options = $extend(options,this.schema.options.select2_options);
-      this.select2 = window.jQuery(this.input).select2(options);
-      this.select2v4 = this.select2.select2.hasOwnProperty("amd");
-
-      var self = this;
-      this.select2.on('select2-blur',function() {
-        if(self.select2v4)
-          self.input.value = self.select2.val();
-        else
-          self.input.value = self.select2.select2('val');
-
-        self.onInputChange();
-      });
-
-      this.select2.on('change',function() {
-        if(self.select2v4)
-          self.input.value = self.select2.val();
-        else
-          self.input.value = self.select2.select2('val');
-
-        self.onInputChange();
-      });
-    }
-    else {
-      this.select2 = null;
-    }
-  },
-  postBuild: function() {
-    this._super();
-    this.theme.afterInputReady(this.input);
-    this.setupSelect2();
-  },
-  onWatchedFieldChange: function() {
-    var self = this, vars, j;
-
-    // If this editor uses a dynamic select box
-    if(this.enumSource) {
-      vars = this.getWatchedFieldValues();
-      var select_options = [];
-      var select_titles = [];
-
-      for(var i=0; i<this.enumSource.length; i++) {
-        // Constant values
-        if(Array.isArray(this.enumSource[i])) {
-          select_options = select_options.concat(this.enumSource[i]);
-          select_titles = select_titles.concat(this.enumSource[i]);
-        }
-        else {
-          var items = [];
-          // Static list of items
-          if(Array.isArray(this.enumSource[i].source)) {
-            items = this.enumSource[i].source;
-          // A watched field
-          } else {
-            items = vars[this.enumSource[i].source];
-          }
-
-          if(items) {
-            // Only use a predefined part of the array
-            if(this.enumSource[i].slice) {
-              items = Array.prototype.slice.apply(items,this.enumSource[i].slice);
-            }
-            // Filter the items
-            if(this.enumSource[i].filter) {
-              var new_items = [];
-              for(j=0; j<items.length; j++) {
-                if(this.enumSource[i].filter({i:j,item:items[j],watched:vars})) new_items.push(items[j]);
-              }
-              items = new_items;
-            }
-
-            var item_titles = [];
-            var item_values = [];
-            for(j=0; j<items.length; j++) {
-              var item = items[j];
-
-              // Rendered value
-              if(this.enumSource[i].value) {
-                item_values[j] = this.enumSource[i].value({
-                  i: j,
-                  item: item
-                });
-              }
-              // Use value directly
-              else {
-                item_values[j] = items[j];
-              }
-
-              // Rendered title
-              if(this.enumSource[i].title) {
-                item_titles[j] = this.enumSource[i].title({
-                  i: j,
-                  item: item
-                });
-              }
-              // Use value as the title also
-              else {
-                item_titles[j] = item_values[j];
-              }
-            }
-
-            // TODO: sort
-
-            select_options = select_options.concat(item_values);
-            select_titles = select_titles.concat(item_titles);
-          }
-        }
-      }
-
-      var prev_value = this.value;
-
-      this.theme.setSelectOptions(this.input, select_options, select_titles);
-      this.enum_options = select_options;
-      this.enum_display = select_titles;
-      this.enum_values = select_options;
-
-      if(this.select2) {
-        this.select2.select2('destroy');
-      }
-
-      // If the previous value is still in the new select options, stick with it
-      if(select_options.indexOf(prev_value) !== -1) {
-        this.input.value = prev_value;
-        this.value = prev_value;
-      }
-      // Otherwise, set the value to the first select option
-      else {
-        this.input.value = select_options[0];
-        this.value = this.typecast(select_options[0] || "");  
-        if(this.parent) this.parent.onChildEditorChange(this);
-        else this.jsoneditor.onChange();
-        this.jsoneditor.notifyWatchers(this.path);
-      }
-
-      this.setupSelect2();
-    }
-
-    this._super();
-  },
-  enable: function() {
-    if(!this.always_disabled) {
-      this.input.disabled = false;
-      if(this.select2) {
-        if(this.select2v4)
-          this.select2.prop("disabled",false);
-        else
-          this.select2.select2("enable",true);
-      }
-    }
-    this._super();
-  },
-  disable: function(always_disabled) {
-    if(always_disabled) this.always_disabled = true;
-    this.input.disabled = true;
-    if(this.select2) {
-      if(this.select2v4)
-        this.select2.prop("disabled",true);
-      else
-        this.select2.select2("enable",false);
-    }
-    this._super();
-  },
-  destroy: function() {
-    if(this.label && this.label.parentNode) this.label.parentNode.removeChild(this.label);
-    if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);
-    if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);
-    if(this.select2) {
-      this.select2.select2('destroy');
-      this.select2 = null;
-    }
-
-    this._super();
-  },
-  showValidationErrors: function (errors) {
-           var self = this;
-
-           if (this.jsoneditor.options.show_errors === "always") {}
-           else if (!this.is_dirty && this.previous_error_setting === this.jsoneditor.options.show_errors) {
-             return;
-           }
-
-           this.previous_error_setting = this.jsoneditor.options.show_errors;
-
-           var messages = [];
-           $each(errors, function (i, error) {
-             if (error.path === self.path) {
-               messages.push(error.message);
-             }
-           });
-
-           this.input.controlgroup = this.control;
-
-           if (messages.length) {
-             this.theme.addInputError(this.input, messages.join('. ') + '.');
-           }
-           else {
-             this.theme.removeInputError(this.input);
-           }
-         }
-});
-
-JSONEditor.defaults.editors.selectize = JSONEditor.AbstractEditor.extend({
-  setValue: function(value,initial) {
-    value = this.typecast(value||'');
-
-    // Sanitize value before setting it
-    var sanitized = value;
-    if(this.enum_values.indexOf(sanitized) < 0) {
-      sanitized = this.enum_values[0];
-    }
-
-    if(this.value === sanitized) {
-      return;
-    }
-
-    this.input.value = this.enum_options[this.enum_values.indexOf(sanitized)];
-
-    if(this.selectize) {
-      this.selectize[0].selectize.addItem(sanitized);
-    }
-
-    this.value = sanitized;
-    this.onChange();
-  },
-  register: function() {
-    this._super();
-    if(!this.input) return;
-    this.input.setAttribute('name',this.formname);
-  },
-  unregister: function() {
-    this._super();
-    if(!this.input) return;
-    this.input.removeAttribute('name');
-  },
-  getNumColumns: function() {
-    if(!this.enum_options) return 3;
-    var longest_text = this.getTitle().length;
-    for(var i=0; i<this.enum_options.length; i++) {
-      longest_text = Math.max(longest_text,this.enum_options[i].length+4);
-    }
-    return Math.min(12,Math.max(longest_text/7,2));
-  },
-  typecast: function(value) {
-    if(this.schema.type === "boolean") {
-      return !!value;
-    }
-    else if(this.schema.type === "number") {
-      return 1*value;
-    }
-    else if(this.schema.type === "integer") {
-      return Math.floor(value*1);
-    }
-    else {
-      return ""+value;
-    }
-  },
-  getValue: function() {
-    if (!this.dependenciesFulfilled) {
-      return undefined;
-    }
-    return this.value;
-  },
-  preBuild: function() {
-    var self = this;
-    this.input_type = 'select';
-    this.enum_options = [];
-    this.enum_values = [];
-    this.enum_display = [];
-    var i;
-
-    // Enum options enumerated
-    if(this.schema.enum) {
-      var display = this.schema.options && this.schema.options.enum_titles || [];
-
-      $each(this.schema.enum,function(i,option) {
-        self.enum_options[i] = ""+option;
-        self.enum_display[i] = ""+(display[i] || option);
-        self.enum_values[i] = self.typecast(option);
-      });
-    }
-    // Boolean
-    else if(this.schema.type === "boolean") {
-      self.enum_display = this.schema.options && this.schema.options.enum_titles || ['true','false'];
-      self.enum_options = ['1','0'];
-      self.enum_values = [true,false];
-    }
-    // Dynamic Enum
-    else if(this.schema.enumSource) {
-      this.enumSource = [];
-      this.enum_display = [];
-      this.enum_options = [];
-      this.enum_values = [];
-
-      // Shortcut declaration for using a single array
-      if(!(Array.isArray(this.schema.enumSource))) {
-        if(this.schema.enumValue) {
-          this.enumSource = [
-            {
-              source: this.schema.enumSource,
-              value: this.schema.enumValue
-            }
-          ];
-        }
-        else {
-          this.enumSource = [
-            {
-              source: this.schema.enumSource
-            }
-          ];
-        }
-      }
-      else {
-        for(i=0; i<this.schema.enumSource.length; i++) {
-          // Shorthand for watched variable
-          if(typeof this.schema.enumSource[i] === "string") {
-            this.enumSource[i] = {
-              source: this.schema.enumSource[i]
-            };
-          }
-          // Make a copy of the schema
-          else if(!(Array.isArray(this.schema.enumSource[i]))) {
-            this.enumSource[i] = $extend({},this.schema.enumSource[i]);
-          }
-          else {
-            this.enumSource[i] = this.schema.enumSource[i];
-          }
-        }
-      }
-
-      // Now, enumSource is an array of sources
-      // Walk through this array and fix up the values
-      for(i=0; i<this.enumSource.length; i++) {
-        if(this.enumSource[i].value) {
-          this.enumSource[i].value = this.jsoneditor.compileTemplate(this.enumSource[i].value, this.template_engine);
-        }
-        if(this.enumSource[i].title) {
-          this.enumSource[i].title = this.jsoneditor.compileTemplate(this.enumSource[i].title, this.template_engine);
-        }
-        if(this.enumSource[i].filter) {
-          this.enumSource[i].filter = this.jsoneditor.compileTemplate(this.enumSource[i].filter, this.template_engine);
-        }
-      }
-    }
-    // Other, not supported
-    else {
-      throw "'select' editor requires the enum property to be set.";
-    }
-  },
-  build: function() {
-    var self = this;
-    if(!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
-    if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);
-    if(this.options.infoText) this.infoButton = this.theme.getInfoButton(this.options.infoText);
-
-    if(this.options.compact) this.container.className += ' compact';
-
-    this.input = this.theme.getSelectInput(this.enum_options);
-    this.theme.setSelectOptions(this.input,this.enum_options,this.enum_display);
-
-    if(this.schema.readOnly || this.schema.readonly) {
-      this.always_disabled = true;
-      this.input.disabled = true;
-    }
-
-    this.input.addEventListener('change',function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-      self.onInputChange();
-    });
-
-    this.control = this.theme.getFormControl(this.label, this.input, this.description, this.infoButton);
-    this.container.appendChild(this.control);
-
-    this.value = this.enum_values[0];
-  },
-  onInputChange: function() {
-    //console.log("onInputChange");
-    var val = this.input.value;
-
-    var sanitized = val;
-    if(this.enum_options.indexOf(val) === -1) {
-      sanitized = this.enum_options[0];
-    }
-
-    //this.value = this.enum_values[this.enum_options.indexOf(val)];
-    this.value = val;
-    this.onChange(true);
-  },
-  setupSelectize: function() {
-    // If the Selectize library is loaded use it when we have lots of items
-    var self = this;
-    if(window.jQuery && window.jQuery.fn && window.jQuery.fn.selectize && (this.enum_options.length >= 2 || (this.enum_options.length && this.enumSource))) {
-      var options = $extend({},JSONEditor.plugins.selectize);
-      if(this.schema.options && this.schema.options.selectize_options) options = $extend(options,this.schema.options.selectize_options);
-      this.selectize = window.jQuery(this.input).selectize($extend(options,
-      {
-        // set the create option to true by default, or to the user specified value if defined
-        create: ( options.create === undefined ? true : options.create),
-        onChange : function() {
-          self.onInputChange();
-        }
-      }));
-    }
-    else {
-      this.selectize = null;
-    }
-  },
-  postBuild: function() {
-    this._super();
-    this.theme.afterInputReady(this.input);
-    this.setupSelectize();
-  },
-  onWatchedFieldChange: function() {
-    var self = this, vars, j;
-
-    // If this editor uses a dynamic select box
-    if(this.enumSource) {
-      vars = this.getWatchedFieldValues();
-      var select_options = [];
-      var select_titles = [];
-
-      for(var i=0; i<this.enumSource.length; i++) {
-        // Constant values
-        if(Array.isArray(this.enumSource[i])) {
-          select_options = select_options.concat(this.enumSource[i]);
-          select_titles = select_titles.concat(this.enumSource[i]);
-        }
-        // A watched field
-        else if(vars[this.enumSource[i].source]) {
-          var items = vars[this.enumSource[i].source];
-
-          // Only use a predefined part of the array
-          if(this.enumSource[i].slice) {
-            items = Array.prototype.slice.apply(items,this.enumSource[i].slice);
-          }
-          // Filter the items
-          if(this.enumSource[i].filter) {
-            var new_items = [];
-            for(j=0; j<items.length; j++) {
-              if(this.enumSource[i].filter({i:j,item:items[j]})) new_items.push(items[j]);
-            }
-            items = new_items;
-          }
-
-          var item_titles = [];
-          var item_values = [];
-          for(j=0; j<items.length; j++) {
-            var item = items[j];
-
-            // Rendered value
-            if(this.enumSource[i].value) {
-              item_values[j] = this.enumSource[i].value({
-                i: j,
-                item: item
-              });
-            }
-            // Use value directly
-            else {
-              item_values[j] = items[j];
-            }
-
-            // Rendered title
-            if(this.enumSource[i].title) {
-              item_titles[j] = this.enumSource[i].title({
-                i: j,
-                item: item
-              });
-            }
-            // Use value as the title also
-            else {
-              item_titles[j] = item_values[j];
-            }
-          }
-
-          // TODO: sort
-
-          select_options = select_options.concat(item_values);
-          select_titles = select_titles.concat(item_titles);
-        }
-      }
-
-      var prev_value = this.value;
-
-      // Check to see if this item is in the list
-      // Note: We have to skip empty string for watch lists to work properly
-      if ((prev_value !== undefined) && (prev_value !== "") && (select_options.indexOf(prev_value) === -1)) {
-        // item is not in the list. Add it.
-        select_options = select_options.concat(prev_value);
-        select_titles = select_titles.concat(prev_value);
-      }
-
-      this.theme.setSelectOptions(this.input, select_options, select_titles);
-      this.enum_options = select_options;
-      this.enum_display = select_titles;
-      this.enum_values = select_options;
-
-      // If the previous value is still in the new select options, stick with it
-      if(select_options.indexOf(prev_value) !== -1) {
-        this.input.value = prev_value;
-        this.value = prev_value;
-      }
-
-      // Otherwise, set the value to the first select option
-      else {
-        this.input.value = select_options[0];
-        this.value = select_options[0] || "";
-        if(this.parent) this.parent.onChildEditorChange(this);
-        else this.jsoneditor.onChange();
-        this.jsoneditor.notifyWatchers(this.path);
-      }
-
-      if(this.selectize) {
-        // Update the Selectize options
-        this.updateSelectizeOptions(select_options);
-      }
-      else {
-        this.setupSelectize();
-      }
-
-      this._super();
-    }
-  },
-  updateSelectizeOptions: function(select_options) {
-    var selectized = this.selectize[0].selectize,
-        self = this;
-
-    selectized.off();
-    selectized.clearOptions();
-    for(var n in select_options) {
-      selectized.addOption({value:select_options[n],text:select_options[n]});
-    }
-    selectized.addItem(this.value);
-    selectized.on('change',function() {
-      self.onInputChange();
-    });
-  },
-  enable: function() {
-    if(!this.always_disabled) {
-      this.input.disabled = false;
-      if(this.selectize) {
-        this.selectize[0].selectize.unlock();
-      }
-      this._super();
-    }
-  },
-  disable: function(always_disabled) {
-    if(always_disabled) this.always_disabled = true;
-    this.input.disabled = true;
-    if(this.selectize) {
-      this.selectize[0].selectize.lock();
-    }
-    this._super();
-  },
-  destroy: function() {
-    if(this.label && this.label.parentNode) this.label.parentNode.removeChild(this.label);
-    if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);
-    if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);
-    if(this.selectize) {
-      this.selectize[0].selectize.destroy();
-      this.selectize = null;
-    }
-    this._super();
-  }
-});
-
-JSONEditor.defaults.editors.multiselect = JSONEditor.AbstractEditor.extend({
-  preBuild: function() {
-    this._super();
-    var i;
-
-    this.select_options = {};
-    this.select_values = {};
-
-    var items_schema = this.jsoneditor.expandRefs(this.schema.items || {});
-
-    var e = items_schema["enum"] || [];
-    var t = items_schema.options? items_schema.options.enum_titles || [] : [];
-    this.option_keys = [];
-    this.option_titles = [];
-    for(i=0; i<e.length; i++) {
-      // If the sanitized value is different from the enum value, don't include it
-      if(this.sanitize(e[i]) !== e[i]) continue;
-
-      this.option_keys.push(e[i]+"");
-      this.option_titles.push((t[i]||e[i])+"");
-      this.select_values[e[i]+""] = e[i];
-    }
-  },
-  build: function() {
-    var self = this, i;
-    if(!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
-    if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);
-
-    if((!this.schema.format && this.option_keys.length < 8) || this.schema.format === "checkbox") {
-      this.input_type = 'checkboxes';
-
-      this.inputs = {};
-      this.controls = {};
-      for(i=0; i<this.option_keys.length; i++) {
-        this.inputs[this.option_keys[i]] = this.theme.getCheckbox();
-        this.select_options[this.option_keys[i]] = this.inputs[this.option_keys[i]];
-        var label = this.theme.getCheckboxLabel(this.option_titles[i]);
-        this.controls[this.option_keys[i]] = this.theme.getFormControl(label, this.inputs[this.option_keys[i]]);
-      }
-
-      this.control = this.theme.getMultiCheckboxHolder(this.controls,this.label,this.description);
-    }
-    else {
-      this.input_type = 'select';
-      this.input = this.theme.getSelectInput(this.option_keys);
-      this.theme.setSelectOptions(this.input,this.option_keys,this.option_titles);
-      this.input.multiple = true;
-      this.input.size = Math.min(10,this.option_keys.length);
-
-      for(i=0; i<this.option_keys.length; i++) {
-        this.select_options[this.option_keys[i]] = this.input.children[i];
-      }
-
-      if(this.schema.readOnly || this.schema.readonly) {
-        this.always_disabled = true;
-        this.input.disabled = true;
-      }
-
-      this.control = this.theme.getFormControl(this.label, this.input, this.description);
-    }
-
-    this.container.appendChild(this.control);
-    this.control.addEventListener('change',function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-
-      var new_value = [];
-      for(i = 0; i<self.option_keys.length; i++) {
-        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]]);
-      }
-
-      self.updateValue(new_value);
-      self.onChange(true);
-    });
-  },
-  setValue: function(value, initial) {
-    var i;
-    value = value || [];
-    if(typeof value !== "object") value = [value];
-    else if(!(Array.isArray(value))) value = [];
-
-    // Make sure we are dealing with an array of strings so we can check for strict equality
-    for(i=0; i<value.length; i++) {
-      if(typeof value[i] !== "string") value[i] += "";
-    }
-
-    // Update selected status of options
-    for(i in this.select_options) {
-      if(!this.select_options.hasOwnProperty(i)) continue;
-
-      this.select_options[i][this.input_type === "select"? "selected" : "checked"] = (value.indexOf(i) !== -1);
-    }
-
-    this.updateValue(value);
-    this.onChange();
-  },
-  setupSelect2: function() {
-    if(window.jQuery && window.jQuery.fn && window.jQuery.fn.select2) {
-        var options = window.jQuery.extend({},JSONEditor.plugins.select2);
-        if(this.schema.options && this.schema.options.select2_options) options = $extend(options,this.schema.options.select2_options);
-        this.select2 = window.jQuery(this.input).select2(options);
-        this.select2v4 = this.select2.select2.hasOwnProperty("amd");
-
-        var self = this;
-        this.select2.on('select2-blur',function() {
-          if(self.select2v4)
-            self.value = self.select2.val();
-          else
-            self.value = self.select2.select2('val');
-
-          self.onChange(true);
-        });
-
-        this.select2.on('change',function() {
-          if(self.select2v4)
-            self.value = self.select2.val();
-          else
-            self.value = self.select2.select2('val');
-
-          self.onChange(true);
-        });
-    }
-    else {
-        this.select2 = null;
-    }
-  },
-  onInputChange: function() {
-      this.value = this.input.value;
-      this.onChange(true);
-  },
-  postBuild: function() {
-      this._super();
-      this.setupSelect2();
-  },
-  register: function() {
-    this._super();
-    if(!this.input) return;
-    this.input.setAttribute('name',this.formname);
-  },
-  unregister: function() {
-    this._super();
-    if(!this.input) return;
-    this.input.removeAttribute('name');
-  },
-  getNumColumns: function() {
-    var longest_text = this.getTitle().length;
-    for(var i in this.select_values) {
-      if(!this.select_values.hasOwnProperty(i)) continue;
-      longest_text = Math.max(longest_text,(this.select_values[i]+"").length+4);
-    }
-
-    return Math.min(12,Math.max(longest_text/7,2));
-  },
-  updateValue: function(value) {
-    var changed = false;
-    var new_value = [];
-    for(var i=0; i<value.length; i++) {
-      if(!this.select_options[value[i]+""]) {
-        changed = true;
-        continue;
-      }
-      var sanitized = this.sanitize(this.select_values[value[i]]);
-      new_value.push(sanitized);
-      if(sanitized !== value[i]) changed = true;
-    }
-    this.value = new_value;
-
-    if(this.select2) {
-      if(this.select2v4)
-        this.select2.val(this.value).trigger("change"); 
-      else
-        this.select2.select2('val',this.value);
-    }
-
-    return changed;
-  },
-  sanitize: function(value) {
-    if(this.schema.items.type === "number") {
-      return 1*value;
-    }
-    else if(this.schema.items.type === "integer") {
-      return Math.floor(value*1);
-    }
-    else {
-      return ""+value;
-    }
-  },
-  enable: function() {
-    if(!this.always_disabled) {
-      if(this.input) {
-        this.input.disabled = false;
-      }
-      else if(this.inputs) {
-        for(var i in this.inputs) {
-          if(!this.inputs.hasOwnProperty(i)) continue;
-          this.inputs[i].disabled = false;
-        }
-      }
-      if(this.select2) {
-        if(this.select2v4)
-          this.select2.prop("disabled",false);
-        else
-          this.select2.select2("enable",true);
-      }
-      this._super();
-    }
-  },
-  disable: function(always_disabled) {
-    if(always_disabled) this.always_disabled = true;
-    if(this.input) {
-      this.input.disabled = true;
-    }
-    else if(this.inputs) {
-      for(var i in this.inputs) {
-        if(!this.inputs.hasOwnProperty(i)) continue;
-        this.inputs[i].disabled = true;
-      }
-    }
-    if(this.select2) {
-      if(this.select2v4)
-        this.select2.prop("disabled",true);
-      else
-        this.select2.select2("enable",false);
-    }
-    this._super();
-  },
-  destroy: function() {
-    if(this.select2) {
-        this.select2.select2('destroy');
-        this.select2 = null;
-    }
-    this._super();
-  }
-});
-
-JSONEditor.defaults.editors.base64 = JSONEditor.AbstractEditor.extend({
-  getNumColumns: function() {
-    return 4;
-  },
-  build: function() {    
-    var self = this;
-    this.title = this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
-    if(this.options.infoText) this.infoButton = this.theme.getInfoButton(this.options.infoText);
-
-    // Input that holds the base64 string
-    this.input = this.theme.getFormInputField('hidden');
-    this.container.appendChild(this.input);
-    
-    // Don't show uploader if this is readonly
-    if(!this.schema.readOnly && !this.schema.readonly) {
-      if(!window.FileReader) throw "FileReader required for base64 editor";
-      
-      // File uploader
-      this.uploader = this.theme.getFormInputField('file');
-      
-      this.uploader.addEventListener('change',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-        
-        if(this.files && this.files.length) {
-          var fr = new FileReader();
-          fr.onload = function(evt) {
-            self.value = evt.target.result;
-            self.refreshPreview();
-            self.onChange(true);
-            fr = null;
-          };
-          fr.readAsDataURL(this.files[0]);
-        }
-      });
-    }
-
-    this.preview = this.theme.getFormInputDescription(this.schema.description);
-    this.container.appendChild(this.preview);
-
-    this.control = this.theme.getFormControl(this.label, this.uploader||this.input, this.preview, this.infoButton);
-    this.container.appendChild(this.control);
-  },
-  refreshPreview: function() {
-    if(this.last_preview === this.value) return;
-    this.last_preview = this.value;
-    
-    this.preview.innerHTML = '';
-    
-    if(!this.value) return;
-    
-    var mime = this.value.match(/^data:([^;,]+)[;,]/);
-    if(mime) mime = mime[1];
-    
-    if(!mime) {
-      this.preview.innerHTML = '<em>Invalid data URI</em>';
-    }
-    else {
-      this.preview.innerHTML = '<strong>Type:</strong> '+mime+', <strong>Size:</strong> '+Math.floor((this.value.length-this.value.split(',')[0].length-1)/1.33333)+' bytes';
-      if(mime.substr(0,5)==="image") {
-        this.preview.innerHTML += '<br>';
-        var img = document.createElement('img');
-        img.style.maxWidth = '100%';
-        img.style.maxHeight = '100px';
-        img.src = this.value;
-        this.preview.appendChild(img);
-      }
-    }
-  },
-  enable: function() {
-    if(!this.always_disabled) {
-      if(this.uploader) this.uploader.disabled = false;
-      this._super();
-    }
-  },
-  disable: function(always_disabled) {
-    if(always_disabled) this.always_disabled = true;
-    if(this.uploader) this.uploader.disabled = true;
-    this._super();
-  },
-  setValue: function(val) {
-    if(this.value !== val) {
-      this.value = val;
-      this.input.value = this.value;
-      this.refreshPreview();
-      this.onChange();
-    }
-  },
-  destroy: function() {
-    if(this.preview && this.preview.parentNode) this.preview.parentNode.removeChild(this.preview);
-    if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);
-    if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);
-    if(this.uploader && this.uploader.parentNode) this.uploader.parentNode.removeChild(this.uploader);
-
-    this._super();
-  }
-});
-
-JSONEditor.defaults.editors.upload = JSONEditor.AbstractEditor.extend({
-  getNumColumns: function() {
-    return 4;
-  },
-  build: function() {    
-    var self = this;
-    this.title = this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
-
-    // Input that holds the base64 string
-    this.input = this.theme.getFormInputField('hidden');
-    this.container.appendChild(this.input);
-    
-    // Don't show uploader if this is readonly
-    if(!this.schema.readOnly && !this.schema.readonly) {
-
-      if(!this.jsoneditor.options.upload) throw "Upload handler required for upload editor";
-
-      // File uploader
-      this.uploader = this.theme.getFormInputField('file');
-      
-      this.uploader.addEventListener('change',function(e) {
-        e.preventDefault();
-        e.stopPropagation();
-        
-        if(this.files && this.files.length) {
-          var fr = new FileReader();
-          fr.onload = function(evt) {
-            self.preview_value = evt.target.result;
-            self.refreshPreview();
-            self.onChange(true);
-            fr = null;
-          };
-          fr.readAsDataURL(this.files[0]);
-        }
-      });
-    }
-
-    var description = this.schema.description;
-    if (!description) description = '';
-
-    this.preview = this.theme.getFormInputDescription(description);
-    this.container.appendChild(this.preview);
-
-    this.control = this.theme.getFormControl(this.label, this.uploader||this.input, this.preview);
-    this.container.appendChild(this.control);
-  },
-  refreshPreview: function() {
-    if(this.last_preview === this.preview_value) return;
-    this.last_preview = this.preview_value;
-
-    this.preview.innerHTML = '';
-    
-    if(!this.preview_value) return;
-
-    var self = this;
-
-    var mime = this.preview_value.match(/^data:([^;,]+)[;,]/);
-    if(mime) mime = mime[1];
-    if(!mime) mime = 'unknown';
-
-    var file = this.uploader.files[0];
-
-    this.preview.innerHTML = '<strong>Type:</strong> '+mime+', <strong>Size:</strong> '+file.size+' bytes';
-    if(mime.substr(0,5)==="image") {
-      this.preview.innerHTML += '<br>';
-      var img = document.createElement('img');
-      img.style.maxWidth = '100%';
-      img.style.maxHeight = '100px';
-      img.src = this.preview_value;
-      this.preview.appendChild(img);
-    }
-
-    this.preview.innerHTML += '<br>';
-    var uploadButton = this.getButton('Upload', 'upload', 'Upload');
-    this.preview.appendChild(uploadButton);
-    uploadButton.addEventListener('click',function(event) {
-      event.preventDefault();
-
-      uploadButton.setAttribute("disabled", "disabled");
-      self.theme.removeInputError(self.uploader);
-
-      if (self.theme.getProgressBar) {
-        self.progressBar = self.theme.getProgressBar();
-        self.preview.appendChild(self.progressBar);
-      }
-
-      self.jsoneditor.options.upload(self.path, file, {
-        success: function(url) {
-          self.setValue(url);
-
-          if(self.parent) self.parent.onChildEditorChange(self);
-          else self.jsoneditor.onChange();
-
-          if (self.progressBar) self.preview.removeChild(self.progressBar);
-          uploadButton.removeAttribute("disabled");
-        },
-        failure: function(error) {
-          self.theme.addInputError(self.uploader, error);
-          if (self.progressBar) self.preview.removeChild(self.progressBar);
-          uploadButton.removeAttribute("disabled");
-        },
-        updateProgress: function(progress) {
-          if (self.progressBar) {
-            if (progress) self.theme.updateProgressBar(self.progressBar, progress);
-            else self.theme.updateProgressBarUnknown(self.progressBar);
-          }
-        }
-      });
-    });
-
-    if(this.jsoneditor.options.auto_upload || this.schema.options.auto_upload) {
-      uploadButton.dispatchEvent(new MouseEvent('click'));
-      this.preview.removeChild(uploadButton);
-    }
-  },
-  enable: function() {
-    if(!this.always_disabled) {
-      if(this.uploader) this.uploader.disabled = false;
-      this._super();
-    }
-  },
-  disable: function(always_disabled) {
-    if(always_disabled) this.always_disabled = true;
-    if(this.uploader) this.uploader.disabled = true;
-    this._super();
-  },
-  setValue: function(val) {
-    if(this.value !== val) {
-      this.value = val;
-      this.input.value = this.value;
-      this.onChange();
-    }
-  },
-  destroy: function() {
-    if(this.preview && this.preview.parentNode) this.preview.parentNode.removeChild(this.preview);
-    if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);
-    if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);
-    if(this.uploader && this.uploader.parentNode) this.uploader.parentNode.removeChild(this.uploader);
-
-    this._super();
-  }
-});
-
-JSONEditor.defaults.editors.checkbox = JSONEditor.AbstractEditor.extend({
-  setValue: function(value,initial) {
-    this.value = !!value;
-    this.input.checked = this.value;
-    this.onChange();
-  },
-  register: function() {
-    this._super();
-    if(!this.input) return;
-    this.input.setAttribute('name',this.formname);
-  },
-  unregister: function() {
-    this._super();
-    if(!this.input) return;
-    this.input.removeAttribute('name');
-  },
-  getNumColumns: function() {
-    return Math.min(12,Math.max(this.getTitle().length/7,2));
-  },
-  build: function() {
-    var self = this;
-    if(!this.options.compact) {
-      this.label = this.header = this.theme.getCheckboxLabel(this.getTitle());
-    }
-    if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);
-    if(this.options.infoText) this.infoButton = this.theme.getInfoButton(this.options.infoText);
-    if(this.options.compact) this.container.className += ' compact';
-
-    this.input = this.theme.getCheckbox();
-    this.control = this.theme.getFormControl(this.label, this.input, this.description, this.infoButton);
-
-    if(this.schema.readOnly || this.schema.readonly) {
-      this.always_disabled = true;
-      this.input.disabled = true;
-    }
-
-    this.input.addEventListener('change',function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-      self.value = this.checked;
-      self.onChange(true);
-    });
-
-    this.container.appendChild(this.control);
-  },
-  enable: function() {
-    if(!this.always_disabled) {
-      this.input.disabled = false;
-      this._super();
-    }
-  },
-  disable: function(always_disabled) {
-    if(always_disabled) this.always_disabled = true;
-    this.input.disabled = true;
-    this._super();
-  },
-  destroy: function() {
-    if(this.label && this.label.parentNode) this.label.parentNode.removeChild(this.label);
-    if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);
-    if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);
-    this._super();
-  },
-  showValidationErrors: function (errors) {
-    var self = this;
-
-    if (this.jsoneditor.options.show_errors === "always") {}
-
-    else if (!this.is_dirty && this.previous_error_setting === this.jsoneditor.options.show_errors) {
-      return;
-    }
-
-    this.previous_error_setting = this.jsoneditor.options.show_errors;
-
-    var messages = [];
-    $each(errors, function (i, error) {
-      if (error.path === self.path) {
-        messages.push(error.message);
-      }
-    });
-
-    this.input.controlgroup = this.control;
-
-    if (messages.length) {
-      this.theme.addInputError(this.input, messages.join('. ') + '.');
-    }
-    else {
-      this.theme.removeInputError(this.input);
-    }
-  }
-});
-
-JSONEditor.defaults.editors.arraySelectize = JSONEditor.AbstractEditor.extend({
-  build: function() {
-    this.title = this.theme.getFormInputLabel(this.getTitle());
-
-    this.title_controls = this.theme.getHeaderButtonHolder();
-    this.title.appendChild(this.title_controls);
-    this.error_holder = document.createElement('div');
-
-    if(this.schema.description) {
-      this.description = this.theme.getDescription(this.schema.description);
-    }
-
-    this.input = document.createElement('select');
-    this.input.setAttribute('multiple', 'multiple');
-
-    var group = this.theme.getFormControl(this.title, this.input, this.description);
-
-    this.container.appendChild(group);
-    this.container.appendChild(this.error_holder);
-
-    window.jQuery(this.input).selectize({
-      delimiter: false,
-      createOnBlur: true,
-      create: true
-    });
-  },
-  postBuild: function() {
-      var self = this;
-      this.input.selectize.on('change', function(event) {
-          self.refreshValue();
-          self.onChange(true);
-      });
-  },
-  destroy: function() {
-    this.empty(true);
-    if(this.title && this.title.parentNode) this.title.parentNode.removeChild(this.title);
-    if(this.description && this.description.parentNode) this.description.parentNode.removeChild(this.description);
-    if(this.input && this.input.parentNode) this.input.parentNode.removeChild(this.input);
-
-    this._super();
-  },
-  empty: function(hard) {},
-  setValue: function(value, initial) {
-    var self = this;
-    // Update the array's value, adding/removing rows when necessary
-    value = value || [];
-    if(!(Array.isArray(value))) value = [value];
-
-    this.input.selectize.clearOptions();
-    this.input.selectize.clear(true);
-
-    value.forEach(function(item) {
-      self.input.selectize.addOption({text: item, value: item});
-    });
-    this.input.selectize.setValue(value);
-
-    this.refreshValue(initial);
-  },
-  refreshValue: function(force) {
-    this.value = this.input.selectize.getValue();
-  },
-  showValidationErrors: function(errors) {
-    var self = this;
-
-    // Get all the errors that pertain to this editor
-    var my_errors = [];
-    var other_errors = [];
-    $each(errors, function(i,error) {
-      if(error.path === self.path) {
-        my_errors.push(error);
-      }
-      else {
-        other_errors.push(error);
-      }
-    });
-
-    // Show errors for this editor
-    if(this.error_holder) {
-
-      if(my_errors.length) {
-        var message = [];
-        this.error_holder.innerHTML = '';
-        this.error_holder.style.display = '';
-        $each(my_errors, function(i,error) {
-          self.error_holder.appendChild(self.theme.getErrorMessage(error.message));
-        });
-      }
-      // Hide error area
-      else {
-        this.error_holder.style.display = 'none';
-      }
-    }
-  }
-});
-
-var matchKey = (function () {
-  var elem = document.documentElement;
-
-  if (elem.matches) return 'matches';
-  else if (elem.webkitMatchesSelector) return 'webkitMatchesSelector';
-  else if (elem.mozMatchesSelector) return 'mozMatchesSelector';
-  else if (elem.msMatchesSelector) return 'msMatchesSelector';
-  else if (elem.oMatchesSelector) return 'oMatchesSelector';
-})();
-
-JSONEditor.AbstractTheme = Class.extend({
-  getContainer: function() {
-    return document.createElement('div');
-  },
-  getFloatRightLinkHolder: function() {
-    var el = document.createElement('div');
-    el.style = el.style || {};
-    el.style.cssFloat = 'right';
-    el.style.marginLeft = '10px';
-    return el;
-  },
-  getModal: function() {
-    var el = document.createElement('div');
-    el.style.backgroundColor = 'white';
-    el.style.border = '1px solid black';
-    el.style.boxShadow = '3px 3px black';
-    el.style.position = 'absolute';
-    el.style.zIndex = '10';
-    el.style.display = 'none';
-    return el;
-  },
-  getGridContainer: function() {
-    var el = document.createElement('div');
-    return el;
-  },
-  getGridRow: function() {
-    var el = document.createElement('div');
-    el.className = 'row';
-    return el;
-  },
-  getGridColumn: function() {
-    var el = document.createElement('div');
-    return el;
-  },
-  setGridColumnSize: function(el,size) {
-
-  },
-  getLink: function(text) {
-    var el = document.createElement('a');
-    el.setAttribute('href','#');
-    el.appendChild(document.createTextNode(text));
-    return el;
-  },
-  disableHeader: function(header) {
-    header.style.color = '#ccc';
-  },
-  disableLabel: function(label) {
-    label.style.color = '#ccc';
-  },
-  enableHeader: function(header) {
-    header.style.color = '';
-  },
-  enableLabel: function(label) {
-    label.style.color = '';
-  },
-  getInfoButton: function(text) {
-    var icon = document.createElement('span');
-    icon.innerText = "ⓘ";
-    icon.style.fontSize = "16px";
-    icon.style.fontWeight = "bold";
-    icon.style.padding = ".25rem";
-    icon.style.position = "relative";
-    icon.style.display = "inline-block";
-
-    var tooltip = document.createElement('span');
-    tooltip.style.fontSize = "12px";
-    icon.style.fontWeight = "normal";
-    tooltip.style["font-family"] = "sans-serif";
-    tooltip.style.visibility = "hidden";
-    tooltip.style["background-color"] = "rgba(50, 50, 50, .75)";
-    tooltip.style.margin = "0 .25rem";
-    tooltip.style.color = "#FAFAFA";
-    tooltip.style.padding = ".5rem 1rem";
-    tooltip.style["border-radius"] = ".25rem";
-    tooltip.style.width = "20rem";
-    tooltip.style.position = "absolute";
-    tooltip.innerText = text;
-    icon.onmouseover = function() {
-      tooltip.style.visibility = "visible";
-    };
-    icon.onmouseleave = function() {
-      tooltip.style.visibility = "hidden";
-    };
-
-    icon.appendChild(tooltip);
-
-    return icon;
-  },
-  getFormInputLabel: function(text) {
-    var el = document.createElement('label');
-    el.appendChild(document.createTextNode(text));
-    return el;
-  },
-  getCheckboxLabel: function(text) {
-    var el = this.getFormInputLabel(text);
-    el.style.fontWeight = 'normal';
-    return el;
-  },
-  getHeader: function(text) {
-    var el = document.createElement('h3');
-    if(typeof text === "string") {
-      el.textContent = text;
-      el.style.fontWeight = 'bold';
-      el.style.fontSize = '12px';
-      el.style.padding = '4px';
-    }
-    else {
-      el.appendChild(text);
-    }
-
-    return el;
-  },
-  getCheckbox: function() {
-    var el = this.getFormInputField('checkbox');
-    el.style.display = 'inline-block';
-    el.style.width = 'auto';
-    return el;
-  },
-  getMultiCheckboxHolder: function(controls,label,description) {
-    var el = document.createElement('div');
-
-    if(label) {
-      label.style.display = 'block';
-      el.appendChild(label);
-    }
-
-    for(var i in controls) {
-      if(!controls.hasOwnProperty(i)) continue;
-      controls[i].style.display = 'inline-block';
-      controls[i].style.marginRight = '20px';
-      el.appendChild(controls[i]);
-    }
-
-    if(description) el.appendChild(description);
-
-    return el;
-  },
-  getSelectInput: function(options) {
-    var select = document.createElement('select');
-    if(options) this.setSelectOptions(select, options);
-    return select;
-  },
-  getSwitcher: function(options) {
-    var switcher = this.getSelectInput(options);
-    switcher.style.backgroundColor = 'transparent';
-    switcher.style.display = 'inline-block';
-    switcher.style.fontStyle = 'italic';
-    switcher.style.fontWeight = 'normal';
-    switcher.style.height = 'auto';
-    switcher.style.marginBottom = 0;
-    switcher.style.marginLeft = '5px';
-    switcher.style.padding = '0 0 0 3px';
-    switcher.style.width = 'auto';
-    return switcher;
-  },
-  getSwitcherOptions: function(switcher) {
-    return switcher.getElementsByTagName('option');
-  },
-  setSwitcherOptions: function(switcher, options, titles) {
-    this.setSelectOptions(switcher, options, titles);
-  },
-  setSelectOptions: function(select, options, titles) {
-    titles = titles || [];
-    select.innerHTML = '';
-    for(var i=0; i<options.length; i++) {
-      var option = document.createElement('option');
-      option.setAttribute('value',options[i]);
-      option.textContent = titles[i] || options[i];
-      select.appendChild(option);
-    }
-  },
-  getTextareaInput: function(rows, cols) {
-    var el = document.createElement('textarea');
-    el.style = el.style || {};
-    el.style.width = '100%';
-    el.style.height = '50px';
-    el.style.fontWeight = 'bold';
-    el.style.fontSize = '1em';
-    el.style.boxSizing = 'border-box';
-    if(typeof rows === undefined) { rows = 1 };
-    if(typeof cols === undefined) { cols = 80 };
-    el.rows = rows;
-    el.cols = cols;
-    el.wrap = 'soft';
-    el.readonly = 'true';
-    return el;
-  },
-  getRangeInput: function(min,max,step) {
-    var el = this.getFormInputField('range');
-    el.setAttribute('min',min);
-    el.setAttribute('max',max);
-    el.setAttribute('step',step);
-    return el;
-  },
-  getFormInputField: function(type) {
-    var el = document.createElement('input');
-    el.setAttribute('type',type);
-    return el;
-  },
-  afterInputReady: function(input) {
-
-  },
-  getFormControl: function(label, input, description, infoText) {
-    var el = document.createElement('div');
-    el.className = 'form-control';
-    if(label) el.appendChild(label);
-    if(input.type === 'checkbox' && label) {
-      label.insertBefore(input,label.firstChild);
-      if(infoText) label.appendChild(infoText);
-    }
-    else {
-      if(infoText) label.appendChild(infoText);
-      el.appendChild(input);
-    }
-
-    if(description) el.appendChild(description);
-    return el;
-  },
-  getIndentedPanel: function() {
-    var el = document.createElement('div');
-    el.style = el.style || {};
-    el.style.paddingLeft = '10px';
-    el.style.marginLeft = '10px';
-    el.style.borderLeft = '1px solid #ccc';
-    return el;
-  },
-  getTopIndentedPanel: function() {
-    var el = document.createElement('div');
-    el.style = el.style || {};
-    el.style.paddingLeft = '10px';
-    el.style.marginLeft = '10px';
-    return el;
-  },
-  getChildEditorHolder: function() {
-    return document.createElement('div');
-  },
-  getDescription: function(text) {
-    var el = document.createElement('p');
-    el.innerHTML = text;
-    return el;
-  },
-  getCheckboxDescription: function(text) {
-    return this.getDescription(text);
-  },
-  getFormInputDescription: function(text) {
-    return this.getDescription(text);
-  },
-  getHeaderButtonHolder: function() {
-    return this.getButtonHolder();
-  },
-  getButtonHolder: function() {
-    return document.createElement('div');
-  },
-  getButton: function(text, icon, title) {
-    var el = document.createElement('button');
-    el.type = 'button';
-    this.setButtonText(el,text,icon,title);
-    return el;
-  },
-  setButtonText: function(button, text, icon, title) {
-    button.innerHTML = '';
-    if(icon) {
-      button.appendChild(icon);
-      button.innerHTML += ' ';
-    }
-    button.appendChild(document.createTextNode(text));
-    if(title) button.setAttribute('title',title);
-  },
-  getTable: function() {
-    return document.createElement('table');
-  },
-  getTableRow: function() {
-    return document.createElement('tr');
-  },
-  getTableHead: function() {
-    return document.createElement('thead');
-  },
-  getTableBody: function() {
-    return document.createElement('tbody');
-  },
-  getTableHeaderCell: function(text) {
-    var el = document.createElement('th');
-    el.textContent = text;
-    return el;
-  },
-  getTableCell: function() {
-    var el = document.createElement('td');
-    return el;
-  },
-  getErrorMessage: function(text) {
-    var el = document.createElement('p');
-    el.style = el.style || {};
-    el.style.color = 'red';
-    el.appendChild(document.createTextNode(text));
-    return el;
-  },
-  addInputError: function(input, text) {
-  },
-  removeInputError: function(input) {
-  },
-  addTableRowError: function(row) {
-  },
-  removeTableRowError: function(row) {
-  },
-  getTabHolder: function(propertyName) {
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    var el = document.createElement('div');
-    el.innerHTML = "<div style='float: left; width: 130px;' class='tabs' id='" + pName + "'></div><div class='content' style='margin-left: 120px;' id='" + pName + "'></div><div style='clear:both;'></div>";
-    return el;
-  },
-  getTopTabHolder: function(propertyName) {
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    var el = document.createElement('div');
-    el.innerHTML = "<div class='tabs' style='margin-left: 10px;' id='" + pName + "'></div><div style='clear:both;'></div><div class='content' id='" + pName + "'></div>";
-    return el;
-  },
-  applyStyles: function(el,styles) {
-    for(var i in styles) {
-      if(!styles.hasOwnProperty(i)) continue;
-      el.style[i] = styles[i];
-    }
-  },
-  closest: function(elem, selector) {
-    while (elem && elem !== document) {
-      if (elem[matchKey]) {
-        if (elem[matchKey](selector)) {
-          return elem;
-        } else {
-          elem = elem.parentNode;
-        }
-      }
-      else {
-        return false;
-      }
-    }
-    return false;
-  },
-  insertBasicTopTab: function(tab, newTabs_holder ) {
-    newTabs_holder.firstChild.insertBefore(tab,newTabs_holder.firstChild.firstChild);
-  },
-  getTab: function(span, tabId) {
-    var el = document.createElement('div');
-    el.appendChild(span);
-    el.id = tabId;
-    el.style = el.style || {};
-    this.applyStyles(el,{
-      border: '1px solid #ccc',
-      borderWidth: '1px 0 1px 1px',
-      textAlign: 'center',
-      lineHeight: '30px',
-      borderRadius: '5px',
-      borderBottomRightRadius: 0,
-      borderTopRightRadius: 0,
-      fontWeight: 'bold',
-      cursor: 'pointer'
-    });
-    return el;
-  },
-  getTopTab: function(span, tabId) {
-    var el = document.createElement('div');
-    el.id = tabId;
-    el.appendChild(span);
-    el.style = el.style || {};
-    this.applyStyles(el,{
-      float: 'left',
-      border: '1px solid #ccc',
-      borderWidth: '1px 1px 0px 1px',
-      textAlign: 'center',
-      lineHeight: '30px',
-      borderRadius: '5px',
-      paddingLeft:'5px',
-      paddingRight:'5px',
-      borderBottomRightRadius: 0,
-      borderBottomLeftRadius: 0,
-      fontWeight: 'bold',
-      cursor: 'pointer'
-    });
-    return el;
-  },
-  getTabContentHolder: function(tab_holder) {
-    return tab_holder.children[1];
-  },
-  getTopTabContentHolder: function(tab_holder) {
-    return tab_holder.children[1];
-  },
-  getTabContent: function() {
-    return this.getIndentedPanel();
-  },
-  getTopTabContent: function() {
-    return this.getTopIndentedPanel();
-  },
-  markTabActive: function(row) {
-    this.applyStyles(row.tab,{
-      opacity: 1,
-      background: 'white'
-    });
-    row.container.style.display = '';
-  },
-  markTabInactive: function(row) {
-    this.applyStyles(row.tab,{
-      opacity:0.5,
-      background: ''
-    });
-    row.container.style.display = 'none';
-  },
-  addTab: function(holder, tab) {
-    holder.children[0].appendChild(tab);
-  },
-  addTopTab: function(holder, tab) {
-    holder.children[0].appendChild(tab);
-  },
-  getBlockLink: function() {
-    var link = document.createElement('a');
-    link.style.display = 'block';
-    return link;
-  },
-  getBlockLinkHolder: function() {
-    var el = document.createElement('div');
-    return el;
-  },
-  getLinksHolder: function() {
-    var el = document.createElement('div');
-    return el;
-  },
-  createMediaLink: function(holder,link,media) {
-    holder.appendChild(link);
-    media.style.width='100%';
-    holder.appendChild(media);
-  },
-  createImageLink: function(holder,link,image) {
-    holder.appendChild(link);
-    link.appendChild(image);
-  },
-  getFirstTab: function(holder){
-    return holder.firstChild.firstChild;
-  }
-});
-
-JSONEditor.defaults.themes.bootstrap2 = JSONEditor.AbstractTheme.extend({
-  getRangeInput: function(min, max, step) {
-    // TODO: use bootstrap slider
-    return this._super(min, max, step);
-  },
-  getGridContainer: function() {
-    var el = document.createElement('div');
-    el.className = 'container-fluid';
-    el.style.padding = '4px';
-    return el;
-  },
-  getGridRow: function() {
-    var el = document.createElement('div');
-    el.className = 'row-fluid';
-    return el;
-  },
-  getFormInputLabel: function(text) {
-    var el = this._super(text);
-    el.style.display = 'inline-block';
-    el.style.fontWeight = 'bold';
-    return el;
-  },
-  setGridColumnSize: function(el,size) {
-    el.className = 'span'+size;
-  },
-  getSelectInput: function(options) {
-    var input = this._super(options);
-    input.style.width = 'auto';
-    input.style.maxWidth = '98%';
-    return input;
-  },
-  getFormInputField: function(type) {
-    var el = this._super(type);
-    el.style.width = '98%';
-    return el;
-  },
-  afterInputReady: function(input) {
-    if(input.controlgroup) return;
-    input.controlgroup = this.closest(input,'.control-group');
-    input.controls = this.closest(input,'.controls');
-    if(this.closest(input,'.compact')) {
-      input.controlgroup.className = input.controlgroup.className.replace(/control-group/g,'').replace(/[ ]{2,}/g,' ');
-      input.controls.className = input.controlgroup.className.replace(/controls/g,'').replace(/[ ]{2,}/g,' ');
-      input.style.marginBottom = 0;
-    }
-    if (this.queuedInputErrorText) {
-        var text = this.queuedInputErrorText;
-        delete this.queuedInputErrorText;
-        this.addInputError(input,text);
-    }
-
-    // TODO: use bootstrap slider
-  },
-  getIndentedPanel: function() {
-    var el = document.createElement('div');
-    el.className = 'well well-small';
-    el.style.padding = '4px';
-    return el;
-  },
-  getInfoButton: function(text) {
-    var icon = document.createElement('span');
-    icon.className = "icon-info-sign pull-right";
-    icon.style.padding = ".25rem";
-    icon.style.position = "relative";
-    icon.style.display = "inline-block";
-
-    var tooltip = document.createElement('span');
-    tooltip.style["font-family"] = "sans-serif";
-    tooltip.style.visibility = "hidden";
-    tooltip.style["background-color"] = "rgba(50, 50, 50, .75)";
-    tooltip.style.margin = "0 .25rem";
-    tooltip.style.color = "#FAFAFA";
-    tooltip.style.padding = ".5rem 1rem";
-    tooltip.style["border-radius"] = ".25rem";
-    tooltip.style.width = "25rem";
-    tooltip.style.transform = "translateX(-27rem) translateY(-.5rem)";
-    tooltip.style.position = "absolute";
-    tooltip.innerText = text;
-    icon.onmouseover = function() {
-      tooltip.style.visibility = "visible";
-    };
-    icon.onmouseleave = function() {
-      tooltip.style.visibility = "hidden";
-    };
-
-    icon.appendChild(tooltip);
-
-    return icon;
-  },
-  getFormInputDescription: function(text) {
-    var el = document.createElement('p');
-    el.className = 'help-inline';
-    el.textContent = text;
-    return el;
-  },
-  getFormControl: function(label, input, description, infoText) {
-    var ret = document.createElement('div');
-    ret.className = 'control-group';
-
-    var controls = document.createElement('div');
-    controls.className = 'controls';
-
-    if(label && input.getAttribute('type') === 'checkbox') {
-      ret.appendChild(controls);
-      label.className += ' checkbox';
-      label.appendChild(input);
-      controls.appendChild(label);
-      if(infoText) controls.appendChild(infoText);
-      controls.style.height = '30px';
-    }
-    else {
-      if(label) {
-        label.className += ' control-label';
-        ret.appendChild(label);
-      }
-      if(infoText) controls.appendChild(infoText);
-      controls.appendChild(input);
-      ret.appendChild(controls);
-    }
-
-    if(description) controls.appendChild(description);
-
-    return ret;
-  },
-  getHeaderButtonHolder: function() {
-    var el = this.getButtonHolder();
-    el.style.marginLeft = '10px';
-    return el;
-  },
-  getButtonHolder: function() {
-    var el = document.createElement('div');
-    el.className = 'btn-group';
-    return el;
-  },
-  getButton: function(text, icon, title) {
-    var el =  this._super(text, icon, title);
-    el.className += ' btn btn-default';
-    el.style.backgroundColor = '#f2bfab';
-    el.style.border = '1px solid #ddd';
-    return el;
-  },
-  getTable: function() {
-    var el = document.createElement('table');
-    el.className = 'table table-bordered';
-    el.style.width = 'auto';
-    el.style.maxWidth = 'none';
-    return el;
-  },
-  addInputError: function(input,text) {
-    if(!input.controlgroup) {
-        this.queuedInputErrorText = text;
-        return;
-    }
-    if(!input.controlgroup || !input.controls) return;
-    input.controlgroup.className += ' error';
-    if(!input.errmsg) {
-      input.errmsg = document.createElement('p');
-      input.errmsg.className = 'help-block errormsg';
-      input.controls.appendChild(input.errmsg);
-    }
-    else {
-      input.errmsg.style.display = '';
-    }
-
-    input.errmsg.textContent = text;
-  },
-  removeInputError: function(input) {
-    if(!input.controlgroup) {
-        delete this.queuedInputErrorText;
-    }
-    if(!input.errmsg) return;
-    input.errmsg.style.display = 'none';
-    input.controlgroup.className = input.controlgroup.className.replace(/\s?error/g,'');
-  },
-  getTabHolder: function(propertyName) {
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    var el = document.createElement('div');
-    el.className = 'tabbable tabs-left';
-    el.innerHTML = "<ul class='nav nav-tabs'  id='" + pName + "'></ul><div class='tab-content well well-small' id='" + pName + "'></div>";
-    return el;
-  },
-  getTopTabHolder: function(propertyName) {
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    var el = document.createElement('div');
-    el.className = 'tabbable tabs-over';
-    el.innerHTML = "<ul class='nav nav-tabs' id='" + pName + "'></ul><div class='tab-content well well-small'  id='" + pName + "'></div>";
-    return el;
-  },
-  getTab: function(text,tabId) {
-    var el = document.createElement('li');
-    el.className = 'nav-item';
-    var a = document.createElement('a');
-    a.setAttribute('href','#' + tabId);
-    a.appendChild(text);
-    el.appendChild(a);
-    return el;
-  },
-  getTopTab: function(text,tabId) {
-    var el = document.createElement('li');
-    el.className = 'nav-item';
-    var a = document.createElement('a');
-    a.setAttribute('href','#' + tabId);
-    a.appendChild(text);
-    el.appendChild(a);
-    return el;
-  },
-  getTabContentHolder: function(tab_holder) {
-    return tab_holder.children[1];
-  },
-  getTopTabContentHolder: function(tab_holder) {
-    return tab_holder.children[1];
-  },
-  getTabContent: function() {
-    var el = document.createElement('div');
-    el.className = 'tab-pane';
-    return el;
-  },
-  getTopTabContent: function() {
-    var el = document.createElement('div');
-    el.className = 'tab-pane';
-    return el;
-  },
-  markTabActive: function(row) {
-    row.tab.className = row.tab.className.replace(/\s?active/g,'');
-    row.tab.className += ' active';
-    row.container.className = row.container.className.replace(/\s?active/g,'');
-    row.container.className += ' active';
-  },
-  markTabInactive: function(row) {
-    row.tab.className = row.tab.className.replace(/\s?active/g,'');
-    row.container.className = row.container.className.replace(/\s?active/g,'');
-  },
-  addTab: function(holder, tab) {
-    holder.children[0].appendChild(tab);
-  },
-  addTopTab: function(holder, tab) {
-    holder.children[0].appendChild(tab);
-  },
-  getProgressBar: function() {
-    var container = document.createElement('div');
-    container.className = 'progress';
-
-    var bar = document.createElement('div');
-    bar.className = 'bar';
-    bar.style.width = '0%';
-    container.appendChild(bar);
-
-    return container;
-  },
-  updateProgressBar: function(progressBar, progress) {
-    if (!progressBar) return;
-
-    progressBar.firstChild.style.width = progress + "%";
-  },
-  updateProgressBarUnknown: function(progressBar) {
-    if (!progressBar) return;
-
-    progressBar.className = 'progress progress-striped active';
-    progressBar.firstChild.style.width = '100%';
-  }
-});
-
-JSONEditor.defaults.themes.bootstrap3 = JSONEditor.AbstractTheme.extend({
-  getSelectInput: function(options) {
-    var el = this._super(options);
-    el.className += 'form-control';
-    //el.style.width = 'auto';
-    return el;
-  },
-  getGridContainer: function() {
-           var el = document.createElement('div');
-           el.className = 'container-fluid';
-           el.style.padding = '4px';
-           return el;
-  },
-  getGridRow: function() {
-           var el = document.createElement('div');
-           el.className = 'row-fluid';
-           el.style.padding = '4px';
-           return el;
-  },
-  setGridColumnSize: function(el,size) {
-    el.className = 'col-md-'+size;
-  },
-  afterInputReady: function(input) {
-    if(input.controlgroup) return;
-    input.controlgroup = this.closest(input,'.form-group');
-    if(this.closest(input,'.compact')) {
-      input.controlgroup.style.marginBottom = 0;
-    }
-    if (this.queuedInputErrorText) {
-        var text = this.queuedInputErrorText;
-        delete this.queuedInputErrorText;
-        this.addInputError(input,text);
-    }
-
-    // TODO: use bootstrap slider
-  },
-  getRangeInput: function(min, max, step) {
-    // TODO: use better slider
-    return this._super(min, max, step);
-  },
-  getFormInputField: function(type) {
-    var el = this._super(type);
-    if(type !== 'checkbox') {
-      el.className += 'form-control';
-    }
-    return el;
-  },
-  getFormControl: function(label, input, description, infoText) {
-    var group = document.createElement('div');
-
-    if(label && input.type === 'checkbox') {
-      group.className += ' checkbox';
-      label.appendChild(input);
-      label.style.fontSize = '12px';
-      group.style.marginTop = '0';
-      if(infoText) group.appendChild(infoText);
-      group.appendChild(label);
-      input.style.position = 'relative';
-      input.style.cssFloat = 'left';
-    }
-    else {
-      group.className += ' form-group';
-      if(label) {
-        label.className += ' control-label';
-        group.appendChild(label);
-      }
-
-      if(infoText) group.appendChild(infoText);
-      group.appendChild(input);
-    }
-
-    if(description) group.appendChild(description);
-
-    return group;
-  },
-  getIndentedPanel: function() {
-    var el = document.createElement('div');
-    el.className = 'well well-sm';
-    el.style.padding = '4px';
-    return el;
-  },
-  getInfoButton: function(text) {
-    var icon = document.createElement('span');
-    icon.className = "glyphicon glyphicon-info-sign pull-right";
-    icon.style.padding = ".25rem";
-    icon.style.position = "relative";
-    icon.style.display = "inline-block";
-
-    var tooltip = document.createElement('span');
-    tooltip.style["font-family"] = "sans-serif";
-    tooltip.style.visibility = "hidden";
-    tooltip.style["background-color"] = "rgba(50, 50, 50, .75)";
-    tooltip.style.margin = "0 .25rem";
-    tooltip.style.color = "#FAFAFA";
-    tooltip.style.padding = ".5rem 1rem";
-    tooltip.style["border-radius"] = ".25rem";
-    tooltip.style.width = "25rem";
-    tooltip.style.transform = "translateX(-27rem) translateY(-.5rem)";
-    tooltip.style.position = "absolute";
-    tooltip.innerText = text;
-    icon.onmouseover = function() {
-      tooltip.style.visibility = "visible";
-    };
-    icon.onmouseleave = function() {
-      tooltip.style.visibility = "hidden";
-    };
-
-    icon.appendChild(tooltip);
-
-    return icon;
-  },
-  getFormInputDescription: function(text) {
-    var el = document.createElement('p');
-    el.className = 'help-block';
-    el.innerHTML = text;
-    return el;
-  },
-  getHeaderButtonHolder: function() {
-    var el = this.getButtonHolder();
-    el.style.marginLeft = '5px';
-    return el;
-  },
-  getButtonHolder: function() {
-    var el = document.createElement('div');
-    el.className = 'btn-group';
-    return el;
-  },
-  getButton: function(text, icon, title) {
-       var el =  this._super(text, icon, title);
-    el.className += ' btn btn-default';
-       el.style.backgroundColor = '#f2bfab';
-       el.style.border = '1px solid #ddd';
-       return el;
-  },
-  getTable: function() {
-    var el = document.createElement('table');
-    el.className = 'table table-bordered';
-    el.style.width = 'auto';
-    el.style.maxWidth = 'none';
-    return el;
-  },
-
-  addInputError: function(input,text) {
-    if(!input.controlgroup) {
-        this.queuedInputErrorText = text;
-        return;
-    }
-    input.controlgroup.className = input.controlgroup.className.replace(/\s?has-error/g,'');
-    input.controlgroup.className += ' has-error';
-    if(!input.errmsg) {
-      input.errmsg = document.createElement('p');
-      input.errmsg.className = 'help-block errormsg';
-      input.controlgroup.appendChild(input.errmsg);
-    }
-    else {
-      input.errmsg.style.display = '';
-    }
-
-    input.errmsg.textContent = text;
-  },
-  removeInputError: function(input) {
-    if(!input.controlgroup) {
-        delete this.queuedInputErrorText;
-    }
-    if(!input.errmsg) return;
-    input.errmsg.style.display = 'none';
-    input.controlgroup.className = input.controlgroup.className.replace(/\s?has-error/g,'');
-  },
-  getTabHolder: function(propertyName) {
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    var el = document.createElement('div');
-    el.innerHTML = "<div class='list-group pull-left' id='" + pName + "'></div><div class='col-sm-10 pull-left' id='" + pName + "'></div>";
-    return el;
-  },
-  getTopTabHolder: function(propertyName) {
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    var el = document.createElement('div');
-    el.innerHTML = "<ul class='nav nav-tabs' style='padding: 4px;' id='" + pName + "'></ul><div class='tab-content' style='overflow:visible;' id='" + pName + "'></div>";
-    return el;
-  },
-  getTab: function(text, tabId) {
-    var el = document.createElement('a');
-    el.className = 'list-group-item';
-    el.setAttribute('href','#'+tabId);
-    el.appendChild(text);
-    return el;
-  },
-  getTopTab: function(text, tabId) {
-    var el = document.createElement('li');
-    var a = document.createElement('a');
-    a.setAttribute('href','#'+tabId);
-    a.appendChild(text);
-    el.appendChild(a);
-    return el;
-  },
-  markTabActive: function(row) {
-    row.tab.className = row.tab.className.replace(/\s?active/g,'');
-    row.tab.className += ' active';
-    row.container.style.display = '';
-  },
-  markTabInactive: function(row) {
-    row.tab.className = row.tab.className.replace(/\s?active/g,'');
-    row.container.style.display = 'none';
-  },
-  getProgressBar: function() {
-    var min = 0, max = 100, start = 0;
-
-    var container = document.createElement('div');
-    container.className = 'progress';
-
-    var bar = document.createElement('div');
-    bar.className = 'progress-bar';
-    bar.setAttribute('role', 'progressbar');
-    bar.setAttribute('aria-valuenow', start);
-    bar.setAttribute('aria-valuemin', min);
-    bar.setAttribute('aria-valuenax', max);
-    bar.innerHTML = start + "%";
-    container.appendChild(bar);
-
-    return container;
-  },
-  updateProgressBar: function(progressBar, progress) {
-    if (!progressBar) return;
-
-    var bar = progressBar.firstChild;
-    var percentage = progress + "%";
-    bar.setAttribute('aria-valuenow', progress);
-    bar.style.width = percentage;
-    bar.innerHTML = percentage;
-  },
-  updateProgressBarUnknown: function(progressBar) {
-    if (!progressBar) return;
-
-    var bar = progressBar.firstChild;
-    progressBar.className = 'progress progress-striped active';
-    bar.removeAttribute('aria-valuenow');
-    bar.style.width = '100%';
-    bar.innerHTML = '';
-  }
-});
-
-JSONEditor.defaults.themes.bootstrap4 = JSONEditor.AbstractTheme.extend({
-  getSelectInput: function(options) {
-    var el = this._super(options);
-    el.className += "form-control";
-    //el.style.width = 'auto';
-    return el;
-  },
-  setGridColumnSize: function(el, size) {
-    el.className = "col-md-" + size;
-  },
-  afterInputReady: function(input) {
-    if (input.controlgroup) return;
-    input.controlgroup = this.closest(input, ".form-group");
-    if (this.closest(input, ".compact")) {
-      input.controlgroup.style.marginBottom = 0;
-    }
-
-    // TODO: use bootstrap slider
-  },
-  getTextareaInput: function() {
-    var el = document.createElement("textarea");
-    el.className = "form-control";
-    return el;
-  },
-  getRangeInput: function(min, max, step) {
-    // TODO: use better slider
-    return this._super(min, max, step);
-  },
-  getFormInputField: function(type) {
-    var el = this._super(type);
-    if (type !== "checkbox") {
-      el.className += "form-control";
-    }
-    return el;
-  },
-  getFormControl: function(label, input, description) {
-    var group = document.createElement("div");
-
-    if (label && input.type === "checkbox") {
-      group.className += " checkbox";
-      label.appendChild(input);
-      label.style.fontSize = "12px";
-      group.style.marginTop = "0";
-      group.appendChild(label);
-      input.style.position = "relative";
-      input.style.cssFloat = "left";
-    } else {
-      group.className += " form-group";
-      if (label) {
-        label.className += " form-control-label";
-        group.appendChild(label);
-      }
-      group.appendChild(input);
-    }
-
-    if (description) group.appendChild(description);
-
-    return group;
-  },
-  getIndentedPanel: function() {
-    var el = document.createElement("div");
-    el.className = "card card-body bg-light";
-    return el;
-  },
-  getFormInputDescription: function(text) {
-    var el = document.createElement("p");
-    el.className = "form-text";
-    el.innerHTML = text;
-    return el;
-  },
-  getHeaderButtonHolder: function() {
-    var el = this.getButtonHolder();
-    el.style.marginLeft = "10px";
-    return el;
-  },
-  getButtonHolder: function() {
-    var el = document.createElement("div");
-    el.className = "btn-group";
-    return el;
-  },
-  getButton: function(text, icon, title) {
-    var el = this._super(text, icon, title);
-    el.className += "btn btn-secondary";
-    return el;
-  },
-  getTable: function() {
-    var el = document.createElement("table");
-    el.className = "table-bordered table-sm";
-    el.style.width = "auto";
-    el.style.maxWidth = "none";
-    return el;
-  },
-
-  addInputError: function(input, text) {
-    if (!input.controlgroup) return;
-    input.controlgroup.className += " has-error";
-    if (!input.errmsg) {
-      input.errmsg = document.createElement("p");
-      input.errmsg.className = "form-text errormsg";
-      input.controlgroup.appendChild(input.errmsg);
-    } else {
-      input.errmsg.style.display = "";
-    }
-
-    input.errmsg.textContent = text;
-  },
-  removeInputError: function(input) {
-    if (!input.errmsg) return;
-    input.errmsg.style.display = "none";
-    input.controlgroup.className = input.controlgroup.className.replace(
-      /\s?has-error/g,
-      ""
-    );
-  },
-  getTabHolder: function(propertyName) {
-    var el = document.createElement("div");
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    el.innerHTML =
-      "<ul class='nav flex-column nav-pills col-md-2' style='padding: 0px;' id='" + pName + "'></ul><div class='tab-content col-md-10' style='padding:5px;' id='" + pName + "'></div>";
-el.className = "row";
-    return el;
-  },
-  getTopTabHolder: function(propertyName) {
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    var el = document.createElement('div');
-    el.innerHTML = "<ul class='nav nav-tabs' id='" + pName + "'></ul><div class='card-body' id='" + pName + "'></div>";
-    return el;
-  },
-  getTab: function(text,tabId) {
-    var liel = document.createElement('li');
-    liel.className = 'nav-item';
-    var ael = document.createElement("a");
-    ael.className = "nav-link";
-    ael.setAttribute("style",'padding:10px;');
-    ael.setAttribute("href", "#" + tabId);
-    ael.appendChild(text);
-    liel.appendChild(ael);
-    return liel;
-  },
-  getTopTab: function(text, tabId) {
-    var el = document.createElement('li');
-    el.className = 'nav-item';
-    var a = document.createElement('a');
-    a.className = 'nav-link';
-    a.setAttribute('href','#'+tabId);
-    a.appendChild(text);
-    el.appendChild(a);
-    return el;
-  },
-  markTabActive: function(row) {
-    var el = row.tab.firstChild;
-    el.className = el.className.replace(/\s?active/g,'');
-    el.className += " active";
-    row.container.style.display = '';
-  },
-  markTabInactive: function(row) {
-    var el = row.tab.firstChild;
-    el.className = el.className.replace(/\s?active/g,'');
-    row.container.style.display = 'none';
-  },
-  getProgressBar: function() {
-    var min = 0,
-      max = 100,
-      start = 0;
-
-    var container = document.createElement("div");
-    container.className = "progress";
-
-    var bar = document.createElement("div");
-    bar.className = "progress-bar";
-    bar.setAttribute("role", "progressbar");
-    bar.setAttribute("aria-valuenow", start);
-    bar.setAttribute("aria-valuemin", min);
-    bar.setAttribute("aria-valuenax", max);
-    bar.innerHTML = start + "%";
-    container.appendChild(bar);
-
-    return container;
-  },
-  updateProgressBar: function(progressBar, progress) {
-    if (!progressBar) return;
-
-    var bar = progressBar.firstChild;
-    var percentage = progress + "%";
-    bar.setAttribute("aria-valuenow", progress);
-    bar.style.width = percentage;
-    bar.innerHTML = percentage;
-  },
-  updateProgressBarUnknown: function(progressBar) {
-    if (!progressBar) return;
-
-    var bar = progressBar.firstChild;
-    progressBar.className = "progress progress-striped active";
-    bar.removeAttribute("aria-valuenow");
-    bar.style.width = "100%";
-    bar.innerHTML = "";
-  }
-});
-
-// Base Foundation theme
-JSONEditor.defaults.themes.foundation = JSONEditor.AbstractTheme.extend({
-  getChildEditorHolder: function() {
-    var el = document.createElement('div');
-    el.style.marginBottom = '15px';
-    return el;
-  },
-  getSelectInput: function(options) {
-    var el = this._super(options);
-    el.style.minWidth = 'none';
-    el.style.padding = '5px';
-    el.style.marginTop = '3px';
-    return el;
-  },
-  getSwitcher: function(options) {
-    var el = this._super(options);
-    el.style.paddingRight = '8px';
-    return el;
-  },
-  afterInputReady: function(input) {
-    if(input.group) return;
-    if(this.closest(input,'.compact')) {
-      input.style.marginBottom = 0;
-    }
-    input.group = this.closest(input,'.form-control');
-    if (this.queuedInputErrorText) {
-        var text = this.queuedInputErrorText;
-        delete this.queuedInputErrorText;
-        this.addInputError(input,text);
-    }
-  },
-  getFormInputLabel: function(text) {
-    var el = this._super(text);
-    el.style.display = 'inline-block';
-    return el;
-  },
-  getFormInputField: function(type) {
-    var el = this._super(type);
-    el.style.width = '100%';
-    el.style.marginBottom = type==='checkbox'? '0' : '12px';
-    return el;
-  },
-  getFormInputDescription: function(text) {
-    var el = document.createElement('p');
-    el.textContent = text;
-    el.style.marginTop = '-10px';
-    el.style.fontStyle = 'italic';
-    return el;
-  },
-  getIndentedPanel: function() {
-    var el = document.createElement('div');
-    el.className = 'panel';
-    el.style.paddingBottom = 0;
-    return el;
-  },
-  getHeaderButtonHolder: function() {
-    var el = this.getButtonHolder();
-    el.style.display = 'inline-block';
-    el.style.marginLeft = '10px';
-    el.style.verticalAlign = 'middle';
-    return el;
-  },
-  getButtonHolder: function() {
-    var el = document.createElement('div');
-    el.className = 'button-group';
-    return el;
-  },
-  getButton: function(text, icon, title) {
-    var el = this._super(text, icon, title);
-    el.className += ' small button';
-    return el;
-  },
-  addInputError: function(input,text) {
-    if(!input.group) {
-        this.queuedInputErrorText = text;
-        return;
-    }
-    input.group.className += ' error';
-
-    if(!input.errmsg) {
-      input.insertAdjacentHTML('afterend','<small class="error"></small>');
-      input.errmsg = input.parentNode.getElementsByClassName('error')[0];
-    }
-    else {
-      input.errmsg.style.display = '';
-    }
-
-    input.errmsg.textContent = text;
-  },
-  removeInputError: function(input) {
-    if(!input.group) {
-        delete this.queuedInputErrorText;
-    }
-    if(!input.errmsg) return;
-    input.group.className = input.group.className.replace(/ error/g,'');
-    input.errmsg.style.display = 'none';
-  },
-  getProgressBar: function() {
-    var progressBar = document.createElement('div');
-    progressBar.className = 'progress';
-
-    var meter = document.createElement('span');
-    meter.className = 'meter';
-    meter.style.width = '0%';
-    progressBar.appendChild(meter);
-    return progressBar;
-  },
-  updateProgressBar: function(progressBar, progress) {
-    if (!progressBar) return;
-    progressBar.firstChild.style.width = progress + '%';
-  },
-  updateProgressBarUnknown: function(progressBar) {
-    if (!progressBar) return;
-    progressBar.firstChild.style.width = '100%';
-  }
-});
-
-// Foundation 3 Specific Theme
-JSONEditor.defaults.themes.foundation3 = JSONEditor.defaults.themes.foundation.extend({
-  getHeaderButtonHolder: function() {
-    var el = this._super();
-    el.style.fontSize = '.6em';
-    return el;
-  },
-  getFormInputLabel: function(text) {
-    var el = this._super(text);
-    el.style.fontWeight = 'bold';
-    return el;
-  },
-  getTabHolder: function(propertyName) {
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    var el = document.createElement('div');
-    el.className = 'row';
-    el.innerHTML = '<dl class="tabs vertical two columns" id="' + pName + '"></dl><div class="tabs-content ten columns" id="' + pName + '"></div>';
-    return el;
-  },
-  getTopTabHolder: function(propertyName) {
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    var el = document.createElement('div');
-    el.className = 'row';
-    el.innerHTML = '<dl class="tabs horizontal" style="padding-left: 10px; margin-left: 10px;" id="' + pName + '"></dl><div class="tabs-content twelve columns" style="padding: 10px; margin-left: 10px;" id="' + pName + '"></div>';
-    return el;
-  },
-  setGridColumnSize: function(el,size) {
-    var sizes = ['zero','one','two','three','four','five','six','seven','eight','nine','ten','eleven','twelve'];
-    el.className = 'columns '+sizes[size];
-  },
-  getTab: function(text, tabId) {
-    var el = document.createElement('dd');
-    var a = document.createElement('a');
-    a.setAttribute('href','#'+tabId);
-    a.appendChild(text);
-    el.appendChild(a);
-    return el;
-  },
-  getTopTab: function(text, tabId) {
-    var el = document.createElement('dd');
-    var a = document.createElement('a');
-    a.setAttribute('href','#'+tabId);
-    a.appendChild(text);
-    el.appendChild(a);
-    return el;
-  },
-  getTabContentHolder: function(tab_holder) {
-    return tab_holder.children[1];
-  },
-  getTopTabContentHolder: function(tab_holder) {
-    return tab_holder.children[1];
-  },
-  getTabContent: function() {
-    var el = document.createElement('div');
-    el.className = 'content active';
-    el.style.paddingLeft = '5px';
-    return el;
-  },
-  getTopTabContent: function() {
-    var el = document.createElement('div');
-    el.className = 'content active';
-    el.style.paddingLeft = '5px';
-    return el;
-  },
-  markTabActive: function(row) {
-    row.tab.className = row.tab.className.replace(/\s?active/g,'');
-    row.tab.className += ' active';
-    row.container.style.display = '';
-  },
-  markTabInactive: function(row) {
-    row.tab.className = row.tab.className.replace(/\s?active/g,'');
-    row.container.style.display = 'none';
-  },
-  addTab: function(holder, tab) {
-    holder.children[0].appendChild(tab);
-  },
-  addTopTab: function(holder, tab) {
-    holder.children[0].appendChild(tab);
-  }
-});
-
-// Foundation 4 Specific Theme
-JSONEditor.defaults.themes.foundation4 = JSONEditor.defaults.themes.foundation.extend({
-  getHeaderButtonHolder: function() {
-    var el = this._super();
-    el.style.fontSize = '.6em';
-    return el;
-  },
-  setGridColumnSize: function(el,size) {
-    el.className = 'columns large-'+size;
-  },
-  getFormInputDescription: function(text) {
-    var el = this._super(text);
-    el.style.fontSize = '.8rem';
-    return el;
-  },
-  getFormInputLabel: function(text) {
-    var el = this._super(text);
-    el.style.fontWeight = 'bold';
-    return el;
-  }
-});
-
-// Foundation 5 Specific Theme
-JSONEditor.defaults.themes.foundation5 = JSONEditor.defaults.themes.foundation.extend({
-  getFormInputDescription: function(text) {
-    var el = this._super(text);
-    el.style.fontSize = '.8rem';
-    return el;
-  },
-  setGridColumnSize: function(el,size) {
-    el.className = 'columns medium-'+size;
-  },
-  getButton: function(text, icon, title) {
-    var el = this._super(text,icon,title);
-    el.className = el.className.replace(/\s*small/g,'') + ' tiny';
-    return el;
-  },
-  getTabHolder: function(propertyName) {
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    var el = document.createElement('div');
-    el.innerHTML = '<dl class="tabs vertical" id="' + pName + '"></dl><div class="tabs-content vertical" id="' + pName + '"></div>';
-    return el;
-  },
-  getTopTabHolder: function(propertyName) {
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    var el = document.createElement('div');
-    el.className = 'row';
-    el.innerHTML = '<dl class="tabs horizontal" style="padding-left: 10px;" id="' + pName + '"></dl><div class="tabs-content horizontal" style="padding: 10px;" id="' + pName + '"></div>';
-    return el;
-  },
-  getTab: function(text, tabId) {
-    var el = document.createElement('dd');
-    var a = document.createElement('a');
-    a.setAttribute('href','#'+tabId);
-    a.appendChild(text);
-    el.appendChild(a);
-    return el;
-  },
-  getTopTab: function(text, tabId) {
-    var el = document.createElement('dd');
-    var a = document.createElement('a');
-    a.setAttribute('href','#'+tabId);
-    a.appendChild(text);
-    el.appendChild(a);
-    return el;
-  },
-  getTabContentHolder: function(tab_holder) {
-    return tab_holder.children[1];
-  },
-  getTopTabContentHolder: function(tab_holder) {
-    return tab_holder.children[1];
-  },
-  getTabContent: function() {
-    var el = document.createElement('div');
-    el.className = 'tab-content active';
-    el.style.paddingLeft = '5px';
-    return el;
-  },
-  getTopTabContent: function() {
-    var el = document.createElement('div');
-    el.className = 'tab-content active';
-    el.style.paddingLeft = '5px';
-    return el;
-  },
-  markTabActive: function(row) {
-    row.tab.className = row.tab.className.replace(/\s?active/g,'');
-    row.tab.className += ' active';
-    row.container.style.display = '';
-  },
-  markTabInactive: function(row) {
-    row.tab.className = row.tab.className.replace(/\s?active/g,'');
-    row.container.style.display = 'none';
-  },
-  addTab: function(holder, tab) {
-    holder.children[0].appendChild(tab);
-  },
-  addTopTab: function(holder, tab) {
-    holder.children[0].appendChild(tab);
-  }
-
-});
-
-JSONEditor.defaults.themes.foundation6 = JSONEditor.defaults.themes.foundation5.extend({
-  getIndentedPanel: function() {
-    var el = document.createElement('div');
-    el.className = 'callout secondary';
-    el.className.style = 'padding-left: 10px; margin-left: 10px;';
-    return el;
-  },
-  getButtonHolder: function() {
-    var el = document.createElement('div');
-    el.className = 'button-group tiny';
-    el.style.marginBottom = 0;
-    return el;
-  },
-  getFormInputLabel: function(text) {
-    var el = this._super(text);
-    el.style.display = 'block';
-    return el;
-  },
-  getFormControl: function(label, input, description, infoText) {
-    var el = document.createElement('div');
-    el.className = 'form-control';
-    if(label) el.appendChild(label);
-    if(input.type === 'checkbox') {
-      label.insertBefore(input,label.firstChild);
-    }
-    else if (label) {
-      if(infoText) label.appendChild(infoText);
-      label.appendChild(input);
-    } else {
-      if(infoText) el.appendChild(infoText);
-      el.appendChild(input);
-    }
-
-    if(description) label.appendChild(description);
-    return el;
-  },
-  addInputError: function(input,text) {
-    if(!input.group) return;
-    input.group.className += ' error';
-
-    if(!input.errmsg) {
-      var errorEl = document.createElement('span');
-      errorEl.className = 'form-error is-visible';
-      input.group.getElementsByTagName('label')[0].appendChild(errorEl);
-
-      input.className = input.className + ' is-invalid-input';
-
-      input.errmsg = errorEl;
-    }
-    else {
-      input.errmsg.style.display = '';
-      input.className = '';
-    }
-
-    input.errmsg.textContent = text;
-  },
-  removeInputError: function(input) {
-    if(!input.errmsg) return;
-    input.className = input.className.replace(/ is-invalid-input/g,'');
-    if(input.errmsg.parentNode) {
-      input.errmsg.parentNode.removeChild(input.errmsg);
-    }
-  },
-  getTabHolder: function(propertyName) {
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    var el = document.createElement('div');
-    el.className = 'grid-x';
-    el.innerHTML = '<div class="medium-2 cell" style="float: left;"><ul class="vertical tabs" data-tabs id="' + pName + '"></ul></div><div class="medium-10 cell" style="float: left;"><div class="tabs-content" data-tabs-content="'+pName+'"></div></div>';
-    return el;
-  },
-  getTopTabHolder: function(propertyName) {
-    var pName = (typeof propertyName === 'undefined')? "" : propertyName;
-    var el = document.createElement('div');
-    el.className = 'grid-y';
-    el.innerHTML = '<div className="cell"><ul class="tabs" data-tabs id="' + pName + '"></ul><div class="tabs-content" data-tabs-content="' + pName + '"></div></div>';
-    return el;
-
-
-  },
-  insertBasicTopTab: function(tab, newTabs_holder ) {
-    newTabs_holder.firstChild.firstChild.insertBefore(tab,newTabs_holder.firstChild.firstChild.firstChild);
-  },
-  getTab: function(text, tabId) {
-    var el = document.createElement('li');
-    el.className = 'tabs-title';
-    var a = document.createElement('a');
-    a.setAttribute('href','#'+tabId);
-    a.appendChild(text);
-    el.appendChild(a);
-    return el;
-  },
-  getTopTab: function(text, tabId) {
-    var el = document.createElement('li');
-    el.className = 'tabs-title';
-    var a = document.createElement('a');
-    a.setAttribute('href','#' + tabId);
-    a.appendChild(text);
-    el.appendChild(a);
-    return el;
-  },
-  getTabContentHolder: function(tab_holder) {
-    return tab_holder.children[1].firstChild;
-  },
-  getTopTabContentHolder: function(tab_holder) {
-    return tab_holder.firstChild.children[1];
-  },
-  getTabContent: function() {
-    var el = document.createElement('div');
-    el.className = 'tabs-panel';
-    el.style.paddingLeft = '5px';
-    return el;
-  },
-  getTopTabContent: function() {
-    var el = document.createElement('div');
-    el.className = 'tabs-panel';
-    el.style.paddingLeft = '5px';
-    return el;
-  },
-  markTabActive: function(row) {
-    row.tab.className = row.tab.className.replace(/\s?is-active/g,'');
-    row.tab.className += ' is-active';
-    row.tab.firstChild.setAttribute('aria-selected', 'true');
-
-    row.container.className  = row.container.className.replace(/\s?is-active/g,'');
-    row.container.className += ' is-active';
-    row.container.setAttribute('aria-selected', 'true');
-  },
-  markTabInactive: function(row) {
-    row.tab.className = row.tab.className.replace(/\s?is-active/g,'');
-    row.tab.firstChild.removeAttribute('aria-selected');
-
-    row.container.className = row.container.className.replace(/\s?is-active/g,'');
-    row.container.removeAttribute('aria-selected');
-  },
-  addTab: function(holder, tab) {
-    holder.children[0].firstChild.appendChild(tab);
-  },
-  addTopTab: function(holder, tab) {
-    holder.firstChild.children[0].appendChild(tab);
-  },
-  getFirstTab: function(holder){
-    return holder.firstChild.firstChild.firstChild;
-  }
-});
-
-JSONEditor.defaults.themes.html = JSONEditor.AbstractTheme.extend({
-  getFormInputLabel: function(text) {
-    var el = this._super(text);
-    el.style.display = 'block';
-    el.style.marginBottom = '3px';
-    el.style.fontWeight = 'bold';
-    return el;
-  },
-  getFormInputDescription: function(text) {
-    var el = this._super(text);
-    el.style.fontSize = '.8em';
-    el.style.margin = 0;
-    el.style.display = 'inline-block';
-    el.style.fontStyle = 'italic';
-    return el;
-  },
-  getIndentedPanel: function() {
-    var el = this._super();
-    el.style.border = '1px solid #ddd';
-    el.style.padding = '5px';
-    el.style.margin = '10px';
-    el.style.borderRadius = '3px';
-    return el;
-  },
-  getTopIndentedPanel: function() {
-    return this.getIndentedPanel();
-  },
-  getChildEditorHolder: function() {
-    var el = this._super();
-    el.style.marginBottom = '8px';
-    return el;
-  },
-  getHeaderButtonHolder: function() {
-    var el = this.getButtonHolder();
-    el.style.display = 'inline-block';
-    el.style.marginLeft = '10px';
-    el.style.fontSize = '.8em';
-    el.style.verticalAlign = 'middle';
-    return el;
-  },
-  getTable: function() {
-    var el = this._super();
-    el.style.borderBottom = '1px solid #ccc';
-    el.style.marginBottom = '5px';
-    return el;
-  },
-  addInputError: function(input, text) {
-    input.style.borderColor = 'red';
-    
-    if(!input.errmsg) {
-      var group = this.closest(input,'.form-control');
-      input.errmsg = document.createElement('div');
-      input.errmsg.setAttribute('class','errmsg');
-      input.errmsg.style = input.errmsg.style || {};
-      input.errmsg.style.color = 'red';
-      group.appendChild(input.errmsg);
-    }
-    else {
-      input.errmsg.style.display = 'block';
-    }
-    
-    input.errmsg.innerHTML = '';
-    input.errmsg.appendChild(document.createTextNode(text));
-  },
-  removeInputError: function(input) {
-    input.style.borderColor = '';
-    if(input.errmsg) input.errmsg.style.display = 'none';
-  },
-  getProgressBar: function() {
-    var max = 100, start = 0;
-
-    var progressBar = document.createElement('progress');
-    progressBar.setAttribute('max', max);
-    progressBar.setAttribute('value', start);
-    return progressBar;
-  },
-  updateProgressBar: function(progressBar, progress) {
-    if (!progressBar) return;
-    progressBar.setAttribute('value', progress);
-  },
-  updateProgressBarUnknown: function(progressBar) {
-    if (!progressBar) return;
-    progressBar.removeAttribute('value');
-  }
-});
-
-JSONEditor.defaults.themes.jqueryui = JSONEditor.AbstractTheme.extend({
-  getTable: function() {
-    var el = this._super();
-    el.setAttribute('cellpadding',5);
-    el.setAttribute('cellspacing',0);
-    return el;
-  },
-  getTableHeaderCell: function(text) {
-    var el = this._super(text);
-    el.className = 'ui-state-active';
-    el.style.fontWeight = 'bold';
-    return el;
-  },
-  getTableCell: function() {
-    var el = this._super();
-    el.className = 'ui-widget-content';
-    return el;
-  },
-  getHeaderButtonHolder: function() {
-    var el = this.getButtonHolder();
-    el.style.marginLeft = '10px';
-    el.style.fontSize = '.6em';
-    el.style.display = 'inline-block';
-    return el;
-  },
-  getFormInputDescription: function(text) {
-    var el = this.getDescription(text);
-    el.style.marginLeft = '10px';
-    el.style.display = 'inline-block';
-    return el;
-  },
-  getFormControl: function(label, input, description, infoText) {
-    var el = this._super(label,input,description, infoText);
-    if(input.type === 'checkbox') {
-      el.style.lineHeight = '25px';
-
-      el.style.padding = '3px 0';
-    }
-    else {
-      el.style.padding = '4px';
-    }
-    return el;
-  },
-  getDescription: function(text) {
-    var el = document.createElement('span');
-    el.style.fontSize = '.8em';
-    el.style.fontStyle = 'italic';
-    el.textContent = text;
-    return el;
-  },
-  getButtonHolder: function() {
-    var el = document.createElement('div');
-    el.className = 'ui-buttonset';
-    el.style.fontSize = '.7em';
-    return el;
-  },
-  getFormInputLabel: function(text) {
-    var el = document.createElement('label');
-    el.style.fontWeight = 'bold';
-    el.style.display = 'block';
-    el.textContent = text;
-    return el;
-  },
-  getButton: function(text, icon, title) {
-    var button = document.createElement("button");
-    button.className = 'ui-button ui-widget ui-state-default ui-corner-all';
-
-    // Icon only
-    if(icon && !text) {
-      button.className += ' ui-button-icon-only';
-      icon.className += ' ui-button-icon-primary ui-icon-primary';
-      button.appendChild(icon);
-    }
-    // Icon and Text
-    else if(icon) {
-      button.className += ' ui-button-text-icon-primary';
-      icon.className += ' ui-button-icon-primary ui-icon-primary';
-      button.appendChild(icon);
-    }
-    // Text only
-    else {
-      button.className += ' ui-button-text-only';
-    }
-
-    var el = document.createElement('span');
-    el.className = 'ui-button-text';
-    el.textContent = text||title||".";
-    button.appendChild(el);
-
-    button.setAttribute('title',title);
-
-    return button;
-  },
-  setButtonText: function(button,text, icon, title) {
-    button.innerHTML = '';
-    button.className = 'ui-button ui-widget ui-state-default ui-corner-all';
-
-    // Icon only
-    if(icon && !text) {
-      button.className += ' ui-button-icon-only';
-      icon.className += ' ui-button-icon-primary ui-icon-primary';
-      button.appendChild(icon);
-    }
-    // Icon and Text
-    else if(icon) {
-      button.className += ' ui-button-text-icon-primary';
-      icon.className += ' ui-button-icon-primary ui-icon-primary';
-      button.appendChild(icon);
-    }
-    // Text only
-    else {
-      button.className += ' ui-button-text-only';
-    }
-
-    var el = document.createElement('span');
-    el.className = 'ui-button-text';
-    el.textContent = text||title||".";
-    button.appendChild(el);
-
-    button.setAttribute('title',title);
-  },
-  getIndentedPanel: function() {
-    var el = document.createElement('div');
-    el.className = 'ui-widget-content ui-corner-all';
-    el.style.padding = '1em 1.4em';
-    el.style.marginBottom = '20px';
-    return el;
-  },
-  afterInputReady: function(input) {
-    if(input.controls) return;
-    input.controls = this.closest(input,'.form-control');
-    if (this.queuedInputErrorText) {
-        var text = this.queuedInputErrorText;
-        delete this.queuedInputErrorText;
-        this.addInputError(input,text);
-    }
-  },
-  addInputError: function(input,text) {
-    if(!input.controls) {
-        this.queuedInputErrorText = text;
-        return;
-    }
-    if(!input.errmsg) {
-      input.errmsg = document.createElement('div');
-      input.errmsg.className = 'ui-state-error';
-      input.controls.appendChild(input.errmsg);
-    }
-    else {
-      input.errmsg.style.display = '';
-    }
-
-    input.errmsg.textContent = text;
-  },
-  removeInputError: function(input) {
-    if(!input.controls) {
-        delete this.queuedInputErrorText;
-    }
-    if(!input.errmsg) return;
-    input.errmsg.style.display = 'none';
-  },
-  markTabActive: function(row) {
-    row.tab.className = row.tab.className.replace(/\s?ui-widget-header/g,'').replace(/\s?ui-state-active/g,'')+' ui-state-active';
-    row.container.style.display = '';
-  },
-  markTabInactive: function(row) {
-    row.tab.className = row.tab.className.replace(/\s?ui-state-active/g,'').replace(/\s?ui-widget-header/g,'')+' ui-widget-header';
-    row.container.style.display = 'none';
-  }
-});
-
-JSONEditor.defaults.themes.barebones = JSONEditor.AbstractTheme.extend({
-    getFormInputLabel: function (text) {
-        var el = this._super(text);
-        return el;
-    },
-    getFormInputDescription: function (text) {
-        var el = this._super(text);
-        return el;
-    },
-    getIndentedPanel: function () {
-        var el = this._super();
-        return el;
-    },
-    getChildEditorHolder: function () {
-        var el = this._super();
-        return el;
-    },
-    getHeaderButtonHolder: function () {
-        var el = this.getButtonHolder();
-        return el;
-    },
-    getTable: function () {
-        var el = this._super();
-        return el;
-    },
-    addInputError: function (input, text) {
-        if (!input.errmsg) {
-            var group = this.closest(input, '.form-control');
-            input.errmsg = document.createElement('div');
-            input.errmsg.setAttribute('class', 'errmsg');
-            group.appendChild(input.errmsg);
-        }
-        else {
-            input.errmsg.style.display = 'block';
-        }
-
-        input.errmsg.innerHTML = '';
-        input.errmsg.appendChild(document.createTextNode(text));
-    },
-    removeInputError: function (input) {
-        input.style.borderColor = '';
-        if (input.errmsg) input.errmsg.style.display = 'none';
-    },
-    getProgressBar: function () {
-        var max = 100, start = 0;
-
-        var progressBar = document.createElement('progress');
-        progressBar.setAttribute('max', max);
-        progressBar.setAttribute('value', start);
-        return progressBar;
-    },
-    updateProgressBar: function (progressBar, progress) {
-        if (!progressBar) return;
-        progressBar.setAttribute('value', progress);
-    },
-    updateProgressBarUnknown: function (progressBar) {
-        if (!progressBar) return;
-        progressBar.removeAttribute('value');
-    }
-});
-
-JSONEditor.defaults.themes.materialize = JSONEditor.AbstractTheme.extend({
-
-    /**
-     * Applies grid size to specified element.
-     * 
-     * @param {HTMLElement} el The DOM element to have specified size applied.
-     * @param {int} size The grid column size.
-     * @see http://materializecss.com/grid.html
-     */
-    setGridColumnSize: function(el, size) {
-        el.className = 'col s' + size;
-    },
-
-    /**
-     * Gets a wrapped button element for a header.
-     * 
-     * @returns {HTMLElement} The wrapped button element.
-     */
-    getHeaderButtonHolder: function() {
-        return this.getButtonHolder();
-    },
-
-    /**
-     * Gets a wrapped button element.
-     * 
-     * @returns {HTMLElement} The wrapped button element.
-     */
-    getButtonHolder: function() {
-        return document.createElement('span');
-    },
-
-    /**
-     * Gets a single button element.
-     * 
-     * @param {string} text The button text.
-     * @param {HTMLElement} icon The icon object.
-     * @param {string} title The button title.
-     * @returns {HTMLElement} The button object.
-     * @see http://materializecss.com/buttons.html
-     */
-    getButton: function(text, icon, title) {
-
-        // Prepare icon.
-        if (text) {
-            icon.className += ' left';
-            icon.style.marginRight = '5px';
-        }
-
-        // Create and return button.
-        var el = this._super(text, icon, title);
-        el.className = 'waves-effect waves-light btn';
-        el.style.fontSize = '0.75rem';
-        el.style.height = '20px';
-        el.style.lineHeight = '20px';
-        el.style.marginLeft = '4px';
-        el.style.padding = '0 0.5rem';
-        return el;
-
-    },
-
-    /**
-     * Gets a form control object consisiting of several sub objects.
-     * 
-     * @param {HTMLElement} label The label element.
-     * @param {HTMLElement} input The input element.
-     * @param {string} description The element description.
-     * @param {string} infoText The element information text.
-     * @returns {HTMLElement} The assembled DOM element.
-     * @see http://materializecss.com/forms.html
-     */
-    getFormControl: function(label, input, description, infoText) {
-
-        var ctrl,
-            type = input.type;
-
-        // Checkboxes get wrapped in p elements.
-        if (type && type === 'checkbox') {
-
-            ctrl = document.createElement('p');
-            ctrl.appendChild(input);
-            if (label) {
-                label.setAttribute('for', input.id);
-                ctrl.appendChild(label);
-            }
-            return ctrl;
-
-        }
-
-        // Anything else gets wrapped in divs.
-        ctrl = this._super(label, input, description, infoText);
-
-        // Not .input-field for select wrappers.
-        if (!type || !type.startsWith('select'))
-            ctrl.className = 'input-field';
-
-        // Color needs special attention.
-        if (type && type === 'color') {
-            input.style.height = '3rem';
-            input.style.width = '100%';
-            input.style.margin = '5px 0 20px 0';
-            input.style.padding = '3px';
-
-            if (label) {
-                label.style.transform = 'translateY(-14px) scale(0.8)';
-                label.style['-webkit-transform'] = 'translateY(-14px) scale(0.8)';
-                label.style['-webkit-transform-origin'] = '0 0';
-                label.style['transform-origin'] = '0 0';
-            }
-        }
-
-        return ctrl;
-
-    },
-
-    getDescription: function(text) {
-        var el = document.createElement('div');
-        el.className = 'grey-text';
-        el.style.marginTop = '-15px';
-        el.innerHTML = text;
-        return el;
-    },
-
-    /**
-     * Gets a header element.
-     * 
-     * @param {string|HTMLElement} text The header text or element.
-     * @returns {HTMLElement} The header element.
-     */
-    getHeader: function(text) {
-
-        var el = document.createElement('h5');
-
-        if (typeof text === 'string') {
-          el.textContent = text;
-        } else {
-          el.appendChild(text);
-        }
-    
-        return el;
-
-    },
-
-    getChildEditorHolder: function() {
-
-        var el = document.createElement('div');
-        el.marginBottom = '10px';
-        return el;
-
-    },
-
-    getIndentedPanel: function() {
-        var el = document.createElement("div");
-        el.className = "card-panel";
-        return el;
-    },
-
-    getTable: function() {
-
-        var el = document.createElement('table');
-        el.className = 'striped bordered';
-        el.style.marginBottom = '10px';
-        return el;
-
-    },
-
-    getTableRow: function() {
-        return document.createElement('tr');
-    },
-
-    getTableHead: function() {
-        return document.createElement('thead');
-    },
-
-    getTableBody: function() {
-        return document.createElement('tbody');
-    },
-
-    getTableHeaderCell: function(text) {
-
-        var el = document.createElement('th');
-        el.textContent = text;
-        return el;
-
-    },
-
-    getTableCell: function() {
-
-        var el = document.createElement('td');
-        return el;
-
-    },
-
-    /**
-     * Gets the tab holder element.
-     * 
-     * @returns {HTMLElement} The tab holder component.
-     * @see https://github.com/Dogfalo/materialize/issues/2542#issuecomment-233458602
-     */
-    getTabHolder: function() {
-
-        var html = [
-            '<div class="col s2">',
-            '   <ul class="tabs" style="height: auto; margin-top: 0.82rem; -ms-flex-direction: column; -webkit-flex-direction: column; flex-direction: column; display: -webkit-flex; display: flex;">',
-            '   </ul>',
-            '</div>',
-            '<div class="col s10">',
-            '<div>'
-        ].join("\n");
-
-        var el = document.createElement('div');
-        el.className = 'row card-panel';
-        el.innerHTML = html;
-        return el;
-
-    },
-
-    /**
-     * Add specified tab to specified holder element.
-     * 
-     * @param {HTMLElement} holder The tab holder element.
-     * @param {HTMLElement} tab The tab to add.
-     */
-    addTab: function(holder, tab) {
-        holder.children[0].children[0].appendChild(tab);
-    },
-
-    /**
-     * Gets a single tab element.
-     * 
-     * @param {HTMLElement} span The tab's content.
-     * @returns {HTMLElement} The tab element.
-     * @see https://github.com/Dogfalo/materialize/issues/2542#issuecomment-233458602
-     */
-    getTab: function(span) {
-
-        var el = document.createElement('li');
-        el.className = 'tab';
-        this.applyStyles(el, {
-            width: '100%',
-            textAlign: 'left',
-            lineHeight: '24px',
-            height: '24px',
-            fontSize: '14px',
-            cursor: 'pointer'
-        });
-        el.appendChild(span);
-        return el;
-    },
-
-    /**
-     * Marks specified tab as active.
-     * 
-     * @returns {HTMLElement} The tab element.
-     * @see https://github.com/Dogfalo/materialize/issues/2542#issuecomment-233458602
-     */
-    markTabActive: function(tab) {
-
-        this.applyStyles(tab, {
-            width: '100%',
-            textAlign: 'left',
-            lineHeight: '24px',
-            height: '24px',
-            fontSize: '14px',
-            cursor: 'pointer',
-            color: 'rgba(238,110,115,1)',
-            transition: 'border-color .5s ease',
-            borderRight: '3px solid #424242'
-        });
-
-    },
-
-    /**
-     * Marks specified tab as inactive.
-     * 
-     * @returns {HTMLElement} The tab element.
-     * @see https://github.com/Dogfalo/materialize/issues/2542#issuecomment-233458602
-     */
-    markTabInactive: function(tab) {
-
-        this.applyStyles(tab, {
-            width: '100%',
-            textAlign: 'left',
-            lineHeight: '24px',
-            height: '24px',
-            fontSize: '14px',
-            cursor: 'pointer',
-            color: 'rgba(238,110,115,0.7)'
-        });
-
-    },
-
-    /**
-     * Returns the element that holds the tab contents.
-     * 
-     * @param {HTMLElement} tabHolder The full tab holder element.
-     * @returns {HTMLElement} The content element inside specified tab holder.
-     */
-    getTabContentHolder: function(tabHolder) {
-        return tabHolder.children[1];
-    },
-
-    /**
-     * Creates and returns a tab content element.
-     * 
-     * @returns {HTMLElement} The new tab content element.
-     */
-    getTabContent: function() {
-        return document.createElement('div');
-    },
-
-    /**
-     * Adds an error message to the specified input element.
-     * 
-     * @param {HTMLElement} input The input element that caused the error.
-     * @param {string} text The error message.
-     */
-    addInputError: function(input, text) {
-
-        // Get the parent element. Should most likely be a <div class="input-field" ... />.
-        var parent = input.parentNode,
-            el;
-
-        if (!parent) return;
-
-        // Remove any previous error.
-        this.removeInputError(input);
-
-        // Append an error message div.
-        el = document.createElement('div');
-        el.className = 'error-text red-text';
-        el.textContent = text;
-        parent.appendChild(el);
-
-    },
-
-    /**
-     * Removes any error message from the specified input element.
-     * 
-     * @param {HTMLElement} input The input element that previously caused the error.
-     */
-    removeInputError: function(input) {
-
-        // Get the parent element. Should most likely be a <div class="input-field" ... />.
-        var parent = input.parentElement,
-            els;
-
-        if (!parent) return;
-
-        // Remove all elements having class .error-text.
-        els = parent.getElementsByClassName('error-text');
-        for (var i = 0; i < els.length; i++)
-            parent.removeChild(els[i]);
-
-    },
-
-    addTableRowError: function(row) {
-    },
-
-    removeTableRowError: function(row) {
-    },
-
-    /**
-     * Gets a select DOM element.
-     * 
-     * @param {object} options The option values.
-     * @return {HTMLElement} The DOM element.
-     * @see http://materializecss.com/forms.html#select
-     */
-    getSelectInput: function(options) {
-
-        var select = this._super(options);
-        select.className = 'browser-default';
-        return select;
-
-    },
-
-    /**
-     * Gets a textarea DOM element.
-     * 
-     * @returns {HTMLElement} The DOM element.
-     * @see http://materializecss.com/forms.html#textarea
-     */
-    getTextareaInput: function() {
-        var el = document.createElement('textarea');
-        el.style.marginBottom = '5px';
-        el.style.fontSize = '1rem';
-        el.style.fontFamily = 'monospace';
-        return el;
-    },
-
-    getCheckbox: function() {
-
-        var el = this.getFormInputField('checkbox');
-        el.id = this.createUuid();
-        return el;
-
-    },
-
-    /**
-     * Gets the modal element for displaying Edit JSON and Properties dialogs.
-     * 
-     * @returns {HTMLElement} The modal DOM element.
-     * @see http://materializecss.com/cards.html
-     */
-    getModal: function() {
-
-        var el = document.createElement('div');
-        el.className = 'card-panel z-depth-3';
-        el.style.padding = '5px';
-        el.style.position = 'absolute';
-        el.style.zIndex = '10';
-        el.style.display = 'none';
-        return el;
-
-    },
-
-    /**
-     * Creates and returns a RFC4122 version 4 compliant unique id.
-     * 
-     * @returns {string} A GUID.
-     * @see https://stackoverflow.com/a/2117523
-     */
-    createUuid: function() {
-
-        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
-            var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
-            return v.toString(16);
-        });
-
-    }
-
-});
-
-JSONEditor.AbstractIconLib = Class.extend({
-  mapping: {
-    collapse: '',
-    expand: '',
-    "delete": '',
-    edit: '',
-    add: '',
-    cancel: '',
-    save: '',
-    moveup: '',
-    movedown: ''
-  },
-  icon_prefix: '',
-  getIconClass: function(key) {
-    if(this.mapping[key]) return this.icon_prefix+this.mapping[key];
-    else return null;
-  },
-  getIcon: function(key) {
-    var iconclass = this.getIconClass(key);
-    
-    if(!iconclass) return null;
-    
-    var i = document.createElement('i');
-    i.className = iconclass;
-    return i;
-  }
-});
-
-JSONEditor.defaults.iconlibs.bootstrap2 = JSONEditor.AbstractIconLib.extend({
-  mapping: {
-    collapse: 'chevron-down',
-    expand: 'chevron-up',
-    "delete": 'trash',
-    edit: 'pencil',
-    add: 'plus',
-    cancel: 'ban-circle',
-    save: 'ok',
-    moveup: 'arrow-up',
-    movedown: 'arrow-down'
-  },
-  icon_prefix: 'glyphicon glyphicon-'
-});
-
-JSONEditor.defaults.iconlibs.bootstrap3 = JSONEditor.AbstractIconLib.extend({
-  mapping: {
-    collapse: 'chevron-down',
-    expand: 'chevron-right',
-    "delete": 'remove',
-    edit: 'pencil',
-    add: 'plus',
-    cancel: 'floppy-remove',
-    save: 'floppy-saved',
-    moveup: 'arrow-up',
-    movedown: 'arrow-down'
-  },
-  icon_prefix: 'glyphicon glyphicon-'
-});
-
-JSONEditor.defaults.iconlibs.fontawesome3 = JSONEditor.AbstractIconLib.extend({
-  mapping: {
-    collapse: 'chevron-down',
-    expand: 'chevron-right',
-    "delete": 'remove',
-    edit: 'pencil',
-    add: 'plus',
-    cancel: 'ban-circle',
-    save: 'save',
-    moveup: 'arrow-up',
-    movedown: 'arrow-down'
-  },
-  icon_prefix: 'icon-'
-});
-
-JSONEditor.defaults.iconlibs.fontawesome4 = JSONEditor.AbstractIconLib.extend({
-  mapping: {
-    collapse: 'caret-square-o-down',
-    expand: 'caret-square-o-right',
-    "delete": 'times',
-    edit: 'pencil',
-    add: 'plus',
-    cancel: 'ban',
-    save: 'save',
-    moveup: 'arrow-up',
-    movedown: 'arrow-down',
-    copy: 'files-o'
-  },
-  icon_prefix: 'fa fa-'
-});
-
-JSONEditor.defaults.iconlibs.foundation2 = JSONEditor.AbstractIconLib.extend({
-  mapping: {
-    collapse: 'minus',
-    expand: 'plus',
-    "delete": 'remove',
-    edit: 'edit',
-    add: 'add-doc',
-    cancel: 'error',
-    save: 'checkmark',
-    moveup: 'up-arrow',
-    movedown: 'down-arrow'
-  },
-  icon_prefix: 'foundicon-'
-});
-
-JSONEditor.defaults.iconlibs.foundation3 = JSONEditor.AbstractIconLib.extend({
-  mapping: {
-    collapse: 'minus',
-    expand: 'plus',
-    "delete": 'x',
-    edit: 'pencil',
-    add: 'page-add',
-    cancel: 'x-circle',
-    save: 'save',
-    moveup: 'arrow-up',
-    movedown: 'arrow-down'
-  },
-  icon_prefix: 'fi-'
-});
-
-JSONEditor.defaults.iconlibs.jqueryui = JSONEditor.AbstractIconLib.extend({
-  mapping: {
-    collapse: 'triangle-1-s',
-    expand: 'triangle-1-e',
-    "delete": 'trash',
-    edit: 'pencil',
-    add: 'plusthick',
-    cancel: 'closethick',
-    save: 'disk',
-    moveup: 'arrowthick-1-n',
-    movedown: 'arrowthick-1-s'
-  },
-  icon_prefix: 'ui-icon ui-icon-'
-});
-
-JSONEditor.defaults.iconlibs.materialicons = JSONEditor.AbstractIconLib.extend({
-
-    mapping: {
-        collapse: 'arrow_drop_up',
-        expand: 'arrow_drop_down',
-        "delete": 'delete',
-        edit: 'edit',
-        add: 'add',
-        cancel: 'cancel',
-        save: 'save',
-        moveup: 'arrow_upward',
-        movedown: 'arrow_downward',
-        copy: 'content_copy'
-    },
-
-    icon_class: 'material-icons',
-    icon_prefix: '',
-
-    getIconClass: function(key) {
-
-        // This method is unused.
-
-        return this.icon_class;
-    },
-
-    getIcon: function(key) {
-
-        // Get the mapping.
-        var mapping = this.mapping[key];
-        if (!mapping) return null;
-
-        // @see http://materializecss.com/icons.html
-        var i = document.createElement('i');
-        i.className = this.icon_class;
-        var t = document.createTextNode(mapping);
-        i.appendChild(t);
-        return i;
-
-    }
-});
-
-JSONEditor.defaults.templates["default"] = function() {
-  return {
-    compile: function(template) {
-      var matches = template.match(/{{\s*([a-zA-Z0-9\-_ \.]+)\s*}}/g);
-      var l = matches && matches.length;
-
-      // Shortcut if the template contains no variables
-      if(!l) return function() { return template; };
-
-      // Pre-compute the search/replace functions
-      // This drastically speeds up template execution
-      var replacements = [];
-      var get_replacement = function(i) {
-        var p = matches[i].replace(/[{}]+/g,'').trim().split('.');
-        var n = p.length;
-        var func;
-        
-        if(n > 1) {
-          var cur;
-          func = function(vars) {
-            cur = vars;
-            for(i=0; i<n; i++) {
-              cur = cur[p[i]];
-              if(!cur) break;
-            }
-            return cur;
-          };
-        }
-        else {
-          p = p[0];
-          func = function(vars) {
-            return vars[p];
-          };
-        }
-        
-        replacements.push({
-          s: matches[i],
-          r: func
-        });
-      };
-      for(var i=0; i<l; i++) {
-        get_replacement(i);
-      }
-
-      // The compiled function
-      return function(vars) {
-        var ret = template+"";
-        var r;
-        for(i=0; i<l; i++) {
-          r = replacements[i];
-          ret = ret.replace(r.s, r.r(vars));
-        }
-        return ret;
-      };
-    }
-  };
-};
-
-JSONEditor.defaults.templates.ejs = function() {
-  if(!window.EJS) return false;
-
-  return {
-    compile: function(template) {
-      var compiled = new window.EJS({
-        text: template
-      });
-
-      return function(context) {
-        return compiled.render(context);
-      };
-    }
-  };
-};
-
-JSONEditor.defaults.templates.handlebars = function() {
-  return window.Handlebars;
-};
-
-JSONEditor.defaults.templates.hogan = function() {
-  if(!window.Hogan) return false;
-
-  return {
-    compile: function(template) {
-      var compiled = window.Hogan.compile(template);
-      return function(context) {
-        return compiled.render(context);
-      };
-    }
-  };
-};
-
-JSONEditor.defaults.templates.lodash = function() {
-  if(!window._) return false;
-
-  return {
-    compile: function(template) {
-      return function(context) {
-        return window._.template(template)(context);
-      };
-    }
-  };
-};
-
-JSONEditor.defaults.templates.markup = function() {
-  if(!window.Mark || !window.Mark.up) return false;
-
-  return {
-    compile: function(template) {
-      return function(context) {
-        return window.Mark.up(template,context);
-      };
-    }
-  };
-};
-
-JSONEditor.defaults.templates.mustache = function() {
-  if(!window.Mustache) return false;
-
-  return {
-    compile: function(template) {
-      return function(view) {
-        return window.Mustache.render(template, view);
-      };
-    }
-  };
-};
-
-JSONEditor.defaults.templates.swig = function() {
-  return window.swig;
-};
-
-JSONEditor.defaults.templates.underscore = function() {
-  if(!window._) return false;
-
-  return {
-    compile: function(template) {
-      return function(context) {
-        return window._.template(template, context);
-      };
-    }
-  };
-};
-
-// Set the default theme
-JSONEditor.defaults.theme = 'html';
-
-// Set the default template engine
-JSONEditor.defaults.template = 'default';
-
-// Default options when initializing JSON Editor
-JSONEditor.defaults.options = {};
-
-JSONEditor.defaults.options.prompt_before_delete = true;
-
-// String translate function
-JSONEditor.defaults.translate = function(key, variables) {
-  var lang = JSONEditor.defaults.languages[JSONEditor.defaults.language];
-  if(!lang) throw "Unknown language "+JSONEditor.defaults.language;
-  
-  var string = lang[key] || JSONEditor.defaults.languages[JSONEditor.defaults.default_language][key];
-  
-  if(typeof string === "undefined") throw "Unknown translate string "+key;
-  
-  if(variables) {
-    for(var i=0; i<variables.length; i++) {
-      string = string.replace(new RegExp('\\{\\{'+i+'}}','g'),variables[i]);
-    }
-  }
-  
-  return string;
-};
-
-// Translation strings and default languages
-JSONEditor.defaults.default_language = 'en';
-JSONEditor.defaults.language = JSONEditor.defaults.default_language;
-JSONEditor.defaults.languages.en = {
-  /**
-   * When a property is not set
-   */
-  error_notset: 'Please populate the required property "{{0}}"',
-  /**
-   * When a string must not be empty
-   */
-  error_notempty: 'Please populate the required property "{{0}}"',
-  /**
-   * When a value is not one of the enumerated values
-   */
-  error_enum: "{{0}} must be one of the enumerated values",
-  /**
-   * When a value doesn't validate any schema of a 'anyOf' combination
-   */
-  error_anyOf: "Value must validate against at least one of the provided schemas",
-  /**
-   * When a value doesn't validate
-   * @variables This key takes one variable: The number of schemas the value does not validate
-   */
-  error_oneOf: 'Value must validate against exactly one of the provided schemas. It currently validates against {{0}} of the schemas.',
-  /**
-   * When a value does not validate a 'not' schema
-   */
-  error_not: "Value must not validate against the provided schema",
-  /**
-   * When a value does not match any of the provided types
-   */
-  error_type_union: "Value must be one of the provided types",
-  /**
-   * When a value does not match the given type
-   * @variables This key takes one variable: The type the value should be of
-   */
-  error_type: "Value must be of type {{0}}",
-  /**
-   *  When the value validates one of the disallowed types
-   */
-  error_disallow_union: "Value must not be one of the provided disallowed types",
-  /**
-   *  When the value validates a disallowed type
-   * @variables This key takes one variable: The type the value should not be of
-   */
-  error_disallow: "Value must not be of type {{0}}",
-  /**
-   * When a value is not a multiple of or divisible by a given number
-   * @variables This key takes one variable: The number mentioned above
-   */
-  error_multipleOf: "Value must be a multiple of {{0}}",
-  /**
-   * When a value is greater than it's supposed to be (exclusive)
-   * @variables This key takes one variable: The maximum
-   */
-  error_maximum_excl: "{{0}} must be less than {{1}}",
-  /**
-   * When a value is greater than it's supposed to be (inclusive)
-   * @variables This key takes one variable: The maximum
-   */
-  error_maximum_incl: "{{0}} must be at most {{1}}",
-  /**
-   * When a value is lesser than it's supposed to be (exclusive)
-   * @variables This key takes one variable: The minimum
-   */
-  error_minimum_excl: "{{0}} must be greater than {{1}}",
-  /**
-   * When a value is lesser than it's supposed to be (inclusive)
-   * @variables This key takes one variable: The minimum
-   */
-  error_minimum_incl: "{{0}} must be at least {{1}}",
-  /**
-   * When a value have too many characters
-   * @variables This key takes one variable: The maximum character count
-   */
-  error_maxLength: "{{0}} must be at most {{1}} characters long",
-  /**
-   * When a value does not have enough characters
-   * @variables This key takes one variable: The minimum character count
-   */
-  error_minLength: "{{0}} must be at least {{1}} characters long",
-  /**
-   * When a value does not match a given pattern
-   */
-  error_pattern: "{{0}} must match the pattern {{1}}",
-  /**
-   * When an array has additional items whereas it is not supposed to
-   */
-  error_additionalItems: "No additional items allowed in this array",
-  /**
-   * When there are to many items in an array
-   * @variables This key takes one variable: The maximum item count
-   */
-  error_maxItems: "{{0}} must have at most {{1}} items",
-  /**
-   * When there are not enough items in an array
-   * @variables This key takes one variable: The minimum item count
-   */
-  error_minItems: "{{0}} must have at least {{1}} items",
-  /**
-   * When an array is supposed to have unique items but has duplicates
-   */
-  error_uniqueItems: "Each tab of {{0}} must specify a unique combination of parameters",
-  /**
-   * When there are too many properties in an object
-   * @variables This key takes one variable: The maximum property count
-   */
-  error_maxProperties: "Object must have at most {{0}} properties",
-  /**
-   * When there are not enough properties in an object
-   * @variables This key takes one variable: The minimum property count
-   */
-  error_minProperties: "Object must have at least {{0}} properties",
-  /**
-   * When a required property is not defined
-   * @variables This key takes one variable: The name of the missing property
-   */
-  error_required: 'Please populate the required property "{{0}}"',
-  /**
-   * When there is an additional property is set whereas there should be none
-   * @variables This key takes one variable: The name of the additional property
-   */
-  error_additional_properties: "No additional properties allowed, but property {{0}} is set",
-  /**
-   * When a dependency is not resolved
-   * @variables This key takes one variable: The name of the missing property for the dependency
-   */
-  error_dependency: "Must have property {{0}}",
-  /**
-   * Text on Delete All buttons
-   */
-  button_delete_all: "All",
-  /**
-   * Title on Delete All buttons
-   */
-  button_delete_all_title: "Delete All",
-  /**
-    * Text on Delete Last buttons
-    * @variable This key takes one variable: The title of object to delete
-    */
-  button_delete_last: "Last {{0}}",
-  /**
-    * Title on Delete Last buttons
-    * @variable This key takes one variable: The title of object to delete
-    */
-  button_delete_last_title: "Delete Last {{0}}",
-  /**
-    * Title on Add Row buttons
-    * @variable This key takes one variable: The title of object to add
-    */
-  button_add_row_title: "Add {{0}}",
-  /**
-    * Title on Move Down buttons
-    */
-  button_move_down_title: "Move down",
-  /**
-    * Title on Move Up buttons
-    */
-  button_move_up_title: "Move up",
-  /**
-    * Title on Delete Row buttons
-    * @variable This key takes one variable: The title of object to delete
-    */
-  button_delete_row_title: "Delete {{0}}",
-  /**
-    * Title on Delete Row buttons, short version (no parameter with the object title)
-    */
-  button_delete_row_title_short: "Delete",
-  /**
-    * Title on Collapse buttons
-    */
-  button_collapse: "Collapse",
-  /**
-    * Title on Expand buttons
-    */
-  button_expand: "Expand"
-};
-
-// Miscellaneous Plugin Settings
-JSONEditor.plugins = {
-  ace: {
-    theme: ''
-  },
-  SimpleMDE: {
-
-  },
-  sceditor: {
-
-  },
-  select2: {
-    
-  },
-  selectize: {
-  }
-};
-
-// Default per-editor options
-$each(JSONEditor.defaults.editors, function(i,editor) {
-  JSONEditor.defaults.editors[i].options = editor.options || {};
-});
-
-// Set the default resolvers
-// Use "multiple" as a fall back for everything
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  if(schema.type === "qbldr") return "qbldr";
-});
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  if(typeof schema.type !== "string") return "multiple";
-});
-// If the type is not set but properties are defined, we can infer the type is actually object
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  // If the schema is a simple type
-  if(!schema.type && schema.properties ) return "object";
-});
-// If the type is set and it's a basic type, use the primitive editor
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  // If the schema is a simple type
-  if(typeof schema.type === "string") return schema.type;
-});
-// Use a specialized editor for ratings
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  if(schema.type === "integer" && schema.format === "rating") return "rating";
-});
-// Use the select editor for all boolean values
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  if(schema.type === 'boolean') {
-    // If explicitly set to 'checkbox', use that
-    if(schema.format === "checkbox" || (schema.options && schema.options.checkbox)) {
-      return "checkbox";
-    }
-    // Otherwise, default to select menu
-    return (JSONEditor.plugins.selectize.enable) ? 'selectize' : 'select';
-  }
-});
-// Use the multiple editor for schemas where the `type` is set to "any"
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  // If the schema can be of any type
-  if(schema.type === "any") return "multiple";
-});
-// Editor for base64 encoded files
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  // If the schema can be of any type
-  if(schema.type === "string" && schema.media && schema.media.binaryEncoding==="base64") {
-    return "base64";
-  }
-});
-// Editor for uploading files
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  if(schema.type === "string" && schema.format === "url" && schema.options && schema.options.upload === true) {
-    if(window.FileReader) return "upload";
-  }
-});
-// Use the table editor for arrays with the format set to `table`
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  // Type `array` with format set to `table`
-  if(schema.type === "array" && schema.format === "table") {
-    return "table";
-  }
-});
-// Use the `select` editor for dynamic enumSource enums
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  if(schema.enumSource) return (JSONEditor.plugins.selectize.enable) ? 'selectize' : 'select';
-});
-// Use the `enum` or `select` editors for schemas with enumerated properties
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  if(schema["enum"]) {
-    if(schema.type === "array" || schema.type === "object") {
-      return "enum";
-    }
-    else if(schema.type === "number" || schema.type === "integer" || schema.type === "string") {
-      return (JSONEditor.plugins.selectize.enable) ? 'selectize' : 'select';
-    }
-  }
-});
-// Specialized editors for arrays of strings
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  if(schema.type === "array" && schema.items && !(Array.isArray(schema.items)) && schema.uniqueItems && ['string','number','integer'].indexOf(schema.items.type) >= 0) {
-    // For enumerated strings, number, or integers
-    if(schema.items.enum) {
-      return 'multiselect';
-    }
-    // For non-enumerated strings (tag editor)
-    else if(JSONEditor.plugins.selectize.enable && schema.items.type === "string") {
-      return 'arraySelectize';
-    }
-  }
-});
-// Use the multiple editor for schemas with `oneOf` set
-JSONEditor.defaults.resolvers.unshift(function(schema) {
-  // If this schema uses `oneOf` or `anyOf`
-  if(schema.oneOf || schema.anyOf) return "multiple";
-});
-
-/**
- * This is a small wrapper for using JSON Editor like a typical jQuery plugin.
- */
-(function() {
-  if(window.jQuery || window.Zepto) {
-    var $ = window.jQuery || window.Zepto;
-    $.jsoneditor = JSONEditor.defaults;
-    
-    $.fn.jsoneditor = function(options) {
-      var self = this;
-      var editor = this.data('jsoneditor');
-      if(options === 'value') {
-        if(!editor) throw "Must initialize jsoneditor before getting/setting the value";
-        
-        // Set value
-        if(arguments.length > 1) {
-          editor.setValue(arguments[1]);
-        }
-        // Get value
-        else {
-          return editor.getValue();
-        }
-      }
-      else if(options === 'validate') {
-        if(!editor) throw "Must initialize jsoneditor before validating";
-        
-        // Validate a specific value
-        if(arguments.length > 1) {
-          return editor.validate(arguments[1]);
-        }
-        // Validate current value
-        else {
-          return editor.validate();
-        }
-      }
-      else if(options === 'destroy') {
-        if(editor) {
-          editor.destroy();
-          this.data('jsoneditor',null);
-        }
-      }
-      else {
-        // Destroy first
-        if(editor) {
-          editor.destroy();
-        }
-        
-        // Create editor
-        editor = new JSONEditor(this.get(0),options);
-        this.data('jsoneditor',editor);
-        
-        // Setup event listeners
-        editor.on('change',function() {
-          self.trigger('change');
-        });
-        editor.on('ready',function() {
-          self.trigger('ready');
-        });
-      }
-      
-      return this;
-    };
-  }
-})();
-
-  window.JSONEditor = JSONEditor;
-})();
+!function(a,b){"use strict";var c=b(a);"object"==typeof module&&null!=module&&module.exports?module.exports=c:"function"==typeof define&&define.amd?define(function(){return c}):a.JSONEditor=c}("undefined"!=typeof window?window:this,function(a,b){var c;!function(){var a=!1,b=/xyz/.test(function(){window.postMessage("xyz")})?/\b_super\b/:/.*/;return c=function(){},c.extend=function d(c){function e(){!a&&this.init&&this.init.apply(this,arguments)}var f=this.prototype;a=!0;var g=new this;a=!1;for(var h in c)g[h]="function"==typeof c[h]&&"function"==typeof f[h]&&b.test(c[h])?function(a,b){return function(){var c=this._super;this._super=f[a];var d=b.apply(this,arguments);return this._super=c,d}}(h,c[h]):c[h];return e.prototype=g,e.prototype.constructor=e,e.extend=d,e},c}(),function(){function a(a,c){c=c||{bubbles:!1,cancelable:!1,detail:b};var d=document.createEvent("CustomEvent");return d.initCustomEvent(a,c.bubbles,c.cancelable,c.detail),d}a.prototype=window.Event.prototype,window.CustomEvent=a}(),function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c<b.length&&!window.requestAnimationFrame;++c)window.requestAnimationFrame=window[b[c]+"RequestAnimationFrame"],window.cancelAnimationFrame=window[b[c]+"CancelAnimationFrame"]||window[b[c]+"CancelRequestAnimationFrame"];window.requestAnimationFrame||(window.requestAnimationFrame=function(b,c){var d=(new Date).getTime(),e=Math.max(0,16-(d-a)),f=window.setTimeout(function(){b(d+e)},e);return a=d+e,f}),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(a){clearTimeout(a)})}(),function(){Array.isArray||(Array.isArray=function(a){return"[object Array]"===Object.prototype.toString.call(a)})}();var d=function(a){return!("object"!=typeof a||a.nodeType||null!==a&&a===a.window)&&!(a.constructor&&!Object.prototype.hasOwnProperty.call(a.constructor.prototype,"isPrototypeOf"))},e=function(a){var b,c,f;for(c=1;c<arguments.length;c++){b=arguments[c];for(f in b)b.hasOwnProperty(f)&&(b[f]&&d(b[f])?(a.hasOwnProperty(f)||(a[f]={}),e(a[f],b[f])):a[f]=b[f])}return a},f=function(a,b){if(a&&"object"==typeof a){var c;if(Array.isArray(a)||"number"==typeof a.length&&a.length>0&&a.length-1 in a){for(c=0;c<a.length;c++)if(b(c,a[c])===!1)return}else if(Object.keys){var d=Object.keys(a);for(c=0;c<d.length;c++)if(b(d[c],a[d[c]])===!1)return}else for(c in a)if(a.hasOwnProperty(c)&&b(c,a[c])===!1)return}},g=function(a,b){var c=document.createEvent("HTMLEvents");c.initEvent(b,!0,!0),a.dispatchEvent(c)},h=function(a,b){if(!(a instanceof Element))throw new Error("element should be an instance of Element");b=e({},h.defaults.options,b||{}),this.element=a,this.options=b,this.init()};h.prototype={constructor:h,init:function(){var a=this;this.ready=!1,this.copyClipboard=null,this.refs_with_info={},this.refs_prefix="#/counter/",this.refs_counter=1;var b=h.defaults.themes[this.options.theme||h.defaults.theme];if(!b)throw"Unknown theme "+(this.options.theme||h.defaults.theme);this.schema=this.options.schema,this.theme=new b,this.template=this.options.template,this.refs=this.options.refs||{},this.uuid=0,this.__data={};var c=h.defaults.iconlibs[this.options.iconlib||h.defaults.iconlib];c&&(this.iconlib=new c),this.root_container=this.theme.getContainer(),this.element.appendChild(this.root_container),this.translate=this.options.translate||h.defaults.translate;var d=document.location.toString(),e=this._getFileBase();this._loadExternalRefs(this.schema,function(){a._getDefinitions(a.schema,d+"#/definitions/");var b={};a.options.custom_validators&&(b.custom_validators=a.options.custom_validators),a.validator=new h.Validator(a,null,b);var c=a.expandRefs(a.schema),e=a.getEditorClass(c);a.root=a.createEditor(e,{jsoneditor:a,schema:c,required:!0,container:a.root_container}),a.root.preBuild(),a.root.build(),a.root.postBuild(),a.options.hasOwnProperty("startval")&&a.root.setValue(a.options.startval),a.validation_results=a.validator.validate(a.root.getValue()),a.root.showValidationErrors(a.validation_results),a.ready=!0,window.requestAnimationFrame(function(){a.ready&&(a.validation_results=a.validator.validate(a.root.getValue()),a.root.showValidationErrors(a.validation_results),a.trigger("ready"),a.trigger("change"))})},d,e)},getValue:function(){if(!this.ready)throw"JSON Editor not ready yet.  Listen for 'ready' event before getting the value";return this.root.getValue()},setValue:function(a){if(!this.ready)throw"JSON Editor not ready yet.  Listen for 'ready' event before setting the value";return this.root.setValue(a),this},validate:function(a){if(!this.ready)throw"JSON Editor not ready yet.  Listen for 'ready' event before validating";return 1===arguments.length?this.validator.validate(a):this.validation_results},destroy:function(){this.destroyed||this.ready&&(this.schema=null,this.options=null,this.root.destroy(),this.root=null,this.root_container=null,this.validator=null,this.validation_results=null,this.theme=null,this.iconlib=null,this.template=null,this.__data=null,this.ready=!1,this.element.innerHTML="",this.destroyed=!0)},on:function(a,b){return this.callbacks=this.callbacks||{},this.callbacks[a]=this.callbacks[a]||[],this.callbacks[a].push(b),this},off:function(a,b){if(a&&b){this.callbacks=this.callbacks||{},this.callbacks[a]=this.callbacks[a]||[];for(var c=[],d=0;d<this.callbacks[a].length;d++)this.callbacks[a][d]!==b&&c.push(this.callbacks[a][d]);this.callbacks[a]=c}else a?(this.callbacks=this.callbacks||{},this.callbacks[a]=[]):this.callbacks={};return this},trigger:function(a){if(this.callbacks&&this.callbacks[a]&&this.callbacks[a].length)for(var b=0;b<this.callbacks[a].length;b++)this.callbacks[a][b].apply(this,[]);return this},setOption:function(a,b){if("show_errors"!==a)throw"Option "+a+" must be set during instantiation and cannot be changed later";return this.options.show_errors=b,this.onChange(),this},getEditorClass:function(a){var b;if(a=this.expandSchema(a),f(h.defaults.resolvers,function(c,d){var e=d(a);if(e&&h.defaults.editors[e])return b=e,!1}),!b)throw"Unknown editor for schema "+JSON.stringify(a);if(!h.defaults.editors[b])throw"Unknown editor "+b;return h.defaults.editors[b]},createEditor:function(a,b){return b=e({},a.options||{},b),new a(b)},onChange:function(){if(this.ready&&!this.firing_change){this.firing_change=!0;var a=this;return window.requestAnimationFrame(function(){a.firing_change=!1,a.ready&&(a.validation_results=a.validator.validate(a.root.getValue()),"never"!==a.options.show_errors?a.root.showValidationErrors(a.validation_results):a.root.showValidationErrors([]),a.trigger("change"))}),this}},compileTemplate:function(a,b){b=b||h.defaults.template;var c;if("string"==typeof b){if(!h.defaults.templates[b])throw"Unknown template engine "+b;if(c=h.defaults.templates[b](),!c)throw"Template engine "+b+" missing required library."}else c=b;if(!c)throw"No template engine set";if(!c.compile)throw"Invalid template engine set";return c.compile(a)},_data:function(a,b,c){if(3!==arguments.length)return a.hasAttribute("data-jsoneditor-"+b)?this.__data[a.getAttribute("data-jsoneditor-"+b)]:null;var d;a.hasAttribute("data-jsoneditor-"+b)?d=a.getAttribute("data-jsoneditor-"+b):(d=this.uuid++,a.setAttribute("data-jsoneditor-"+b,d)),this.__data[d]=c},registerEditor:function(a){return this.editors=this.editors||{},this.editors[a.path]=a,this},unregisterEditor:function(a){return this.editors=this.editors||{},this.editors[a.path]=null,this},getEditor:function(a){if(this.editors)return this.editors[a]},watch:function(a,b){return this.watchlist=this.watchlist||{},this.watchlist[a]=this.watchlist[a]||[],this.watchlist[a].push(b),this},unwatch:function(a,b){if(!this.watchlist||!this.watchlist[a])return this;if(!b)return this.watchlist[a]=null,this;for(var c=[],d=0;d<this.watchlist[a].length;d++)this.watchlist[a][d]!==b&&c.push(this.watchlist[a][d]);return this.watchlist[a]=c.length?c:null,this},notifyWatchers:function(a){if(!this.watchlist||!this.watchlist[a])return this;for(var b=0;b<this.watchlist[a].length;b++)this.watchlist[a][b]()},isEnabled:function(){return!this.root||this.root.isEnabled()},enable:function(){this.root.enable()},disable:function(){this.root.disable()},_getDefinitions:function(a,b){if(a.definitions)for(var c in a.definitions)a.definitions.hasOwnProperty(c)&&(this.refs[b+c]=a.definitions[c],a.definitions[c].definitions&&this._getDefinitions(a.definitions[c],b+c+"/definitions/"))},_getExternalRefs:function(a,b){var c={},d=function(a){for(var b in a)a.hasOwnProperty(b)&&(c[b]=!0)};if(a.$ref&&"object"!=typeof a.$ref){var e=this.refs_prefix+this.refs_counter++;"#"===a.$ref.substr(0,1)||this.refs[a.$ref]||(c[a.$ref]=!0),this.refs_with_info[e]={fetchUrl:b,$ref:a.$ref},a.$ref=e}for(var f in a)if(a.hasOwnProperty(f)&&a[f]&&"object"==typeof a[f])if(Array.isArray(a[f]))for(var g=0;g<a[f].length;g++)a[f][g]&&"object"==typeof a[f][g]&&d(this._getExternalRefs(a[f][g],b));else d(this._getExternalRefs(a[f],b));return c},_getFileBase:function(){var a=this.options.ajaxBase;return"undefined"==typeof a&&(a=this._getFileBaseFromFileLocation(document.location.toString())),a},_getFileBaseFromFileLocation:function(a){var b=a.split("/");return b.pop(),b.join("/")+"/"},_loadExternalRefs:function(a,b,c,d){var e=this,g=this._getExternalRefs(a,c),h=0,i=0,j=!1;f(g,function(a){if(!e.refs[a]){if(!e.options.ajax)throw"Must set ajax option to true to load external ref "+a;e.refs[a]="loading",i++;var c=a;d!=a.substr(0,d.length)&&"http"!=a.substr(0,4)&&"/"!=a.substr(0,1)&&(c=d+a);var f=new XMLHttpRequest;f.overrideMimeType("application/json"),f.open("GET",c,!0),e.options.ajaxCredentials&&(f.withCredentials=e.options.ajaxCredentials),f.onreadystatechange=function(){if(4==f.readyState){if(200!==f.status)throw window.console.log(f),"Failed to fetch ref via ajax- "+a;var d;try{d=JSON.parse(f.responseText)}catch(g){throw window.console.log(g),"Failed to parse external ref "+c}if("boolean"!=typeof d&&"object"!=typeof d||null===d||Array.isArray(d))throw"External ref does not contain a valid schema - "+c;e.refs[a]=d;var k=e._getFileBaseFromFileLocation(c);e._getDefinitions(d,c+"#/definitions/"),e._loadExternalRefs(d,function(){h++,h>=i&&!j&&(j=!0,b())},c,k)}},f.send()}}),i||b()},expandRefs:function(a){for(a=e({},a);a.$ref;){var b=this.refs_with_info[a.$ref];delete a.$ref;var c="";b.$ref.startsWith("#")&&(c=b.fetchUrl);var d=c+b.$ref;this.refs[d]||(d=c+decodeURIComponent(b.$ref)),a=this.extendSchemas(a,e({},this.refs[d]))}return a},expandSchema:function(a,b){var c,d=this,g=e({},a);if("object"==typeof a.type&&(Array.isArray(a.type)?f(a.type,function(b,c){"object"==typeof c&&(a.type[b]=d.expandSchema(c))}):a.type=d.expandSchema(a.type)),"object"==typeof a.disallow&&(Array.isArray(a.disallow)?f(a.disallow,function(b,c){"object"==typeof c&&(a.disallow[b]=d.expandSchema(c))}):a.disallow=d.expandSchema(a.disallow)),a.anyOf&&f(a.anyOf,function(b,c){a.anyOf[b]=d.expandSchema(c)}),a.dependencies&&f(a.dependencies,function(b,c){"object"!=typeof c||Array.isArray(c)||(a.dependencies[b]=d.expandSchema(c))}),a.not&&(a.not=this.expandSchema(a.not)),a.allOf){for(c=0;c<a.allOf.length;c++)g=this.extendSchemas(g,this.expandSchema(a.allOf[c]));delete g.allOf}if(a["extends"]){if(Array.isArray(a["extends"]))for(c=0;c<a["extends"].length;c++)g=this.extendSchemas(g,this.expandSchema(a["extends"][c]));else g=this.extendSchemas(g,this.expandSchema(a["extends"]));delete g["extends"]}if(a.oneOf){var h=e({},g);for(delete h.oneOf,c=0;c<a.oneOf.length;c++)g.oneOf[c]=this.extendSchemas(this.expandSchema(a.oneOf[c]),h)}return this.expandRefs(g)},extendSchemas:function(a,b){a=e({},a),b=e({},b);var c=this,d={};return f(a,function(a,e){"undefined"!=typeof b[a]?"required"!==a&&"defaultProperties"!==a||"object"!=typeof e||!Array.isArray(e)?"type"!==a||"string"!=typeof e&&!Array.isArray(e)?"object"==typeof e&&Array.isArray(e)?d[a]=e.filter(function(c){return b[a].indexOf(c)!==-1}):"object"==typeof e&&null!==e?d[a]=c.extendSchemas(e,b[a]):d[a]=e:("string"==typeof e&&(e=[e]),"string"==typeof b.type&&(b.type=[b.type]),b.type&&b.type.length?d.type=e.filter(function(a){return b.type.indexOf(a)!==-1}):d.type=e,1===d.type.length&&"string"==typeof d.type[0]?d.type=d.type[0]:0===d.type.length&&delete d.type):d[a]=e.concat(b[a]).reduce(function(a,b){return a.indexOf(b)<0&&a.push(b),a},[]):d[a]=e}),f(b,function(b,c){"undefined"==typeof a[b]&&(d[b]=c)}),d},setCopyClipboardContents:function(a){this.copyClipboard=a},getCopyClipboardContents:function(){return this.copyClipboard}},h.defaults={themes:{},templates:{},iconlibs:{},editors:{},languages:{},resolvers:[],custom_validators:[]},h.Validator=c.extend({init:function(a,b,c){this.jsoneditor=a,this.schema=b||this.jsoneditor.schema,this.options=c||{},this.translate=this.jsoneditor.translate||h.defaults.translate},validate:function(a){return this._validateSchema(this.schema,a)},_validateSchema:function(a,c,d){var g,i,j,k=this,l=[],m=JSON.stringify(c);if(d=d||"root",a=e({},this.jsoneditor.expandRefs(a)),"undefined"==typeof c)return("undefined"!=typeof a.required&&a.required===!0||"undefined"==typeof a.required&&this.jsoneditor.options.required_by_default===!0)&&l.push({path:d,property:"required",message:this.translate("error_notset")}),l;if(a["enum"]){for(g=!1,i=0;i<a["enum"].length;i++)m===JSON.stringify(a["enum"][i])&&(g=!0);g||l.push({path:d,property:"enum",message:this.translate("error_enum")})}if(a["extends"])for(i=0;i<a["extends"].length;i++)l=l.concat(this._validateSchema(a["extends"][i],c,d));if(a.allOf)for(i=0;i<a.allOf.length;i++)l=l.concat(this._validateSchema(a.allOf[i],c,d));if(a.anyOf){for(g=!1,i=0;i<a.anyOf.length;i++)if(!this._validateSchema(a.anyOf[i],c,d).length){g=!0;break}g||l.push({path:d,property:"anyOf",message:this.translate("error_anyOf")})}if(a.oneOf){g=0;var n=[];for(i=0;i<a.oneOf.length;i++){var o=this._validateSchema(a.oneOf[i],c,d);for(o.length||g++,j=0;j<o.length;j++)o[j].path=d+".oneOf["+i+"]"+o[j].path.substr(d.length);n=n.concat(o)}1!==g&&(l.push({path:d,property:"oneOf",message:this.translate("error_oneOf",[g])}),l=l.concat(n))}if(a.not&&(this._validateSchema(a.not,c,d).length||l.push({path:d,property:"not",message:this.translate("error_not")})),a.type)if(Array.isArray(a.type)){for(g=!1,i=0;i<a.type.length;i++)if(this._checkType(a.type[i],c)){g=!0;break}g||l.push({path:d,property:"type",message:this.translate("error_type_union")})}else["date","time","datetime-local"].indexOf(a.format)!=-1&&"integer"==a.type?this._checkType("string",""+c)||l.push({path:d,property:"type",message:this.translate("error_type",[a.format])}):this._checkType(a.type,c)||l.push({path:d,property:"type",message:this.translate("error_type",[a.type])});if(a.disallow)if(Array.isArray(a.disallow)){for(g=!0,i=0;i<a.disallow.length;i++)if(this._checkType(a.disallow[i],c)){g=!1;break}g||l.push({path:d,property:"disallow",message:this.translate("error_disallow_union")})}else this._checkType(a.disallow,c)&&l.push({path:d,property:"disallow",message:this.translate("error_disallow",[a.disallow])});if("number"==typeof c){if(a.multipleOf||a.divisibleBy){var p=a.multipleOf||a.divisibleBy;g=c/p===Math.floor(c/p),window.math?g=window.math.mod(window.math.bignumber(c),window.math.bignumber(p)).equals(0):window.Decimal&&(g=new window.Decimal(c).mod(new window.Decimal(p)).equals(0)),g||l.push({path:d,property:a.multipleOf?"multipleOf":"divisibleBy",message:this.translate("error_multipleOf",[p])})}a.hasOwnProperty("maximum")&&(g=a.exclusiveMaximum?c<a.maximum:c<=a.maximum,window.math?g=window.math[a.exclusiveMaximum?"smaller":"smallerEq"](window.math.bignumber(c),window.math.bignumber(a.maximum)):window.Decimal&&(g=new window.Decimal(c)[a.exclusiveMaximum?"lt":"lte"](new window.Decimal(a.maximum))),g||l.push({path:d,property:"maximum",message:this.translate(a.exclusiveMaximum?"error_maximum_excl":"error_maximum_incl",[a.maximum])})),a.hasOwnProperty("minimum")&&(g=a.exclusiveMinimum?c>a.minimum:c>=a.minimum,window.math?g=window.math[a.exclusiveMinimum?"larger":"largerEq"](window.math.bignumber(c),window.math.bignumber(a.minimum)):window.Decimal&&(g=new window.Decimal(c)[a.exclusiveMinimum?"gt":"gte"](new window.Decimal(a.minimum))),g||l.push({path:d,property:"minimum",message:this.translate(a.exclusiveMinimum?"error_minimum_excl":"error_minimum_incl",[a.minimum])}))}else if("string"==typeof c)a.maxLength&&(c+"").length>a.maxLength&&l.push({path:d,property:"maxLength",message:this.translate("error_maxLength",[a.maxLength])}),a.minLength&&(c+"").length<a.minLength&&l.push({path:d,property:"minLength",message:this.translate(1===a.minLength?"error_notempty":"error_minLength",[a.minLength])}),a.pattern&&(new RegExp(a.pattern).test(c)||l.push({path:d,property:"pattern",message:this.translate("error_pattern",[a.pattern])}));else if("object"==typeof c&&null!==c&&Array.isArray(c)){if(a.items)if(Array.isArray(a.items))for(i=0;i<c.length;i++)if(a.items[i])l=l.concat(this._validateSchema(a.items[i],c[i],d+"."+i));else{if(a.additionalItems===!0)break;if(!a.additionalItems){if(a.additionalItems===!1){l.push({path:d,property:"additionalItems",message:this.translate("error_additionalItems")});break}break}l=l.concat(this._validateSchema(a.additionalItems,c[i],d+"."+i))}else for(i=0;i<c.length;i++)l=l.concat(this._validateSchema(a.items,c[i],d+"."+i));if(a.maxItems&&c.length>a.maxItems&&l.push({path:d,property:"maxItems",message:this.translate("error_maxItems",[a.maxItems])}),a.minItems&&c.length<a.minItems&&l.push({path:d,property:"minItems",message:this.translate("error_minItems",[a.minItems])}),a.uniqueItems){var q={};for(i=0;i<c.length;i++){if(g=JSON.stringify(c[i]),q[g]){l.push({path:d,property:"uniqueItems",message:this.translate("error_uniqueItems")});break}q[g]=!0}}}else if("object"==typeof c&&null!==c){if(a.maxProperties){g=0;for(i in c)c.hasOwnProperty(i)&&g++;g>a.maxProperties&&l.push({path:d,property:"maxProperties",message:this.translate("error_maxProperties",[a.maxProperties])})}if(a.minProperties){g=0;for(i in c)c.hasOwnProperty(i)&&g++;g<a.minProperties&&l.push({path:d,property:"minProperties",message:this.translate("error_minProperties",[a.minProperties])})}if("undefined"!=typeof a.required&&Array.isArray(a.required))for(i=0;i<a.required.length;i++)"undefined"==typeof c[a.required[i]]&&l.push({path:d,property:"required",message:this.translate("error_required",[a.required[i]])});var r={};for(i in a.properties)a.properties.hasOwnProperty(i)&&(r[i]=!0,l=l.concat(this._validateSchema(a.properties[i],c[i],d+"."+i)));if(a.patternProperties)for(i in a.patternProperties)if(a.patternProperties.hasOwnProperty(i)){var s=new RegExp(i);for(j in c)c.hasOwnProperty(j)&&s.test(j)&&(r[j]=!0,l=l.concat(this._validateSchema(a.patternProperties[i],c[j],d+"."+j)))}if("undefined"!=typeof a.additionalProperties||!this.jsoneditor.options.no_additional_properties||a.oneOf||a.anyOf||(a.additionalProperties=!1),"undefined"!=typeof a.additionalProperties)for(i in c)if(c.hasOwnProperty(i)&&!r[i]){if(!a.additionalProperties){l.push({path:d,property:"additionalProperties",message:this.translate("error_additional_properties",[i])});break}if(a.additionalProperties===!0)break;l=l.concat(this._validateSchema(a.additionalProperties,c[i],d+"."+i))}if(a.dependencies)for(i in a.dependencies)if(a.dependencies.hasOwnProperty(i)&&"undefined"!=typeof c[i])if(Array.isArray(a.dependencies[i]))for(j=0;j<a.dependencies[i].length;j++)"undefined"==typeof c[a.dependencies[i][j]]&&l.push({path:d,property:"dependencies",message:this.translate("error_dependency",[a.dependencies[i][j]])});else l=l.concat(this._validateSchema(a.dependencies[i],c,d))}if(["date","time","datetime-local"].indexOf(a.format)!=-1){var t={date:/^(\d{4}\D\d{2}\D\d{2})?$/,time:/^(\d{2}:\d{2}(?::\d{2})?)?$/,"datetime-local":/^(\d{4}\D\d{2}\D\d{2} \d{2}:\d{2}(?::\d{2})?)?$/},u={date:'"YYYY-MM-DD"',time:'"HH:MM"',"datetime-local":'"YYYY-MM-DD HH:MM"'},v=this.jsoneditor.getEditor(d),w=v.flatpickr?v.flatpickr.config.dateFormat:u[v.format];if("integer"==a.type)1*c<1?l.push({path:d,property:"format",message:this.translate("error_invalid_epoch")}):c!=Math.abs(parseInt(c))&&l.push({path:d,property:"format",message:this.translate("error_"+v.format.replace(/-/g,"_"),[w])});else if(v.flatpickr){if(""!==c){var x;if("single"!=v.flatpickr.config.mode){var y="range"==v.flatpickr.config.mode?v.flatpickr.l10n.rangeSeparator:", ",z=v.flatpickr.selectedDates.map(function(a){return v.flatpickr.formatDate(a,v.flatpickr.config.dateFormat)});x=z.join(y)}try{if(x){if(x!=c)throw v.flatpickr.config.mode+" mismatch"}else if(v.flatpickr.formatDate(v.flatpickr.parseDate(c,v.flatpickr.config.dateFormat),v.flatpickr.config.dateFormat)!=c)throw"mismatch"}catch(A){var B=v.flatpickr.config.errorDateFormat!==b?v.flatpickr.config.errorDateFormat:v.flatpickr.config.dateFormat;l.push({path:d,property:"format",message:this.translate("error_"+v.format.replace(/-/g,"_"),[B])})}}}else t[v.format].test(c)||l.push({path:d,property:"format",message:this.translate("error_"+v.format.replace(/-/g,"_"),[u[v.format]])})}return f(h.defaults.custom_validators,function(b,e){l=l.concat(e.call(k,a,c,d))}),this.options.custom_validators&&f(this.options.custom_validators,function(b,e){l=l.concat(e.call(k,a,c,d))}),l},_checkType:function(a,b){return"string"==typeof a?"string"===a?"string"==typeof b:"number"===a?"number"==typeof b:"integer"===a?"number"==typeof b&&b===Math.floor(b):"boolean"===a?"boolean"==typeof b:"array"===a?Array.isArray(b):"object"===a?null!==b&&!Array.isArray(b)&&"object"==typeof b:"null"!==a||null===b:!this._validateSchema(a,b).length}}),h.AbstractEditor=c.extend({onChildEditorChange:function(a){this.onChange(!0)},notify:function(){this.path&&this.jsoneditor.notifyWatchers(this.path)},change:function(){this.parent?this.parent.onChildEditorChange(this):this.jsoneditor&&this.jsoneditor.onChange()},onChange:function(a){this.notify(),this.watch_listener&&this.watch_listener(),a&&this.change()},register:function(){this.jsoneditor.registerEditor(this),this.onChange()},unregister:function(){this.jsoneditor&&this.jsoneditor.unregisterEditor(this)},getNumColumns:function(){return 12},init:function(a){this.jsoneditor=a.jsoneditor,this.theme=this.jsoneditor.theme,this.template_engine=this.jsoneditor.template,this.iconlib=this.jsoneditor.iconlib,this.translate=this.jsoneditor.translate||h.defaults.translate,this.original_schema=a.schema,this.schema=this.jsoneditor.expandSchema(this.original_schema),this.options=e({},this.options||{},this.schema.options||{},a.schema.options||{},a),a.path||this.schema.id||(this.schema.id="root"),this.path=a.path||"root",this.formname=a.formname||this.path.replace(/\.([^.]+)/g,"[$1]"),this.jsoneditor.options.form_name_root&&(this.formname=this.formname.replace(/^root\[/,this.jsoneditor.options.form_name_root+"[")),this.key=this.path.split(".").pop(),this.parent=a.parent,this.link_watchers=[],a.container&&this.setContainer(a.container),this.registerDependencies()},registerDependencies:function(){this.dependenciesFulfilled=!0;var a=this.options.dependencies;if(a){var b=this;Object.keys(a).forEach(function(c){var d=b.path.split(".");d[d.length-1]=c,d=d.join(".");var e=a[c];b.jsoneditor.watch(d,function(){b.checkDependency(d,e)})})}},checkDependency:function(a,c){var d=this.control||this.container;if(this.path!==a&&d){var e=this,f=this.jsoneditor.getEditor(a),g=f?f.getValue():b,h=this.dependenciesFulfilled;this.dependenciesFulfilled=!1,f&&f.dependenciesFulfilled?Array.isArray(c)?c.some(function(a){if(g===a)return e.dependenciesFulfilled=!0,!0}):"object"==typeof c?"object"!=typeof g?this.dependenciesFulfilled=c===g:Object.keys(c).some(function(a){return!!c.hasOwnProperty(a)&&(g.hasOwnProperty(a)&&c[a]===g[a]?void(e.dependenciesFulfilled=!0):(e.dependenciesFulfilled=!1,!0))}):"string"==typeof c||"number"==typeof c?this.dependenciesFulfilled=g===c:"boolean"==typeof c&&(c?this.dependenciesFulfilled=g&&g.length>0:this.dependenciesFulfilled=!g||0===g.length):this.dependenciesFulfilled=!1,this.dependenciesFulfilled!==h&&this.notify(),this.dependenciesFulfilled?d.style.display="block":d.style.display="none"}},setContainer:function(a){this.container=a,this.schema.id&&this.container.setAttribute("data-schemaid",this.schema.id),this.schema.type&&"string"==typeof this.schema.type&&this.container.setAttribute("data-schematype",this.schema.type),this.container.setAttribute("data-schemapath",this.path)},preBuild:function(){},build:function(){},postBuild:function(){this.setupWatchListeners(),this.addLinks(),this.setValue(this.getDefault(),!0),this.updateHeaderText(),this.register(),this.onWatchedFieldChange()},setupWatchListeners:function(){var a=this;if(this.watched={},this.schema.vars&&(this.schema.watch=this.schema.vars),this.watched_values={},this.watch_listener=function(){a.refreshWatchedFieldValues()&&a.onWatchedFieldChange()},this.schema.hasOwnProperty("watch")){var b,c,d,e,f;for(var g in this.schema.watch)if(this.schema.watch.hasOwnProperty(g)){if(b=this.schema.watch[g],Array.isArray(b)){if(b.length<2)continue;c=[b[0]].concat(b[1].split("."))}else c=b.split("."),a.theme.closest(a.container,'[data-schemaid="'+c[0]+'"]')||c.unshift("#");if(d=c.shift(),"#"===d&&(d=a.jsoneditor.schema.id||"root"),e=a.theme.closest(a.container,'[data-schemaid="'+d+'"]'),!e)throw"Could not find ancestor node with id "+d;f=e.getAttribute("data-schemapath")+"."+c.join("."),a.jsoneditor.watch(f,a.watch_listener),a.watched[g]=f}}this.schema.headerTemplate&&(this.header_template=this.jsoneditor.compileTemplate(this.schema.headerTemplate,this.template_engine))},addLinks:function(){if(!this.no_link_holder&&(this.link_holder=this.theme.getLinksHolder(),this.container.appendChild(this.link_holder),this.schema.links))for(var a=0;a<this.schema.links.length;a++)this.addLink(this.getLink(this.schema.links[a]))},onMove:function(){},getButton:function(a,b,c){var d="json-editor-btn-"+b;b=this.iconlib?this.iconlib.getIcon(b):null,!b&&c&&(a=c,c=null);var e=this.theme.getButton(a,b,c);return e.classList.add(d),e},setButtonText:function(a,b,c,d){return c=this.iconlib?this.iconlib.getIcon(c):null,!c&&d&&(b=d,d=null),this.theme.setButtonText(a,b,c,d)},addLink:function(a){this.link_holder&&this.link_holder.appendChild(a)},getLink:function(a){var b,c,d=a.mediaType||"application/javascript",e=d.split("/")[0],f=this.jsoneditor.compileTemplate(a.href,this.template_engine),g=this.jsoneditor.compileTemplate(a.rel?a.rel:a.href,this.template_engine),h=null;if(a.download&&(h=a.download),h&&h!==!0&&(h=this.jsoneditor.compileTemplate(h,this.template_engine)),"image"===e){b=this.theme.getBlockLinkHolder(),c=document.createElement("a"),c.setAttribute("target","_blank");var i=document.createElement("img");this.theme.createImageLink(b,c,i),this.link_watchers.push(function(a){var b=f(a),d=g(a);c.setAttribute("href",b),c.setAttribute("title",d||b),i.setAttribute("src",b)})}else if(["audio","video"].indexOf(e)>=0){b=this.theme.getBlockLinkHolder(),c=this.theme.getBlockLink(),c.setAttribute("target","_blank");var j=document.createElement(e);j.setAttribute("controls","controls"),this.theme.createMediaLink(b,c,j),this.link_watchers.push(function(a){var b=f(a),d=g(a);c.setAttribute("href",b),c.textContent=d||b,j.setAttribute("src",b)})}else c=b=this.theme.getBlockLink(),b.setAttribute("target","_blank"),b.textContent=a.rel,this.link_watchers.push(function(a){var c=f(a),d=g(a);b.setAttribute("href",c),b.textContent=d||c});return h&&c&&(h===!0?c.setAttribute("download",""):this.link_watchers.push(function(a){c.setAttribute("download",h(a))})),a["class"]&&c.classList.add(a["class"]),b},refreshWatchedFieldValues:function(){if(this.watched_values){var a={},b=!1,c=this;if(this.watched){var d,e;for(var f in this.watched)this.watched.hasOwnProperty(f)&&(e=c.jsoneditor.getEditor(this.watched[f]),d=e?e.getValue():null,c.watched_values[f]!==d&&(b=!0),a[f]=d)}return a.self=this.getValue(),this.watched_values.self!==a.self&&(b=!0),this.watched_values=a,b}},getWatchedFieldValues:function(){return this.watched_values},updateHeaderText:function(){if(this.header)if(this.header.children.length){for(var a=0;a<this.header.childNodes.length;a++)if(3===this.header.childNodes[a].nodeType){this.header.childNodes[a].nodeValue=this.getHeaderText();break}}else this.header.textContent=this.getHeaderText()},getHeaderText:function(a){return this.header_text?this.header_text:a?this.schema.title:this.getTitle()},onWatchedFieldChange:function(){var a;if(this.header_template){a=e(this.getWatchedFieldValues(),{key:this.key,i:this.key,i0:1*this.key,i1:1*this.key+1,title:this.getTitle()});var b=this.header_template(a);b!==this.header_text&&(this.header_text=b,this.updateHeaderText(),this.notify())}if(this.link_watchers.length){a=this.getWatchedFieldValues();for(var c=0;c<this.link_watchers.length;c++)this.link_watchers[c](a)}},setValue:function(a){this.value=a},getValue:function(){return this.dependenciesFulfilled?this.value:b},refreshValue:function(){},getChildEditors:function(){return!1},destroy:function(){var a=this;this.unregister(this),f(this.watched,function(b,c){a.jsoneditor.unwatch(c,a.watch_listener)}),this.watched=null,this.watched_values=null,this.watch_listener=null,this.header_text=null,this.header_template=null,this.value=null,this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container),this.container=null,this.jsoneditor=null,this.schema=null,this.path=null,this.key=null,this.parent=null},getDefault:function(){if("undefined"!=typeof this.schema["default"])return this.schema["default"];if("undefined"!=typeof this.schema["enum"])return this.schema["enum"][0];var a=this.schema.type||this.schema.oneOf;if(a&&Array.isArray(a)&&(a=a[0]),a&&"object"==typeof a&&(a=a.type),a&&Array.isArray(a)&&(a=a[0]),"string"==typeof a){if("number"===a)return 0;if("boolean"===a)return!1;if("integer"===a)return 0;if("string"===a)return"";if("object"===a)return{};if("array"===a)return[]}return null},getTitle:function(){return this.schema.title||this.key},enable:function(){this.disabled=!1},disable:function(){this.disabled=!0},isEnabled:function(){return!this.disabled},isRequired:function(){return"boolean"==typeof this.schema.required?this.schema.required:this.parent&&this.parent.schema&&Array.isArray(this.parent.schema.required)?this.parent.schema.required.indexOf(this.key)>-1:!!this.jsoneditor.options.required_by_default},getDisplayText:function(a){var b=[],c={};f(a,function(a,b){b.title&&(c[b.title]=c[b.title]||0,c[b.title]++),b.description&&(c[b.description]=c[b.description]||0,c[b.description]++),b.format&&(c[b.format]=c[b.format]||0,c[b.format]++),b.type&&(c[b.type]=c[b.type]||0,c[b.type]++)}),f(a,function(a,d){var e;e="string"==typeof d?d:d.title&&c[d.title]<=1?d.title:d.format&&c[d.format]<=1?d.format:d.type&&c[d.type]<=1?d.type:d.description&&c[d.description]<=1?d.descripton:d.title?d.title:d.format?d.format:d.type?d.type:d.description?d.description:JSON.stringify(d).length<500?JSON.stringify(d):"type",b.push(e)});var d={};return f(b,function(a,e){d[e]=d[e]||0,d[e]++,c[e]>1&&(b[a]=e+" "+d[e])}),b},getValidId:function(a){return a=a===b?"":a.toString(),a.replace(/\s+/g,"-")},setInputAttributes:function(a){if(this.schema.options&&this.schema.options.inputAttributes){var b=this.schema.options.inputAttributes,c=["name","type"].concat(a);for(var d in b)b.hasOwnProperty(d)&&c.indexOf(d.toLowerCase())==-1&&this.input.setAttribute(d,b[d])}},getOption:function(a){try{throw"getOption is deprecated"}catch(b){window.console.error(b)}return this.options[a]},showValidationErrors:function(a){}}),h.defaults.editors["null"]=h.AbstractEditor.extend({getValue:function(){return this.dependenciesFulfilled?null:b},setValue:function(){this.onChange()},getNumColumns:function(){return 2}}),h.defaults.editors.string=h.AbstractEditor.extend({register:function(){this._super(),this.input&&this.input.setAttribute("name",this.formname)},unregister:function(){this._super(),this.input&&this.input.removeAttribute("name")},setValue:function(a,b,c){if((!this.template||c)&&(null===a||"undefined"==typeof a?a="":"object"==typeof a?a=JSON.stringify(a):"string"!=typeof a&&(a=""+a),
+a!==this.serialized)){var d=this.sanitize(a);if(this.input.value!==d){this.input.value=d,this.sceditor_instance?this.sceditor_instance.val(d):this.SimpleMDE?this.SimpleMDE.value(d):this.ace_editor&&(this.ace_editor.setValue(d),this.ace_editor.session.getSelection().clearSelection(),this.ace_editor.resize());var e=c||this.getValue()!==a;this.refreshValue(),b?this.is_dirty=!1:"change"===this.jsoneditor.options.show_errors&&(this.is_dirty=!0),this.adjust_height&&this.adjust_height(this.input),this.onChange(e)}}},getNumColumns:function(){var a,b=Math.ceil(Math.max(this.getTitle().length,this.schema.maxLength||0,this.schema.minLength||0)/5);return a="textarea"===this.input_type?6:["text","email"].indexOf(this.input_type)>=0?4:2,Math.min(12,Math.max(b,a))},build:function(){var a=this;if(this.options.compact||(this.header=this.label=this.theme.getFormInputLabel(this.getTitle())),this.schema.description&&(this.description=this.theme.getFormInputDescription(this.schema.description)),this.options.infoText&&(this.infoButton=this.theme.getInfoButton(this.options.infoText)),this.format=this.schema.format,!this.format&&this.schema.media&&this.schema.media.type&&(this.format=this.schema.media.type.replace(/(^(application|text)\/(x-)?(script\.)?)|(-source$)/g,"")),!this.format&&this.options.default_format&&(this.format=this.options.default_format),this.options.format&&(this.format=this.options.format),this.format)if("textarea"===this.format)this.input_type="textarea",this.input=this.theme.getTextareaInput();else if("range"===this.format){this.input_type="range";var b=this.schema.minimum||0,c=this.schema.maximum||Math.max(100,b+1),d=1;this.schema.multipleOf&&(b%this.schema.multipleOf&&(b=Math.ceil(b/this.schema.multipleOf)*this.schema.multipleOf),c%this.schema.multipleOf&&(c=Math.floor(c/this.schema.multipleOf)*this.schema.multipleOf),d=this.schema.multipleOf),this.input=this.theme.getRangeInput(b,c,d)}else["actionscript","batchfile","bbcode","c","c++","cpp","coffee","csharp","css","dart","django","ejs","erlang","golang","groovy","handlebars","haskell","haxe","html","ini","jade","java","javascript","json","less","lisp","lua","makefile","markdown","matlab","mysql","objectivec","pascal","perl","pgsql","php","python","r","ruby","sass","scala","scss","smarty","sql","sqlserver","stylus","svg","twig","vbscript","xml","yaml"].indexOf(this.format)>=0?(this.input_type=this.format,this.source_code=!0,this.input=this.theme.getTextareaInput()):(this.input_type=this.format,this.input=this.theme.getFormInputField(this.input_type));else this.input_type="text",this.input=this.theme.getFormInputField(this.input_type);if("undefined"!=typeof this.schema.maxLength&&this.input.setAttribute("maxlength",this.schema.maxLength),"undefined"!=typeof this.schema.pattern?this.input.setAttribute("pattern",this.schema.pattern):"undefined"!=typeof this.schema.minLength&&this.input.setAttribute("pattern",".{"+this.schema.minLength+",}"),this.options.compact?this.container.classList.add("compact"):this.options.input_width&&(this.input.style.width=this.options.input_width),(this.schema.readOnly||this.schema.readonly||this.schema.template)&&(this.always_disabled=!0,this.input.setAttribute("readonly","true")),this.setInputAttributes(["maxlength","pattern","readonly","min","max","step"]),this.input.addEventListener("change",function(b){if(b.preventDefault(),b.stopPropagation(),a.schema.template)return void(this.value=a.value);var c=this.value,d=a.sanitize(c);c!==d&&(this.value=d),a.is_dirty=!0,a.refreshValue(),a.onChange(!0)}),this.options.input_height&&(this.input.style.height=this.options.input_height),this.options.expand_height&&(this.adjust_height=function(a){if(a){var b,c=a.offsetHeight;if(a.offsetHeight<a.scrollHeight)for(b=0;a.offsetHeight<a.scrollHeight+3&&!(b>100);)b++,c++,a.style.height=c+"px";else{for(b=0;a.offsetHeight>=a.scrollHeight+3&&!(b>100);)b++,c--,a.style.height=c+"px";a.style.height=c+1+"px"}}},this.input.addEventListener("keyup",function(b){a.adjust_height(this)}),this.input.addEventListener("change",function(b){a.adjust_height(this)}),this.adjust_height()),this.format&&this.input.setAttribute("data-schemaformat",this.format),this.control=this.theme.getFormControl(this.label,this.input,this.description,this.infoButton),"range"===this.format){var e=document.createElement("output");e.setAttribute("class","range-output"),this.control.appendChild(e),e.value=this.schema["default"],this.input.addEventListener("change",function(){e.value=a.input.value}),this.input.addEventListener("input",function(){e.value=a.input.value})}this.container.appendChild(this.control),window.requestAnimationFrame(function(){a.input.parentNode&&a.afterInputReady(),a.adjust_height&&a.adjust_height(a.input)}),this.schema.template?(this.template=this.jsoneditor.compileTemplate(this.schema.template,this.template_engine),this.refreshValue()):this.refreshValue()},postBuild:function(){this._super(),window.Cleave&&this.schema.options&&"object"==typeof this.schema.options.cleave&&(this.cleave=new window.Cleave(this.input,this.schema.options.cleave))},enable:function(){this.always_disabled||(this.input.disabled=!1,this._super())},disable:function(a){a&&(this.always_disabled=!0),this.input.disabled=!0,this._super()},afterInputReady:function(){var a,b=this;if(this.source_code)if(this.options.wysiwyg&&["html","bbcode"].indexOf(this.input_type)>=0&&window.jQuery&&window.jQuery.fn&&window.jQuery.fn.sceditor)a=e({},{plugins:"html"===b.input_type?"xhtml":"bbcode",emoticonsEnabled:!1,width:"100%",height:300},h.plugins.sceditor,b.options.sceditor_options||{}),window.jQuery(b.input).sceditor(a),b.sceditor_instance=window.jQuery(b.input).sceditor("instance"),b.sceditor_instance.blur(function(){var a=window.jQuery("<div>"+b.sceditor_instance.val()+"</div>");window.jQuery("#sceditor-start-marker,#sceditor-end-marker,.sceditor-nlf",a).remove(),b.input.value=a.html(),b.value=b.input.value,b.is_dirty=!0,b.onChange(!0)});else if("markdown"===this.input_type&&window.SimpleMDE)a=e({},h.plugins.SimpleMDE,{element:this.input}),this.SimpleMDE=new window.SimpleMDE(a),this.SimpleMDE.codemirror.on("change",function(){b.value=b.SimpleMDE.value(),b.is_dirty=!0,b.onChange(!0)});else if(window.ace){var c=this.input_type;"cpp"!==c&&"c++"!==c&&"c"!==c||(c="c_cpp"),this.ace_container=document.createElement("div"),this.ace_container.style.width="100%",this.ace_container.style.position="relative",this.ace_container.style.height="400px",this.input.parentNode.insertBefore(this.ace_container,this.input),this.input.style.display="none",this.ace_editor=window.ace.edit(this.ace_container);var d=this.schema.options&&this.schema.options.ace;d&&this.ace_editor.setOptions(d),this.ace_editor.setValue(this.getValue()),this.ace_editor.session.getSelection().clearSelection(),this.ace_editor.resize(),h.plugins.ace.theme&&this.ace_editor.setTheme("ace/theme/"+h.plugins.ace.theme),this.ace_editor.getSession().setMode("ace/mode/"+this.schema.format),this.ace_editor.on("change",function(){var a=b.ace_editor.getValue();b.input.value=a,b.refreshValue(),b.is_dirty=!0,b.onChange(!0)})}b.theme.afterInputReady(b.input)},refreshValue:function(){this.value=this.input.value,"string"!=typeof this.value&&(this.value=""),this.serialized=this.value},destroy:function(){this.sceditor_instance?this.sceditor_instance.destroy():this.SimpleMDE?(this.SimpleMDE.toTextArea(),this.SimpleMDE=null):this.ace_editor&&this.ace_editor.destroy(),this.cleave&&this.cleave.destroy(),this.template=null,this.input&&this.input.parentNode&&this.input.parentNode.removeChild(this.input),this.label&&this.label.parentNode&&this.label.parentNode.removeChild(this.label),this.description&&this.description.parentNode&&this.description.parentNode.removeChild(this.description),this._super()},sanitize:function(a){return a},onWatchedFieldChange:function(){var a;this.template&&(a=this.getWatchedFieldValues(),this.setValue(this.template(a),!1,!0)),this._super()},showValidationErrors:function(a){var b=this;if("always"===this.jsoneditor.options.show_errors);else if(!this.is_dirty&&this.previous_error_setting===this.jsoneditor.options.show_errors)return;this.previous_error_setting=this.jsoneditor.options.show_errors;var c=[];f(a,function(a,d){d.path===b.path&&c.push(d.message)}),c.length?this.theme.addInputError(this.input,c.join(". ")+"."):this.theme.removeInputError(this.input)}}),h.defaults.editors.hidden=h.AbstractEditor.extend({register:function(){this._super(),this.input&&this.input.setAttribute("name",this.formname)},unregister:function(){this._super(),this.input&&this.input.removeAttribute("name")},setValue:function(a,b,c){if((!this.template||c)&&(null===a||"undefined"==typeof a?a="":"object"==typeof a?a=JSON.stringify(a):"string"!=typeof a&&(a=""+a),a!==this.serialized)){var d=this.sanitize(a);if(this.input.value!==d){this.input.value=d;var e=c||this.getValue()!==a;this.refreshValue(),b?this.is_dirty=!1:"change"===this.jsoneditor.options.show_errors&&(this.is_dirty=!0),this.adjust_height&&this.adjust_height(this.input),this.onChange(e)}}},getNumColumns:function(){return 2},enable:function(){this._super()},disable:function(){this._super()},refreshValue:function(){this.value=this.input.value,"string"!=typeof this.value&&(this.value=""),this.serialized=this.value},destroy:function(){this.template=null,this.input&&this.input.parentNode&&this.input.parentNode.removeChild(this.input),this.label&&this.label.parentNode&&this.label.parentNode.removeChild(this.label),this.description&&this.description.parentNode&&this.description.parentNode.removeChild(this.description),this._super()},sanitize:function(a){return a},onWatchedFieldChange:function(){var a;this.template&&(a=this.getWatchedFieldValues(),this.setValue(this.template(a),!1,!0)),this._super()},build:function(){this.format=this.schema.format,!this.format&&this.options.default_format&&(this.format=this.options.default_format),this.options.format&&(this.format=this.options.format),this.input_type="hidden",this.input=this.theme.getFormInputField(this.input_type),this.format&&this.input.setAttribute("data-schemaformat",this.format),this.container.appendChild(this.input),this.schema.template?(this.template=this.jsoneditor.compileTemplate(this.schema.template,this.template_engine),this.refreshValue()):this.refreshValue()}}),h.defaults.editors.number=h.defaults.editors.string.extend({build:function(){if(this._super(),"undefined"!=typeof this.schema.minimum){var a=this.schema.minimum;"undefined"!=typeof this.schema.exclusiveMinimum&&(a+=1),this.input.setAttribute("min",a)}if("undefined"!=typeof this.schema.maximum){var b=this.schema.maximum;"undefined"!=typeof this.schema.exclusiveMaximum&&(b-=1),this.input.setAttribute("max",b)}if("undefined"!=typeof this.schema.step){var c=this.schema.step||1;this.input.setAttribute("step",c)}this.setInputAttributes(["maxlength","pattern","readonly","min","max","step"])},sanitize:function(a){return(a+"").replace(/[^0-9\.\-eE]/g,"")},getNumColumns:function(){return 2},getValue:function(){return this.dependenciesFulfilled?""===this.value?b:1*this.value:b}}),h.defaults.editors.integer=h.defaults.editors.number.extend({sanitize:function(a){return a+="",a.replace(/[^0-9\-]/g,"")},getNumColumns:function(){return 2}}),h.defaults.editors.rating=h.defaults.editors.integer.extend({build:function(){var a,b=this;this.options.compact||(this.header=this.label=this.theme.getFormInputLabel(this.getTitle())),this.schema.description&&(this.description=this.theme.getFormInputDescription(this.schema.description));var c="json-editor-style-rating",d=document.getElementById(c);if(!d){var e=document.createElement("style");e.id=c,e.type="text/css",e.innerHTML="      .rating-container {        display: inline-block;        clear: both;      }            .rating {        float:left;      }            /* :not(:checked) is a filter, so that browsers that don’t support :checked don’t         follow these rules. Every browser that supports :checked also supports :not(), so         it doesn’t make the test unnecessarily selective */      .rating:not(:checked) > input {        position:absolute;        top:-9999px;        clip:rect(0,0,0,0);      }            .rating:not(:checked) > label {        float:right;        width:1em;        padding:0 .1em;        overflow:hidden;        white-space:nowrap;        cursor:pointer;        color:#ddd;      }            .rating:not(:checked) > label:before {        content: '★ ';      }            .rating > input:checked ~ label {        color: #FFB200;      }            .rating:not([readOnly]):not(:checked) > label:hover,      .rating:not([readOnly]):not(:checked) > label:hover ~ label {        color: #FFDA00;      }            .rating:not([readOnly]) > input:checked + label:hover,      .rating:not([readOnly]) > input:checked + label:hover ~ label,      .rating:not([readOnly]) > input:checked ~ label:hover,      .rating:not([readOnly]) > input:checked ~ label:hover ~ label,      .rating:not([readOnly]) > label:hover ~ input:checked ~ label {        color: #FF8C0D;      }            .rating:not([readOnly])  > label:active {        position:relative;        top:2px;        left:2px;      }",document.getElementsByTagName("head")[0].appendChild(e)}this.input=this.theme.getFormInputField("hidden"),this.container.appendChild(this.input);var g=document.createElement("div");g.classList.add("rating-container");var h=document.createElement("div");h.setAttribute("name",this.formname),h.classList.add("rating"),g.appendChild(h),this.options.compact&&this.container.setAttribute("class",this.container.getAttribute("class")+" compact");var i=this.schema.maximum?this.schema.maximum:5;for(this.schema.exclusiveMaximum&&i--,this.inputs=[],a=i;a>0;a--){var j=this.formname+a,k=this.theme.getFormInputField("radio");k.setAttribute("id",j),k.setAttribute("value",a),k.setAttribute("name",this.formname),h.appendChild(k),this.inputs.push(k);var l=document.createElement("label");l.setAttribute("for",j),l.appendChild(document.createTextNode(a+(1==a?" star":" stars"))),h.appendChild(l)}(this.schema.readOnly||this.schema.readonly)&&(this.always_disabled=!0,f(this.inputs,function(a,b){h.setAttribute("readOnly","readOnly"),b.disabled=!0})),g.addEventListener("change",function(a){a.preventDefault(),a.stopPropagation(),b.input.value=a.srcElement.value,b.is_dirty=!0,b.refreshValue(),b.watch_listener(),b.jsoneditor.notifyWatchers(b.path),b.parent?b.parent.onChildEditorChange(b):b.jsoneditor.onChange()}),this.control=this.theme.getFormControl(this.label,g,this.description),this.container.appendChild(this.control),this.refreshValue()},setValue:function(a){var b=this.sanitize(a);if(this.value!==b){var c=this;f(this.inputs,function(a,d){if(d.value===b)return d.checked=!0,c.value=b,c.input.value=c.value,c.watch_listener(),c.jsoneditor.notifyWatchers(c.path),!1})}}}),h.defaults.editors.object=h.AbstractEditor.extend({getDefault:function(){return e({},this.schema["default"]||{})},getChildEditors:function(){return this.editors},register:function(){if(this._super(),this.editors)for(var a in this.editors)this.editors.hasOwnProperty(a)&&this.editors[a].register()},unregister:function(){if(this._super(),this.editors)for(var a in this.editors)this.editors.hasOwnProperty(a)&&this.editors[a].unregister()},getNumColumns:function(){return Math.max(Math.min(12,this.maxwidth),3)},enable:function(){if(!this.always_disabled&&(this.editjson_button&&(this.editjson_button.disabled=!1),this.addproperty_button&&(this.addproperty_button.disabled=!1),this._super(),this.editors))for(var a in this.editors)this.editors.hasOwnProperty(a)&&this.editors[a].enable()},disable:function(a){if(a&&(this.always_disabled=!0),this.editjson_button&&(this.editjson_button.disabled=!0),this.addproperty_button&&(this.addproperty_button.disabled=!0),this.hideEditJSON(),this._super(),this.editors)for(var b in this.editors)this.editors.hasOwnProperty(b)&&this.editors[b].disable(a)},layoutEditors:function(){var a,b,c=this;if(this.row_container){this.property_order=Object.keys(this.editors),this.property_order=this.property_order.sort(function(a,b){var d=c.editors[a].schema.propertyOrder,e=c.editors[b].schema.propertyOrder;return"number"!=typeof d&&(d=1e3),"number"!=typeof e&&(e=1e3),d-e});var d,e="categories"===this.format;if("grid"===this.format){var h=[];for(f(this.property_order,function(a,b){var d=c.editors[b];if(!d.property_removed){for(var e=!1,f=d.options.hidden?0:d.options.grid_columns||d.getNumColumns(),g=d.options.hidden?0:d.container.offsetHeight,i=0;i<h.length;i++)h[i].width+f<=12&&(!g||.5*h[i].minh<g&&2*h[i].maxh>g)&&(e=i);e===!1&&(h.push({width:0,minh:999999,maxh:0,editors:[]}),e=h.length-1),h[e].editors.push({key:b,width:f,height:g}),h[e].width+=f,h[e].minh=Math.min(h[e].minh,g),h[e].maxh=Math.max(h[e].maxh,g)}}),a=0;a<h.length;a++)if(h[a].width<12){var i=!1,j=0;for(b=0;b<h[a].editors.length;b++)i===!1?i=b:h[a].editors[b].width>h[a].editors[i].width&&(i=b),h[a].editors[b].width*=12/h[a].width,h[a].editors[b].width=Math.floor(h[a].editors[b].width),j+=h[a].editors[b].width;j<12&&(h[a].editors[i].width+=12-j),h[a].width=12}if(this.layout===JSON.stringify(h))return!1;for(this.layout=JSON.stringify(h),d=document.createElement("div"),a=0;a<h.length;a++){var k=this.theme.getGridRow();for(d.appendChild(k),b=0;b<h[a].editors.length;b++){var l=h[a].editors[b].key,m=this.editors[l];m.options.hidden?m.container.style.display="none":this.theme.setGridColumnSize(m.container,h[a].editors[b].width),k.appendChild(m.container)}}}else{if(d=document.createElement("div"),e){var n=document.createElement("div"),o=this.theme.getTopTabHolder(this.schema.title),p=this.theme.getTopTabContentHolder(o);for(f(this.property_order,function(a,b){var d=c.editors[b];if(!d.property_removed){var e=c.theme.getTabContent(),f=d.schema&&("object"===d.schema.type||"array"===d.schema.type);e.isObjOrArray=f;var g=c.theme.getGridRow();d.tab||("undefined"==typeof c.basicPane?c.addRow(d,o,e):c.addRow(d,o,c.basicPane)),e.id=c.getValidId(d.tab_text.textContent),f?(e.appendChild(g),p.appendChild(e),c.theme.addTopTab(o,d.tab)):(n.appendChild(g),p.childElementCount>0?p.firstChild.isObjOrArray&&(e.appendChild(n),p.insertBefore(e,p.firstChild),c.theme.insertBasicTopTab(d.tab,o),d.basicPane=e):(e.appendChild(n),p.appendChild(e),c.theme.addTopTab(o,d.tab),d.basicPane=e)),d.options.hidden?d.container.style.display="none":c.theme.setGridColumnSize(d.container,12),g.appendChild(d.container),d.rowPane=e}});this.tabPanesContainer.firstChild;)this.tabPanesContainer.removeChild(this.tabPanesContainer.firstChild);var q=this.tabs_holder.parentNode;q.removeChild(q.firstChild),q.appendChild(o),this.tabPanesContainer=p,this.tabs_holder=o;var r=this.theme.getFirstTab(this.tabs_holder);return void(r&&g(r,"click"))}f(this.property_order,function(a,b){var e=c.editors[b];if(!e.property_removed){var f=c.theme.getGridRow();d.appendChild(f),e.options.hidden?e.container.style.display="none":c.theme.setGridColumnSize(e.container,12),f.appendChild(e.container)}})}for(;this.row_container.firstChild;)this.row_container.removeChild(this.row_container.firstChild);this.row_container.appendChild(d)}},getPropertySchema:function(a){var b=this.schema.properties[a]||{};b=e({},b);var c=!!this.schema.properties[a];if(this.schema.patternProperties)for(var d in this.schema.patternProperties)if(this.schema.patternProperties.hasOwnProperty(d)){var f=new RegExp(d);f.test(a)&&(b.allOf=b.allOf||[],b.allOf.push(this.schema.patternProperties[d]),c=!0)}return!c&&this.schema.additionalProperties&&"object"==typeof this.schema.additionalProperties&&(b=e({},this.schema.additionalProperties)),b},preBuild:function(){this._super(),this.editors={},this.cached_editors={};var a=this;if(this.format=this.options.layout||this.options.object_layout||this.schema.format||this.jsoneditor.options.object_layout||"normal",this.schema.properties=this.schema.properties||{},this.minwidth=0,this.maxwidth=0,this.options.table_row)f(this.schema.properties,function(b,c){var d=a.jsoneditor.getEditorClass(c);a.editors[b]=a.jsoneditor.createEditor(d,{jsoneditor:a.jsoneditor,schema:c,path:a.path+"."+b,parent:a,compact:!0,required:!0}),a.editors[b].preBuild();var e=a.editors[b].options.hidden?0:a.editors[b].options.grid_columns||a.editors[b].getNumColumns();a.minwidth+=e,a.maxwidth+=e}),this.no_link_holder=!0;else{if(this.options.table)throw"Not supported yet";this.schema.defaultProperties||(this.jsoneditor.options.display_required_only||this.options.display_required_only?(this.schema.defaultProperties=[],f(this.schema.properties,function(b,c){a.isRequired({key:b,schema:c})&&a.schema.defaultProperties.push(b)})):a.schema.defaultProperties=Object.keys(a.schema.properties)),a.maxwidth+=1,f(this.schema.defaultProperties,function(b,c){a.addObjectProperty(c,!0),a.editors[c]&&(a.minwidth=Math.max(a.minwidth,a.editors[c].options.grid_columns||a.editors[c].getNumColumns()),a.maxwidth+=a.editors[c].options.grid_columns||a.editors[c].getNumColumns())})}this.property_order=Object.keys(this.editors),this.property_order=this.property_order.sort(function(b,c){var d=a.editors[b].schema.propertyOrder,e=a.editors[c].schema.propertyOrder;return"number"!=typeof d&&(d=1e3),"number"!=typeof e&&(e=1e3),d-e})},addTab:function(a){var b=this,c=b.rows[a].schema&&("object"===b.rows[a].schema.type||"array"===b.rows[a].schema.type);b.tabs_holder&&(b.rows[a].tab_text=document.createElement("span"),c?b.rows[a].tab_text.textContent=b.rows[a].getHeaderText():b.rows[a].tab_text.textContent="undefined"==typeof b.schema.basicCategoryTitle?"Basic":b.schema.basicCategoryTitle,b.rows[a].tab=b.theme.getTopTab(b.rows[a].tab_text,this.getValidId(b.rows[a].tab_text.textContent)),b.rows[a].tab.addEventListener("click",function(c){b.active_tab=b.rows[a].tab,b.refreshTabs(),c.preventDefault(),c.stopPropagation()}))},addRow:function(a,b,c){var d=this,e=this.rows.length,f="object"===a.schema.type||"array"===a.schema.type;d.rows[e]=a,d.rows[e].rowPane=c,f?(d.addTab(e),d.theme.addTopTab(b,d.rows[e].tab)):"undefined"==typeof d.basicTab?(d.addTab(e),d.basicTab=e,d.basicPane=c,d.theme.addTopTab(b,d.rows[e].tab)):(d.rows[e].tab=d.rows[d.basicTab].tab,d.rows[e].tab_text=d.rows[d.basicTab].tab_text,d.rows[e].rowPane=d.rows[d.basicTab].rowPane)},refreshTabs:function(a){var b=this,c="undefined"!=typeof b.basicTab,d=!1;f(this.rows,function(e,f){f.tab&&f.rowPane&&f.rowPane.parentNode&&(c&&f.tab==b.rows[b.basicTab].tab&&d||(a?f.tab_text.textContent=f.getHeaderText():(c&&f.tab==b.rows[b.basicTab].tab&&(d=!0),f.tab===b.active_tab?b.theme.markTabActive(f):b.theme.markTabInactive(f))))})},build:function(){var a=this,b="categories"===this.format;if(this.rows=[],this.active_tab=null,this.options.table_row)this.editor_holder=this.container,f(this.editors,function(b,c){var d=a.theme.getTableCell();a.editor_holder.appendChild(d),c.setContainer(d),c.build(),c.postBuild(),a.editors[b].options.hidden&&(d.style.display="none"),a.editors[b].options.input_width&&(d.style.width=a.editors[b].options.input_width)});else{if(this.options.table)throw"Not supported yet";this.header=document.createElement("span"),this.header.textContent=this.getTitle(),this.title=this.theme.getHeader(this.header),this.container.appendChild(this.title),this.container.style.position="relative",this.editjson_holder=this.theme.getModal(),this.editjson_textarea=this.theme.getTextareaInput(),this.editjson_textarea.style.height="170px",this.editjson_textarea.style.width="300px",this.editjson_textarea.style.display="block",this.editjson_save=this.getButton("Save","save","Save"),this.editjson_save.classList.add("json-editor-btntype-save"),this.editjson_save.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation(),a.saveJSON()}),this.editjson_copy=this.getButton("Copy","copy","Copy"),this.editjson_copy.classList.add("json-editor-btntype-copy"),this.editjson_copy.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation(),a.copyJSON()}),this.editjson_cancel=this.getButton("Cancel","cancel","Cancel"),this.editjson_cancel.classList.add("json-editor-btntype-cancel"),this.editjson_cancel.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation(),a.hideEditJSON()}),this.editjson_holder.appendChild(this.editjson_textarea),this.editjson_holder.appendChild(this.editjson_save),this.editjson_holder.appendChild(this.editjson_copy),this.editjson_holder.appendChild(this.editjson_cancel),this.addproperty_holder=this.theme.getModal(),this.addproperty_list=document.createElement("div"),this.addproperty_list.style.width="295px",this.addproperty_list.style.maxHeight="160px",this.addproperty_list.style.padding="5px 0",this.addproperty_list.style.overflowY="auto",this.addproperty_list.style.overflowX="hidden",this.addproperty_list.style.paddingLeft="5px",this.addproperty_list.setAttribute("class","property-selector"),this.addproperty_add=this.getButton("add","add","add"),this.addproperty_add.classList.add("json-editor-btntype-add"),this.addproperty_input=this.theme.getFormInputField("text"),this.addproperty_input.setAttribute("placeholder","Property name..."),this.addproperty_input.style.width="220px",this.addproperty_input.style.marginBottom="0",this.addproperty_input.style.display="inline-block",this.addproperty_add.addEventListener("click",function(b){if(b.preventDefault(),b.stopPropagation(),a.addproperty_input.value){if(a.editors[a.addproperty_input.value])return void window.alert("there is already a property with that name");a.addObjectProperty(a.addproperty_input.value),a.editors[a.addproperty_input.value]&&a.editors[a.addproperty_input.value].disable(),a.onChange(!0)}}),this.addproperty_holder.appendChild(this.addproperty_list),this.addproperty_holder.appendChild(this.addproperty_input),this.addproperty_holder.appendChild(this.addproperty_add);var c=document.createElement("div");c.style.clear="both",this.addproperty_holder.appendChild(c),document.addEventListener("click",function(a){!this.addproperty_holder.contains(a.target)&&this.adding_property&&(a.preventDefault(),a.stopPropagation(),this.toggleAddProperty())}.bind(this)),this.schema.description&&(this.description=this.theme.getDescription(this.schema.description),this.container.appendChild(this.description)),this.error_holder=document.createElement("div"),this.container.appendChild(this.error_holder),this.editor_holder=this.theme.getIndentedPanel(),this.container.appendChild(this.editor_holder),this.row_container=this.theme.getGridContainer(),b?(this.tabs_holder=this.theme.getTopTabHolder(this.getValidId(this.schema.title)),this.tabPanesContainer=this.theme.getTopTabContentHolder(this.tabs_holder),this.editor_holder.appendChild(this.tabs_holder)):(this.tabs_holder=this.theme.getTabHolder(this.getValidId(this.schema.title)),this.tabPanesContainer=this.theme.getTabContentHolder(this.tabs_holder),this.editor_holder.appendChild(this.row_container)),f(this.editors,function(c,d){var e=a.theme.getTabContent(),f=a.theme.getGridColumn(),g=!(!d.schema||"object"!==d.schema.type&&"array"!==d.schema.type);if(e.isObjOrArray=g,b){if(g){var h=a.theme.getGridContainer();h.appendChild(f),e.appendChild(h),a.tabPanesContainer.appendChild(e),a.row_container=h}else"undefined"==typeof a.row_container_basic&&(a.row_container_basic=a.theme.getGridContainer(),e.appendChild(a.row_container_basic),0==a.tabPanesContainer.childElementCount?a.tabPanesContainer.appendChild(e):a.tabPanesContainer.insertBefore(e,a.tabPanesContainer.childNodes[1])),a.row_container_basic.appendChild(f);a.addRow(d,a.tabs_holder,e),e.id=a.getValidId(d.schema.title)}else a.row_container.appendChild(f);d.setContainer(f),d.build(),d.postBuild()}),this.rows[0]&&g(this.rows[0].tab,"click"),this.title_controls=this.theme.getHeaderButtonHolder(),this.editjson_controls=this.theme.getHeaderButtonHolder(),this.addproperty_controls=this.theme.getHeaderButtonHolder(),this.title.appendChild(this.title_controls),this.title.appendChild(this.editjson_controls),this.title.appendChild(this.addproperty_controls),this.collapsed=!1,this.toggle_button=this.getButton("","collapse",this.translate("button_collapse")),this.toggle_button.classList.add("json-editor-btntype-toggle"),this.title_controls.appendChild(this.toggle_button),this.toggle_button.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation(),a.collapsed?(a.editor_holder.style.display="",a.collapsed=!1,a.setButtonText(a.toggle_button,"","collapse",a.translate("button_collapse"))):(a.editor_holder.style.display="none",a.collapsed=!0,a.setButtonText(a.toggle_button,"","expand",a.translate("button_expand")))}),this.options.collapsed&&g(this.toggle_button,"click"),this.schema.options&&"undefined"!=typeof this.schema.options.disable_collapse?this.schema.options.disable_collapse&&(this.toggle_button.style.display="none"):this.jsoneditor.options.disable_collapse&&(this.toggle_button.style.display="none"),this.editjson_button=this.getButton("JSON","edit","Edit JSON"),this.editjson_button.classList.add("json-editor-btntype-editjson"),this.editjson_button.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation(),a.toggleEditJSON()}),this.editjson_controls.appendChild(this.editjson_button),this.editjson_controls.appendChild(this.editjson_holder),this.schema.options&&"undefined"!=typeof this.schema.options.disable_edit_json?this.schema.options.disable_edit_json&&(this.editjson_button.style.display="none"):this.jsoneditor.options.disable_edit_json&&(this.editjson_button.style.display="none"),this.addproperty_button=this.getButton("Properties","edit","Object Properties"),this.addproperty_button.classList.add("json-editor-btntype-properties"),this.addproperty_button.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation(),a.toggleAddProperty()}),this.addproperty_controls.appendChild(this.addproperty_button),this.addproperty_controls.appendChild(this.addproperty_holder),this.refreshAddProperties()}this.options.table_row?(this.editor_holder=this.container,f(this.property_order,function(b,c){a.editor_holder.appendChild(a.editors[c].container)})):(this.layoutEditors(),this.layoutEditors())},showEditJSON:function(){this.editjson_holder&&(this.hideAddProperty(),this.editjson_holder.style.left=this.editjson_button.offsetLeft+"px",this.editjson_holder.style.top=this.editjson_button.offsetTop+this.editjson_button.offsetHeight+"px",this.editjson_textarea.value=JSON.stringify(this.getValue(),null,2),this.disable(),this.editjson_holder.style.display="",this.editjson_button.disabled=!1,this.editing_json=!0)},hideEditJSON:function(){this.editjson_holder&&this.editing_json&&(this.editjson_holder.style.display="none",this.enable(),this.editing_json=!1)},copyJSON:function(){if(this.editjson_holder){var a=document.createElement("textarea");a.value=this.editjson_textarea.value,a.setAttribute("readonly",""),a.style.position="absolute",a.style.left="-9999px",document.body.appendChild(a),a.select(),document.execCommand("copy"),document.body.removeChild(a)}},saveJSON:function(){if(this.editjson_holder)try{var a=JSON.parse(this.editjson_textarea.value);this.setValue(a),this.hideEditJSON(),this.onChange(!0)}catch(b){throw window.alert("invalid JSON"),b}},toggleEditJSON:function(){this.editing_json?this.hideEditJSON():this.showEditJSON()},insertPropertyControlUsingPropertyOrder:function(a,b,c){var d;this.schema.properties[a]&&(d=this.schema.properties[a].propertyOrder),"number"!=typeof d&&(d=1e3),b.propertyOrder=d;for(var e=0;e<c.childNodes.length;e++){var f=c.childNodes[e];if(b.propertyOrder<f.propertyOrder){this.addproperty_list.insertBefore(b,f),b=null;break}}b&&this.addproperty_list.appendChild(b)},addPropertyCheckbox:function(a){var b,c,d,e,f=this;return b=f.theme.getCheckbox(),b.style.width="auto",d=this.schema.properties[a]&&this.schema.properties[a].title?this.schema.properties[a].title:a,c=f.theme.getCheckboxLabel(d),e=f.theme.getFormControl(c,b),e.style.paddingBottom=e.style.marginBottom=e.style.paddingTop=e.style.marginTop=0,e.style.height="auto",this.insertPropertyControlUsingPropertyOrder(a,e,this.addproperty_list),
+b.checked=a in this.editors,b.addEventListener("change",function(){b.checked?f.addObjectProperty(a):f.removeObjectProperty(a),f.onChange(!0)}),f.addproperty_checkboxes[a]=b,b},showAddProperty:function(){this.addproperty_holder&&(this.hideEditJSON(),this.addproperty_holder.style.left=this.addproperty_button.offsetLeft+"px",this.addproperty_holder.style.top=this.addproperty_button.offsetTop+this.addproperty_button.offsetHeight+"px",this.disable(),this.adding_property=!0,this.addproperty_button.disabled=!1,this.addproperty_holder.style.display="",this.refreshAddProperties())},hideAddProperty:function(){this.addproperty_holder&&this.adding_property&&(this.addproperty_holder.style.display="none",this.enable(),this.adding_property=!1)},toggleAddProperty:function(){this.adding_property?this.hideAddProperty():this.showAddProperty()},removeObjectProperty:function(a){this.editors[a]&&(this.editors[a].unregister(),delete this.editors[a],this.refreshValue(),this.layoutEditors())},addObjectProperty:function(a,b){var c=this;if(!this.editors[a]){if(this.cached_editors[a]){if(this.editors[a]=this.cached_editors[a],b)return;this.editors[a].register()}else{if(!(this.canHaveAdditionalProperties()||this.schema.properties&&this.schema.properties[a]))return;var d=c.getPropertySchema(a);"number"!=typeof d.propertyOrder&&(d.propertyOrder=Object.keys(c.editors).length+1e3);var e=c.jsoneditor.getEditorClass(d);if(c.editors[a]=c.jsoneditor.createEditor(e,{jsoneditor:c.jsoneditor,schema:d,path:c.path+"."+a,parent:c}),c.editors[a].preBuild(),!b){var f=c.theme.getChildEditorHolder();c.editor_holder.appendChild(f),c.editors[a].setContainer(f),c.editors[a].build(),c.editors[a].postBuild()}c.cached_editors[a]=c.editors[a]}b||(c.refreshValue(),c.layoutEditors())}},onChildEditorChange:function(a){this.refreshValue(),this._super(a)},canHaveAdditionalProperties:function(){return"boolean"==typeof this.schema.additionalProperties?this.schema.additionalProperties:!this.jsoneditor.options.no_additional_properties},destroy:function(){f(this.cached_editors,function(a,b){b.destroy()}),this.editor_holder&&(this.editor_holder.innerHTML=""),this.title&&this.title.parentNode&&this.title.parentNode.removeChild(this.title),this.error_holder&&this.error_holder.parentNode&&this.error_holder.parentNode.removeChild(this.error_holder),this.editors=null,this.cached_editors=null,this.editor_holder&&this.editor_holder.parentNode&&this.editor_holder.parentNode.removeChild(this.editor_holder),this.editor_holder=null,this._super()},getValue:function(){if(!this.dependenciesFulfilled)return b;var a=this._super();if(this.jsoneditor.options.remove_empty_properties||this.options.remove_empty_properties)for(var c in a)a.hasOwnProperty(c)&&("undefined"==typeof a[c]||""===a[c]||a[c]===Object(a[c])&&0==Object.keys(a[c]).length&&a[c].constructor==Object)&&delete a[c];return a},refreshValue:function(){this.value={};for(var a in this.editors)this.editors.hasOwnProperty(a)&&(this.value[a]=this.editors[a].getValue());this.adding_property&&this.refreshAddProperties()},refreshAddProperties:function(){if(this.options.disable_properties||this.options.disable_properties!==!1&&this.jsoneditor.options.disable_properties)return void(this.addproperty_controls.style.display="none");var a,b=!1,c=!1,d=0,e=!1;for(a in this.editors)this.editors.hasOwnProperty(a)&&d++;b=this.canHaveAdditionalProperties()&&!("undefined"!=typeof this.schema.maxProperties&&d>=this.schema.maxProperties),this.addproperty_checkboxes&&(this.addproperty_list.innerHTML=""),this.addproperty_checkboxes={};for(a in this.cached_editors)this.cached_editors.hasOwnProperty(a)&&(this.addPropertyCheckbox(a),this.isRequired(this.cached_editors[a])&&a in this.editors&&(this.addproperty_checkboxes[a].disabled=!0),"undefined"!=typeof this.schema.minProperties&&d<=this.schema.minProperties?(this.addproperty_checkboxes[a].disabled=this.addproperty_checkboxes[a].checked,this.addproperty_checkboxes[a].checked||(e=!0)):a in this.editors?(e=!0,c=!0):b||this.schema.properties.hasOwnProperty(a)?(this.addproperty_checkboxes[a].disabled=!1,e=!0):this.addproperty_checkboxes[a].disabled=!0);this.canHaveAdditionalProperties()&&(e=!0);for(a in this.schema.properties)this.schema.properties.hasOwnProperty(a)&&(this.cached_editors[a]||(e=!0,this.addPropertyCheckbox(a)));e?this.canHaveAdditionalProperties()?b?this.addproperty_add.disabled=!1:this.addproperty_add.disabled=!0:(this.addproperty_add.style.display="none",this.addproperty_input.style.display="none"):(this.hideAddProperty(),this.addproperty_controls.style.display="none")},isRequired:function(a){return"boolean"==typeof a.schema.required?a.schema.required:Array.isArray(this.schema.required)?this.schema.required.indexOf(a.key)>-1:!!this.jsoneditor.options.required_by_default},setValue:function(a,b){var c=this;a=a||{},("object"!=typeof a||Array.isArray(a))&&(a={}),f(this.cached_editors,function(d,e){"undefined"!=typeof a[d]?(c.addObjectProperty(d),e.setValue(a[d],b)):b||c.isRequired(e)?e.setValue(e.getDefault(),b):c.removeObjectProperty(d)}),f(a,function(a,d){c.cached_editors[a]||(c.addObjectProperty(a),c.editors[a]&&c.editors[a].setValue(d,b))}),this.refreshValue(),this.layoutEditors(),this.onChange()},showValidationErrors:function(a){var b=this,c=[],d=[];if(f(a,function(a,e){e.path===b.path?c.push(e):d.push(e)}),this.error_holder)if(c.length){this.error_holder.innerHTML="",this.error_holder.style.display="",f(c,function(a,c){b.error_holder.appendChild(b.theme.getErrorMessage(c.message))})}else this.error_holder.style.display="none";this.options.table_row&&(c.length?this.theme.addTableRowError(this.container):this.theme.removeTableRowError(this.container)),f(this.editors,function(a,b){b.showValidationErrors(d)})}}),h.defaults.editors.array=h.AbstractEditor.extend({askConfirmation:function(){return this.jsoneditor.options.prompt_before_delete!==!0||confirm("Are you sure you want to remove this node?")!==!1},getDefault:function(){return this.schema["default"]||[]},register:function(){if(this._super(),this.rows)for(var a=0;a<this.rows.length;a++)this.rows[a].register()},unregister:function(){if(this._super(),this.rows)for(var a=0;a<this.rows.length;a++)this.rows[a].unregister()},getNumColumns:function(){var a=this.getItemInfo(0);return this.tabs_holder&&"tabs-top"!==this.schema.format?Math.max(Math.min(12,a.width+2),4):a.width},enable:function(){if(!this.always_disabled){if(this.add_row_button&&(this.add_row_button.disabled=!1),this.remove_all_rows_button&&(this.remove_all_rows_button.disabled=!1),this.delete_last_row_button&&(this.delete_last_row_button.disabled=!1),this.rows)for(var a=0;a<this.rows.length;a++)this.rows[a].enable(),this.rows[a].moveup_button&&(this.rows[a].moveup_button.disabled=!1),this.rows[a].movedown_button&&(this.rows[a].movedown_button.disabled=!1),this.rows[a].delete_button&&(this.rows[a].delete_button.disabled=!1);this._super()}},disable:function(a){if(a&&(this.always_disabled=!0),this.add_row_button&&(this.add_row_button.disabled=!0),this.remove_all_rows_button&&(this.remove_all_rows_button.disabled=!0),this.delete_last_row_button&&(this.delete_last_row_button.disabled=!0),this.rows)for(var b=0;b<this.rows.length;b++)this.rows[b].disable(a),this.rows[b].moveup_button&&(this.rows[b].moveup_button.disabled=!0),this.rows[b].movedown_button&&(this.rows[b].movedown_button.disabled=!0),this.rows[b].delete_button&&(this.rows[b].delete_button.disabled=!0);this._super()},preBuild:function(){this._super(),this.rows=[],this.row_cache=[],this.hide_delete_buttons=this.options.disable_array_delete||this.jsoneditor.options.disable_array_delete,this.hide_delete_all_rows_buttons=this.hide_delete_buttons||this.options.disable_array_delete_all_rows||this.jsoneditor.options.disable_array_delete_all_rows,this.hide_delete_last_row_buttons=this.hide_delete_buttons||this.options.disable_array_delete_last_row||this.jsoneditor.options.disable_array_delete_last_row,this.hide_move_buttons=this.options.disable_array_reorder||this.jsoneditor.options.disable_array_reorder,this.hide_add_button=this.options.disable_array_add||this.jsoneditor.options.disable_array_add,this.show_copy_button=this.options.enable_array_copy||this.jsoneditor.options.enable_array_copy,this.array_controls_top=this.options.array_controls_top||this.jsoneditor.options.array_controls_top},build:function(){this.options.compact?(this.panel=this.theme.getIndentedPanel(),this.container.appendChild(this.panel),this.title_controls=this.theme.getHeaderButtonHolder(),this.panel.appendChild(this.title_controls),this.controls=this.theme.getButtonHolder(),this.panel.appendChild(this.controls),this.row_holder=document.createElement("div"),this.panel.appendChild(this.row_holder)):(this.header=document.createElement("span"),this.header.textContent=this.getTitle(),this.title=this.theme.getHeader(this.header),this.container.appendChild(this.title),this.title_controls=this.theme.getHeaderButtonHolder(),this.title.appendChild(this.title_controls),this.schema.description&&(this.description=this.theme.getDescription(this.schema.description),this.container.appendChild(this.description)),this.error_holder=document.createElement("div"),this.container.appendChild(this.error_holder),"tabs-top"===this.schema.format?(this.controls=this.theme.getHeaderButtonHolder(),this.title.appendChild(this.controls),this.tabs_holder=this.theme.getTopTabHolder(this.getValidId(this.getItemTitle())),this.container.appendChild(this.tabs_holder),this.row_holder=this.theme.getTopTabContentHolder(this.tabs_holder),this.active_tab=null):"tabs"===this.schema.format?(this.controls=this.theme.getHeaderButtonHolder(),this.title.appendChild(this.controls),this.tabs_holder=this.theme.getTabHolder(this.getValidId(this.getItemTitle())),this.container.appendChild(this.tabs_holder),this.row_holder=this.theme.getTabContentHolder(this.tabs_holder),this.active_tab=null):(this.panel=this.theme.getIndentedPanel(),this.container.appendChild(this.panel),this.row_holder=document.createElement("div"),this.panel.appendChild(this.row_holder),this.controls=this.theme.getButtonHolder(),this.array_controls_top?this.title.appendChild(this.controls):this.panel.appendChild(this.controls))),this.addControls()},onChildEditorChange:function(a){this.refreshValue(),this.refreshTabs(!0),this._super(a)},getItemTitle:function(){if(!this.item_title)if(this.schema.items&&!Array.isArray(this.schema.items)){var a=this.jsoneditor.expandRefs(this.schema.items);this.item_title=a.title||"item"}else this.item_title="item";return this.item_title},getItemSchema:function(a){return Array.isArray(this.schema.items)?a>=this.schema.items.length?this.schema.additionalItems===!0?{}:this.schema.additionalItems?e({},this.schema.additionalItems):void 0:e({},this.schema.items[a]):this.schema.items?e({},this.schema.items):{}},getItemInfo:function(a){var b=this.getItemSchema(a);this.item_info=this.item_info||{};var c=JSON.stringify(b);return"undefined"!=typeof this.item_info[c]?this.item_info[c]:(b=this.jsoneditor.expandRefs(b),this.item_info[c]={title:b.title||"item","default":b["default"],width:12,child_editors:b.properties||b.items},this.item_info[c])},getElementEditor:function(a){var b=this.getItemInfo(a),c=this.getItemSchema(a);c=this.jsoneditor.expandRefs(c),c.title=b.title+" "+(a+1);var d,e=this.jsoneditor.getEditorClass(c);this.tabs_holder?(d="tabs-top"===this.schema.format?this.theme.getTopTabContent():this.theme.getTabContent(),d.id=this.path+"."+a):d=b.child_editors?this.theme.getChildEditorHolder():this.theme.getIndentedPanel(),this.row_holder.appendChild(d);var f=this.jsoneditor.createEditor(e,{jsoneditor:this.jsoneditor,schema:c,container:d,path:this.path+"."+a,parent:this,required:!0});return f.preBuild(),f.build(),f.postBuild(),f.title_controls||(f.array_controls=this.theme.getButtonHolder(),d.appendChild(f.array_controls)),f},destroy:function(){this.empty(!0),this.title&&this.title.parentNode&&this.title.parentNode.removeChild(this.title),this.description&&this.description.parentNode&&this.description.parentNode.removeChild(this.description),this.row_holder&&this.row_holder.parentNode&&this.row_holder.parentNode.removeChild(this.row_holder),this.controls&&this.controls.parentNode&&this.controls.parentNode.removeChild(this.controls),this.panel&&this.panel.parentNode&&this.panel.parentNode.removeChild(this.panel),this.rows=this.row_cache=this.title=this.description=this.row_holder=this.panel=this.controls=null,this._super()},empty:function(a){if(this.rows){var b=this;f(this.rows,function(c,d){a&&(d.tab&&d.tab.parentNode&&d.tab.parentNode.removeChild(d.tab),b.destroyRow(d,!0),b.row_cache[c]=null),b.rows[c]=null}),b.rows=[],a&&(b.row_cache=[])}},destroyRow:function(a,b){var c=a.container;b?(a.destroy(),c.parentNode&&c.parentNode.removeChild(c),a.tab&&a.tab.parentNode&&a.tab.parentNode.removeChild(a.tab)):(a.tab&&(a.tab.style.display="none"),c.style.display="none",a.unregister())},getMax:function(){return Array.isArray(this.schema.items)&&this.schema.additionalItems===!1?Math.min(this.schema.items.length,this.schema.maxItems||1/0):this.schema.maxItems||1/0},refreshTabs:function(a){var b=this;f(this.rows,function(c,d){d.tab&&(a?d.tab_text.textContent=d.getHeaderText():d.tab===b.active_tab?b.theme.markTabActive(d):b.theme.markTabInactive(d))})},setValue:function(a,b){a=a||[],Array.isArray(a)||(a=[a]);var c=JSON.stringify(a);if(c!==this.serialized){if(this.schema.minItems)for(;a.length<this.schema.minItems;)a.push(this.getItemInfo(a.length)["default"]);this.getMax()&&a.length>this.getMax()&&(a=a.slice(0,this.getMax()));var d=this;f(a,function(a,c){d.rows[a]?d.rows[a].setValue(c,b):d.row_cache[a]?(d.rows[a]=d.row_cache[a],d.rows[a].setValue(c,b),d.rows[a].container.style.display="",d.rows[a].tab&&(d.rows[a].tab.style.display=""),d.rows[a].register()):d.addRow(c,b)});for(var e=a.length;e<d.rows.length;e++)d.destroyRow(d.rows[e]),d.rows[e]=null;d.rows=d.rows.slice(0,a.length);var g=null;f(d.rows,function(a,b){if(b.tab===d.active_tab)return g=b.tab,!1}),!g&&d.rows.length&&(g=d.rows[0].tab),d.active_tab=g,d.refreshValue(b),d.refreshTabs(!0),d.refreshTabs(),d.onChange()}},refreshValue:function(a){var b=this,c=this.value?this.value.length:0;if(this.value=[],f(this.rows,function(a,c){b.value[a]=c.getValue()}),c!==this.value.length||a){var d=this.schema.minItems&&this.schema.minItems>=this.rows.length;f(this.rows,function(a,c){c.movedown_button&&(a===b.rows.length-1?c.movedown_button.style.display="none":c.movedown_button.style.display=""),c.delete_button&&(d?c.delete_button.style.display="none":c.delete_button.style.display=""),b.value[a]=c.getValue()});var e=!1;this.value.length?1===this.value.length?(this.remove_all_rows_button.style.display="none",d||this.hide_delete_last_row_buttons?this.delete_last_row_button.style.display="none":(this.delete_last_row_button.style.display="",e=!0)):(d||this.hide_delete_last_row_buttons?this.delete_last_row_button.style.display="none":(this.delete_last_row_button.style.display="",e=!0),d||this.hide_delete_all_rows_buttons?this.remove_all_rows_button.style.display="none":(this.remove_all_rows_button.style.display="",e=!0)):(this.delete_last_row_button.style.display="none",this.remove_all_rows_button.style.display="none"),this.getMax()&&this.getMax()<=this.rows.length||this.hide_add_button?this.add_row_button.style.display="none":(this.add_row_button.style.display="",e=!0),!this.collapsed&&e?this.controls.style.display="inline-block":this.controls.style.display="none"}},addRow:function(a,b){var c=this,d=this.rows.length;c.rows[d]=this.getElementEditor(d),c.row_cache[d]=c.rows[d],c.tabs_holder&&(c.rows[d].tab_text=document.createElement("span"),c.rows[d].tab_text.textContent=c.rows[d].getHeaderText(),"tabs-top"===c.schema.format?(c.rows[d].tab=c.theme.getTopTab(c.rows[d].tab_text,this.getValidId(c.rows[d].path)),c.theme.addTopTab(c.tabs_holder,c.rows[d].tab)):(c.rows[d].tab=c.theme.getTab(c.rows[d].tab_text,this.getValidId(c.rows[d].path)),c.theme.addTab(c.tabs_holder,c.rows[d].tab)),c.rows[d].tab.addEventListener("click",function(a){c.active_tab=c.rows[d].tab,c.refreshTabs(),a.preventDefault(),a.stopPropagation()}));var e=c.rows[d].title_controls||c.rows[d].array_controls;c.hide_delete_buttons||(c.rows[d].delete_button=this.getButton(c.getItemTitle(),"delete",this.translate("button_delete_row_title",[c.getItemTitle()])),c.rows[d].delete_button.classList.add("delete","json-editor-btntype-delete"),c.rows[d].delete_button.setAttribute("data-i",d),c.rows[d].delete_button.addEventListener("click",function(a){if(a.preventDefault(),a.stopPropagation(),!c.askConfirmation())return!1;var b=1*this.getAttribute("data-i"),d=c.getValue(),e=[],g=null;f(d,function(a,c){a!==b&&e.push(c)}),c.empty(!0),c.setValue(e),c.rows[b]?g=c.rows[b].tab:c.rows[b-1]&&(g=c.rows[b-1].tab),g&&(c.active_tab=g,c.refreshTabs()),c.onChange(!0),c.jsoneditor.trigger("deleteRow")}),e&&e.appendChild(c.rows[d].delete_button)),c.show_copy_button&&(c.rows[d].copy_button=this.getButton(c.getItemTitle(),"copy","Copy "+c.getItemTitle()),c.rows[d].copy_button.classList.add("copy","json-editor-btntype-copy"),c.rows[d].copy_button.setAttribute("data-i",d),c.rows[d].copy_button.addEventListener("click",function(a){var b=c.getValue();a.preventDefault(),a.stopPropagation();var d=1*this.getAttribute("data-i");f(b,function(a,c){a===d&&b.push(c)}),c.setValue(b),c.refreshValue(!0),c.onChange(!0)}),e.appendChild(c.rows[d].copy_button)),d&&!c.hide_move_buttons&&(c.rows[d].moveup_button=this.getButton("","moveup",this.translate("button_move_up_title")),c.rows[d].moveup_button.classList.add("moveup","json-editor-btntype-move"),c.rows[d].moveup_button.setAttribute("data-i",d),c.rows[d].moveup_button.addEventListener("click",function(a){a.preventDefault(),a.stopPropagation();var b=1*this.getAttribute("data-i");if(!(b<=0)){var d=c.getValue(),e=d[b-1];d[b-1]=d[b],d[b]=e,c.setValue(d),c.active_tab=c.rows[b-1].tab,c.refreshTabs(),c.onChange(!0),c.jsoneditor.trigger("moveRow")}}),e&&e.appendChild(c.rows[d].moveup_button)),c.hide_move_buttons||(c.rows[d].movedown_button=this.getButton("","movedown",this.translate("button_move_down_title")),c.rows[d].movedown_button.classList.add("movedown","json-editor-btntype-move"),c.rows[d].movedown_button.setAttribute("data-i",d),c.rows[d].movedown_button.addEventListener("click",function(a){a.preventDefault(),a.stopPropagation();var b=1*this.getAttribute("data-i"),d=c.getValue();if(!(b>=d.length-1)){var e=d[b+1];d[b+1]=d[b],d[b]=e,c.setValue(d),c.active_tab=c.rows[b+1].tab,c.refreshTabs(),c.onChange(!0),c.jsoneditor.trigger("moveRow")}}),e&&e.appendChild(c.rows[d].movedown_button)),a&&c.rows[d].setValue(a,b),c.refreshTabs()},addControls:function(){var a=this;this.collapsed=!1,this.toggle_button=this.getButton("","collapse",this.translate("button_collapse")),this.toggle_button.classList.add("json-editor-btntype-toggle"),this.title_controls.appendChild(this.toggle_button);var b=a.row_holder.style.display,c=a.controls.style.display;this.toggle_button.addEventListener("click",function(d){d.preventDefault(),d.stopPropagation(),a.collapsed?(a.collapsed=!1,a.panel&&(a.panel.style.display=""),a.row_holder.style.display=b,a.tabs_holder&&(a.tabs_holder.style.display=""),a.controls.style.display=c,a.setButtonText(this,"","collapse",a.translate("button_collapse"))):(a.collapsed=!0,a.row_holder.style.display="none",a.tabs_holder&&(a.tabs_holder.style.display="none"),a.controls.style.display="none",a.panel&&(a.panel.style.display="none"),a.setButtonText(this,"","expand",a.translate("button_expand")))}),this.options.collapsed&&g(this.toggle_button,"click"),this.schema.options&&"undefined"!=typeof this.schema.options.disable_collapse?this.schema.options.disable_collapse&&(this.toggle_button.style.display="none"):this.jsoneditor.options.disable_collapse&&(this.toggle_button.style.display="none"),this.add_row_button=this.getButton(this.getItemTitle(),"add",this.translate("button_add_row_title",[this.getItemTitle()])),this.add_row_button.classList.add("json-editor-btntype-add"),this.add_row_button.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation();var c=a.rows.length;a.row_cache[c]?(a.rows[c]=a.row_cache[c],a.rows[c].setValue(a.rows[c].getDefault(),!0),a.rows[c].container.style.display="",a.rows[c].tab&&(a.rows[c].tab.style.display=""),a.rows[c].register()):a.addRow(),a.active_tab=a.rows[c].tab,a.refreshTabs(),a.refreshValue(),a.onChange(!0),a.jsoneditor.trigger("addRow")}),a.controls.appendChild(this.add_row_button),this.delete_last_row_button=this.getButton(this.translate("button_delete_last",[this.getItemTitle()]),"delete",this.translate("button_delete_last_title",[this.getItemTitle()])),this.delete_last_row_button.classList.add("json-editor-btntype-deletelast"),this.delete_last_row_button.addEventListener("click",function(b){if(b.preventDefault(),b.stopPropagation(),!a.askConfirmation())return!1;var c=a.getValue(),d=null;c.pop(),a.empty(!0),a.setValue(c),a.rows[a.rows.length-1]&&(d=a.rows[a.rows.length-1].tab),d&&(a.active_tab=d,a.refreshTabs()),a.onChange(!0),a.jsoneditor.trigger("deleteRow")}),a.controls.appendChild(this.delete_last_row_button),this.remove_all_rows_button=this.getButton(this.translate("button_delete_all"),"delete",this.translate("button_delete_all_title")),this.remove_all_rows_button.classList.add("json-editor-btntype-deleteall"),this.remove_all_rows_button.addEventListener("click",function(b){return b.preventDefault(),b.stopPropagation(),!!a.askConfirmation()&&(a.empty(!0),a.setValue([]),a.onChange(!0),void a.jsoneditor.trigger("deleteAllRows"))}),a.controls.appendChild(this.remove_all_rows_button),a.tabs&&(this.add_row_button.style.width="100%",this.add_row_button.style.textAlign="left",this.add_row_button.style.marginBottom="3px",this.delete_last_row_button.style.width="100%",this.delete_last_row_button.style.textAlign="left",this.delete_last_row_button.style.marginBottom="3px",this.remove_all_rows_button.style.width="100%",this.remove_all_rows_button.style.textAlign="left",this.remove_all_rows_button.style.marginBottom="3px")},showValidationErrors:function(a){var b=this,c=[],d=[];if(f(a,function(a,e){e.path===b.path?c.push(e):d.push(e)}),this.error_holder)if(c.length){this.error_holder.innerHTML="",this.error_holder.style.display="",f(c,function(a,c){b.error_holder.appendChild(b.theme.getErrorMessage(c.message))})}else this.error_holder.style.display="none";f(this.rows,function(a,b){b.showValidationErrors(d)})}}),h.defaults.editors.table=h.defaults.editors.array.extend({register:function(){if(this._super(),this.rows)for(var a=0;a<this.rows.length;a++)this.rows[a].register()},unregister:function(){if(this._super(),this.rows)for(var a=0;a<this.rows.length;a++)this.rows[a].unregister()},getNumColumns:function(){return Math.max(Math.min(12,this.width),3)},preBuild:function(){var a=this.jsoneditor.expandRefs(this.schema.items||{});this.item_title=a.title||"row",this.item_default=a["default"]||null,this.item_has_child_editors=a.properties||a.items,this.width=12,this._super()},build:function(){var a=this;this.table=this.theme.getTable(),this.container.appendChild(this.table),this.thead=this.theme.getTableHead(),this.table.appendChild(this.thead),this.header_row=this.theme.getTableRow(),this.thead.appendChild(this.header_row),this.row_holder=this.theme.getTableBody(),this.table.appendChild(this.row_holder);var b=this.getElementEditor(0,!0);if(this.item_default=b.getDefault(),this.width=b.getNumColumns()+2,this.options.compact?(this.panel=document.createElement("div"),this.container.appendChild(this.panel)):(this.title=this.theme.getHeader(this.getTitle()),this.container.appendChild(this.title),this.title_controls=this.theme.getHeaderButtonHolder(),this.title.appendChild(this.title_controls),this.schema.description&&(this.description=this.theme.getDescription(this.schema.description),this.container.appendChild(this.description)),this.panel=this.theme.getIndentedPanel(),this.container.appendChild(this.panel),this.error_holder=document.createElement("div"),this.panel.appendChild(this.error_holder)),this.panel.appendChild(this.table),this.controls=this.theme.getButtonHolder(),this.panel.appendChild(this.controls),this.item_has_child_editors)for(var c=b.getChildEditors(),d=b.property_order||Object.keys(c),e=0;e<d.length;e++){var f=a.theme.getTableHeaderCell(c[d[e]].getTitle());c[d[e]].options.hidden&&(f.style.display="none"),a.header_row.appendChild(f)}else a.header_row.appendChild(a.theme.getTableHeaderCell(this.item_title));b.destroy(),this.row_holder.innerHTML="",this.controls_header_cell=a.theme.getTableHeaderCell(" "),a.header_row.appendChild(this.controls_header_cell),this.addControls()},onChildEditorChange:function(a){this.refreshValue(),this._super()},getItemDefault:function(){return e({},{"default":this.item_default})["default"]},getItemTitle:function(){return this.item_title},getElementEditor:function(a,b){var c=e({},this.schema.items),d=this.jsoneditor.getEditorClass(c,this.jsoneditor),f=this.row_holder.appendChild(this.theme.getTableRow()),g=f;this.item_has_child_editors||(g=this.theme.getTableCell(),f.appendChild(g));var h=this.jsoneditor.createEditor(d,{jsoneditor:this.jsoneditor,schema:c,container:g,path:this.path+"."+a,parent:this,compact:!0,table_row:!0});return h.preBuild(),b||(h.build(),h.postBuild(),h.controls_cell=f.appendChild(this.theme.getTableCell()),h.row=f,h.table_controls=this.theme.getButtonHolder(),h.controls_cell.appendChild(h.table_controls),h.table_controls.style.margin=0,h.table_controls.style.padding=0),h},destroy:function(){this.innerHTML="",this.title&&this.title.parentNode&&this.title.parentNode.removeChild(this.title),this.description&&this.description.parentNode&&this.description.parentNode.removeChild(this.description),this.row_holder&&this.row_holder.parentNode&&this.row_holder.parentNode.removeChild(this.row_holder),this.table&&this.table.parentNode&&this.table.parentNode.removeChild(this.table),this.panel&&this.panel.parentNode&&this.panel.parentNode.removeChild(this.panel),this.rows=this.title=this.description=this.row_holder=this.table=this.panel=null,this._super()},setValue:function(a,b){if(a=a||[],this.schema.minItems)for(;a.length<this.schema.minItems;)a.push(this.getItemDefault());this.schema.maxItems&&a.length>this.schema.maxItems&&(a=a.slice(0,this.schema.maxItems));var c=JSON.stringify(a);if(c!==this.serialized){var d=!1,e=this;f(a,function(a,b){e.rows[a]?e.rows[a].setValue(b):(e.addRow(b),d=!0)});for(var g=a.length;g<e.rows.length;g++){var h=e.rows[g].container;e.item_has_child_editors||e.rows[g].row.parentNode.removeChild(e.rows[g].row),e.rows[g].destroy(),h.parentNode&&h.parentNode.removeChild(h),e.rows[g]=null,d=!0}e.rows=e.rows.slice(0,a.length),e.refreshValue(),(d||b)&&e.refreshRowButtons(),e.onChange()}},refreshRowButtons:function(){var a=this,b=this.schema.minItems&&this.schema.minItems>=this.rows.length,c=!1;f(this.rows,function(d,e){e.movedown_button&&(d===a.rows.length-1?e.movedown_button.style.display="none":(c=!0,e.movedown_button.style.display="")),e.delete_button&&(b?e.delete_button.style.display="none":(c=!0,e.delete_button.style.display="")),e.moveup_button&&(c=!0)}),f(this.rows,function(a,b){c?b.controls_cell.style.display="":b.controls_cell.style.display="none"}),c?this.controls_header_cell.style.display="":this.controls_header_cell.style.display="none";var d=!1;this.value.length?1===this.value.length?(this.table.style.display="",this.remove_all_rows_button.style.display="none",b||this.hide_delete_last_row_buttons?this.delete_last_row_button.style.display="none":(this.delete_last_row_button.style.display="",d=!0)):(this.table.style.display="",b||this.hide_delete_last_row_buttons?this.delete_last_row_button.style.display="none":(this.delete_last_row_button.style.display="",d=!0),b||this.hide_delete_all_rows_buttons?this.remove_all_rows_button.style.display="none":(this.remove_all_rows_button.style.display="",d=!0)):(this.delete_last_row_button.style.display="none",this.remove_all_rows_button.style.display="none",this.table.style.display="none"),this.schema.maxItems&&this.schema.maxItems<=this.rows.length||this.hide_add_button?this.add_row_button.style.display="none":(this.add_row_button.style.display="",d=!0),d?this.controls.style.display="":this.controls.style.display="none"},refreshValue:function(){var a=this;this.value=[],f(this.rows,function(b,c){a.value[b]=c.getValue()}),this.serialized=JSON.stringify(this.value)},addRow:function(a){var b=this,c=this.rows.length;b.rows[c]=this.getElementEditor(c);var d=b.rows[c].table_controls;this.hide_delete_buttons||(b.rows[c].delete_button=this.getButton("","delete",this.translate("button_delete_row_title_short")),b.rows[c].delete_button.classList.add("delete","json-editor-btntype-delete"),b.rows[c].delete_button.setAttribute("data-i",c),b.rows[c].delete_button.addEventListener("click",function(a){if(a.preventDefault(),a.stopPropagation(),!b.askConfirmation())return!1;var c=1*this.getAttribute("data-i"),d=b.getValue(),e=[];f(d,function(a,b){a!==c&&e.push(b)}),b.setValue(e),b.onChange(!0)}),d.appendChild(b.rows[c].delete_button)),c&&!this.hide_move_buttons&&(b.rows[c].moveup_button=this.getButton("","moveup",this.translate("button_move_up_title")),b.rows[c].moveup_button.classList.add("moveup","json-editor-btntype-move"),b.rows[c].moveup_button.setAttribute("data-i",c),b.rows[c].moveup_button.addEventListener("click",function(a){a.preventDefault(),a.stopPropagation();var c=1*this.getAttribute("data-i");if(!(c<=0)){var d=b.getValue(),e=d[c-1];d[c-1]=d[c],d[c]=e,b.setValue(d),b.onChange(!0)}}),d.appendChild(b.rows[c].moveup_button)),this.hide_move_buttons||(b.rows[c].movedown_button=this.getButton("","movedown",this.translate("button_move_down_title")),b.rows[c].movedown_button.classList.add("movedown","json-editor-btntype-move"),b.rows[c].movedown_button.setAttribute("data-i",c),b.rows[c].movedown_button.addEventListener("click",function(a){a.preventDefault(),a.stopPropagation();var c=1*this.getAttribute("data-i"),d=b.getValue();if(!(c>=d.length-1)){var e=d[c+1];d[c+1]=d[c],d[c]=e,b.setValue(d),b.onChange(!0)}}),d.appendChild(b.rows[c].movedown_button)),a&&b.rows[c].setValue(a)},addControls:function(){var a=this;this.collapsed=!1,this.toggle_button=this.getButton("","collapse",this.translate("button_collapse")),this.toggle_button.classList.add("json-editor-btntype-toggle"),this.title_controls&&(this.title_controls.appendChild(this.toggle_button),this.toggle_button.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation(),a.collapsed?(a.collapsed=!1,a.panel.style.display="",a.setButtonText(this,"","collapse",a.translate("button_collapse"))):(a.collapsed=!0,a.panel.style.display="none",a.setButtonText(this,"","expand",a.translate("button_expand")))}),this.options.collapsed&&g(this.toggle_button,"click"),this.schema.options&&"undefined"!=typeof this.schema.options.disable_collapse?this.schema.options.disable_collapse&&(this.toggle_button.style.display="none"):this.jsoneditor.options.disable_collapse&&(this.toggle_button.style.display="none")),this.add_row_button=this.getButton(this.getItemTitle(),"add",this.translate("button_add_row_title",[this.getItemTitle()])),this.add_row_button.classList.add("json-editor-btntype-add"),this.add_row_button.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation(),a.addRow(),a.refreshValue(),a.refreshRowButtons(),a.onChange(!0)}),a.controls.appendChild(this.add_row_button),this.delete_last_row_button=this.getButton(this.translate("button_delete_last",[this.getItemTitle()]),"delete",this.translate("button_delete_last_title",[this.getItemTitle()])),this.delete_last_row_button.classList.add("json-editor-btntype-deletelast"),this.delete_last_row_button.addEventListener("click",function(b){if(b.preventDefault(),b.stopPropagation(),!a.askConfirmation())return!1;var c=a.getValue();c.pop(),a.setValue(c),a.onChange(!0)}),a.controls.appendChild(this.delete_last_row_button),this.remove_all_rows_button=this.getButton(this.translate("button_delete_all"),"delete",this.translate("button_delete_all_title")),
+this.remove_all_rows_button.classList.add("json-editor-btntype-deleteall"),this.remove_all_rows_button.addEventListener("click",function(b){return b.preventDefault(),b.stopPropagation(),!!a.askConfirmation()&&(a.setValue([]),void a.onChange(!0))}),a.controls.appendChild(this.remove_all_rows_button)}}),h.defaults.editors.multiple=h.AbstractEditor.extend({register:function(){if(this.editors){for(var a=0;a<this.editors.length;a++)this.editors[a]&&this.editors[a].unregister();this.editors[this.type]&&this.editors[this.type].register()}this._super()},unregister:function(){if(this._super(),this.editors)for(var a=0;a<this.editors.length;a++)this.editors[a]&&this.editors[a].unregister()},getNumColumns:function(){return this.editors[this.type]?Math.max(this.editors[this.type].getNumColumns(),4):4},enable:function(){if(!this.always_disabled){if(this.editors)for(var a=0;a<this.editors.length;a++)this.editors[a]&&this.editors[a].enable();this.switcher.disabled=!1,this._super()}},disable:function(a){if(a&&(this.always_disabled=!0),this.editors)for(var b=0;b<this.editors.length;b++)this.editors[b]&&this.editors[b].disable(a);this.switcher.disabled=!0,this._super()},switchEditor:function(a){var b=this;this.editors[a]||this.buildChildEditor(a);var c=b.getValue();b.type=a,b.register(),f(b.editors,function(a,d){d&&(b.type===a?(b.keep_values&&d.setValue(c,!0),d.container.style.display=""):d.container.style.display="none")}),b.refreshValue(),b.refreshHeaderText()},buildChildEditor:function(a){var b=this,c=this.types[a],d=b.theme.getChildEditorHolder();b.editor_holder.appendChild(d);var f;"string"==typeof c?(f=e({},b.schema),f.type=c):(f=e({},b.schema,c),f=b.jsoneditor.expandRefs(f),c&&c.required&&Array.isArray(c.required)&&b.schema.required&&Array.isArray(b.schema.required)&&(f.required=b.schema.required.concat(c.required)));var g=b.jsoneditor.getEditorClass(f);b.editors[a]=b.jsoneditor.createEditor(g,{jsoneditor:b.jsoneditor,schema:f,container:d,path:b.path,parent:b,required:!0}),b.editors[a].preBuild(),b.editors[a].build(),b.editors[a].postBuild(),b.editors[a].header&&(b.editors[a].header.style.display="none"),b.editors[a].option=b.switcher_options[a],d.addEventListener("change_header_text",function(){b.refreshHeaderText()}),a!==b.type&&(d.style.display="none")},preBuild:function(){if(this.types=[],this.type=0,this.editors=[],this.validators=[],this.keep_values=!0,"undefined"!=typeof this.jsoneditor.options.keep_oneof_values&&(this.keep_values=this.jsoneditor.options.keep_oneof_values),"undefined"!=typeof this.options.keep_oneof_values&&(this.keep_values=this.options.keep_oneof_values),this.schema.oneOf)this.oneOf=!0,this.types=this.schema.oneOf,delete this.schema.oneOf;else if(this.schema.anyOf)this.anyOf=!0,this.types=this.schema.anyOf,delete this.schema.anyOf;else{if(this.schema.type&&"any"!==this.schema.type)Array.isArray(this.schema.type)?this.types=this.schema.type:this.types=[this.schema.type];else if(this.types=["string","number","integer","boolean","object","array","null"],this.schema.disallow){var a=this.schema.disallow;"object"==typeof a&&Array.isArray(a)||(a=[a]);var b=[];f(this.types,function(c,d){a.indexOf(d)===-1&&b.push(d)}),this.types=b}delete this.schema.type}this.display_text=this.getDisplayText(this.types)},build:function(){var a=this,b=this.container;this.header=this.label=this.theme.getFormInputLabel(this.getTitle()),this.container.appendChild(this.header),this.switcher=this.theme.getSwitcher(this.display_text),b.appendChild(this.switcher),this.switcher.addEventListener("change",function(b){b.preventDefault(),b.stopPropagation(),a.switchEditor(a.display_text.indexOf(this.value)),a.onChange(!0)}),this.editor_holder=document.createElement("div"),b.appendChild(this.editor_holder);var c={};a.jsoneditor.options.custom_validators&&(c.custom_validators=a.jsoneditor.options.custom_validators),this.switcher_options=this.theme.getSwitcherOptions(this.switcher),f(this.types,function(b,d){a.editors[b]=!1;var f;"string"==typeof d?(f=e({},a.schema),f.type=d):(f=e({},a.schema,d),d.required&&Array.isArray(d.required)&&a.schema.required&&Array.isArray(a.schema.required)&&(f.required=a.schema.required.concat(d.required))),a.validators[b]=new h.Validator(a.jsoneditor,f,c)}),this.switchEditor(0)},onChildEditorChange:function(a){this.editors[this.type]&&(this.refreshValue(),this.refreshHeaderText()),this._super()},refreshHeaderText:function(){var a=this.getDisplayText(this.types);f(this.switcher_options,function(b,c){c.textContent=a[b]})},refreshValue:function(){this.value=this.editors[this.type].getValue()},setValue:function(a,b){var c=this,d=this.type;f(this.validators,function(b,d){if(!d.validate(a).length)return c.type=b,c.switcher.value=c.display_text[b],!1});var e=this.type!=d;e&&this.switchEditor(this.type),this.editors[this.type].setValue(a,b),this.refreshValue(),c.onChange(e)},destroy:function(){f(this.editors,function(a,b){b&&b.destroy()}),this.editor_holder&&this.editor_holder.parentNode&&this.editor_holder.parentNode.removeChild(this.editor_holder),this.switcher&&this.switcher.parentNode&&this.switcher.parentNode.removeChild(this.switcher),this._super()},showValidationErrors:function(a){var b=this;if(this.oneOf||this.anyOf){var c=this.oneOf?"oneOf":"anyOf";f(this.editors,function(d,g){if(g){var h=b.path+"."+c+"["+d+"]",i=[];f(a,function(a,c){if(c.path.substr(0,h.length)===h){var d=e({},c);d.path=b.path+d.path.substr(h.length),i.push(d)}}),g.showValidationErrors(i)}})}else f(this.editors,function(b,c){c&&c.showValidationErrors(a)})}}),h.defaults.editors["enum"]=h.AbstractEditor.extend({getNumColumns:function(){return 4},build:function(){this.container;this.title=this.header=this.label=this.theme.getFormInputLabel(this.getTitle()),this.container.appendChild(this.title),this.options.enum_titles=this.options.enum_titles||[],this["enum"]=this.schema["enum"],this.selected=0,this.select_options=[],this.html_values=[];for(var a=this,b=0;b<this["enum"].length;b++)this.select_options[b]=this.options.enum_titles[b]||"Value "+(b+1),this.html_values[b]=this.getHTML(this["enum"][b]);this.switcher=this.theme.getSwitcher(this.select_options),this.container.appendChild(this.switcher),this.display_area=this.theme.getIndentedPanel(),this.container.appendChild(this.display_area),this.options.hide_display&&(this.display_area.style.display="none"),this.switcher.addEventListener("change",function(){a.selected=a.select_options.indexOf(this.value),a.value=a["enum"][a.selected],a.refreshValue(),a.onChange(!0)}),this.value=this["enum"][0],this.refreshValue(),1===this["enum"].length&&(this.switcher.style.display="none")},refreshValue:function(){var a=this;a.selected=-1;var b=JSON.stringify(this.value);return f(this["enum"],function(c,d){if(b===JSON.stringify(d))return a.selected=c,!1}),a.selected<0?void a.setValue(a["enum"][0]):(this.switcher.value=this.select_options[this.selected],void(this.display_area.innerHTML=this.html_values[this.selected]))},enable:function(){this.always_disabled||(this.switcher.disabled=!1,this._super())},disable:function(a){a&&(this.always_disabled=!0),this.switcher.disabled=!0,this._super()},getHTML:function(a){var b=this;if(null===a)return"<em>null</em>";if("object"==typeof a){var c="";return f(a,function(d,e){var f=b.getHTML(e);Array.isArray(a)||(f="<div><em>"+d+"</em>: "+f+"</div>"),c+="<li>"+f+"</li>"}),c=Array.isArray(a)?"<ol>"+c+"</ol>":"<ul style='margin-top:0;margin-bottom:0;padding-top:0;padding-bottom:0;'>"+c+"</ul>"}return"boolean"==typeof a?a?"true":"false":"string"==typeof a?a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"):a},setValue:function(a){this.value!==a&&(this.value=a,this.refreshValue(),this.onChange())},destroy:function(){this.display_area&&this.display_area.parentNode&&this.display_area.parentNode.removeChild(this.display_area),this.title&&this.title.parentNode&&this.title.parentNode.removeChild(this.title),this.switcher&&this.switcher.parentNode&&this.switcher.parentNode.removeChild(this.switcher),this._super()}}),h.defaults.editors.select=h.AbstractEditor.extend({setValue:function(a,b){a=this.typecast(a||"");var c=a;this.enum_values.indexOf(c)<0&&(c=this.enum_values[0]),this.value!==c&&(b?this.is_dirty=!1:"change"===this.jsoneditor.options.show_errors&&(this.is_dirty=!0),this.input.value=this.enum_options[this.enum_values.indexOf(c)],this.select2&&(this.select2v4?this.select2.val(this.input.value).trigger("change"):this.select2.select2("val",this.input.value)),this.value=c,this.onChange(),this.change())},register:function(){this._super(),this.input&&this.input.setAttribute("name",this.formname)},unregister:function(){this._super(),this.input&&this.input.removeAttribute("name")},getNumColumns:function(){if(!this.enum_options)return 3;for(var a=this.getTitle().length,b=0;b<this.enum_options.length;b++)a=Math.max(a,this.enum_options[b].length+4);return Math.min(12,Math.max(a/7,2))},typecast:function(a){return"boolean"===this.schema.type?!!a:"number"===this.schema.type?1*a:"integer"===this.schema.type?Math.floor(1*a):""+a},getValue:function(){return this.dependenciesFulfilled?this.typecast(this.value):b},preBuild:function(){var a=this;this.input_type="select",this.enum_options=[],this.enum_values=[],this.enum_display=[];var c;if(this.schema["enum"]){var d=this.schema.options&&this.schema.options.enum_titles||[];f(this.schema["enum"],function(b,c){a.enum_options[b]=""+c,a.enum_display[b]=""+(d[b]||c),a.enum_values[b]=a.typecast(c)}),this.isRequired()||(a.enum_display.unshift(" "),a.enum_options.unshift("undefined"),a.enum_values.unshift(b))}else if("boolean"===this.schema.type)a.enum_display=this.schema.options&&this.schema.options.enum_titles||["true","false"],a.enum_options=["1",""],a.enum_values=[!0,!1],this.isRequired()||(a.enum_display.unshift(" "),a.enum_options.unshift("undefined"),a.enum_values.unshift(b));else{if(!this.schema.enumSource)throw"'select' editor requires the enum property to be set.";if(this.enumSource=[],this.enum_display=[],this.enum_options=[],this.enum_values=[],Array.isArray(this.schema.enumSource))for(c=0;c<this.schema.enumSource.length;c++)"string"==typeof this.schema.enumSource[c]?this.enumSource[c]={source:this.schema.enumSource[c]}:Array.isArray(this.schema.enumSource[c])?this.enumSource[c]=this.schema.enumSource[c]:this.enumSource[c]=e({},this.schema.enumSource[c]);else this.schema.enumValue?this.enumSource=[{source:this.schema.enumSource,value:this.schema.enumValue}]:this.enumSource=[{source:this.schema.enumSource}];for(c=0;c<this.enumSource.length;c++)this.enumSource[c].value&&(this.enumSource[c].value=this.jsoneditor.compileTemplate(this.enumSource[c].value,this.template_engine)),this.enumSource[c].title&&(this.enumSource[c].title=this.jsoneditor.compileTemplate(this.enumSource[c].title,this.template_engine)),this.enumSource[c].filter&&(this.enumSource[c].filter=this.jsoneditor.compileTemplate(this.enumSource[c].filter,this.template_engine))}},build:function(){var a=this;this.options.compact||(this.header=this.label=this.theme.getFormInputLabel(this.getTitle())),this.schema.description&&(this.description=this.theme.getFormInputDescription(this.schema.description)),this.options.infoText&&(this.infoButton=this.theme.getInfoButton(this.options.infoText)),this.options.compact&&this.container.classList.add("compact"),this.input=this.theme.getSelectInput(this.enum_options),this.theme.setSelectOptions(this.input,this.enum_options,this.enum_display),(this.schema.readOnly||this.schema.readonly)&&(this.always_disabled=!0,this.input.disabled=!0),this.setInputAttributes([]),this.input.addEventListener("change",function(b){b.preventDefault(),b.stopPropagation(),a.onInputChange()}),this.control=this.theme.getFormControl(this.label,this.input,this.description,this.infoButton),this.container.appendChild(this.control),this.value=this.enum_values[0]},onInputChange:function(){var a,b=this.typecast(this.input.value);a=this.enum_values.indexOf(b)===-1?this.enum_values[0]:this.enum_values[this.enum_values.indexOf(b)],a!==this.value&&(this.is_dirty=!0,this.value=a,this.onChange(!0))},setupSelect2:function(){if(window.jQuery&&window.jQuery.fn&&window.jQuery.fn.select2&&(this.enum_options.length>2||this.enum_options.length&&this.enumSource)){var a=e({},h.plugins.select2);this.schema.options&&this.schema.options.select2_options&&(a=e(a,this.schema.options.select2_options)),this.select2=window.jQuery(this.input).select2(a),this.select2v4=this.select2.select2.hasOwnProperty("amd");var b=this;this.select2.on("select2-blur",function(){b.select2v4?b.input.value=b.select2.val():b.input.value=b.select2.select2("val"),b.onInputChange()}),this.select2.on("change",function(){b.select2v4?b.input.value=b.select2.val():b.input.value=b.select2.select2("val"),b.onInputChange()})}else this.select2=null},postBuild:function(){this._super(),this.theme.afterInputReady(this.input),this.setupSelect2()},onWatchedFieldChange:function(){var a,b;if(this.enumSource){a=this.getWatchedFieldValues();for(var c=[],d=[],e=0;e<this.enumSource.length;e++)if(Array.isArray(this.enumSource[e]))c=c.concat(this.enumSource[e]),d=d.concat(this.enumSource[e]);else{var f=[];if(f=Array.isArray(this.enumSource[e].source)?this.enumSource[e].source:a[this.enumSource[e].source]){if(this.enumSource[e].slice&&(f=Array.prototype.slice.apply(f,this.enumSource[e].slice)),this.enumSource[e].filter){var g=[];for(b=0;b<f.length;b++)this.enumSource[e].filter({i:b,item:f[b],watched:a})&&g.push(f[b]);f=g}var h=[],i=[];for(b=0;b<f.length;b++){var j=f[b];this.enumSource[e].value?i[b]=this.typecast(this.enumSource[e].value({i:b,item:j})):i[b]=f[b],this.enumSource[e].title?h[b]=this.enumSource[e].title({i:b,item:j}):h[b]=i[b]}c=c.concat(i),d=d.concat(h)}}var k=this.value;this.theme.setSelectOptions(this.input,c,d),this.enum_options=c,this.enum_display=d,this.enum_values=c,this.select2&&this.select2.select2("destroy"),c.indexOf(k)!==-1?(this.input.value=k,this.value=k):(this.input.value=c[0],this.value=this.typecast(c[0]||""),this.parent?this.parent.onChildEditorChange(this):this.jsoneditor.onChange(),this.jsoneditor.notifyWatchers(this.path)),this.setupSelect2()}this._super()},enable:function(){this.always_disabled||(this.input.disabled=!1,this.select2&&(this.select2v4?this.select2.prop("disabled",!1):this.select2.select2("enable",!0))),this._super()},disable:function(a){a&&(this.always_disabled=!0),this.input.disabled=!0,this.select2&&(this.select2v4?this.select2.prop("disabled",!0):this.select2.select2("enable",!1)),this._super()},destroy:function(){this.label&&this.label.parentNode&&this.label.parentNode.removeChild(this.label),this.description&&this.description.parentNode&&this.description.parentNode.removeChild(this.description),this.input&&this.input.parentNode&&this.input.parentNode.removeChild(this.input),this.select2&&(this.select2.select2("destroy"),this.select2=null),this._super()},showValidationErrors:function(a){var b=this;if("always"===this.jsoneditor.options.show_errors);else if(!this.is_dirty&&this.previous_error_setting===this.jsoneditor.options.show_errors)return;this.previous_error_setting=this.jsoneditor.options.show_errors;var c=[];f(a,function(a,d){d.path===b.path&&c.push(d.message)}),c.length?this.theme.addInputError(this.input,c.join(". ")+"."):this.theme.removeInputError(this.input)}}),h.defaults.editors.selectize=h.AbstractEditor.extend({setValue:function(a,b){a=this.typecast(a||"");var c=a;this.enum_values.indexOf(c)<0&&(c=this.enum_values[0]),this.value!==c&&(this.input.value=this.enum_options[this.enum_values.indexOf(c)],this.selectize&&this.selectize[0].selectize.addItem(c),this.value=c,this.onChange())},register:function(){this._super(),this.input&&this.input.setAttribute("name",this.formname)},unregister:function(){this._super(),this.input&&this.input.removeAttribute("name")},getNumColumns:function(){if(!this.enum_options)return 3;for(var a=this.getTitle().length,b=0;b<this.enum_options.length;b++)a=Math.max(a,this.enum_options[b].length+4);return Math.min(12,Math.max(a/7,2))},typecast:function(a){return"boolean"===this.schema.type?!!a:"number"===this.schema.type?1*a:"integer"===this.schema.type?Math.floor(1*a):""+a},getValue:function(){return this.dependenciesFulfilled?this.value:b},preBuild:function(){var a=this;this.input_type="select",this.enum_options=[],this.enum_values=[],this.enum_display=[];var b;if(this.schema["enum"]){var c=this.schema.options&&this.schema.options.enum_titles||[];f(this.schema["enum"],function(b,d){a.enum_options[b]=""+d,a.enum_display[b]=""+(c[b]||d),a.enum_values[b]=a.typecast(d)})}else if("boolean"===this.schema.type)a.enum_display=this.schema.options&&this.schema.options.enum_titles||["true","false"],a.enum_options=["1","0"],a.enum_values=[!0,!1];else{if(!this.schema.enumSource)throw"'select' editor requires the enum property to be set.";if(this.enumSource=[],this.enum_display=[],this.enum_options=[],this.enum_values=[],Array.isArray(this.schema.enumSource))for(b=0;b<this.schema.enumSource.length;b++)"string"==typeof this.schema.enumSource[b]?this.enumSource[b]={source:this.schema.enumSource[b]}:Array.isArray(this.schema.enumSource[b])?this.enumSource[b]=this.schema.enumSource[b]:this.enumSource[b]=e({},this.schema.enumSource[b]);else this.schema.enumValue?this.enumSource=[{source:this.schema.enumSource,value:this.schema.enumValue}]:this.enumSource=[{source:this.schema.enumSource}];for(b=0;b<this.enumSource.length;b++)this.enumSource[b].value&&(this.enumSource[b].value=this.jsoneditor.compileTemplate(this.enumSource[b].value,this.template_engine)),this.enumSource[b].title&&(this.enumSource[b].title=this.jsoneditor.compileTemplate(this.enumSource[b].title,this.template_engine)),this.enumSource[b].filter&&(this.enumSource[b].filter=this.jsoneditor.compileTemplate(this.enumSource[b].filter,this.template_engine))}},build:function(){var a=this;this.options.compact||(this.header=this.label=this.theme.getFormInputLabel(this.getTitle())),this.schema.description&&(this.description=this.theme.getFormInputDescription(this.schema.description)),this.options.infoText&&(this.infoButton=this.theme.getInfoButton(this.options.infoText)),this.options.compact&&this.container.classList.add("compact"),this.input=this.theme.getSelectInput(this.enum_options),this.theme.setSelectOptions(this.input,this.enum_options,this.enum_display),(this.schema.readOnly||this.schema.readonly)&&(this.always_disabled=!0,this.input.disabled=!0),this.input.addEventListener("change",function(b){b.preventDefault(),b.stopPropagation(),a.onInputChange()}),this.control=this.theme.getFormControl(this.label,this.input,this.description,this.infoButton),this.container.appendChild(this.control),this.value=this.enum_values[0]},onInputChange:function(){var a=this.input.value,b=a;this.enum_options.indexOf(a)===-1&&(b=this.enum_options[0]),this.value=a,this.onChange(!0)},setupSelectize:function(){var a=this;if(window.jQuery&&window.jQuery.fn&&window.jQuery.fn.selectize&&(this.enum_options.length>=2||this.enum_options.length&&this.enumSource)){var c=e({},h.plugins.selectize);this.schema.options&&this.schema.options.selectize_options&&(c=e(c,this.schema.options.selectize_options)),this.selectize=window.jQuery(this.input).selectize(e(c,{create:c.create===b||c.create,onChange:function(){a.onInputChange()}}))}else this.selectize=null},postBuild:function(){this._super(),this.theme.afterInputReady(this.input),this.setupSelectize()},onWatchedFieldChange:function(){var a,c;if(this.enumSource){a=this.getWatchedFieldValues();for(var d=[],e=[],f=0;f<this.enumSource.length;f++)if(Array.isArray(this.enumSource[f]))d=d.concat(this.enumSource[f]),e=e.concat(this.enumSource[f]);else if(a[this.enumSource[f].source]){var g=a[this.enumSource[f].source];if(this.enumSource[f].slice&&(g=Array.prototype.slice.apply(g,this.enumSource[f].slice)),this.enumSource[f].filter){var h=[];for(c=0;c<g.length;c++)this.enumSource[f].filter({i:c,item:g[c]})&&h.push(g[c]);g=h}var i=[],j=[];for(c=0;c<g.length;c++){var k=g[c];this.enumSource[f].value?j[c]=this.enumSource[f].value({i:c,item:k}):j[c]=g[c],this.enumSource[f].title?i[c]=this.enumSource[f].title({i:c,item:k}):i[c]=j[c]}d=d.concat(j),e=e.concat(i)}var l=this.value;l!==b&&""!==l&&d.indexOf(l)===-1&&(d=d.concat(l),e=e.concat(l)),this.theme.setSelectOptions(this.input,d,e),this.enum_options=d,this.enum_display=e,this.enum_values=d,d.indexOf(l)!==-1?(this.input.value=l,this.value=l):(this.input.value=d[0],this.value=d[0]||"",this.parent?this.parent.onChildEditorChange(this):this.jsoneditor.onChange(),this.jsoneditor.notifyWatchers(this.path)),this.selectize?this.updateSelectizeOptions(d):this.setupSelectize(),this._super()}},updateSelectizeOptions:function(a){var b=this.selectize[0].selectize,c=this;b.off(),b.clearOptions();for(var d in a)b.addOption({value:a[d],text:a[d]});b.addItem(this.value),b.on("change",function(){c.onInputChange()})},enable:function(){this.always_disabled||(this.input.disabled=!1,this.selectize&&this.selectize[0].selectize.unlock(),this._super())},disable:function(a){a&&(this.always_disabled=!0),this.input.disabled=!0,this.selectize&&this.selectize[0].selectize.lock(),this._super()},destroy:function(){this.label&&this.label.parentNode&&this.label.parentNode.removeChild(this.label),this.description&&this.description.parentNode&&this.description.parentNode.removeChild(this.description),this.input&&this.input.parentNode&&this.input.parentNode.removeChild(this.input),this.selectize&&(this.selectize[0].selectize.destroy(),this.selectize=null),this._super()}}),h.defaults.editors.multiselect=h.AbstractEditor.extend({preBuild:function(){this._super();var a;this.select_options={},this.select_values={};var b=this.jsoneditor.expandRefs(this.schema.items||{}),c=b["enum"]||[],d=b.options?b.options.enum_titles||[]:[];for(this.option_keys=[],this.option_titles=[],a=0;a<c.length;a++)this.sanitize(c[a])===c[a]&&(this.option_keys.push(c[a]+""),this.option_titles.push((d[a]||c[a])+""),this.select_values[c[a]+""]=c[a])},build:function(){var a,b=this;if(this.options.compact||(this.header=this.label=this.theme.getFormInputLabel(this.getTitle())),this.schema.description&&(this.description=this.theme.getFormInputDescription(this.schema.description)),!this.schema.format&&this.option_keys.length<8||"checkbox"===this.schema.format){for(this.input_type="checkboxes",this.inputs={},this.controls={},a=0;a<this.option_keys.length;a++){this.inputs[this.option_keys[a]]=this.theme.getCheckbox(),this.select_options[this.option_keys[a]]=this.inputs[this.option_keys[a]];var c=this.theme.getCheckboxLabel(this.option_titles[a]);this.controls[this.option_keys[a]]=this.theme.getFormControl(c,this.inputs[this.option_keys[a]])}this.control=this.theme.getMultiCheckboxHolder(this.controls,this.label,this.description)}else{for(this.input_type="select",this.input=this.theme.getSelectInput(this.option_keys),this.theme.setSelectOptions(this.input,this.option_keys,this.option_titles),this.input.multiple=!0,this.input.size=Math.min(10,this.option_keys.length),a=0;a<this.option_keys.length;a++)this.select_options[this.option_keys[a]]=this.input.children[a];(this.schema.readOnly||this.schema.readonly)&&(this.always_disabled=!0,this.input.disabled=!0),this.control=this.theme.getFormControl(this.label,this.input,this.description)}this.container.appendChild(this.control),this.control.addEventListener("change",function(c){c.preventDefault(),c.stopPropagation();var d=[];for(a=0;a<b.option_keys.length;a++)(b.select_options[b.option_keys[a]].selected||b.select_options[b.option_keys[a]].checked)&&d.push(b.select_values[b.option_keys[a]]);b.updateValue(d),b.onChange(!0)})},setValue:function(a,b){var c;for(a=a||[],"object"!=typeof a?a=[a]:Array.isArray(a)||(a=[]),c=0;c<a.length;c++)"string"!=typeof a[c]&&(a[c]+="");for(c in this.select_options)this.select_options.hasOwnProperty(c)&&(this.select_options[c]["select"===this.input_type?"selected":"checked"]=a.indexOf(c)!==-1);this.updateValue(a),this.onChange()},setupSelect2:function(){if(window.jQuery&&window.jQuery.fn&&window.jQuery.fn.select2){var a=window.jQuery.extend({},h.plugins.select2);this.schema.options&&this.schema.options.select2_options&&(a=e(a,this.schema.options.select2_options)),this.select2=window.jQuery(this.input).select2(a),this.select2v4=this.select2.select2.hasOwnProperty("amd");var b=this;this.select2.on("select2-blur",function(){b.select2v4?b.value=b.select2.val():b.value=b.select2.select2("val"),b.onChange(!0)}),this.select2.on("change",function(){b.select2v4?b.value=b.select2.val():b.value=b.select2.select2("val"),b.onChange(!0)})}else this.select2=null},onInputChange:function(){this.value=this.input.value,this.onChange(!0)},postBuild:function(){this._super(),this.setupSelect2()},register:function(){this._super(),this.input&&this.input.setAttribute("name",this.formname)},unregister:function(){this._super(),this.input&&this.input.removeAttribute("name")},getNumColumns:function(){var a=this.getTitle().length;for(var b in this.select_values)this.select_values.hasOwnProperty(b)&&(a=Math.max(a,(this.select_values[b]+"").length+4));return Math.min(12,Math.max(a/7,2))},updateValue:function(a){for(var b=!1,c=[],d=0;d<a.length;d++)if(this.select_options[a[d]+""]){var e=this.sanitize(this.select_values[a[d]]);c.push(e),e!==a[d]&&(b=!0)}else b=!0;return this.value=c,this.select2&&(this.select2v4?this.select2.val(this.value).trigger("change"):this.select2.select2("val",this.value)),b},sanitize:function(a){return"number"===this.schema.items.type?1*a:"integer"===this.schema.items.type?Math.floor(1*a):""+a},enable:function(){if(!this.always_disabled){if(this.input)this.input.disabled=!1;else if(this.inputs)for(var a in this.inputs)this.inputs.hasOwnProperty(a)&&(this.inputs[a].disabled=!1);this.select2&&(this.select2v4?this.select2.prop("disabled",!1):this.select2.select2("enable",!0)),this._super()}},disable:function(a){if(a&&(this.always_disabled=!0),this.input)this.input.disabled=!0;else if(this.inputs)for(var b in this.inputs)this.inputs.hasOwnProperty(b)&&(this.inputs[b].disabled=!0);this.select2&&(this.select2v4?this.select2.prop("disabled",!0):this.select2.select2("enable",!1)),this._super()},destroy:function(){this.select2&&(this.select2.select2("destroy"),this.select2=null),this._super()}}),h.defaults.editors.base64=h.AbstractEditor.extend({getNumColumns:function(){return 4},setFileReaderListener:function(a){var b=this;a.addEventListener("load",function(a){if(b.count==b.current_item_index)b.value[b.count][b.key]=a.target.result;else{var c={};for(var d in b.parent.schema.properties)c[d]="";c[b.key]=a.target.result,b.value.splice(b.count,0,c)}b.count+=1,b.count==b.total+b.current_item_index&&b.arrayEditor.setValue(b.value)})},build:function(){var a=this;if(this.title=this.header=this.label=this.theme.getFormInputLabel(this.getTitle()),this.options.infoText&&(this.infoButton=this.theme.getInfoButton(this.options.infoText)),this.input=this.theme.getFormInputField("hidden"),this.container.appendChild(this.input),!this.schema.readOnly&&!this.schema.readonly){if(!window.FileReader)throw"FileReader required for base64 editor";this.uploader=this.theme.getFormInputField("file"),a.schema.options&&a.schema.options.multiple&&1==a.schema.options.multiple&&a.parent&&"object"==a.parent.schema.type&&a.parent.parent&&"array"==a.parent.parent.schema.type&&this.uploader.setAttribute("multiple",""),this.uploader.addEventListener("change",function(b){if(b.preventDefault(),b.stopPropagation(),this.files&&this.files.length)if(this.files.length>1&&a.schema.options&&a.schema.options.multiple&&1==a.schema.options.multiple&&a.parent&&"object"==a.parent.schema.type&&a.parent.parent&&"array"==a.parent.parent.schema.type){a.arrayEditor=a.jsoneditor.getEditor(a.parent.parent.path),a.value=a.arrayEditor.getValue(),a.total=this.files.length,a.current_item_index=parseInt(a.parent.key),a.count=a.current_item_index;for(var c=0;c<a.total;c++){var d=new FileReader;a.setFileReaderListener(d),d.readAsDataURL(this.files[c])}}else{var e=new FileReader;e.onload=function(b){a.value=b.target.result,a.refreshPreview(),a.onChange(!0),e=null},e.readAsDataURL(this.files[0])}})}this.preview=this.theme.getFormInputDescription(this.schema.description),this.container.appendChild(this.preview),this.control=this.theme.getFormControl(this.label,this.uploader||this.input,this.preview,this.infoButton),this.container.appendChild(this.control)},refreshPreview:function(){if(this.last_preview!==this.value&&(this.last_preview=this.value,this.preview.innerHTML="",this.value)){var a=this.value.match(/^data:([^;,]+)[;,]/);if(a&&(a=a[1]),a){if(this.preview.innerHTML="<strong>Type:</strong> "+a+", <strong>Size:</strong> "+Math.floor((this.value.length-this.value.split(",")[0].length-1)/1.33333)+" bytes","image"===a.substr(0,5)){this.preview.innerHTML+="<br>";var b=document.createElement("img");b.style.maxWidth="100%",b.style.maxHeight="100px",b.src=this.value,this.preview.appendChild(b)}}else this.preview.innerHTML="<em>Invalid data URI</em>"}},enable:function(){this.always_disabled||(this.uploader&&(this.uploader.disabled=!1),this._super())},disable:function(a){a&&(this.always_disabled=!0),this.uploader&&(this.uploader.disabled=!0),this._super()},setValue:function(a){this.value!==a&&(this.value=a,this.input.value=this.value,this.refreshPreview(),this.onChange())},destroy:function(){this.preview&&this.preview.parentNode&&this.preview.parentNode.removeChild(this.preview),this.title&&this.title.parentNode&&this.title.parentNode.removeChild(this.title),this.input&&this.input.parentNode&&this.input.parentNode.removeChild(this.input),this.uploader&&this.uploader.parentNode&&this.uploader.parentNode.removeChild(this.uploader),this._super()}}),h.defaults.editors.upload=h.AbstractEditor.extend({getNumColumns:function(){return 4},build:function(){var a=this;if(this.title=this.header=this.label=this.theme.getFormInputLabel(this.getTitle()),this.input=this.theme.getFormInputField("hidden"),this.container.appendChild(this.input),!this.schema.readOnly&&!this.schema.readonly){if(!this.jsoneditor.options.upload)throw"Upload handler required for upload editor";this.uploader=this.theme.getFormInputField("file"),this.uploader.addEventListener("change",function(b){if(b.preventDefault(),b.stopPropagation(),this.files&&this.files.length){var c=new FileReader;c.onload=function(b){a.preview_value=b.target.result,a.refreshPreview(),a.onChange(!0),c=null},c.readAsDataURL(this.files[0])}})}var b=this.schema.description;b||(b=""),this.preview=this.theme.getFormInputDescription(b),this.container.appendChild(this.preview),this.control=this.theme.getFormControl(this.label,this.uploader||this.input,this.preview),this.container.appendChild(this.control),window.requestAnimationFrame(function(){if(a.value){var b=document.createElement("img");b.style.maxWidth="100%",b.style.maxHeight="100px",b.onload=function(c){a.preview.appendChild(b)},b.onerror=function(a){console.error("upload error",a)},b.src=a.container.querySelector("a").href}})},refreshPreview:function(){if(this.last_preview!==this.preview_value&&(this.last_preview=this.preview_value,this.preview.innerHTML="",this.preview_value)){var a=this,b=this.preview_value.match(/^data:([^;,]+)[;,]/);b&&(b=b[1]),b||(b="unknown");var c=this.uploader.files[0];if(this.preview.innerHTML="<strong>Type:</strong> "+b+", <strong>Size:</strong> "+c.size+" bytes","image"===b.substr(0,5)){this.preview.innerHTML+="<br>";var d=document.createElement("img");d.style.maxWidth="100%",d.style.maxHeight="100px",d.src=this.preview_value,this.preview.appendChild(d)}this.preview.innerHTML+="<br>";var e=this.getButton("Upload","upload","Upload");this.preview.appendChild(e),e.addEventListener("click",function(b){b.preventDefault(),e.setAttribute("disabled","disabled"),a.theme.removeInputError(a.uploader),a.theme.getProgressBar&&(a.progressBar=a.theme.getProgressBar(),a.preview.appendChild(a.progressBar)),a.jsoneditor.options.upload(a.path,c,{success:function(b){a.setValue(b),a.parent?a.parent.onChildEditorChange(a):a.jsoneditor.onChange(),
+a.progressBar&&a.preview.removeChild(a.progressBar),e.removeAttribute("disabled")},failure:function(b){a.theme.addInputError(a.uploader,b),a.progressBar&&a.preview.removeChild(a.progressBar),e.removeAttribute("disabled")},updateProgress:function(b){a.progressBar&&(b?a.theme.updateProgressBar(a.progressBar,b):a.theme.updateProgressBarUnknown(a.progressBar))}})}),(this.jsoneditor.options.auto_upload||this.schema.options.auto_upload)&&(e.dispatchEvent(new MouseEvent("click")),this.preview.removeChild(e))}},enable:function(){this.always_disabled||(this.uploader&&(this.uploader.disabled=!1),this._super())},disable:function(a){a&&(this.always_disabled=!0),this.uploader&&(this.uploader.disabled=!0),this._super()},setValue:function(a){this.value!==a&&(this.value=a,this.input.value=this.value,this.onChange())},destroy:function(){this.preview&&this.preview.parentNode&&this.preview.parentNode.removeChild(this.preview),this.title&&this.title.parentNode&&this.title.parentNode.removeChild(this.title),this.input&&this.input.parentNode&&this.input.parentNode.removeChild(this.input),this.uploader&&this.uploader.parentNode&&this.uploader.parentNode.removeChild(this.uploader),this._super()}}),h.defaults.editors.checkbox=h.AbstractEditor.extend({setValue:function(a,b){this.value=!!a,this.input.checked=this.value,this.onChange()},register:function(){this._super(),this.input&&this.input.setAttribute("name",this.formname)},unregister:function(){this._super(),this.input&&this.input.removeAttribute("name")},getNumColumns:function(){return Math.min(12,Math.max(this.getTitle().length/7,2))},build:function(){var a=this;this.options.compact||(this.label=this.header=this.theme.getCheckboxLabel(this.getTitle())),this.schema.description&&(this.description=this.theme.getFormInputDescription(this.schema.description)),this.options.infoText&&(this.infoButton=this.theme.getInfoButton(this.options.infoText)),this.options.compact&&this.container.classList.add("compact"),this.input=this.theme.getCheckbox(),this.control=this.theme.getFormControl(this.label,this.input,this.description,this.infoButton),(this.schema.readOnly||this.schema.readonly)&&(this.always_disabled=!0,this.input.disabled=!0),this.input.addEventListener("change",function(b){b.preventDefault(),b.stopPropagation(),a.value=this.checked,a.onChange(!0)}),this.container.appendChild(this.control)},enable:function(){this.always_disabled||(this.input.disabled=!1,this._super())},disable:function(a){a&&(this.always_disabled=!0),this.input.disabled=!0,this._super()},destroy:function(){this.label&&this.label.parentNode&&this.label.parentNode.removeChild(this.label),this.description&&this.description.parentNode&&this.description.parentNode.removeChild(this.description),this.input&&this.input.parentNode&&this.input.parentNode.removeChild(this.input),this._super()},showValidationErrors:function(a){var b=this;if("always"===this.jsoneditor.options.show_errors);else if(!this.is_dirty&&this.previous_error_setting===this.jsoneditor.options.show_errors)return;this.previous_error_setting=this.jsoneditor.options.show_errors;var c=[];f(a,function(a,d){d.path===b.path&&c.push(d.message)}),this.input.controlgroup=this.control,c.length?this.theme.addInputError(this.input,c.join(". ")+"."):this.theme.removeInputError(this.input)}}),h.defaults.editors.arraySelectize=h.AbstractEditor.extend({build:function(){this.title=this.theme.getFormInputLabel(this.getTitle()),this.title_controls=this.theme.getHeaderButtonHolder(),this.title.appendChild(this.title_controls),this.error_holder=document.createElement("div"),this.schema.description&&(this.description=this.theme.getDescription(this.schema.description)),this.input=document.createElement("select"),this.input.setAttribute("multiple","multiple");var a=this.theme.getFormControl(this.title,this.input,this.description);this.container.appendChild(a),this.container.appendChild(this.error_holder),window.jQuery(this.input).selectize({delimiter:!1,createOnBlur:!0,create:!0})},postBuild:function(){var a=this;this.input.selectize.on("change",function(b){a.refreshValue(),a.onChange(!0)})},destroy:function(){this.empty(!0),this.title&&this.title.parentNode&&this.title.parentNode.removeChild(this.title),this.description&&this.description.parentNode&&this.description.parentNode.removeChild(this.description),this.input&&this.input.parentNode&&this.input.parentNode.removeChild(this.input),this._super()},empty:function(a){},setValue:function(a,b){var c=this;a=a||[],Array.isArray(a)||(a=[a]),this.input.selectize.clearOptions(),this.input.selectize.clear(!0),a.forEach(function(a){c.input.selectize.addOption({text:a,value:a})}),this.input.selectize.setValue(a),this.refreshValue(b)},refreshValue:function(a){this.value=this.input.selectize.getValue()},showValidationErrors:function(a){var b=this,c=[],d=[];if(f(a,function(a,e){e.path===b.path?c.push(e):d.push(e)}),this.error_holder)if(c.length){this.error_holder.innerHTML="",this.error_holder.style.display="",f(c,function(a,c){b.error_holder.appendChild(b.theme.getErrorMessage(c.message))})}else this.error_holder.style.display="none"}}),h.defaults.editors.starrating=h.defaults.editors.string.extend({build:function(){var a=this;this.options.compact||(this.header=this.label=this.theme.getFormInputLabel(this.getTitle())),this.schema.description&&(this.description=this.theme.getFormInputDescription(this.schema.description)),this.options.infoText&&(this.infoButton=this.theme.getInfoButton(this.options.infoText)),this.options.compact&&this.container.classList.add("compact"),this.ratingContainer=document.createElement("div"),this.ratingContainer.classList.add("starrating"),this.enum_values=this.schema["enum"],this.radioGroup=[];for(var b=function(b){b.preventDefault(),b.stopPropagation(),a.setValue(this.value),a.onChange(!0)},c=this.enum_values.length-1;c>-1;c--){var d=this.key+"-"+c,e=this.theme.getFormInputField("radio");e.name=this.formname+"[starrating]",e.value=this.enum_values[c],e.id=d,e.addEventListener("change",b,!1),this.radioGroup.push(e);var f=document.createElement("label");f.htmlFor=d,f.title=this.enum_values[c],this.options.displayValue&&f.classList.add("starrating-display-enabled"),this.ratingContainer.appendChild(e),this.ratingContainer.appendChild(f)}if(this.options.displayValue&&(this.displayRating=document.createElement("div"),this.displayRating.classList.add("starrating-display"),this.displayRating.innerText=this.enum_values[0],this.ratingContainer.appendChild(this.displayRating)),this.schema.readOnly||this.schema.readonly){this.always_disabled=!0;for(var g=0;c<this.radioGroup.length;g++)this.radioGroup[g].disabled=!0;this.ratingContainer.classList.add("readonly")}var h=this.theme.getContainer();h.appendChild(this.ratingContainer),this.input=h,this.control=this.theme.getFormControl(this.label,h,this.description,this.infoButton),this.container.appendChild(this.control)},enable:function(){if(!this.always_disabled){for(var a=0;a<this.radioGroup.length;a++)this.radioGroup[a].disabled=!1;this.ratingContainer.classList.remove("readonly"),this._super()}},disable:function(a){a&&(this.always_disabled=!0);for(var b=0;b<this.radioGroup.length;b++)this.radioGroup[b].disabled=!0;this.ratingContainer.classList.add("readonly"),this._super()},destroy:function(){this.ratingContainer.parentNode&&this.ratingContainer.parentNode.parentNode&&this.ratingContainer.parentNode.parentNode.removeChild(this.ratingContainer.parentNode),this.label&&this.label.parentNode&&this.label.parentNode.removeChild(this.label),this.description&&this.description.parentNode&&this.description.parentNode.removeChild(this.description),this._super()},getNumColumns:function(){return 2},setValue:function(a){for(var b=0;b<this.radioGroup.length;b++)if(this.radioGroup[b].value==a){this.radioGroup[b].checked=!0,this.value=a,this.options.displayValue&&(this.displayRating.innerHTML=this.value),this.onChange();break}}}),h.defaults.editors.datetime=h.defaults.editors.string.extend({build:function(){if(this._super(),this.input&&window.flatpickr&&"object"==typeof this.options.flatpickr){this.options.flatpickr.enableTime="date"!=this.schema.format,this.options.flatpickr.noCalendar="time"==this.schema.format,"integer"==this.schema.type&&(this.options.flatpickr.mode="single"),this.input.setAttribute("data-input","");var a=this.input;if(this.options.flatpickr.wrap===!0){var c=[];if(this.options.flatpickr.showToggleButton!==!1){var d=this.getButton("","time"==this.schema.format?"time":"calendar",this.translate("flatpickr_toggle_button"));d.setAttribute("data-toggle",""),c.push(d)}if(this.options.flatpickr.showClearButton!==!1){var e=this.getButton("","clear",this.translate("flatpickr_clear_button"));e.setAttribute("data-clear",""),c.push(e)}var f=this.input.parentNode,g=this.input.nextSibling,h=this.theme.getInputGroup(this.input,c);h!==b?(this.options.flatpickr.inline=!1,f.insertBefore(h,g),a=h):this.options.flatpickr.wrap=!1}this.flatpickr=window.flatpickr(a,this.options.flatpickr),this.options.flatpickr.inline===!0&&this.options.flatpickr.inlineHideInput===!0&&this.input.setAttribute("type","hidden")}},getValue:function(){if(!this.dependenciesFulfilled)return b;if("string"==this.schema.type)return this.value;if(""===this.value||this.value===b)return b;var a="time"==this.schema.format?"1970-01-01 "+this.value:this.value;return parseInt(new Date(a).getTime()/1e3)},setValue:function(a,b,c){if("string"==this.schema.type)this._super(a,b,c),this.flatpickr&&this.flatpickr.setDate(a);else if(a>0){var d=new Date(1e3*a),e=d.getFullYear(),f=this.zeroPad(d.getMonth()+1),g=this.zeroPad(d.getDate()),h=this.zeroPad(d.getHours()),i=this.zeroPad(d.getMinutes()),j=this.zeroPad(d.getSeconds()),k=[e,f,g].join("-"),l=[h,i,j].join(":"),m=k+" "+l;"date"==this.schema.format?m=k:"time"==this.schema.format&&(m=l),this.input.value=m,this.flatpickr&&this.flatpickr.setDate(m)}},destroy:function(){this.flatpickr&&this.flatpickr.destroy(),this.flatpickr=null,this._super()},zeroPad:function(a){return("0"+a).slice(-2)}}),h.defaults.editors.signature=h.defaults.editors.string.extend({build:function(){var a=this;this.options.compact||(this.header=this.label=this.theme.getFormInputLabel(this.getTitle())),this.schema.description&&(this.description=this.theme.getFormInputDescription(this.schema.description));var b=this.formname.replace(/\W/g,"");if("function"==typeof SignaturePad){var c="json-editor-style-signature";document.getElementById(c);this.input=this.theme.getFormInputField("hidden"),this.container.appendChild(this.input);var d=document.createElement("div");d.classList.add("signature-container");var e=document.createElement("canvas");e.setAttribute("name",b),e.classList.add("signature"),d.appendChild(e),a.signaturePad=new window.SignaturePad(e,{onEnd:function(){a.signaturePad.isEmpty()?a.input.value="":a.input.value=a.signaturePad.toDataURL(),a.is_dirty=!0,a.refreshValue(),a.watch_listener(),a.jsoneditor.notifyWatchers(a.path),a.parent?a.parent.onChildEditorChange(a):a.jsoneditor.onChange()}});var g=document.createElement("div"),h=document.createElement("button");h.classList.add("tiny","button"),h.innerHTML="Clear signature",g.appendChild(h),d.appendChild(g),this.options.compact&&this.container.setAttribute("class",this.container.getAttribute("class")+" compact"),(this.schema.readOnly||this.schema.readonly)&&(this.always_disabled=!0,f(this.inputs,function(a,b){e.setAttribute("readOnly","readOnly"),b.disabled=!0})),h.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation(),a.signaturePad.clear(),a.signaturePad.strokeEnd()}),this.control=this.theme.getFormControl(this.label,d,this.description),this.container.appendChild(this.control),this.refreshValue(),e.width=d.offsetWidth,a.options&&a.options.canvas_height?e.height=a.options.canvas_height:e.height="300"}else{var i=document.createElement("p");i.innerHTML="Signature pad is not available, please include SignaturePad from https://github.com/szimek/signature_pad",this.container.appendChild(i)}},setValue:function(a){var b=this;if("function"==typeof SignaturePad){var c=(this.formname.replace(/\W/g,""),this.sanitize(a));if(this.value===c)return;return b.value=c,b.input.value=b.value,b.signaturePad.clear(),a&&""!=a&&b.signaturePad.fromDataURL(a),b.watch_listener(),b.jsoneditor.notifyWatchers(b.path),!1}},destroy:function(){var a=this;this.formname.replace(/\W/g,"");a.signaturePad.off(),delete a.signaturePad}});var i=function(){var a=document.documentElement;return a.matches?"matches":a.webkitMatchesSelector?"webkitMatchesSelector":a.mozMatchesSelector?"mozMatchesSelector":a.msMatchesSelector?"msMatchesSelector":a.oMatchesSelector?"oMatchesSelector":void 0}();return h.AbstractTheme=c.extend({getContainer:function(){return document.createElement("div")},getFloatRightLinkHolder:function(){var a=document.createElement("div");return a.style=a.style||{},a.style.cssFloat="right",a.style.marginLeft="10px",a},getModal:function(){var a=document.createElement("div");return a.style.backgroundColor="white",a.style.border="1px solid black",a.style.boxShadow="3px 3px black",a.style.position="absolute",a.style.zIndex="10",a.style.display="none",a},getGridContainer:function(){var a=document.createElement("div");return a},getGridRow:function(){var a=document.createElement("div");return a.classList.add("row"),a},getGridColumn:function(){var a=document.createElement("div");return a},setGridColumnSize:function(a,b){},getLink:function(a){var b=document.createElement("a");return b.setAttribute("href","#"),b.appendChild(document.createTextNode(a)),b},disableHeader:function(a){a.style.color="#ccc"},disableLabel:function(a){a.style.color="#ccc"},enableHeader:function(a){a.style.color=""},enableLabel:function(a){a.style.color=""},getInfoButton:function(a){var b=document.createElement("span");b.innerText="ⓘ",b.style.fontSize="16px",b.style.fontWeight="bold",b.style.padding=".25rem",b.style.position="relative",b.style.display="inline-block";var c=document.createElement("span");return c.style.fontSize="12px",b.style.fontWeight="normal",c.style["font-family"]="sans-serif",c.style.visibility="hidden",c.style["background-color"]="rgba(50, 50, 50, .75)",c.style.margin="0 .25rem",c.style.color="#FAFAFA",c.style.padding=".5rem 1rem",c.style["border-radius"]=".25rem",c.style.width="20rem",c.style.position="absolute",c.innerText=a,b.onmouseover=function(){c.style.visibility="visible"},b.onmouseleave=function(){c.style.visibility="hidden"},b.appendChild(c),b},getFormInputLabel:function(a){var b=document.createElement("label");return b.appendChild(document.createTextNode(a)),b},getCheckboxLabel:function(a){var b=this.getFormInputLabel(a);return b.style.fontWeight="normal",b},getHeader:function(a){var b=document.createElement("h3");return"string"==typeof a?b.textContent=a:b.appendChild(a),b},getCheckbox:function(){var a=this.getFormInputField("checkbox");return a.style.display="inline-block",a.style.width="auto",a},getMultiCheckboxHolder:function(a,b,c){var d=document.createElement("div");b&&(b.style.display="block",d.appendChild(b));for(var e in a)a.hasOwnProperty(e)&&(a[e].style.display="inline-block",a[e].style.marginRight="20px",d.appendChild(a[e]));return c&&d.appendChild(c),d},getSelectInput:function(a){var b=document.createElement("select");return a&&this.setSelectOptions(b,a),b},getSwitcher:function(a){var b=this.getSelectInput(a);return b.style.backgroundColor="transparent",b.style.display="inline-block",b.style.fontStyle="italic",b.style.fontWeight="normal",b.style.height="auto",b.style.marginBottom=0,b.style.marginLeft="5px",b.style.padding="0 0 0 3px",b.style.width="auto",b},getSwitcherOptions:function(a){return a.getElementsByTagName("option")},setSwitcherOptions:function(a,b,c){this.setSelectOptions(a,b,c)},setSelectOptions:function(a,b,c){c=c||[],a.innerHTML="";for(var d=0;d<b.length;d++){var e=document.createElement("option");e.setAttribute("value",b[d]),e.textContent=c[d]||b[d],a.appendChild(e)}},getTextareaInput:function(){var a=document.createElement("textarea");return a.style=a.style||{},a.style.width="100%",a.style.height="300px",a.style.boxSizing="border-box",a},getRangeInput:function(a,b,c){var d=this.getFormInputField("range");return d.setAttribute("min",a),d.setAttribute("max",b),d.setAttribute("step",c),d},getFormInputField:function(a){var b=document.createElement("input");return b.setAttribute("type",a),b},afterInputReady:function(a){},getFormControl:function(a,b,c,d){var e=document.createElement("div");return e.classList.add("form-control"),a&&e.appendChild(a),"checkbox"===b.type&&a?(a.insertBefore(b,a.firstChild),d&&a.appendChild(d)):(d&&a.appendChild(d),e.appendChild(b)),c&&e.appendChild(c),e},getIndentedPanel:function(){var a=document.createElement("div");return a.style=a.style||{},a.style.paddingLeft="10px",a.style.marginLeft="10px",a.style.borderLeft="1px solid #ccc",a},getTopIndentedPanel:function(){var a=document.createElement("div");return a.style=a.style||{},a.style.paddingLeft="10px",a.style.marginLeft="10px",a},getChildEditorHolder:function(){return document.createElement("div")},getDescription:function(a){var b=document.createElement("p");return b.innerHTML=a,b},getCheckboxDescription:function(a){return this.getDescription(a)},getFormInputDescription:function(a){return this.getDescription(a)},getHeaderButtonHolder:function(){return this.getButtonHolder()},getButtonHolder:function(){return document.createElement("div")},getButton:function(a,b,c){var d=document.createElement("button");return d.type="button",this.setButtonText(d,a,b,c),d},setButtonText:function(a,b,c,d){for(;a.firstChild;)a.removeChild(a.firstChild);c&&(a.appendChild(c),b=" "+b);var e=document.createElement("span");e.appendChild(document.createTextNode(b)),a.appendChild(e),d&&a.setAttribute("title",d)},getTable:function(){return document.createElement("table")},getTableRow:function(){return document.createElement("tr")},getTableHead:function(){return document.createElement("thead")},getTableBody:function(){return document.createElement("tbody")},getTableHeaderCell:function(a){var b=document.createElement("th");return b.textContent=a,b},getTableCell:function(){var a=document.createElement("td");return a},getErrorMessage:function(a){var b=document.createElement("p");return b.style=b.style||{},b.style.color="red",b.appendChild(document.createTextNode(a)),b},addInputError:function(a,b){},removeInputError:function(a){},addTableRowError:function(a){},removeTableRowError:function(a){},getTabHolder:function(a){var b="undefined"==typeof a?"":a,c=document.createElement("div");return c.innerHTML="<div style='float: left; width: 130px;' class='tabs' id='"+b+"'></div><div class='content' style='margin-left: 120px;' id='"+b+"'></div><div style='clear:both;'></div>",c},getTopTabHolder:function(a){var b="undefined"==typeof a?"":a,c=document.createElement("div");return c.innerHTML="<div class='tabs' style='margin-left: 10px;' id='"+b+"'></div><div style='clear:both;'></div><div class='content' id='"+b+"'></div>",c},applyStyles:function(a,b){for(var c in b)b.hasOwnProperty(c)&&(a.style[c]=b[c])},closest:function(a,b){for(;a&&a!==document;){if(!a[i])return!1;if(a[i](b))return a;a=a.parentNode}return!1},insertBasicTopTab:function(a,b){b.firstChild.insertBefore(a,b.firstChild.firstChild)},getTab:function(a,b){var c=document.createElement("div");return c.appendChild(a),c.id=b,c.style=c.style||{},this.applyStyles(c,{border:"1px solid #ccc",borderWidth:"1px 0 1px 1px",textAlign:"center",lineHeight:"30px",borderRadius:"5px",borderBottomRightRadius:0,borderTopRightRadius:0,fontWeight:"bold",cursor:"pointer"}),c},getTopTab:function(a,b){var c=document.createElement("div");return c.id=b,c.appendChild(a),c.style=c.style||{},this.applyStyles(c,{"float":"left",border:"1px solid #ccc",borderWidth:"1px 1px 0px 1px",textAlign:"center",lineHeight:"30px",borderRadius:"5px",paddingLeft:"5px",paddingRight:"5px",borderBottomRightRadius:0,borderBottomLeftRadius:0,fontWeight:"bold",cursor:"pointer"}),c},getTabContentHolder:function(a){return a.children[1]},getTopTabContentHolder:function(a){return a.children[1]},getTabContent:function(){return this.getIndentedPanel()},getTopTabContent:function(){return this.getTopIndentedPanel()},markTabActive:function(a){this.applyStyles(a.tab,{opacity:1,background:"white"}),"undefined"!=typeof a.rowPane?a.rowPane.style.display="":a.container.style.display=""},markTabInactive:function(a){this.applyStyles(a.tab,{opacity:.5,background:""}),"undefined"!=typeof a.rowPane?a.rowPane.style.display="none":a.container.style.display="none"},addTab:function(a,b){a.children[0].appendChild(b)},addTopTab:function(a,b){a.children[0].appendChild(b)},getBlockLink:function(){var a=document.createElement("a");return a.style.display="block",a},getBlockLinkHolder:function(){var a=document.createElement("div");return a},getLinksHolder:function(){var a=document.createElement("div");return a},createMediaLink:function(a,b,c){a.appendChild(b),c.style.width="100%",a.appendChild(c)},createImageLink:function(a,b,c){a.appendChild(b),b.appendChild(c)},getFirstTab:function(a){return a.firstChild.firstChild},getInputGroup:function(a,c){return b}}),h.defaults.themes.bootstrap2=h.AbstractTheme.extend({getRangeInput:function(a,b,c){return this._super(a,b,c)},getGridContainer:function(){var a=document.createElement("div");return a.classList.add("container-fluid"),a},getGridRow:function(){var a=document.createElement("div");return a.classList.add("row-fluid"),a},getFormInputLabel:function(a){var b=this._super(a);return b.style.display="inline-block",b.style.fontWeight="bold",b},setGridColumnSize:function(a,b){a.classList.add("span"+b)},getSelectInput:function(a){var b=this._super(a);return b.style.width="auto",b.style.maxWidth="98%",b},getFormInputField:function(a){var b=this._super(a);return b.style.width="98%",b},afterInputReady:function(a){if(!a.controlgroup&&(a.controlgroup=this.closest(a,".control-group"),a.controls=this.closest(a,".controls"),this.closest(a,".compact")&&(a.controlgroup.className=a.controlgroup.className.replace(/control-group/g,"").replace(/[ ]{2,}/g," "),a.controls.className=a.controlgroup.className.replace(/controls/g,"").replace(/[ ]{2,}/g," "),a.style.marginBottom=0),this.queuedInputErrorText)){var b=this.queuedInputErrorText;delete this.queuedInputErrorText,this.addInputError(a,b)}},getIndentedPanel:function(){var a=document.createElement("div");return a.classList.add("well","well-small"),a.style.paddingBottom=0,a},getInfoButton:function(a){var b=document.createElement("span");b.classList.add("icon-info-sign","pull-right"),b.style.padding=".25rem",b.style.position="relative",b.style.display="inline-block";var c=document.createElement("span");return c.style["font-family"]="sans-serif",c.style.visibility="hidden",c.style["background-color"]="rgba(50, 50, 50, .75)",c.style.margin="0 .25rem",c.style.color="#FAFAFA",c.style.padding=".5rem 1rem",c.style["border-radius"]=".25rem",c.style.width="25rem",c.style.transform="translateX(-27rem) translateY(-.5rem)",c.style.position="absolute",c.innerText=a,b.onmouseover=function(){c.style.visibility="visible"},b.onmouseleave=function(){c.style.visibility="hidden"},b.appendChild(c),b},getFormInputDescription:function(a){var b=document.createElement("p");return b.classList.add("help-inline"),b.textContent=a,b},getFormControl:function(a,b,c,d){var e=document.createElement("div");e.classList.add("control-group");var f=document.createElement("div");return f.classList.add("controls"),a&&"checkbox"===b.getAttribute("type")?(e.appendChild(f),a.classList.add("checkbox"),a.appendChild(b),f.appendChild(a),d&&f.appendChild(d),f.style.height="30px"):(a&&(a.classList.add("control-label"),e.appendChild(a)),d&&f.appendChild(d),f.appendChild(b),e.appendChild(f)),c&&f.appendChild(c),e},getHeaderButtonHolder:function(){var a=this.getButtonHolder();return a.style.marginLeft="10px",a},getButtonHolder:function(){var a=document.createElement("div");return a.classList.add("btn-group"),a},getButton:function(a,b,c){var d=this._super(a,b,c);return d.classList.add("btn","btn-default"),d},getTable:function(){var a=document.createElement("table");return a.classList.add("table","table-bordered"),a.style.width="auto",a.style.maxWidth="none",a},addInputError:function(a,b){return a.controlgroup?void(a.controlgroup&&a.controls&&(a.controlgroup.classList.add("error"),a.errmsg?a.errmsg.style.display="":(a.errmsg=document.createElement("p"),a.errmsg.classList.add("help-block","errormsg"),a.controls.appendChild(a.errmsg)),a.errmsg.textContent=b)):void(this.queuedInputErrorText=b)},removeInputError:function(a){a.controlgroup||delete this.queuedInputErrorText,a.errmsg&&(a.errmsg.style.display="none",a.controlgroup.classList.remove("error"))},getTabHolder:function(a){var b="undefined"==typeof a?"":a,c=document.createElement("div");return c.classList.add("tabbable","tabs-left"),c.innerHTML="<ul class='nav nav-tabs'  id='"+b+"'></ul><div class='tab-content well well-small' id='"+b+"'></div>",c},getTopTabHolder:function(a){var b="undefined"==typeof a?"":a,c=document.createElement("div");return c.classList.add("tabbable","tabs-over"),c.innerHTML="<ul class='nav nav-tabs' id='"+b+"'></ul><div class='tab-content well well-small'  id='"+b+"'></div>",c},getTab:function(a,b){var c=document.createElement("li");c.classList.add("nav-item");var d=document.createElement("a");return d.setAttribute("href","#"+b),d.appendChild(a),c.appendChild(d),c},getTopTab:function(a,b){var c=document.createElement("li");c.classList.add("nav-item");var d=document.createElement("a");return d.setAttribute("href","#"+b),d.appendChild(a),c.appendChild(d),c},getTabContentHolder:function(a){return a.children[1]},getTopTabContentHolder:function(a){return a.children[1]},getTabContent:function(){var a=document.createElement("div");return a.classList.add("tab-pane"),a},getTopTabContent:function(){var a=document.createElement("div");return a.classList.add("tab-pane"),a},markTabActive:function(a){a.tab.classList.add("active"),"undefined"!=typeof a.rowPane?a.rowPane.classList.add("active"):a.container.classList.add("active")},markTabInactive:function(a){a.tab.classList.remove("active"),"undefined"!=typeof a.rowPane?a.rowPane.classList.remove("active"):a.container.classList.remove("active")},addTab:function(a,b){a.children[0].appendChild(b)},addTopTab:function(a,b){a.children[0].appendChild(b)},getProgressBar:function(){var a=document.createElement("div");a.classList.add("progress");var b=document.createElement("div");return b.classList.add("bar"),b.style.width="0%",a.appendChild(b),a},updateProgressBar:function(a,b){a&&(a.firstChild.style.width=b+"%")},updateProgressBarUnknown:function(a){a&&(a.classList.add("progress","progress-striped","active"),a.firstChild.style.width="100%")},getInputGroup:function(a,b){if(a){var c=document.createElement("div");c.classList.add("input-append"),c.appendChild(a);for(var d=0;d<b.length;d++)b[d].classList.add("btn"),c.appendChild(b[d]);return c}}}),h.defaults.themes.bootstrap3=h.AbstractTheme.extend({getSelectInput:function(a){var b=this._super(a);return b.classList.add("form-control"),b},setGridColumnSize:function(a,b){a.classList.add("col-md-"+b)},afterInputReady:function(a){if(!a.controlgroup&&(a.controlgroup=this.closest(a,".form-group"),this.closest(a,".compact")&&(a.controlgroup.style.marginBottom=0),this.queuedInputErrorText)){var b=this.queuedInputErrorText;delete this.queuedInputErrorText,this.addInputError(a,b)}},getTextareaInput:function(){var a=document.createElement("textarea");return a.classList.add("form-control"),a},getRangeInput:function(a,b,c){return this._super(a,b,c)},getFormInputField:function(a){var b=this._super(a);return"checkbox"!==a&&b.classList.add("form-control"),b},getFormControl:function(a,b,c,d){var e=document.createElement("div");return a&&"checkbox"===b.type?(e.classList.add("checkbox"),a.appendChild(b),a.style.fontSize="14px",e.style.marginTop="0",d&&e.appendChild(d),e.appendChild(a),b.style.position="relative",b.style.cssFloat="left"):(e.classList.add("form-group"),a&&(a.classList.add("control-label"),e.appendChild(a)),d&&e.appendChild(d),e.appendChild(b)),c&&e.appendChild(c),e},getIndentedPanel:function(){var a=document.createElement("div");return a.classList.add("well","well-sm"),a.style.paddingBottom=0,a},getInfoButton:function(a){var b=document.createElement("span");b.classList.add("glyphicon","glyphicon-info-sign","pull-right"),b.style.padding=".25rem",b.style.position="relative",b.style.display="inline-block";var c=document.createElement("span");return c.style["font-family"]="sans-serif",c.style.visibility="hidden",c.style["background-color"]="rgba(50, 50, 50, .75)",c.style.margin="0 .25rem",c.style.color="#FAFAFA",c.style.padding=".5rem 1rem",c.style["border-radius"]=".25rem",c.style.width="25rem",c.style.transform="translateX(-27rem) translateY(-.5rem)",c.style.position="absolute",c.innerText=a,b.onmouseover=function(){c.style.visibility="visible"},b.onmouseleave=function(){c.style.visibility="hidden"},b.appendChild(c),b},getFormInputDescription:function(a){var b=document.createElement("p");return b.classList.add("help-block"),b.innerHTML=a,b},getHeaderButtonHolder:function(){var a=this.getButtonHolder();return a.style.marginLeft="10px",a},getButtonHolder:function(){var a=document.createElement("div");return a.classList.add("btn-group"),a},getButton:function(a,b,c){var d=this._super(a,b,c);return d.classList.add("btn","btn-default"),d},getTable:function(){var a=document.createElement("table");return a.classList.add("table","table-bordered"),a.style.width="auto",a.style.maxWidth="none",a},addInputError:function(a,b){return a.controlgroup?(a.controlgroup.classList.add("has-error"),a.errmsg?a.errmsg.style.display="":(a.errmsg=document.createElement("p"),a.errmsg.classList.add("help-block","errormsg"),a.controlgroup.appendChild(a.errmsg)),void(a.errmsg.textContent=b)):void(this.queuedInputErrorText=b)},removeInputError:function(a){a.controlgroup||delete this.queuedInputErrorText,a.errmsg&&(a.errmsg.style.display="none",a.controlgroup.classList.remove("has-error"))},getTabHolder:function(a){var b="undefined"==typeof a?"":a,c=document.createElement("div");return c.innerHTML="<ul class='col-md-2 nav nav-pills nav-stacked' id='"+b+"' role='tablist'></ul><div class='col-md-10 tab-content well well-small'  id='"+b+"'></div>",c},getTopTabHolder:function(a){var b="undefined"==typeof a?"":a,c=document.createElement("div");return c.innerHTML="<ul class='nav nav-tabs' id='"+b+"' role='tablist'></ul><div class='tab-content well well-small'  id='"+b+"'></div>",c},getTab:function(a,b){var c=document.createElement("li");c.setAttribute("role","presentation");var d=document.createElement("a");return d.setAttribute("href","#"+b),d.appendChild(a),d.setAttribute("aria-controls",b),d.setAttribute("role","tab"),d.setAttribute("data-toggle","tab"),c.appendChild(d),c},getTopTab:function(a,b){var c=document.createElement("li");c.setAttribute("role","presentation");var d=document.createElement("a");return d.setAttribute("href","#"+b),d.appendChild(a),d.setAttribute("aria-controls",b),d.setAttribute("role","tab"),d.setAttribute("data-toggle","tab"),c.appendChild(d),c},getTabContent:function(){var a=document.createElement("div");return a.classList.add("tab-pane"),a.setAttribute("role","tabpanel"),a},getTopTabContent:function(){var a=document.createElement("div");return a.classList.add("tab-pane"),a.setAttribute("role","tabpanel"),a},markTabActive:function(a){a.tab.classList.add("active"),"undefined"!=typeof a.rowPane?a.rowPane.classList.add("active"):a.container.classList.add("active")},markTabInactive:function(a){a.tab.classList.remove("active"),"undefined"!=typeof a.rowPane?a.rowPane.classList.remove("active"):a.container.classList.remove("active")},getProgressBar:function(){var a=0,b=100,c=0,d=document.createElement("div");d.classList.add("progress");var e=document.createElement("div");return e.classList.add("progress-bar"),e.setAttribute("role","progressbar"),e.setAttribute("aria-valuenow",c),
+e.setAttribute("aria-valuemin",a),e.setAttribute("aria-valuenax",b),e.innerHTML=c+"%",d.appendChild(e),d},updateProgressBar:function(a,b){if(a){var c=a.firstChild,d=b+"%";c.setAttribute("aria-valuenow",b),c.style.width=d,c.innerHTML=d}},updateProgressBarUnknown:function(a){if(a){var b=a.firstChild;a.classList.add("progress","progress-striped","active"),b.removeAttribute("aria-valuenow"),b.style.width="100%",b.innerHTML=""}},getInputGroup:function(a,b){if(a){var c=document.createElement("div");c.classList.add("input-group"),c.appendChild(a);var d=document.createElement("div");d.classList.add("input-group-btn"),c.appendChild(d);for(var e=0;e<b.length;e++)d.appendChild(b[e]);return c}}}),h.defaults.themes.bootstrap4=h.AbstractTheme.extend({getSelectInput:function(a){var b=this._super(a);return b.classList.add("form-control"),b},setGridColumnSize:function(a,b){a.classList.add("col-md-"+b)},afterInputReady:function(a){a.controlgroup||(a.controlgroup=this.closest(a,".form-group"),this.closest(a,".compact")&&(a.controlgroup.style.marginBottom=0))},getTextareaInput:function(){var a=document.createElement("textarea");return a.classList.add("form-control"),a},getRangeInput:function(a,b,c){return this._super(a,b,c)},getFormInputField:function(a){var b=this._super(a);return"checkbox"!==a&&b.classList.add("form-control"),b},getFormControl:function(a,b,c){var d=document.createElement("div");return a&&"checkbox"===b.type?(d.classList.add("checkbox"),a.appendChild(b),a.style.fontSize="14px",d.style.marginTop="0",d.appendChild(a),b.style.position="relative",b.style.cssFloat="left"):(d.classList.add("form-group"),a&&(a.classList.add("form-control-label"),d.appendChild(a)),d.appendChild(b)),c&&d.appendChild(c),d},getIndentedPanel:function(){var a=document.createElement("div");return a.classList.add("card","card-body","bg-light"),a},getFormInputDescription:function(a){var b=document.createElement("p");return b.classList.add("form-text"),b.innerHTML=a,b},getHeaderButtonHolder:function(){var a=this.getButtonHolder();return a.style.marginLeft="10px",a},getButtonHolder:function(){var a=document.createElement("div");return a.classList.add("btn-group"),a},getButton:function(a,b,c){var d=this._super(a,b,c);return d.classList.add("btn","btn-secondary"),d},getTable:function(){var a=document.createElement("table");return a.classList.add("table-bordered","table-sm"),a.style.width="auto",a.style.maxWidth="none",a},addInputError:function(a,b){a.controlgroup&&(a.controlgroup.classList.add("has-danger"),a.classList.add("is-invalid"),a.errmsg?a.errmsg.style.display="":(a.errmsg=document.createElement("p"),a.errmsg.classList.add("form-text","invalid-feedback"),a.controlgroup.appendChild(a.errmsg)),a.errmsg.textContent=b)},removeInputError:function(a){a.errmsg&&(a.errmsg.style.display="none",a.classList.remove("is-invalid"),a.controlgroup.classList.remove("has-danger"))},getTabHolder:function(a){var b=document.createElement("div"),c="undefined"==typeof a?"":a;return b.innerHTML="<div class='col-md-2' id='"+c+"'><ul class='nav flex-column nav-pills'></ul></div><div class='tab-content col-md-10' id='"+c+"'></div>",b.classList.add("row"),b},addTab:function(a,b){a.children[0].children[0].appendChild(b)},getTopTabHolder:function(a){var b="undefined"==typeof a?"":a,c=document.createElement("div");return c.innerHTML="<ul class='nav nav-tabs' id='"+b+"'></ul><div class='card-body tab-content' id='"+b+"'></div>",c},getTab:function(a,b){var c=document.createElement("li");c.classList.add("nav-item");var d=document.createElement("a");return d.classList.add("nav-link"),d.setAttribute("style","padding:10px;"),d.setAttribute("href","#"+b),d.setAttribute("data-toggle","tab"),d.appendChild(a),c.appendChild(d),c},getTopTab:function(a,b){var c=document.createElement("li");c.classList.add("nav-item");var d=document.createElement("a");return d.classList.add("nav-link"),d.setAttribute("href","#"+b),d.setAttribute("data-toggle","tab"),d.appendChild(a),c.appendChild(d),c},getTabContent:function(){var a=document.createElement("div");return a.classList.add("tab-pane"),a.setAttribute("role","tabpanel"),a},getTopTabContent:function(){var a=document.createElement("div");return a.classList.add("tab-pane"),a.setAttribute("role","tabpanel"),a},markTabActive:function(a){a.tab.firstChild.classList.add("active"),"undefined"!=typeof a.rowPane?a.rowPane.classList.add("active"):a.container.classList.add("active")},markTabInactive:function(a){a.tab.firstChild.classList.remove("active"),"undefined"!=typeof a.rowPane?a.rowPane.classList.remove("active"):a.container.classList.remove("active")},getProgressBar:function(){var a=0,b=100,c=0,d=document.createElement("div");d.classList.add("progress");var e=document.createElement("div");return e.classList.add("progress-bar"),e.setAttribute("role","progressbar"),e.setAttribute("aria-valuenow",c),e.setAttribute("aria-valuemin",a),e.setAttribute("aria-valuenax",b),e.innerHTML=c+"%",d.appendChild(e),d},updateProgressBar:function(a,b){if(a){var c=a.firstChild,d=b+"%";c.setAttribute("aria-valuenow",b),c.style.width=d,c.innerHTML=d}},updateProgressBarUnknown:function(a){if(a){var b=a.firstChild;a.classList.add("progress","progress-striped","active"),b.removeAttribute("aria-valuenow"),b.style.width="100%",b.innerHTML=""}},getInputGroup:function(a,b){if(a){var c=document.createElement("div");c.classList.add("input-group"),c.appendChild(a);var d=document.createElement("div");d.classList.add("input-group-prepend"),c.appendChild(d);for(var e=0;e<b.length;e++)d.appendChild(b[e]);return c}}}),h.defaults.themes.foundation=h.AbstractTheme.extend({getChildEditorHolder:function(){var a=document.createElement("div");return a.style.marginBottom="15px",a},getSelectInput:function(a){var b=this._super(a);return b.style.minWidth="none",b.style.padding="5px",b.style.marginTop="3px",b},getSwitcher:function(a){var b=this._super(a);return b.style.paddingRight="8px",b},afterInputReady:function(a){if(!a.group&&(this.closest(a,".compact")&&(a.style.marginBottom=0),a.group=this.closest(a,".form-control"),this.queuedInputErrorText)){var b=this.queuedInputErrorText;delete this.queuedInputErrorText,this.addInputError(a,b)}},getFormInputLabel:function(a){var b=this._super(a);return b.style.display="inline-block",b},getFormInputField:function(a){var b=this._super(a);return b.style.width="100%",b.style.marginBottom="checkbox"===a?"0":"12px",b},getFormInputDescription:function(a){var b=document.createElement("p");return b.textContent=a,b.style.marginTop="-10px",b.style.fontStyle="italic",b},getIndentedPanel:function(){var a=document.createElement("div");return a.classList.add("panel"),a.style.paddingBottom=0,a},getHeaderButtonHolder:function(){var a=this.getButtonHolder();return a.style.display="inline-block",a.style.marginLeft="10px",a.style.verticalAlign="middle",a},getButtonHolder:function(){var a=document.createElement("div");return a.classList.add("button-group"),a},getButton:function(a,b,c){var d=this._super(a,b,c);return d.classList.add("small","button"),d},addInputError:function(a,b){return a.group?(a.group.classList.add("error"),a.errmsg?a.errmsg.style.display="":(a.insertAdjacentHTML("afterend",'<small class="error"></small>'),a.errmsg=a.parentNode.getElementsByClassName("error")[0]),void(a.errmsg.textContent=b)):void(this.queuedInputErrorText=b)},removeInputError:function(a){a.group||delete this.queuedInputErrorText,a.errmsg&&(a.group.classList.remove("error"),a.errmsg.style.display="none")},getProgressBar:function(){var a=document.createElement("div");a.classList.add("progress");var b=document.createElement("span");return b.classList.add("meter"),b.style.width="0%",a.appendChild(b),a},updateProgressBar:function(a,b){a&&(a.firstChild.style.width=b+"%")},updateProgressBarUnknown:function(a){a&&(a.firstChild.style.width="100%")},getInputGroup:function(a,c){if(!a)return b;var d=document.createElement("div");d.classList.add("input-group"),a.classList.add("input-group-field"),d.appendChild(a);for(var e=0;e<c.length;e++){var f=document.createElement("div");f.classList.add("input-group-button"),f.style.verticalAlign="top",c[e].classList.remove("small"),f.appendChild(c[e]),d.appendChild(f)}return d}}),h.defaults.themes.foundation3=h.defaults.themes.foundation.extend({getHeaderButtonHolder:function(){var a=this._super();return a.style.fontSize=".6em",a},getFormInputLabel:function(a){var b=this._super(a);return b.style.fontWeight="bold",b},getTabHolder:function(a){var b="undefined"==typeof a?"":a,c=document.createElement("div");return c.classList.add("row"),c.innerHTML='<dl class="tabs vertical two columns" id="'+b+'"></dl><div class="tabs-content ten columns" id="'+b+'"></div>',c},getTopTabHolder:function(a){var b="undefined"==typeof a?"":a,c=document.createElement("div");return c.classList.add("row"),c.innerHTML='<dl class="tabs horizontal" style="padding-left: 10px; margin-left: 10px;" id="'+b+'"></dl><div class="tabs-content twelve columns" style="padding: 10px; margin-left: 10px;" id="'+b+'"></div>',c},setGridColumnSize:function(a,b){var c=["zero","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve"];a.classList.add("columns",c[b])},getTab:function(a,b){var c=document.createElement("dd"),d=document.createElement("a");return d.setAttribute("href","#"+b),d.appendChild(a),c.appendChild(d),c},getTopTab:function(a,b){var c=document.createElement("dd"),d=document.createElement("a");return d.setAttribute("href","#"+b),d.appendChild(a),c.appendChild(d),c},getTabContentHolder:function(a){return a.children[1]},getTopTabContentHolder:function(a){return a.children[1]},getTabContent:function(){var a=document.createElement("div");return a.classList.add("content","active"),a.style.paddingLeft="5px",a},getTopTabContent:function(){var a=document.createElement("div");return a.classList.add("content","active"),a.style.paddingLeft="5px",a},markTabActive:function(a){a.tab.classList.add("active"),"undefined"!=typeof a.rowPane?a.rowPane.style.display="":a.container.style.display=""},markTabInactive:function(a){a.tab.classList.remove("active"),"undefined"!=typeof a.rowPane?a.rowPane.style.display="none":a.container.style.display="none"},addTab:function(a,b){a.children[0].appendChild(b)},addTopTab:function(a,b){a.children[0].appendChild(b)}}),h.defaults.themes.foundation4=h.defaults.themes.foundation.extend({getHeaderButtonHolder:function(){var a=this._super();return a.style.fontSize=".6em",a},setGridColumnSize:function(a,b){a.classList.add("columns","large-"+b)},getFormInputDescription:function(a){var b=this._super(a);return b.style.fontSize=".8rem",b},getFormInputLabel:function(a){var b=this._super(a);return b.style.fontWeight="bold",b}}),h.defaults.themes.foundation5=h.defaults.themes.foundation.extend({getFormInputDescription:function(a){var b=this._super(a);return b.style.fontSize=".8rem",b},setGridColumnSize:function(a,b){a.classList.add("columns","medium-"+b)},getButton:function(a,b,c){var d=this._super(a,b,c);return d.className=d.className.replace(/\s*small/g,"")+" tiny",d},getTabHolder:function(a){var b="undefined"==typeof a?"":a,c=document.createElement("div");return c.innerHTML='<dl class="tabs vertical" id="'+b+'"></dl><div class="tabs-content vertical" id="'+b+'"></div>',c},getTopTabHolder:function(a){var b="undefined"==typeof a?"":a,c=document.createElement("div");return c.classList.add("row"),c.innerHTML='<dl class="tabs horizontal" style="padding-left: 10px;" id="'+b+'"></dl><div class="tabs-content horizontal" style="padding: 10px;" id="'+b+'"></div>',c},getTab:function(a,b){var c=document.createElement("dd"),d=document.createElement("a");return d.setAttribute("href","#"+b),d.appendChild(a),c.appendChild(d),c},getTopTab:function(a,b){var c=document.createElement("dd"),d=document.createElement("a");return d.setAttribute("href","#"+b),d.appendChild(a),c.appendChild(d),c},getTabContentHolder:function(a){return a.children[1]},getTopTabContentHolder:function(a){return a.children[1]},getTabContent:function(){var a=document.createElement("div");return a.classList.add("tab-content","active"),a.style.paddingLeft="5px",a},getTopTabContent:function(){var a=document.createElement("div");return a.classList.add("tab-content","active"),a.style.paddingLeft="5px",a},markTabActive:function(a){a.tab.classList.add("active"),"undefined"!=typeof a.rowPane?a.rowPane.style.display="":a.container.style.display=""},markTabInactive:function(a){a.tab.classList.remove("active"),"undefined"!=typeof a.rowPane?a.rowPane.style.display="none":a.container.style.display="none"},addTab:function(a,b){a.children[0].appendChild(b)},addTopTab:function(a,b){a.children[0].appendChild(b)}}),h.defaults.themes.foundation6=h.defaults.themes.foundation5.extend({getIndentedPanel:function(){var a=document.createElement("div");return a.classList.add("callout","secondary"),a.style="padding-left: 10px; margin-left: 10px;",a},getButtonHolder:function(){var a=document.createElement("div");return a.classList.add("button-group","tiny"),a.style.marginBottom=0,a},getFormInputLabel:function(a){var b=this._super(a);return b.style.display="block",b},getFormControl:function(a,b,c,d){var e=document.createElement("div");return e.classList.add("form-control"),a&&e.appendChild(a),"checkbox"===b.type?a.insertBefore(b,a.firstChild):a?(d&&a.appendChild(d),a.appendChild(b)):(d&&e.appendChild(d),e.appendChild(b)),c&&a.appendChild(c),e},addInputError:function(a,b){if(a.group){if(a.group.classList.add("error"),a.errmsg)a.errmsg.style.display="",a.className="";else{var c=document.createElement("span");c.classList.add("form-error","is-visible"),a.group.getElementsByTagName("label")[0].appendChild(c),a.classList.add("is-invalid-input"),a.errmsg=c}a.errmsg.textContent=b}},removeInputError:function(a){a.errmsg&&(a.classList.remove("is-invalid-input"),a.errmsg.parentNode&&a.errmsg.parentNode.removeChild(a.errmsg))},getTabHolder:function(a){var b="undefined"==typeof a?"":a,c=document.createElement("div");return c.classList.add("grid-x"),c.innerHTML='<div class="medium-2 cell" style="float: left;"><ul class="vertical tabs" data-tabs id="'+b+'"></ul></div><div class="medium-10 cell" style="float: left;"><div class="tabs-content" data-tabs-content="'+b+'"></div></div>',c},getTopTabHolder:function(a){var b="undefined"==typeof a?"":a,c=document.createElement("div");return c.classList.add("grid-y"),c.innerHTML='<div className="cell"><ul class="tabs" data-tabs id="'+b+'"></ul><div class="tabs-content" data-tabs-content="'+b+'"></div></div>',c},insertBasicTopTab:function(a,b){b.firstChild.firstChild.insertBefore(a,b.firstChild.firstChild.firstChild)},getTab:function(a,b){var c=document.createElement("li");c.classList.add("tabs-title");var d=document.createElement("a");return d.setAttribute("href","#"+b),d.appendChild(a),c.appendChild(d),c},getTopTab:function(a,b){var c=document.createElement("li");c.classList.add("tabs-title");var d=document.createElement("a");return d.setAttribute("href","#"+b),d.appendChild(a),c.appendChild(d),c},getTabContentHolder:function(a){return a.children[1].firstChild},getTopTabContentHolder:function(a){return a.firstChild.children[1]},getTabContent:function(){var a=document.createElement("div");return a.classList.add("tabs-panel"),a.style.paddingLeft="5px",a},getTopTabContent:function(){var a=document.createElement("div");return a.classList.add("tabs-panel"),a.style.paddingLeft="5px",a},markTabActive:function(a){a.tab.classList.add("is-active"),a.tab.firstChild.setAttribute("aria-selected","true"),"undefined"!=typeof a.rowPane?(a.rowPane.classList.add("is-active"),a.rowPane.setAttribute("aria-selected","true")):(a.container.classList.add("is-active"),a.container.setAttribute("aria-selected","true"))},markTabInactive:function(a){a.tab.classList.remove("is-active"),a.tab.firstChild.removeAttribute("aria-selected"),"undefined"!=typeof a.rowPane?(a.rowPane.classList.remove("is-active"),a.rowPane.removeAttribute("aria-selected")):(a.container.classList.remove("is-active"),a.container.removeAttribute("aria-selected"))},addTab:function(a,b){a.children[0].firstChild.appendChild(b)},addTopTab:function(a,b){a.firstChild.children[0].appendChild(b)},getFirstTab:function(a){return a.firstChild.firstChild.firstChild}}),h.defaults.themes.html=h.AbstractTheme.extend({getFormInputLabel:function(a){var b=this._super(a);return b.style.display="block",b.style.marginBottom="3px",b.style.fontWeight="bold",b},getFormInputDescription:function(a){var b=this._super(a);return b.style.fontSize=".8em",b.style.margin=0,b.style.display="inline-block",b.style.fontStyle="italic",b},getIndentedPanel:function(){var a=this._super();return a.style.border="1px solid #ddd",a.style.padding="5px",a.style.margin="10px",a.style.borderRadius="3px",a},getTopIndentedPanel:function(){return this.getIndentedPanel()},getChildEditorHolder:function(){var a=this._super();return a.style.marginBottom="8px",a},getHeaderButtonHolder:function(){var a=this.getButtonHolder();return a.style.display="inline-block",a.style.marginLeft="10px",a.style.fontSize=".8em",a.style.verticalAlign="middle",a},getTable:function(){var a=this._super();return a.style.borderBottom="1px solid #ccc",a.style.marginBottom="5px",a},addInputError:function(a,b){if(a.style.borderColor="red",a.errmsg)a.errmsg.style.display="block";else{var c=this.closest(a,".form-control");a.errmsg=document.createElement("div"),a.errmsg.setAttribute("class","errmsg"),a.errmsg.style=a.errmsg.style||{},a.errmsg.style.color="red",c.appendChild(a.errmsg)}a.errmsg.innerHTML="",a.errmsg.appendChild(document.createTextNode(b))},removeInputError:function(a){a.style.borderColor="",a.errmsg&&(a.errmsg.style.display="none")},getProgressBar:function(){var a=100,b=0,c=document.createElement("progress");return c.setAttribute("max",a),c.setAttribute("value",b),c},updateProgressBar:function(a,b){a&&a.setAttribute("value",b)},updateProgressBarUnknown:function(a){a&&a.removeAttribute("value")}}),h.defaults.themes.jqueryui=h.AbstractTheme.extend({getTable:function(){var a=this._super();return a.setAttribute("cellpadding",5),a.setAttribute("cellspacing",0),a},getTableHeaderCell:function(a){var b=this._super(a);return b.classList.add("ui-state-active"),b.style.fontWeight="bold",b},getTableCell:function(){var a=this._super();return a.classList.add("ui-widget-content"),a},getHeaderButtonHolder:function(){var a=this.getButtonHolder();return a.style.marginLeft="10px",a.style.fontSize=".6em",a.style.display="inline-block",a},getFormInputDescription:function(a){var b=this.getDescription(a);return b.style.marginLeft="10px",b.style.display="inline-block",b},getFormControl:function(a,b,c,d){var e=this._super(a,b,c,d);return"checkbox"===b.type?(e.style.lineHeight="25px",e.style.padding="3px 0"):e.style.padding="4px 0 8px 0",e},getDescription:function(a){var b=document.createElement("span");return b.style.fontSize=".8em",b.style.fontStyle="italic",b.textContent=a,b},getButtonHolder:function(){var a=document.createElement("div");return a.classList.add("ui-buttonset"),a.style.fontSize=".7em",a},getFormInputLabel:function(a){var b=document.createElement("label");return b.style.fontWeight="bold",b.style.display="block",b.textContent=a,b},getButton:function(a,b,c){var d=document.createElement("button");d.classList.add("ui-button","ui-widget","ui-state-default","ui-corner-all"),b&&!a?(d.classList.add("ui-button-icon-only"),b.classList.add("ui-button-icon-primary","ui-icon-primary"),d.appendChild(b)):b?(d.classList.add("ui-button-text-icon-primary"),b.classList.add("ui-button-icon-primary","ui-icon-primary"),d.appendChild(b)):d.classList.add("ui-button-text-only");var e=document.createElement("span");return e.classList.add("ui-button-text"),e.textContent=a||c||".",d.appendChild(e),d.setAttribute("title",c),d},setButtonText:function(a,b,c,d){a.innerHTML="",a.classList.add("ui-button","ui-widget","ui-state-default","ui-corner-all"),c&&!b?(a.classList.add("ui-button-icon-only"),c.classList.add("ui-button-icon-primary","ui-icon-primary"),a.appendChild(c)):c?(a.classList.add("ui-button-text-icon-primary"),c.classList.add("ui-button-icon-primary","ui-icon-primary"),a.appendChild(c)):a.classList.add("ui-button-text-only");var e=document.createElement("span");e.classList.add("ui-button-text"),e.textContent=b||d||".",a.appendChild(e),a.setAttribute("title",d)},getIndentedPanel:function(){var a=document.createElement("div");return a.classList.add("ui-widget-content","ui-corner-all"),a.style.padding="1em 1.4em",a.style.marginBottom="20px",a},afterInputReady:function(a){if(!a.controls&&(a.controls=this.closest(a,".form-control"),this.queuedInputErrorText)){var b=this.queuedInputErrorText;delete this.queuedInputErrorText,this.addInputError(a,b)}},addInputError:function(a,b){return a.controls?(a.errmsg?a.errmsg.style.display="":(a.errmsg=document.createElement("div"),a.errmsg.classList.add("ui-state-error"),a.controls.appendChild(a.errmsg)),void(a.errmsg.textContent=b)):void(this.queuedInputErrorText=b)},removeInputError:function(a){a.controls||delete this.queuedInputErrorText,a.errmsg&&(a.errmsg.style.display="none")},markTabActive:function(a){a.tab.classList.remove("ui-widget-header"),a.tab.classList.add("ui-state-active"),"undefined"!=typeof a.rowPane?a.rowPane.style.display="":a.container.style.display=""},markTabInactive:function(a){a.tab.classList.add("ui-widget-header"),a.tab.classList.remove("ui-state-active"),"undefined"!=typeof a.rowPane?a.rowPane.style.display="none":a.container.style.display="none"}}),h.defaults.themes.barebones=h.AbstractTheme.extend({getFormInputLabel:function(a){var b=this._super(a);return b},getFormInputDescription:function(a){var b=this._super(a);return b},getIndentedPanel:function(){var a=this._super();return a},getChildEditorHolder:function(){var a=this._super();return a},getHeaderButtonHolder:function(){var a=this.getButtonHolder();return a},getTable:function(){var a=this._super();return a},addInputError:function(a,b){if(a.errmsg)a.errmsg.style.display="block";else{var c=this.closest(a,".form-control");a.errmsg=document.createElement("div"),a.errmsg.setAttribute("class","errmsg"),c.appendChild(a.errmsg)}a.errmsg.innerHTML="",a.errmsg.appendChild(document.createTextNode(b))},removeInputError:function(a){a.style.borderColor="",a.errmsg&&(a.errmsg.style.display="none")},getProgressBar:function(){var a=100,b=0,c=document.createElement("progress");return c.setAttribute("max",a),c.setAttribute("value",b),c},updateProgressBar:function(a,b){a&&a.setAttribute("value",b)},updateProgressBarUnknown:function(a){a&&a.removeAttribute("value")}}),h.defaults.themes.materialize=h.AbstractTheme.extend({setGridColumnSize:function(a,b){a.classList.add("col"),a.classList.add("s"+b)},getHeaderButtonHolder:function(){return this.getButtonHolder()},getButtonHolder:function(){return document.createElement("span")},getButton:function(a,b,c){a&&(b.classList.add("left"),b.style.marginRight="5px");var d=this._super(a,b,c);return d.classList.add("waves-effect","waves-light","btn"),d.style.fontSize="0.75rem",d.style.height="24px",d.style.lineHeight="24px",d.style.marginLeft="5px",d.style.padding="0 0.5rem",d},getFormControl:function(a,b,c,d){var e,f=b.type;if(f&&"checkbox"===f){if(e=document.createElement("p"),a){var g=document.createElement("span");g.innerHTML=a.innerHTML,a.innerHTML="",a.setAttribute("for",b.id),e.appendChild(a),a.appendChild(b),a.appendChild(g)}else e.appendChild(b);return e}return e=this._super(a,b,c,d),f&&f.startsWith("select")||e.classList.add("input-field"),f&&"color"===f&&(b.style.height="3rem",b.style.width="100%",b.style.margin="5px 0 20px 0",b.style.padding="3px",a&&(a.style.transform="translateY(-14px) scale(0.8)",a.style["-webkit-transform"]="translateY(-14px) scale(0.8)",a.style["-webkit-transform-origin"]="0 0",a.style["transform-origin"]="0 0")),e},getDescription:function(a){var b=document.createElement("div");return b.classList.add("grey-text"),b.style.marginTop="-15px",b.innerHTML=a,b},getHeader:function(a){var b=document.createElement("h5");return"string"==typeof a?b.textContent=a:b.appendChild(a),b},getChildEditorHolder:function(){var a=document.createElement("div");return a.marginBottom="10px",a},getIndentedPanel:function(){var a=document.createElement("div");return a.classList.add("card-panel"),a},getTable:function(){var a=document.createElement("table");return a.classList.add("striped","bordered"),a.style.marginBottom="10px",a},getTableRow:function(){return document.createElement("tr")},getTableHead:function(){return document.createElement("thead")},getTableBody:function(){return document.createElement("tbody")},getTableHeaderCell:function(a){var b=document.createElement("th");return b.textContent=a,b},getTableCell:function(){var a=document.createElement("td");return a},getTabHolder:function(){var a=['<div class="col s2">','   <ul class="tabs" style="height: auto; margin-top: 0.82rem; -ms-flex-direction: column; -webkit-flex-direction: column; flex-direction: column; display: -webkit-flex; display: flex;">',"   </ul>","</div>",'<div class="col s10">',"<div>"].join("\n"),b=document.createElement("div");return b.classList.add("row","card-panel"),b.innerHTML=a,b},addTab:function(a,b){a.children[0].children[0].appendChild(b)},getTab:function(a){var b=document.createElement("li");return b.classList.add("tab"),b.style=b.style||{},this.applyStyles(b,{width:"100%",textAlign:"left",lineHeight:"24px",height:"24px",fontSize:"14px",cursor:"pointer"}),b.appendChild(a),b},markTabActive:function(a){a.style=a.style||{},this.applyStyles(a,{width:"100%",textAlign:"left",lineHeight:"24px",height:"24px",fontSize:"14px",cursor:"pointer",color:"rgba(238,110,115,1)",transition:"border-color .5s ease",borderRight:"3px solid #424242"})},markTabInactive:function(a){a.style=a.style||{},this.applyStyles(a,{width:"100%",textAlign:"left",lineHeight:"24px",height:"24px",fontSize:"14px",cursor:"pointer",color:"rgba(238,110,115,0.7)"})},getTabContentHolder:function(a){return a.children[1]},getTabContent:function(){return document.createElement("div")},addInputError:function(a,b){var c,d=a.parentNode;d&&(this.removeInputError(a),c=document.createElement("div"),c.classList.add("error-text","red-text"),c.textContent=b,d.appendChild(c))},removeInputError:function(a){var b,c=a.parentElement;if(c){b=c.getElementsByClassName("error-text");for(var d=0;d<b.length;d++)c.removeChild(b[d])}},addTableRowError:function(a){},removeTableRowError:function(a){},getSelectInput:function(a){var b=this._super(a);return b.classList.add("browser-default"),b},getTextareaInput:function(){var a=document.createElement("textarea");return a.style.marginBottom="5px",a.style.fontSize="1rem",a.style.fontFamily="monospace",a},getCheckbox:function(){var a=this.getFormInputField("checkbox");return a.id=this.createUuid(),a},getModal:function(){var a=document.createElement("div");return a.classList.add("card-panel","z-depth-3"),a.style.padding="5px",a.style.position="absolute",a.style.zIndex="10",a.style.display="none",a},createUuid:function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(a){var b=16*Math.random()|0,c="x"==a?b:3&b|8;return c.toString(16)})}}),h.AbstractIconLib=c.extend({mapping:{collapse:"",expand:"","delete":"",edit:"",add:"",cancel:"",save:"",moveup:"",movedown:""},icon_prefix:"",getIconClass:function(a){return this.mapping[a]?this.icon_prefix+this.mapping[a]:null},getIcon:function(a){var b=this.getIconClass(a);if(!b)return null;var c=document.createElement("i");return c.classList.add.apply(c.classList,b.split(" ")),c}}),h.defaults.iconlibs.bootstrap2=h.AbstractIconLib.extend({mapping:{collapse:"chevron-down",expand:"chevron-up","delete":"trash",edit:"pencil",add:"plus",cancel:"ban-circle",save:"ok",moveup:"arrow-up",movedown:"arrow-down",clear:"remove-circle",time:"time",calendar:"calendar"},icon_prefix:"icon-"}),h.defaults.iconlibs.bootstrap3=h.AbstractIconLib.extend({mapping:{collapse:"chevron-down",expand:"chevron-right","delete":"remove",edit:"pencil",add:"plus",cancel:"floppy-remove",save:"floppy-saved",moveup:"arrow-up",movedown:"arrow-down",clear:"remove-circle",time:"time",calendar:"calendar"},icon_prefix:"glyphicon glyphicon-"}),h.defaults.iconlibs.fontawesome3=h.AbstractIconLib.extend({mapping:{collapse:"chevron-down",expand:"chevron-right","delete":"remove",edit:"pencil",add:"plus",cancel:"ban-circle",save:"save",moveup:"arrow-up",movedown:"arrow-down",clear:"remove-circle",time:"time",calendar:"calendar"},icon_prefix:"icon-"}),h.defaults.iconlibs.fontawesome4=h.AbstractIconLib.extend({mapping:{collapse:"caret-square-o-down",expand:"caret-square-o-right","delete":"times",edit:"pencil",add:"plus",cancel:"ban",save:"save",moveup:"arrow-up",movedown:"arrow-down",copy:"files-o",clear:"times-circle-o",time:"clock-o",calendar:"calendar"},icon_prefix:"fa fa-"}),h.defaults.iconlibs.fontawesome5=h.AbstractIconLib.extend({mapping:{collapse:"caret-down",expand:"caret-right","delete":"times",edit:"pen",add:"plus",cancel:"ban",save:"save",moveup:"arrow-up",movedown:"arrow-down",copy:"copy",clear:"times-circle",time:"clock",calendar:"calendar"},icon_prefix:"fas fa-"}),h.defaults.iconlibs.foundation2=h.AbstractIconLib.extend({mapping:{collapse:"minus",expand:"plus","delete":"remove",edit:"edit",add:"add-doc",cancel:"error",save:"checkmark",moveup:"up-arrow",movedown:"down-arrow",clear:"remove",time:"clock",calendar:"calendar"},icon_prefix:"foundicon-"}),h.defaults.iconlibs.foundation3=h.AbstractIconLib.extend({mapping:{collapse:"minus",expand:"plus","delete":"x",edit:"pencil",add:"page-add",cancel:"x-circle",save:"save",moveup:"arrow-up",movedown:"arrow-down",clear:"x-circle",time:"clock",calendar:"calendar"},icon_prefix:"fi-"}),h.defaults.iconlibs.jqueryui=h.AbstractIconLib.extend({mapping:{collapse:"triangle-1-s",expand:"triangle-1-e","delete":"trash",edit:"pencil",add:"plusthick",cancel:"closethick",save:"disk",moveup:"arrowthick-1-n",movedown:"arrowthick-1-s",clear:"circle-close",time:"time",calendar:"calendar"},icon_prefix:"ui-icon ui-icon-"}),h.defaults.iconlibs.materialicons=h.AbstractIconLib.extend({mapping:{collapse:"arrow_drop_up",expand:"arrow_drop_down","delete":"delete",edit:"edit",add:"add",cancel:"cancel",save:"save",moveup:"arrow_upward",movedown:"arrow_downward",copy:"content_copy",clear:"highlight_off",time:"access_time",calendar:"calendar_today",upload:"cloud_upload"},icon_class:"material-icons",icon_prefix:"",getIconClass:function(a){return this.icon_class},getIcon:function(a){var b=this.mapping[a];if(!b)return null;var c=document.createElement("i");c.classList.add(this.icon_class);var d=document.createTextNode(b);return c.appendChild(d),c}}),h.defaults.templates["default"]=function(){return{compile:function(a){var b=a.match(/{{\s*([a-zA-Z0-9\-_ \.]+)\s*}}/g),c=b&&b.length;if(!c)return function(){return a};for(var d=[],e=function(a){var c,e=b[a].replace(/[{}]+/g,"").trim().split("."),f=e.length;if(f>1){var g;c=function(b){for(g=b,a=0;a<f&&(g=g[e[a]],g);a++);return g}}else e=e[0],c=function(a){return a[e]};d.push({s:b[a],r:c})},f=0;f<c;f++)e(f);return function(b){var e,g=a+"";for(f=0;f<c;f++)e=d[f],g=g.replace(e.s,e.r(b));return g}}}},h.defaults.templates.ejs=function(){return!!window.EJS&&{compile:function(a){var b=new window.EJS({text:a});return function(a){return b.render(a)}}}},h.defaults.templates.handlebars=function(){return window.Handlebars},h.defaults.templates.hogan=function(){return!!window.Hogan&&{compile:function(a){var b=window.Hogan.compile(a);return function(a){return b.render(a)}}}},h.defaults.templates.lodash=function(){return!!window._&&{compile:function(a){return function(b){return window._.template(a)(b)}}}},h.defaults.templates.markup=function(){return!(!window.Mark||!window.Mark.up)&&{compile:function(a){return function(b){return window.Mark.up(a,b)}}}},h.defaults.templates.mustache=function(){return!!window.Mustache&&{compile:function(a){return function(b){return window.Mustache.render(a,b)}}}},h.defaults.templates.swig=function(){return window.swig},h.defaults.templates.underscore=function(){
+return!!window._&&{compile:function(a){return function(b){return window._.template(a,b)}}}},h.defaults.theme="html",h.defaults.template="default",h.defaults.options={},h.defaults.options.prompt_before_delete=!0,h.defaults.options.upload=function(a,b,c){console.log("Upload handler required for upload editor")},h.defaults.translate=function(a,b){var c=h.defaults.languages[h.defaults.language];if(!c)throw"Unknown language "+h.defaults.language;var d=c[a]||h.defaults.languages[h.defaults.default_language][a];if("undefined"==typeof d)throw"Unknown translate string "+a;if(b)for(var e=0;e<b.length;e++)d=d.replace(new RegExp("\\{\\{"+e+"}}","g"),b[e]);return d},h.defaults.default_language="en",h.defaults.language=h.defaults.default_language,h.defaults.languages.en={error_notset:"Property must be set",error_notempty:"Value required",error_enum:"Value must be one of the enumerated values",error_anyOf:"Value must validate against at least one of the provided schemas",error_oneOf:"Value must validate against exactly one of the provided schemas. It currently validates against {{0}} of the schemas.",error_not:"Value must not validate against the provided schema",error_type_union:"Value must be one of the provided types",error_type:"Value must be of type {{0}}",error_disallow_union:"Value must not be one of the provided disallowed types",error_disallow:"Value must not be of type {{0}}",error_multipleOf:"Value must be a multiple of {{0}}",error_maximum_excl:"Value must be less than {{0}}",error_maximum_incl:"Value must be at most {{0}}",error_minimum_excl:"Value must be greater than {{0}}",error_minimum_incl:"Value must be at least {{0}}",error_maxLength:"Value must be at most {{0}} characters long",error_minLength:"Value must be at least {{0}} characters long",error_pattern:"Value must match the pattern {{0}}",error_additionalItems:"No additional items allowed in this array",error_maxItems:"Value must have at most {{0}} items",error_minItems:"Value must have at least {{0}} items",error_uniqueItems:"Array must have unique items",error_maxProperties:"Object must have at most {{0}} properties",error_minProperties:"Object must have at least {{0}} properties",error_required:"Object is missing the required property '{{0}}'",error_additional_properties:"No additional properties allowed, but property {{0}} is set",error_dependency:"Must have property {{0}}",error_date:"Date must be in the format {{0}}",error_time:"Time must be in the format {{0}}",error_datetime_local:"Datetime must be in the format {{0}}",error_invalid_epoch:"Date must be greater than 1 January 1970",button_delete_all:"All",button_delete_all_title:"Delete All",button_delete_last:"Last {{0}}",button_delete_last_title:"Delete Last {{0}}",button_add_row_title:"Add {{0}}",button_move_down_title:"Move down",button_move_up_title:"Move up",button_delete_row_title:"Delete {{0}}",button_delete_row_title_short:"Delete",button_collapse:"Collapse",button_expand:"Expand",flatpickr_toggle_button:"Toggle",flatpickr_clear_button:"Clear"},h.plugins={ace:{theme:""},SimpleMDE:{},sceditor:{},select2:{},selectize:{}},f(h.defaults.editors,function(a,b){h.defaults.editors[a].options=b.options||{}}),h.defaults.resolvers.unshift(function(a){if("string"!=typeof a.type)return"multiple"}),h.defaults.resolvers.unshift(function(a){if(!a.type&&a.properties)return"object"}),h.defaults.resolvers.unshift(function(a){if("string"==typeof a.type)return a.type}),h.defaults.resolvers.unshift(function(a){if("string"===a.type&&"signature"===a.format)return"signature"}),h.defaults.resolvers.unshift(function(a){if("integer"===a.type&&"rating"===a.format)return"rating"}),h.defaults.resolvers.unshift(function(a){if("boolean"===a.type)return"checkbox"===a.format||a.options&&a.options.checkbox?"checkbox":h.plugins.selectize.enable?"selectize":"select"}),h.defaults.resolvers.unshift(function(a){if("any"===a.type)return"multiple"}),h.defaults.resolvers.unshift(function(a){if("string"===a.type&&a.media&&"base64"===a.media.binaryEncoding)return"base64"}),h.defaults.resolvers.unshift(function(a){if("string"===a.type&&"url"===a.format&&a.options&&a.options.upload===!0&&window.FileReader)return"upload"}),h.defaults.resolvers.unshift(function(a){if("array"===a.type&&"table"===a.format)return"table"}),h.defaults.resolvers.unshift(function(a){if(a.enumSource)return h.plugins.selectize.enable?"selectize":"select"}),h.defaults.resolvers.unshift(function(a){if(a["enum"]){if("array"===a.type||"object"===a.type)return"enum";if("number"===a.type||"integer"===a.type||"string"===a.type)return h.plugins.selectize.enable?"selectize":"select"}}),h.defaults.resolvers.unshift(function(a){if("array"===a.type&&a.items&&!Array.isArray(a.items)&&a.uniqueItems&&["string","number","integer"].indexOf(a.items.type)>=0){if(a.items["enum"])return"multiselect";if(h.plugins.selectize.enable&&"string"===a.items.type)return"arraySelectize"}}),h.defaults.resolvers.unshift(function(a){if(a.oneOf||a.anyOf)return"multiple"}),h.defaults.resolvers.unshift(function(a){if(["string","integer"].indexOf(a.type)!==-1&&["date","time","datetime-local"].indexOf(a.format)!==-1)return"datetime"}),h.defaults.resolvers.unshift(function(a){if("string"===a.type&&"starrating"===a.format)return"starrating"}),function(){if(window.jQuery||window.Zepto){var a=window.jQuery||window.Zepto;a.jsoneditor=h.defaults,a.fn.jsoneditor=function(a){var b=this,c=this.data("jsoneditor");if("value"===a){if(!c)throw"Must initialize jsoneditor before getting/setting the value";if(!(arguments.length>1))return c.getValue();c.setValue(arguments[1])}else{if("validate"===a){if(!c)throw"Must initialize jsoneditor before validating";return arguments.length>1?c.validate(arguments[1]):c.validate()}"destroy"===a?c&&(c.destroy(),this.data("jsoneditor",null)):(c&&c.destroy(),c=new h(this.get(0),a),this.data("jsoneditor",c),c.on("change",function(){b.trigger("change")}),c.on("ready",function(){b.trigger("ready")}))}return this}}}(),h});
+//# sourceMappingURL=jsoneditor.min.js.map
\ No newline at end of file
index 6255698..203b3cd 100644 (file)
@@ -311,7 +311,6 @@ label {
        </div>
 
        <div attribute-test="policywindowpropertiesf" class="modal-footer">
-               <!--<button ng-click="reset()" class="btn btn-primary" style="float:left">Reset</button>-->
                <button id="savePropsBtn" class="btn btn-primary">Close</button>
                <button ng-click="close(true)" id="close_button"
                        class="btn btn-primary">Cancel</button>
index 97b26de..7943f72 100644 (file)
@@ -305,7 +305,7 @@ app.directive('expandable', function ($compile) {
 });
 
 
-app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','dialogs', '$filter','Datafactory','soapRequestService', function($scope,$rootScope, $location,dialogs,$filter,Datafactory,soapRequestService){
+app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','dialogs', '$filter','Datafactory', function($scope,$rootScope, $location,dialogs,$filter,Datafactory){
        
        
        $scope.count=0;
@@ -385,7 +385,7 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
                }
        };
        
-       //Functionality for Hierarchical Elements
+       // Functionality for Hierarchical Elements
        $scope.addHierarchicalElement1 = function(schemaElement, parentElement, elementKey, index){
         console.log("addHeirarchicalElement1");
                if($rootScope.isHorR){
@@ -396,7 +396,8 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
                if($scope.clonedSchemaElement.repeatableHierarchicalPrefix == null)
                        $scope.clonedSchemaElement.repeatableHierarchicalPrefix = "";
                
-               //Remove any Heirarchical/Repeatable Elements in the ClonedSchemaElement
+               // Remove any Heirarchical/Repeatable Elements in the
+               // ClonedSchemaElement
                for(var i=0;i<schemaElement.type.elements.length;i++) {
                        if(schemaElement.type.elements[i].element.name.indexOf(schemaElement.element.name) != -1) {
                                $scope.clonedSchemaElement.type.elements.splice(i,(schemaElement.type.elements.length-i));
@@ -410,7 +411,7 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
                
        }
        
-       //Functionality for Hierarchical Elements
+       // Functionality for Hierarchical Elements
        $scope.addHierarchicalElement = function(schemaElement, parentElement, elementKey){
         console.log("addHierarchicalElement");
                $rootScope.isHorR = false;
@@ -420,7 +421,8 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
                if($scope.clonedSchemaElement.repeatableHierarchicalPrefix == null)
                        $scope.clonedSchemaElement.repeatableHierarchicalPrefix = "";
                
-               //Remove any Heirarchical/Repeatable Elements in the ClonedSchemaElement
+               // Remove any Heirarchical/Repeatable Elements in the
+               // ClonedSchemaElement
                for(var i=0;i<schemaElement.type.elements.length;i++) {
                        if(schemaElement.type.elements[i].element.name.indexOf(schemaElement.element.name) != -1) {
                                $scope.clonedSchemaElement.type.elements.splice(i,(schemaElement.type.elements.length-i));
@@ -578,7 +580,8 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
                if($scope.clonedSchemaElement.repeatableHierarchicalPrefix == null)
                        $scope.clonedSchemaElement.repeatableHierarchicalPrefix = "";
                
-               //Remove any Heirarchical/Repeatable Elements in the ClonedSchemaElement
+               // Remove any Heirarchical/Repeatable Elements in the
+               // ClonedSchemaElement
                if(schemaElement.type.complexType != null){
                for(var i=0;i<schemaElement.type.elements.length;i++) {
                        if(schemaElement.type.elements[i].element.name.indexOf(schemaElement.element.name) != -1) {
@@ -598,7 +601,8 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
                if(schemaElement.type.complexType != null){
                        for(var i=0;i<$scope.childElements.length;i++){
                                if(angular.equals($scope.childElements[i],schemaElement)){      
-                                       //console.log("Complex Element List Match :" +$scope.childElements[i]);
+                                       // console.log("Complex Element List Match :"
+                                       // +$scope.childElements[i]);
                                        $scope.childElements.splice((i+1),0,$scope.clonedSchemaElement);
                                        break;
                                }
@@ -606,7 +610,8 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
                } else if(schemaElement.element.name !=null) {                  
                        for(var j=0;j<$scope.childElements.length;j++){
                                if(angular.equals($scope.childElements[j],schemaElement)){                              
-                                       //console.log("Element List Match :" +$scope.childElements[j]);                            
+                                       // console.log("Element List Match :"
+                                       // +$scope.childElements[j]);
                                        $scope.childElements.splice((j+1),0,$scope.clonedSchemaElement);                          
                                        break;
                                }
@@ -671,7 +676,8 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
                if(schemaElement.type.complexType != null){
                        for(var i=0;i<$scope.childElements.length;i++){
                                if(angular.equals($scope.childElements[i],schemaElement)){      
-                                       //console.log("Complex Element List Match :" +$scope.childElements[i]);
+                                       // console.log("Complex Element List Match :"
+                                       // +$scope.childElements[i]);
                                        $scope.childElements.splice(i,1);
                                        $scope.index =i;
                                        break;
@@ -680,7 +686,8 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
                } else if(schemaElement.element.name !=null) {                  
                        for(var j=0;j<$scope.childElements.length;j++){
                                if(angular.equals($scope.childElements[j],schemaElement)){                              
-                                       //console.log("Element List Match :" +$scope.childElements[j]);                            
+                                       // console.log("Element List Match :"
+                                       // +$scope.childElements[j]);
                                        $scope.childElements.splice(j,1);       
                                        $scope.index= j;
                                        break;
@@ -746,83 +753,6 @@ app.controller('ActivityModellingCtrl', ['$scope', '$rootScope', '$location','di
                }
                
        };
-       
-       
-       
-       //Tst functions
-       
-       
-       //Generate and Download tst
-       $scope.generateTST = function(index){
-               console.log("generateTST");
-               Datafactory.setSelectedTestCase($rootScope.modeltestset.activityTestCases[index]);
-               
-               var tstInput={};
-               console.log("inside generateTST() method");
-               var generateTSTUrl ="/utm-service/soa_integration/generateTST";
-               var tempActivityTestcase= {};
-               angular.copy(Datafactory.getSelectedTestCase(),tempActivityTestcase);
-               
-               tstInput.activityTestCase = tempActivityTestcase;
-               
-               if(tstInput.activityTestCase.version != null){
-                       var newTestCaseName = tstInput.activityTestCase.testCaseName + "_"+ tstInput.activityTestCase.version;
-                       tstInput.activityTestCase.testCaseName = newTestCaseName;
-                       
-               }
-                       
-               tstInput.projectPreferenceInfo =  Datafactory.getProjectPreferenceInfo();
-               tstInput.environmentData =  $rootScope.environmentData;
-               tstInput.writeFileToolList=Datafactory.getWriteFileDataList();
-               tstInput.fileStreamWriterList=Datafactory.getFileStreamWriterList();
-               tstInput.commonPythonScriptList = Datafactory.getCommonPythonScriptList();
-               
-               
-               soapRequestService.generateTst(tstInput, generateTSTUrl)
-               .then(function(pars) {
-            console.log("pars");
-                       
-                       
-                       var dlg = dialogs.confirm('Message','Do you want to download TST file?');
-                       dlg.result.then(function(btn){
-                console.log("btn");
-                       $scope.confirmed = 'You confirmed "Yes."';
-                       var downloadTSTUrl ="/utm-service/soa_integration/downloadTST";
-                       
-                       soapRequestService.downloadTst(pars, tstInput.activityTestCase.testCaseName, downloadTSTUrl)
-                       .then(function(results) {
-                console.log("results");
-                               
-                               var sets=results.data;
-                        console.log("Sets value"+sets);            
-                    var headerValue=results.headers;
-                    
-                    var fileName=results.config.data.tstName + ".tst";
-                    console.log("Filename "+fileName);
-                    
-                    var hiddenElement = document.createElement('a');
-                    var objectUrl = URL.createObjectURL(results.data);
-                               
-                            hiddenElement.href = objectUrl;
-                                hiddenElement.download = fileName;
-                                
-                        hiddenElement.target = '_blank';
-                        document.body.appendChild(hiddenElement);
-                        hiddenElement.click(); 
-                        document.body.removeChild(hiddenElement);
-                        
-                       });
-                       },function(btn){
-                console.log("btn");
-                       $scope.confirmed = 'You confirmed "No."';
-                       });
-                       
-               },
-               function(data) {
-            console.log("data");
 
-               });
-               
-               
-       }
+
 }]);
\ No newline at end of file
diff --git a/src/main/resources/META-INF/resources/designer/scripts/ExportFileCtrl.js b/src/main/resources/META-INF/resources/designer/scripts/ExportFileCtrl.js
deleted file mode 100644 (file)
index 3de9d34..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
- *                             reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- * 
- */
-app.controller('exportCtrl', [ '$scope', '$rootScope', 'exportService',
-'dialogs', function($scope, $rootScope, exportService, dialogs) {
-       console.log("exportCtrl");
-} ]);
diff --git a/src/main/resources/META-INF/resources/designer/scripts/ExportFileService.js b/src/main/resources/META-INF/resources/designer/scripts/ExportFileService.js
deleted file mode 100644 (file)
index e2474aa..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
- *                             reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- * 
- */
-app.service('exportService', [
-'$http',
-'$q',
-function($http, $q) {
-       console.log("/////////exportService");
-       this.exportToUrl = function(testsetValue, formatValue, exporturl) {
-               console.log("exportToUrl");
-               var def = $q.defer();
-               var sets = [];
-               var testExportRequest = {
-               testSet : testsetValue,
-               format : formatValue
-               };
-               if (angular.equals(formatValue, "Excel")) {
-                       $http({
-                       url : exporturl,
-                       method : "POST",
-                       data : testExportRequest, // this is your json data string
-                                                                               // headers: {
-                       responseType : 'arraybuffer'
-                       }).success(function(data, status, headers, config) {
-                               console.log("success");
-                               /*
-                                * sets = data; def.resolve(data);
-                                */
-                               var results = [];
-                               results.data = data;
-                               results.headers = headers();
-                               results.status = status;
-                               results.config = config;
-                               def.resolve(results);
-                       }).error(function(data) {
-                               console.log("data");
-                               def.reject("Export file not successful");
-                       });
-               } else {
-                       $http.post(exporturl, testExportRequest).success(
-                       function(data, status, headers, config) {
-                               console.log("function");
-                               var results = [];
-                               results.data = data;
-                               results.headers = headers();
-                               results.status = status;
-                               results.config = config;
-                               def.resolve(results);
-                               // alert("Data in success without scope and q_def for scope
-                               // parametes :: " + parameters);'Content-type':
-                               // 'application/json',
-                       }).error(function(data) {
-                               console.log("data");
-                               // alert("Data in error :: " + data);
-                               def.reject("Export file not successful");
-                       });
-               }
-               return def.promise;
-       };
-} ]);
diff --git a/src/main/resources/META-INF/resources/designer/scripts/FileUploadCtrl.js b/src/main/resources/META-INF/resources/designer/scripts/FileUploadCtrl.js
deleted file mode 100644 (file)
index 9efbc49..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
- *                             reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- * 
- */
-app
-.controller(
-'fileUploadCtrl',
-[
-'$scope',
-'$rootScope',
-'fileUpload',
-function($scope, $rootScope, fileUpload) {
-       console.log("///////////fileUploadCtrl");
-       $rootScope.isAllOption = false;
-       // -----For Required Radio button functionality
-       $scope.requiredonly = function() {
-               console.log("requiredonly");
-               // var tempArray = $rootScope.SUT;
-               // var tempParam = tempArray.parameters;
-               // alert("testParam.length:"+tempParam.length);
-               var parameter = $scope.parArray;
-               var param = $scope.parameters;
-               var i = 0;
-               $('.req').each(function() {
-                       console.log(".req");
-                       var newID = 'requiredval' + i;
-                       // jQuery(this).prev("req").attr("requiredval", "newID");
-                       // $(this).attr("requiredval","newID");
-                       // var newval=$(this).val(newID);
-                       var newval = $(this).attr('id', newID);
-                       console.log("Angular id: " + newval);
-                       if (i < param.length) {
-                               document.getElementById(newID).disabled = false;
-                               if (parameter[i]) {
-                                       param[i].required = parameter[i];
-                                       // document.getElementById(newID).disabled=true;
-                                       document.getElementById(newID).checked = true;
-                               } else {
-                                       param[i].required = parameter[i];
-                                       // document.getElementById(newID).disabled=false;
-                                       document.getElementById(newID).checked = false;
-                               }
-                       }
-                       i++;
-               });
-       };
-       $scope.allrequired = function() {
-               console.log("allrequired");
-               var param = $scope.parameters;
-               var i = 0;
-               $('.req').each(function() {
-                       console.log("req");
-                       var newID = 'requiredval' + i;
-                       // jQuery(this).prev("req").attr("requiredval", "newID");
-                       // $(this).attr("requiredval","newID");
-                       // var newval=$(this).val(newID);
-                       var newval = $(this).attr('id', newID);
-                       console.log("Angular id: " + newval);
-                       if (i < param.length) {
-                               param[i].required = true;
-                               document.getElementById(newID).checked = true;
-                               document.getElementById(newID).disabled = true;
-                       }
-                       i++;
-               });
-       };
-       $scope.uploadSUTFile = function(element) {
-               console.log("uploadSUTFile");
-               $scope
-               .$apply(function($scope) {
-                       console.log("apply");
-                       $rootScope.isAllOption = false;
-                       $rootScope.isStatic = true;
-                       $scope.requiredval = false;
-                       $rootScope.rightTabName = "UTM Build Configuration";
-                       $rootScope.testSet = null;
-                       if ($rootScope.isStatic == true) {
-                               document.getElementById('buidConfigBtn').style.visibility = "hidden";
-                       }
-                       var file = element.files[0];/* $scope.requestFile; */
-                       console.log('file is ' + JSON.stringify(file));
-                       $rootScope.file_type = "SUT";
-                       var uploadUrl = "/utm-service/sut_upload/uploadSUT";
-                       fileUpload.uploadFileToUrl(file, uploadUrl).then(function(pars) {
-                               console.log("uploadFileToUrl");
-                               $rootScope.SUT = pars;
-                               console.log("file name :" + pars.name);
-                               $scope.fileName = pars.name;
-                               $scope.parameters = pars.parameters;
-                               $scope.constraints = pars.constraints;
-                               $scope.relations = pars.relations;
-                               var con = $scope.constraints;
-                       }, function(data) {
-                               console.log("data");
-                               // alert("File upload failed and parameters not returned");
-                       });
-                       angular.forEach(angular.element("input[type='file']"),
-                       function(inputElem) {
-                               console.log("inputElem");
-                               angular.element(inputElem).val(null);
-                       });
-               });
-       };
-       $scope.buildConfig = function() {
-               console.log("buildConfig");
-               $rootScope.isStatic = true;
-               $rootScope.rightTabName = "UTM Build Configuration";
-               document.getElementById('buidConfigBtn').style.visibility = "hidden";
-               $rootScope.testset = null;
-       };
-       /*
-        * $scope.close = function(){ $modalInstance.close('closed'); };
-        * 
-        * $scope.importSchema= function(){ var file = $scope.requestFile;
-        * console.log('file is ' + JSON.stringify(file)); var uploadUrl =
-        * "/utm-service/schema_upload/uploadSchema";
-        * fileUpload.uploadFileToUrl(file, uploadUrl) .then(function(pars) {
-        * $rootScope.SUT = pars; console.log("file name :"+pars.name);
-        * $scope.fileName = pars.name; $scope.parameters = pars.parameters; var
-        * param = pars.parameters; }, function(data) { //alert("File upload failed
-        * and parameters not returned"); });
-        * 
-        *  };
-        */
-} ]);
-function clearFileInput(id) {
-       console.log("clearFileInput");
-       var oldInput = document.getElementById(id);
-       var newInput = document.createElement("input");
-       newInput.type = "file";
-       newInput.id = oldInput.id;
-       newInput.name = oldInput.name;
-       newInput.className = oldInput.className;
-       newInput.style.cssText = oldInput.style.cssText;
-       // TODO: copy any other relevant attributes
-       oldInput.parentNode.replaceChild(newInput, oldInput);
-}
diff --git a/src/main/resources/META-INF/resources/designer/scripts/FileUploadService.js b/src/main/resources/META-INF/resources/designer/scripts/FileUploadService.js
deleted file mode 100644 (file)
index d1826a9..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
- *                             reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- * 
- */
-app.directive('fileModel', [ '$parse', function($parse) {
-       console.log("////////fileModel");
-       return {
-       restrict : 'A',
-       link : function(scope, element, attrs) {
-               console.log("link");
-               var model = $parse(attrs.fileModel);
-               // alert("uploadFileToUrl directive model :: " + model);
-               var modelSetter = model.assign;
-               element.bind('change', function() {
-                       console.log("change");
-                       scope.$apply(function() {
-                               console.log("apply");
-                               modelSetter(scope, element[0].files[0]);
-                       });
-               });
-       }
-       };
-} ]);
-app.service('fileUpload', [ '$http', '$q', function($http, $q) {
-       console.log("fileUpload");
-       this.uploadFileToUrl = function(file, uploadUrl) {
-               console.log("uploadFileToUrl");
-               var def = $q.defer();
-               var pars = [];
-               var fd = new FormData();
-               fd.append('requestFile', file);
-               $http.post(uploadUrl, fd, {
-               transformRequest : angular.identity,
-               headers : {
-                       'Content-Type' : undefined
-               }
-               }).success(function(data) {
-                       console.log("success");
-                       pars = data;
-                       def.resolve(data);
-               }).error(function(data) {
-                       console.log("error");
-                       def.reject("Upload file not successful");
-               });
-               return def.promise;
-       };
-       this.uploadFile = function(path, inputFile, uploadURL) {
-               console.log("uploadFile");
-               var def = $q.defer();
-               var pars = [];
-               var fd = new FormData();
-               fd.append('requestFile', inputFile);
-               fd.append('path', path)
-               $http.post(uploadURL, fd, {
-               transformRequest : angular.identity,
-               headers : {
-                       'Content-Type' : undefined
-               }
-               }).success(function(data) {
-                       console.log("success");
-                       pars = data;
-                       def.resolve(data);
-               }).error(function(data) {
-                       console.log("error");
-                       def.reject("Upload file not successful");
-               });
-               return def.promise;
-       };
-} ]);
\ No newline at end of file
diff --git a/src/main/resources/META-INF/resources/designer/scripts/ImportSchemaCtrl.js b/src/main/resources/META-INF/resources/designer/scripts/ImportSchemaCtrl.js
deleted file mode 100644 (file)
index e2f1913..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
- *                             reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- * 
- */
-app
-.controller(
-'ImportSchemaCtrl',
-[
-'$scope',
-'$rootScope',
-'$uibModalInstance',
-'data',
-'svnservice',
-'fileUpload',
-'dialogs',
-function($scope, $rootScope, $uibModalInstance, data, svnservice, fileUpload,
-         dialogs) {
-       console.log("//////ImportSchemaCtrl");
-       $rootScope.serviceInfo;
-       $rootScope.serviceInput;
-       $rootScope.serviceOutput;
-       $rootScope.serviceFault;
-       $rootScope.serviceInputPartInfo;
-       $rootScope.schemElemant1;
-       $rootScope.updateServiceInfo;
-       $rootScope.updateServiceInput;
-       $rootScope.updateServiceOutput;
-       $rootScope.updateServiceFault;
-       $rootScope.updateServiceInputPartInfo;
-       $rootScope.updateSchemElemant1;
-       // Below code is added to get the policyNames
-       var policies = getOperationalPolicyProperty();
-       for ( var obj in policies) {
-                       if (!($.isEmptyObject(obj))) {
-                               allPolicies = jQuery.extend({}, obj);
-                               $scope.policyNames = [];
-                               for ( var policy in allPolicies) {
-                                       $scope.policyNames.push(policy);
-                               }
-                       }
-       }
-       setTimeout(function() {
-               console.log("setTimeout");
-               setMultiSelect();
-       }, 100);
-       $scope.close = function() {
-               console.log("close");
-               $uibModalInstance.close("closed");
-       };
-       $rootScope.file_path;
-       $scope.importSchema = function() {
-               console.log("importSchema");
-               isImportSchema = true;
-               var file = $rootScope.file_path;
-               // alert("file:"+schemaFile);
-               // console.log('file is ' + JSON.stringify(file));
-               var userID = document.getElementById("userID").value;
-               var password = document.getElementById("password").value;
-               var svnURL = document.getElementById("schemaLocation").value;
-               var schemaLocation = document.getElementById("schemaLocation").value;
-               if (schemaLocation && userID && password
-               && document.getElementById("schemaLocation").disabled == false) {
-                       $scope.schemaLocation = schemaLocation;
-                       $scope.userID = userID;
-                       $scope.password = password;
-                       document.getElementById("fileUpload").disabled = true;
-                       var svnUploadURL = "/utm-service/schema_upload/svnUploadWSDL";
-                       svnservice
-                       .SVNToUrl(schemaLocation, userID, password, svnURL, svnUploadURL)
-                       .then(
-                       function(pars) {
-                               console.log("pars");
-                               document.getElementById('Upgrade Schema Version').classList
-                               .remove('ThisLink');
-                               document.getElementById('Set Default Values').classList
-                               .remove('ThisLink');
-                               $rootScope.wsdlInfo = angular.fromJson(pars);
-                               $rootScope.serviceInfo = $rootScope.wsdlInfo.serviceInfo;
-                               serviceName = $rootScope.serviceInfo.service.name;
-                               $rootScope.schemaLocation = $rootScope.wsdlInfo.schemaLocation;
-                               $rootScope.serviceInput = $rootScope.serviceInfo.bindingInfo.portTypeInfo.operationInfo[0].inputMessage;
-                               $rootScope.serviceInputPartInfo = $rootScope.serviceInfo.bindingInfo.portTypeInfo.operationInfo[0].inputMessage.partInfo;
-                               $rootScope.serviceOutput = $rootScope.serviceInfo.bindingInfo.portTypeInfo.operationInfo[0].outputMessage;
-                               $rootScope.serviceOutputPartInfo = $rootScope.serviceInfo.bindingInfo.portTypeInfo.operationInfo[0].outputMessage.partInfo;
-                               $rootScope.servicefault = $rootScope.serviceInfo.bindingInfo.portTypeInfo.operationInfo[0].faultMessage;
-                               $rootScope.servicefaultPartInfo = $rootScope.serviceInfo.bindingInfo.portTypeInfo.operationInfo[0].faultMessage.partInfo;
-                               // alert("serviceInputPartInfo :: " +
-                               // JSON.stringify($rootScope.serviceInputPartInfo));
-                               $rootScope.inputSchemaServiceInputPartInfo = [];
-                               $rootScope.inputSchemaServiceOutputPartInfo = [];
-                               $rootScope.inputSchemaServicefaultPartInfo = [];
-                               angular.copy($rootScope.serviceInputPartInfo,
-                               $rootScope.inputSchemaServiceInputPartInfo);
-                               angular.copy($rootScope.serviceOutputPartInfo,
-                               $rootScope.inputSchemaServiceOutputPartInfo);
-                               angular.copy($rootScope.servicefaultPartInfo,
-                               $rootScope.inputSchemaServicefaultPartInfo);
-                               $rootScope.isModel = true;
-                       }, function(data) {
-                               console.log("data");
-                               // alert("File upload failed and parameters not returned");
-                       });
-               } else {
-                       var uploadUrl = "/utm-service/schema_upload/uploadWSDL";
-                       fileUpload
-                       .uploadFileToUrl(file, uploadUrl)
-                       .then(
-                       function(pars) {
-                               console.log("pars");
-                               document.getElementById('Upgrade Schema Version').classList
-                               .remove('ThisLink');
-                               document.getElementById('Set Default Values').classList
-                               .remove('ThisLink');
-                               // document.getElementById('Define/Modify
-                               // Schema').classList.remove('ThisLink');
-                               $rootScope.wsdlInfo = angular.fromJson(pars);
-                               $rootScope.serviceInfo = $rootScope.wsdlInfo.serviceInfo;
-                               serviceName = $rootScope.serviceInfo.service.name;
-                               $rootScope.serviceInput = $rootScope.serviceInfo.bindingInfo.portTypeInfo.operationInfo[0].inputMessage;
-                               $rootScope.serviceInputPartInfo = $rootScope.serviceInfo.bindingInfo.portTypeInfo.operationInfo[0].inputMessage.partInfo;
-                               // alert("Input Part Info :: " +
-                               // JSON.stringify($rootScope.serviceInputPartInfo));
-                               // alert("Input Part 1 Info :: " +
-                               // JSON.stringify($rootScope.serviceInputPartInfo[1]));
-                               // alert("Input Element :: " +
-                               // JSON.stringify($rootScope.serviceInputPartInfo[1].schemaElements[1].elements[0]));
-                               $rootScope.serviceOutput = $rootScope.serviceInfo.bindingInfo.portTypeInfo.operationInfo[0].outputMessage;
-                               $rootScope.serviceOutputPartInfo = $rootScope.serviceInfo.bindingInfo.portTypeInfo.operationInfo[0].outputMessage.partInfo;
-                               $rootScope.servicefault = $rootScope.serviceInfo.bindingInfo.portTypeInfo.operationInfo[0].faultMessage;
-                               $rootScope.servicefaultPartInfo = $rootScope.serviceInfo.bindingInfo.portTypeInfo.operationInfo[0].faultMessage.partInfo;
-                               // alert("servicefaultPartInfo :: " +
-                               // JSON.stringify($rootScope.servicefaultPartInfo));
-                               $rootScope.inputSchemaServiceInputPartInfo = [];
-                               $rootScope.inputSchemaServiceOutputPartInfo = [];
-                               $rootScope.inputSchemaServicefaultPartInfo = [];
-                               angular.copy($rootScope.serviceInputPartInfo,
-                               $rootScope.inputSchemaServiceInputPartInfo);
-                               angular.copy($rootScope.serviceOutputPartInfo,
-                               $rootScope.inputSchemaServiceOutputPartInfo);
-                               angular.copy($rootScope.servicefaultPartInfo,
-                               $rootScope.inputSchemaServicefaultPartInfo);
-                               $rootScope.isModel = true;
-                       }, function(data) {
-                               console.log("data");
-                       });
-               }
-               $uibModalInstance.close("closed");
-       };
-       $scope.setFile = function(element) {
-               console.log("setFile");
-               $scope.$apply(function($scope) {
-                       console.log("apply");
-                       $scope.theFile = element.files[0];
-                       $rootScope.fileName = $scope.theFile.name;
-                       var file = element.files[0];
-                       $rootScope.file_path = file;
-                       // $uibModalInstance.close("closed");
-                       angular.element(document.getElementById('fileUpload')).val(null);
-               });
-       };
-       $scope.setUpgradeFile = function(element) {
-               console.log("setUpgradeFile");
-               $scope.$apply(function($scope) {
-                       console.log("apply");
-                       $scope.theUpgradeFile = element.files[0];
-                       $rootScope.upgradeFileName = $scope.theUpgradeFile.name;
-                       // alert("fname1"+$rootScope.upgradeFileName);
-                       var file = element.files[0];
-                       $rootScope.file_path = file;
-                       // $uibModalInstance.close("closed");
-                       angular.element(document.getElementById('fileUpload')).val(null);
-               });
-       };
-       $scope.reset = function() {
-               console.log("reset");
-               document.getElementById("fileUpload").disabled = false;
-               document.getElementById("schemaLocation").disabled = false;
-               document.getElementById("userID").disabled = false;
-               document.getElementById("password").disabled = false;
-               document.getElementById("schemaLocation").value = '';
-               document.getElementById("userID").value = '';
-               document.getElementById("password").value = '';
-               $scope.theFile = null;
-               angular.element(document.getElementById('fileUpload')).val(null);
-       };
-       $scope.upgradeSchema = function() {
-               console.log("upgradeSchema");
-               // alert("inside upgrade schema");
-               var file = $rootScope.file_path;
-               // alert("file:"+schemaFile);
-               // console.log('file is ' + JSON.stringify(file));
-               var userID = document.getElementById("userID").value;
-               var password = document.getElementById("password").value;
-               var schemaLocation = document.getElementById("upgradeSchemaLocation").value;
-               var svnURL = document.getElementById("upgradeSchemaLocation").value;
-               console.log("after");
-               $rootScope.Currentmappedvalues = [];
-               if (schemaLocation && userID && password
-               && document.getElementById("upgradeSchemaLocation").disabled == false) {
-                       $scope.schemaLocation = schemaLocation;
-                       $scope.userID = userID;
-                       $scope.password = password;
-                       document.getElementById("fileUpload").disabled = true;
-                       var svnUploadURL = "/utm-service/schema_upload/svnUploadWSDL";
-                       svnservice
-                       .SVNToUrl(schemaLocation, userID, password, svnURL, svnUploadURL)
-                       .then(
-                       function(pars) {
-                               console.log("pars");
-                               $rootScope.updateWsdlInfo = angular.fromJson(pars);
-                               $rootScope.updateServiceInfo = $rootScope.updateWsdlInfo.serviceInfo;
-                               $rootScope.schemaLocation = $rootScope.updateWsdlInfo.schemaLocation;
-                               $rootScope.updateServiceInput = $rootScope.updateServiceInfo.bindingInfo.portTypeInfo.operationInfo[0].inputMessage;
-                               $rootScope.updateServiceInputPartInfo = $rootScope.updateServiceInfo.bindingInfo.portTypeInfo.operationInfo[0].inputMessage.partInfo;
-                               $rootScope.updateServiceOutput = $rootScope.updateServiceInfo.bindingInfo.portTypeInfo.operationInfo[0].outputMessage;
-                               $rootScope.updateServiceOutputPartInfo = $rootScope.updateServiceInfo.bindingInfo.portTypeInfo.operationInfo[0].outputMessage.partInfo;
-                               $rootScope.updateServicefault = $rootScope.updateServiceInfo.bindingInfo.portTypeInfo.operationInfo[0].faultMessage;
-                               $rootScope.updateServicefaultPartInfo = $rootScope.updateServiceInfo.bindingInfo.portTypeInfo.operationInfo[0].faultMessage.partInfo;
-                               // alert("serviceInputPartInfo :: " +
-                               // JSON.stringify($rootScope.serviceInputPartInfo));
-                               // $rootScope.isModel = true;
-                       }, function(data) {
-                               console.log("data");
-                               // alert("File upload failed and parameters not returned");
-                       });
-               } else {
-                       var uploadUrl = "/utm-service/schema_upload/uploadWSDL";
-                       fileUpload
-                       .uploadFileToUrl(file, uploadUrl)
-                       .then(
-                       function(pars) {
-                               console.log("pars");
-                               $rootScope.updateWsdlInfo = angular.fromJson(pars);
-                               // alert("wsdlinfo:"+$rootScope.updateWsdlInfo);
-                               $rootScope.updateServiceInfo = $rootScope.updateWsdlInfo.serviceInfo;
-                               $rootScope.updateServiceInput = $rootScope.updateServiceInfo.bindingInfo.portTypeInfo.operationInfo[0].inputMessage;
-                               $rootScope.updateServiceInputPartInfo = $rootScope.updateServiceInfo.bindingInfo.portTypeInfo.operationInfo[0].inputMessage.partInfo;
-                               $rootScope.updateServiceOutput = $rootScope.updateServiceInfo.bindingInfo.portTypeInfo.operationInfo[0].outputMessage;
-                               $rootScope.updateServiceOutputPartInfo = $rootScope.updateServiceInfo.bindingInfo.portTypeInfo.operationInfo[0].outputMessage.partInfo;
-                               $rootScope.updateServicefault = $rootScope.updateServiceInfo.bindingInfo.portTypeInfo.operationInfo[0].faultMessage;
-                               $rootScope.updateServicefaultPartInfo = $rootScope.updateServiceInfo.bindingInfo.portTypeInfo.operationInfo[0].faultMessage.partInfo;
-                               // alert("servicefaultPartInfo :: " +
-                               // JSON.stringify($rootScope.servicefaultPartInfo));
-                               // $rootScope.isModel = true;
-                       }, function(data) {
-                               console.log("data");
-                       });
-               }
-               $uibModalInstance.close("closed");
-               var dlg = dialogs.create(
-               'partials/portfolios/upgrade_schema_dtls.html', 'UpgradeSchemaCtrl',
-               {}, {
-               size : 'xlg',
-               keyboard : true,
-               backdrop : true,
-               windowClass : 'my-class'
-               });
-               dlg.result.then(function(name) {
-                       console.log("dlg.result");
-                       // $scope.name = name;
-               }, function() {
-                       // if(angular.equals($scope.name,''))
-                       // $scope.name = 'You did not enter in your name!';
-               });
-       };
-
-       $scope.submitForm = function(obj) {
-               var operationalPolicies = JSON.parse(JSON.stringify(getOperationalPolicies()));
-               if (obj !== null) {
-                       operationalPolicies[0]["configurationsJson"] = obj;
-               }
-               svnservice.saveOpPolicyProperties(operationalPolicies).then(function(pars) {
-                       updateOpPolicyProperties(operationalPolicies);
-               }, function(data) {
-               });
-     };
-
-} ]);
\ No newline at end of file
diff --git a/src/main/resources/META-INF/resources/designer/scripts/OperationalPolicyCtrl.js b/src/main/resources/META-INF/resources/designer/scripts/OperationalPolicyCtrl.js
new file mode 100644 (file)
index 0000000..d1f3e0c
--- /dev/null
@@ -0,0 +1,79 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ *                             reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ * 
+ */
+app
+.controller(
+'operationalPolicyCtrl',
+[
+'$scope',
+'$rootScope',
+'$uibModalInstance',
+'data',
+'operationalPolicyService',
+'dialogs',
+function($scope, $rootScope, $uibModalInstance, data, operationalPolicyService, 
+         dialogs) {
+       console.log("//////operationalPolicyCtrl");
+       $rootScope.serviceInfo;
+       $rootScope.serviceInput;
+       $rootScope.serviceOutput;
+       $rootScope.serviceFault;
+       $rootScope.serviceInputPartInfo;
+       $rootScope.schemElemant1;
+       $rootScope.updateServiceInfo;
+       $rootScope.updateServiceInput;
+       $rootScope.updateServiceOutput;
+       $rootScope.updateServiceFault;
+       $rootScope.updateServiceInputPartInfo;
+       $rootScope.updateSchemElemant1;
+       // Below code is added to get the policyNames
+       var policies = getOperationalPolicyProperty();
+       for ( var obj in policies) {
+                       if (!($.isEmptyObject(obj))) {
+                               allPolicies = jQuery.extend({}, obj);
+                               $scope.policyNames = [];
+                               for ( var policy in allPolicies) {
+                                       $scope.policyNames.push(policy);
+                               }
+                       }
+       }
+       setTimeout(function() {
+               console.log("setTimeout");
+               setMultiSelect();
+       }, 100);
+       $scope.close = function() {
+               console.log("close");
+               $uibModalInstance.close("closed");
+       };
+
+       $scope.submitForm = function(obj) {
+               var operationalPolicies = JSON.parse(JSON.stringify(getOperationalPolicies()));
+               if (obj !== null) {
+                       operationalPolicies[0]["configurationsJson"] = obj;
+               }
+               operationalPolicyService.saveOpPolicyProperties(operationalPolicies).then(function(pars) {
+                       updateOpPolicyProperties(operationalPolicies);
+               }, function(data) {
+               });
+     };
+
+} ]);
\ No newline at end of file
  * ===================================================================
  * 
  */
-app.service('svnservice', ['$http', '$q', function ($http, $q) {
-    console.log("//////svnservice");
-    this.SVNToUrl = function(schemaLocation, userID, password,svnURL,svnUploadURL){
-        console.log("SVNToUrl");
-       
-       
-       var def = $q.defer();
-       var sets = [];
-       
-        var svnRequest = {schemaLocation: schemaLocation, userID: userID, password: password,svnURL:svnURL};
-        
-       
-        $http.post(svnUploadURL, svnRequest)
-        .success(function(data){  
-        console.log("success");        
-               pars = data;
-               def.resolve(data);              
-               
-        })
-        .error(function(data){  
-        console.log("error");                        
-                       def.reject("SVN Import not successful");
-        });
-        
-        return def.promise;
-    };
+app.service('operationalPolicyService', ['$http', '$q', function ($http, $q) {
+    console.log("//////OperationalPolicyService");
     
        this.saveOpPolicyProperties = function(form) {
                var modelName = getLoopName();
index 129c5d9..1901d95 100644 (file)
@@ -36,11 +36,11 @@ app.controller('ToscaModelCtrl',
                                }
                                var editorData = getMsProperty(selectedPolicy);
 
-                               JSONEditor.defaults.options.theme = 'bootstrap3';
-                               JSONEditor.defaults.options.iconlib = 'bootstrap2';
+                               JSONEditor.defaults.options.theme = 'bootstrap4';
+                               //JSONEditor.defaults.options.iconlib = 'bootstrap2';
                                JSONEditor.defaults.options.object_layout = 'grid';
                                JSONEditor.defaults.options.disable_properties = true;
-                               JSONEditor.defaults.options.disable_edit_json = true;
+                               JSONEditor.defaults.options.disable_edit_json = false;
                                JSONEditor.defaults.options.disable_array_reorder = true;
                                JSONEditor.defaults.options.disable_array_delete_last_row = true;
                                JSONEditor.defaults.options.disable_array_delete_all_rows = false;
diff --git a/src/main/resources/META-INF/resources/designer/scripts/UpgradeSchemaCtrl.js b/src/main/resources/META-INF/resources/designer/scripts/UpgradeSchemaCtrl.js
deleted file mode 100644 (file)
index db8b126..0000000
+++ /dev/null
@@ -1,479 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
- *                             reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- * 
- */
-var elementKeys = [];
-app
-.directive(
-'inputInfoUpgradeClass',
-function($compile) {
-       console.log("////UpgradeSchemaCtrl");
-       return {
-       restrict : "C",
-       replace : true,
-       link : function(scope, element, attrs) {
-               var elementHTML = '';
-               angular
-               .forEach(
-               scope.infoType.schemaElements,
-               function(value, key) {
-                       scope.schemaElement = value;
-                       if (scope.schemaElement.complexType != null) {
-                               if (scope.currentElementName == '') {
-                                       scope.currentElementName = scope.schemaElement.complexType.name;
-                               }
-                               scope.ParentKey = scope.parentName + '_'
-                               + scope.currentElementName;
-                               if (scope.schemaElement.repeatableHierarchicalPrefix != null) {
-                                       scope.ParentKey = scope.ParentKey
-                                       + scope.schemaElement.repeatableHierarchicalPrefix;
-                               }
-                               scope.parElement = scope.schemaElement;
-                               scope.tableStyle = 'table-level' + scope.heirarchyLevel
-                               + '-tree';
-                               scope.tdLabelStyle = 'td-level' + scope.heirarchyLevel
-                               + '-label-tree';
-                               scope.heirLevel = scope.heirarchyLevel;
-                               elementHTML = elementHTML
-                               + '<div ng-show="schemaElement.complexType != null">';
-                               elementHTML = elementHTML
-                               + '<table class="{{tableStyle}}"> <tr>';
-                               elementHTML = elementHTML + '<td class="{{tdLabelStyle}}">';
-                               elementHTML = elementHTML
-                               + '<span class="pull-left" ng-click="showUTMViewMsgHeader=!showUTMViewMsgHeader">';
-                               elementHTML = elementHTML
-                               + '<i ng-class="showUTMViewMsgHeader == true ?\'fa fa-plus-circle\':\'fa fa-minus-circle\'"></i>';
-                               elementHTML = elementHTML + '</span>';
-                               elementHTML = elementHTML + '<b>{{currentElementName}}</b>';
-                               elementHTML = elementHTML + '</td>';
-                               elementHTML = elementHTML + '<td class="td-tree"></td>';
-                               elementHTML = elementHTML
-                               + '<td class="td-default_value-tree"> </td>';
-                               elementHTML = elementHTML + '</tr></table>';
-                               elementHTML = elementHTML
-                               + '<div style="margin-left: 10px" ng-class="{hidden:showUTMViewMsgHeader,chaldean:showUTMViewMsgHeader}">';
-                               elementHTML = elementHTML
-                               + '<div class="inputInfoUpgradeClassMember" style="margin-left: 10px" ng-repeat="schemaElement in schemaElement.elements"></div>';
-                               elementHTML = elementHTML + '</div>';
-                               elementHTML = elementHTML + '</div>';
-                               var x = angular.element(elementHTML);
-                               element.append(x);
-                               $compile(x)(scope);
-                       }
-               });
-       }
-       }
-});
-app
-.directive(
-'inputInfoUpgradeClassMember',
-function($compile) {
-       return {
-       restrict : "C",
-       link : function(scope, element, attrs) {
-               var elementHTML = '';
-               scope.currentElementName = scope.objectName;
-               scope.parentName = scope.ParentKey;
-               scope.parentElement = scope.parElement;
-               scope.heirarchyLevel = scope.heirLevel + 1;
-               if (scope.schemaElement.element.name != null) {
-                       scope.elementKey = scope.parentName + '_'
-                       + scope.schemaElement.element.name;
-                       if (scope.schemaElement.repeatableHierarchicalPrefix != null) {
-                               scope.elementKey = scope.elementKey
-                               + scope.schemaElement.repeatableHierarchicalPrefix;
-                       }
-                       scope.tableStyle = 'table-level' + scope.heirarchyLevel + '-tree';
-                       scope.tdLabelStyle = 'td-level' + scope.heirarchyLevel
-                       + '-label-tree';
-                       if (scope.schemaElement.type.complexType != null) {
-                               scope.showUTMViewMsgHeader = false;
-                       } else {
-                               scope.showUTMViewMsgHeader = true;
-                       }
-                       elementHTML = elementHTML
-                       + '<div ng-show="schemaElement.element.name != null">';
-                       elementHTML = elementHTML + '<table class="{{tableStyle}}"> ';
-                       elementHTML = elementHTML + '<tr>';
-                       elementHTML = elementHTML
-                       + '<td style="text-align: left;vertical-align: top;" class="{{tdLabelStyle}}">';
-                       elementHTML = elementHTML
-                       + '<span class="pull-left" ng-click="showUTMViewMsgHeader=!showUTMViewMsgHeader">';
-                       elementHTML = elementHTML + '<div style="display:inline">';
-                       elementHTML = elementHTML
-                       + '<input type="radio" name={{radioName}} id="{{elementKey}}" value={{schemaElement.element.name}}>';
-                       elementHTML = elementHTML + '</div>';
-                       elementHTML = elementHTML
-                       + '<i expandable ng-class="showUTMViewMsgHeader == true ?\'fa fa-minus-circle\':\'fa fa-plus-circle\'"></i>';
-                       elementHTML = elementHTML + '{{schemaElement.element.name}}  ';
-                       elementHTML = elementHTML + '';
-                       elementHTML = elementHTML + '';
-                       elementHTML = elementHTML + '';
-                       elementHTML = elementHTML + '';
-                       elementHTML = elementHTML + '</span>';
-                       elementHTML = elementHTML
-                       + '<div ng-init="complexMapElements(elementKey,schemaElement,radioName)"></div>';
-                       elementHTML = elementHTML + '</td>';
-                       elementHTML = elementHTML + '</tr>';
-                       elementHTML = elementHTML + '</table>';
-                       elementHTML = elementHTML + '';
-                       elementHTML = elementHTML + '';
-                       elementHTML = elementHTML + '</div>';
-                       var x = angular.element(elementHTML);
-                       element.append(x);
-                       $compile(x)(scope);
-                       if (scope.schemaElement.type.complexType != null) {
-                               var elementHTML2 = '<div ng-show="schemaElement.type.complexType != null">'
-                               elementHTML2 = elementHTML2
-                               + '<div ng-init="parKey=parentName + \'_\' + schemaElement.element.name + (schemaElement.repeatableHierarchicalPrefix != null ? schemaElement.repeatableHierarchicalPrefix : \'\'); heirLevel=heirarchyLevel; parElement=schemaElement; ParentKey=ParentKey+\'_\'+schemaElement.element.name + (schemaElement.repeatableHierarchicalPrefix != null ? schemaElement.repeatableHierarchicalPrefix : \'\')">'
-                               elementHTML2 = elementHTML2
-                               + '<div style="margin-left: 10px" ng-class="{hidden:!showUTMViewMsgHeader,chaldean:!showUTMViewMsgHeader}">'
-                               elementHTML2 = elementHTML2
-                               + '<div class="{{sourceExplorer+\'_\'+parKey}}"></div>'
-                               elementHTML2 = elementHTML2 + '</div>'
-                               elementHTML2 = elementHTML2 + '</div>'
-                               elementHTML2 = elementHTML2 + '</div>';
-                               var x = angular.element(elementHTML2);
-                               element.append(x);
-                               $compile(x)(scope);
-                       }
-               }
-       }
-       }
-});
-app
-.controller(
-'UpgradeSchemaCtrl',
-[
-'$scope',
-'$rootScope',
-'$uibModalInstance',
-'dialogs',
-function($scope, $rootScope, $uibModalInstance, dialogs) {
-       $rootScope.Currentmappedvalues = [];
-       $scope.utmSchemaExts = {};
-       $scope.callFromMap = false;
-       $scope.oldMapValFlag = false;
-       $scope.complexMappedValuesOld = {};
-       $scope.complexMappedValuesNew = {};
-       var allCurrentElementKeyArray = [];
-       $scope.checkedValues = {};
-       var checkedElementValueArray = [];
-       $scope.complexMapElements = function(elementKey, schemaElement, radioName) {
-               if (schemaElement.complexType != null
-               || (schemaElement.type != null && schemaElement.type.complexType != null)) {
-                       if (radioName == "oldChk")
-                               $scope.complexMappedValuesOld[elementKey] = schemaElement;
-                       else if (radioName == "newChk")
-                               $scope.complexMappedValuesNew[elementKey] = schemaElement;
-               }
-               if (elementKey != null)
-                       allCurrentElementKeyArray.push(elementKey);
-       };
-       $scope.mapElements = function() {
-               var oldVal = $('input[name=oldChk]:checked').val();
-               var newVal = $('input[name=newChk]:checked').val();
-               var oldId = $('input[name=oldChk]:checked').attr('id');
-               var newId = $('input[name=newChk]:checked').attr('id');
-               $scope.mappedvalues = {};
-               $scope.checkedValues.oldVal = oldVal;
-               $scope.checkedValues.newVal = newVal;
-               checkedElementValueArray.push($scope.checkedValues);
-               $scope.oldMappedvaluesKeyArray = [];
-               $scope.newMappedvaluesKeyArray = [];
-               $scope.oldmappedvaluesArray = [];
-               $scope.newMappedvaluesArray = [];
-               if ($scope.complexMappedValuesOld[oldId] != null
-               && $scope.complexMappedValuesNew[newId] != null) {
-                       $scope.matchType = '';
-                       $scope.matchType = $scope.compareElements(
-                       $scope.complexMappedValuesOld[oldId],
-                       $scope.complexMappedValuesNew[newId]);
-                       if ($scope.matchType == "true") {
-                               console
-                               .log("Element Type Matches and eligible for upgrade schema");
-                               $scope.callFromMap = true;
-                               for (var i = 0; i < $scope.complexMappedValuesOld[oldId].type.elements.length; i++) {
-                                       $scope.oldMapValFlag = true;
-                                       getElementkeys(oldId,
-                                       $scope.complexMappedValuesOld[oldId].type.elements[i]);
-                               }
-                               for (var j = 0; j < $scope.complexMappedValuesNew[newId].type.elements.length; j++) {
-                                       $scope.oldMapValFlag = false;
-                                       getElementkeys(newId,
-                                       $scope.complexMappedValuesNew[newId].type.elements[j]);
-                               }
-                               for (var k = 0; k < $scope.oldmappedvaluesArray.length; k++) {
-                                       $scope.mappedvalues = {};
-                                       $scope.mappedvalues.oldvalue = $scope.oldmappedvaluesArray[k];
-                                       $scope.mappedvalues.newvalue = $scope.newMappedvaluesArray[k];
-                                       $scope.mappedvalues.oldidvalue = $scope.oldMappedvaluesKeyArray[k];
-                                       $scope.mappedvalues.newidvalue = $scope.newMappedvaluesKeyArray[k];
-                                       $rootScope.Currentmappedvalues.push($scope.mappedvalues);
-                               }
-                       } else if ($scope.matchType == "false") {
-                               dialogs
-                               .error(
-                               'Invalid Selection Error',
-                               'The mapping of the selected elements is invalid. Please select valid complex elements for Upgrade Schema');
-                       }
-               } else if (($scope.complexMappedValuesOld[oldId] == null && $scope.complexMappedValuesNew[newId] != null)
-               || ($scope.complexMappedValuesOld[oldId] != null && $scope.complexMappedValuesNew[newId] == null)) {
-                       dialogs
-                       .error(
-                       'Invalid Selection Error',
-                       'The mapping of the selected elements is invalid. Please select valid complex elements for Upgrade Schema');
-               } else {
-                       $scope.mappedvalues.oldvalue = oldVal;
-                       $scope.mappedvalues.newvalue = newVal;
-                       $scope.mappedvalues.oldidvalue = oldId;
-                       $scope.mappedvalues.newidvalue = newId;
-                       $rootScope.Currentmappedvalues.push($scope.mappedvalues);
-               }
-               $rootScope.checkRepeatable = false;
-       };
-       // Utility Method to compare Object Structure of Complex Type Elements
-       // before upgrade schema
-       $scope.compareElements = function(oldElement, newElement) {
-               if (oldElement.type.complexType != null
-               && newElement.type.complexType != null) {
-                       if (oldElement.type.elements.length == newElement.type.elements.length) {
-                               for (var i = 0; i < oldElement.type.elements.length; i++) {
-                                       if (oldElement.type.elements[i].type.complexType != null
-                                       && newElement.type.elements[i].type.complexType != null) {
-                                               $scope.compareElements(oldElement.type.elements[i],
-                                               newElement.type.elements[i]);
-                                       } else if (oldElement.type.elements[i].type.complexType == null
-                                       && newElement.type.elements[i].type.complexType != null) {
-                                               $scope.matchType = "false";
-                                               return $scope.matchType;
-                                       }
-                                       if ($scope.matchType == "false")
-                                               return $scope.matchType;
-                               }
-                               for (var i = 0; i < newElement.type.elements.length; i++) {
-                                       if (newElement.type.elements[i].type.complexType != null
-                                       && oldElement.type.elements[i].type.complexType != null) {
-                                               $scope.compareElements(newElement.type.elements[i],
-                                               oldElement.type.elements[i]);
-                                       } else if (newElement.type.elements[i].type.complexType == null
-                                       && oldElement.type.elements[i].type.complexType != null) {
-                                               $scope.matchType = "false";
-                                               return $scope.matchType;
-                                       }
-                                       if ($scope.matchType == "false")
-                                               return $scope.matchType;
-                               }
-                               $scope.matchType = "true";
-                               return $scope.matchType;
-                       } else
-                               $scope.matchType = "false";
-                       return $scope.matchType;
-               }
-       };
-       $scope.checkRepeatableElement = function(elementKey, key) {
-               if (elementKey != key)
-                       $rootScope.checkRepeatable = true;
-       };
-       $scope.upgradeSchema = function() {
-               // console.log("List Model Path Details before Upgrade Schema :: " +
-               // JSON.stringify(list_model_path_details[selected_model]));
-               $scope.callFromMap = false;
-               $rootScope.isHorR = true;
-               $rootScope.repeatableHeirarchicalElementMap = map_model_repeatable_heirarchical_elements[selected_model];
-               // Checking Repeatable Hierarchical elements mapping and changing
-               // elementkey if repeatable hierarchical is mapped
-               for ( var key in $rootScope.repeatableHeirarchicalElementMap) {
-                       for (var i = 0; i < allCurrentElementKeyArray.length; i++) {
-                               if (allCurrentElementKeyArray[i].indexOf(key) > -1)
-                                       elementKeys.push(allCurrentElementKeyArray[i]);
-                       }
-                       for (var j = 0; j < checkedElementValueArray.length; j++) {
-                               var currentCheckedMappedvalue = checkedElementValueArray[j];
-                               if (key.indexOf(currentCheckedMappedvalue.oldVal) > -1) {
-                                       var newObject = JSON
-                                       .stringify($rootScope.repeatableHeirarchicalElementMap);
-                                       var oldvalue = currentCheckedMappedvalue.oldVal;
-                                       var newvalue = currentCheckedMappedvalue.newVal;
-                                       var modObject = newObject.replace(oldvalue, newvalue);
-                                       $rootScope.repeatableHeirarchicalElementMap = angular
-                                       .fromJson(modObject);
-                               }
-                       }
-               }
-               $scope.oldSchemaLocation = $rootScope.wsdlInfo.schemaLocation;
-               $rootScope.wsdlInfo = $rootScope.updateWsdlInfo;
-               $rootScope.wsdlInfo.schemaUpgradedFlag = true;
-               $rootScope.wsdlInfo.oldSchemaLocation = $scope.oldSchemaLocation;
-               $rootScope.serviceInfo = $rootScope.updateServiceInfo;
-               $rootScope.schemaLocation = $rootScope.updateWsdlInfo.schemaLocation;
-               $rootScope.serviceInput = $rootScope.updateServiceInput;
-               $rootScope.serviceInputPartInfo = $rootScope.updateServiceInputPartInfo;
-               $rootScope.inputSchemaServiceInputPartInfo = [];
-               $rootScope.inputSchemaServiceOutputPartInfo = [];
-               $rootScope.inputSchemaServicefaultPartInfo = [];
-               angular.copy($rootScope.serviceInputPartInfo,
-               $rootScope.inputSchemaServiceInputPartInfo);
-               angular.copy($rootScope.serviceOutputPartInfo,
-               $rootScope.inputSchemaServiceOutputPartInfo);
-               angular.copy($rootScope.servicefaultPartInfo,
-               $rootScope.inputSchemaServicefaultPartInfo);
-               // Form all the element keys of the Upgraded Schema so that to know the
-               // attibutes removed
-               for (var i = 0; i < $rootScope.serviceInputPartInfo.length; i++) {
-                       for (var j = 0; j < $rootScope.serviceInputPartInfo[i].schemaElements.length; j++) {
-                               getElementkeys('ServiceInput',
-                               $rootScope.serviceInputPartInfo[i].schemaElements[j]);
-                       }
-               }
-               $rootScope.serviceOutput = $rootScope.updateServiceOutput;
-               $rootScope.serviceOutputPartInfo = $rootScope.updateServiceOutputPartInfo;
-               for (var i = 0; i < $rootScope.serviceOutputPartInfo.length; i++) {
-                       for (var j = 0; j < $rootScope.serviceOutputPartInfo[i].schemaElements.length; j++) {
-                               getElementkeys('ServiceOutput',
-                               $rootScope.serviceOutputPartInfo[i].schemaElements[j]);
-                       }
-               }
-               $rootScope.servicefault = $rootScope.updateServicefault;
-               $rootScope.servicefaultPartInfo = $rootScope.updateServicefaultPartInfo;
-               for (var i = 0; i < $rootScope.servicefaultPartInfo.length; i++) {
-                       for (var j = 0; j < $rootScope.servicefaultPartInfo[i].schemaElements.length; j++) {
-                               getElementkeys('ServiceFault',
-                               $rootScope.servicefaultPartInfo[i].schemaElements[j]);
-                       }
-               }
-               console.log("mapped values of current"
-               + JSON.stringify($rootScope.Currentmappedvalues));
-               // For each model in the project
-               // a) For the mapped elements
-               // i) replace the old ids with new ids for the Schema Extensions
-               // ii) replace the old ids with new ids for the Path Details
-               // b) For the deleted attributes in the Upgraded schema
-               // i) Remove the ids from Schema Extensions
-               // ii) Remove the ids from Path Details
-               for (var modelIndex = 0; modelIndex < $rootScope.models.length; modelIndex++) {
-                       var current_model = $rootScope.models[modelIndex];
-                       $scope.utmSchemaExts = list_model_schema_extensions[current_model].utmSchemaExtentionMap;
-                       $scope.pathDetailsArray = list_model_path_details[current_model];
-                       for (var i = 0; i < $rootScope.Currentmappedvalues.length; i++) {
-                               $scope.mappedvalues = $rootScope.Currentmappedvalues[i];
-                               if ($scope.utmSchemaExts != null) {
-                                       $scope.utmSchemaExts[$scope.mappedvalues.newidvalue] = $scope.utmSchemaExts[$scope.mappedvalues.oldidvalue];
-                                       if ($scope.mappedvalues.newidvalue != $scope.mappedvalues.oldidvalue)
-                                               delete $scope.utmSchemaExts[$scope.mappedvalues.oldidvalue];
-                               }
-                               if ($scope.pathDetailsArray != null
-                               && $scope.pathDetailsArray.length > 0) {
-                                       for (var k = 0; k < $scope.pathDetailsArray.length; k++) {
-                                               $scope.pathDetails = $scope.pathDetailsArray[k];
-                                               if ($scope.pathDetails != null) {
-                                                       for (var j = 0; j < $scope.pathDetails.decisionIdentifiers.length; j++) {
-                                                               if ($scope.pathDetails.decisionIdentifiers[j].elementValues[$scope.mappedvalues.oldidvalue] != null)
-                                                                       $scope.pathDetails.decisionIdentifiers[j].elementValues[$scope.mappedvalues.newidvalue] = $scope.pathDetails.decisionIdentifiers[j].elementValues[$scope.mappedvalues.oldidvalue];
-                                                               if ($scope.mappedvalues.newidvalue != $scope.mappedvalues.oldidvalue)
-                                                                       delete $scope.pathDetails.decisionIdentifiers[j].elementValues[$scope.mappedvalues.oldidvalue];
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-                       $scope.schemenExts = angular.copy($scope.utmSchemaExts);
-                       // If an attribute is removed from upgraded schema, remove that
-                       // attribute related details from SchemaExtensions
-                       Object.keys($scope.schemenExts).forEach(function(key) {
-                               var key_isavailable = false;
-                               for (var j = 0; j < elementKeys.length; j++) {
-                                       if (elementKeys[j] === key) {
-                                               key_isavailable = true;
-                                       }
-                               }
-                               if (!key_isavailable) {
-                                       // Implement this later. Commented this as this is wiping
-                                       // out all the Repeatable/Heirarchical values
-                                       // delete $scope.utmSchemaExts[key];
-                               }
-                       });
-                       // If an attribute is removed from upgraded schema, remove that
-                       // attribute related details from PathDetails
-                       if ($scope.pathDetailsArray != null
-                       && $scope.pathDetailsArray.length > 0) {
-                               for (var k = 0; k < $scope.pathDetailsArray.length; k++) {
-                                       $scope.pathDetails = $scope.pathDetailsArray[k];
-                                       for (var j = 0; j < $scope.pathDetails.decisionIdentifiers.length; j++) {
-                                               $scope.decisionElementValues = angular
-                                               .copy($scope.pathDetails.decisionIdentifiers[j].elementValues);
-                                               Object.keys($scope.decisionElementValues).forEach(
-                                               function(key) {
-                                                       var key_isavailable = false;
-                                                       for (var l = 0; l < elementKeys.length; l++) {
-                                                               if (elementKeys[l] === key) {
-                                                                       key_isavailable = true;
-                                                               }
-                                                       }
-                                                       if (!key_isavailable) {
-                                                               // Implement this later. Commented this as this
-                                                               // is wiping out all the Repeatable/Heirarchical
-                                                               // values
-                                                               // delete
-                                                               // $scope.pathDetails.decisionIdentifiers[j].elementValues[key];
-                                                       }
-                                               });
-                                       }
-                               }
-                       }
-               }
-               $uibModalInstance.close("closed");
-       };
-       $scope.close = function() {
-               $uibModalInstance.close("closed");
-       };
-       function getElementkeys(parentname, schemaelement) {
-               if (schemaelement.complexType != null) {
-                       var parentkey = parentname + "_" + schemaelement.complexType.name;
-                       for (var i = 0; i < schemaelement.elements.length; i++) {
-                               getElementkeys(parentkey, schemaelement.elements[i]);
-                       }
-               }
-               if (schemaelement.element != null && schemaelement.element.name != null) {
-                       var elementKey = parentname + '_' + schemaelement.element.name;
-                       if (!$scope.callFromMap) {
-                               elementKeys.push(elementKey);
-                       } else {
-                               if ($scope.oldMapValFlag) {
-                                       $scope.oldmappedvaluesArray
-                                       .push(schemaelement.element.name);
-                                       $scope.oldMappedvaluesKeyArray.push(elementKey);
-                               } else {
-                                       $scope.newMappedvaluesArray
-                                       .push(schemaelement.element.name);
-                                       $scope.newMappedvaluesKeyArray.push(elementKey);
-                               }
-                       }
-               }
-               if (schemaelement.type != null
-               && schemaelement.type.complexType != null) {
-                       var parentkey = parentname + '_' + schemaelement.element.name;
-                       for (var i = 0; i < schemaelement.type.elements.length; i++) {
-                               getElementkeys(parentkey, schemaelement.type.elements[i]);
-                       }
-               }
-       }
-} ]);
index 59a27bd..b0b3453 100644 (file)
@@ -678,7 +678,7 @@ function($scope, $rootScope, $timeout, dialogs) {
 
                    var dlg = dialogs.create(
                    'partials/portfolios/PolicyWindow_properties.html',
-                   'ImportSchemaCtrl', {
+                   'operationalPolicyCtrl', {
                        closable : true,
                        draggable : true
                    }, {
@@ -768,18 +768,7 @@ app.run([ '$route', function($route) {
 
        $route.reload();
 } ]);
-function TestCtrl($scope) {
 
-       $scope.msg = "Hello from a controller method.";
-       $scope.returnHello = function() {
-
-               return $scope.msg;
-       }
-}
-function importshema() {
-
-       angular.element(document.getElementById('navbar')).scope().importSchema();
-}
 function F5Window() {
 
        angular.element(document.getElementById('navbar')).scope().F5Window();
@@ -790,7 +779,7 @@ function GOCWindow() {
 }
 function ToscaModelWindow() {
     angular.element(document.getElementById('navbar')).scope().ToscaModelWindow();
-};
+}
 function PolicyWindow(PolicyWin) {
 
        angular.element(document.getElementById('navbar')).scope().PolicyWindow(
@@ -806,23 +795,11 @@ function setdefaultvalue() {
        angular.element(document.getElementById('navbar')).scope()
        .setDefaultValue();
 }
-function upgradeSchemaVersion() {
-
-       angular.element(document.getElementById('navbar')).scope()
-       .upgradeSchemaVersion();
-}
 function saveProject() {
 
        angular.element(document.getElementById('navbar')).scope().saveProject();
 }
-function modifySchema() {
 
-       angular.element(document.getElementById('navbar')).scope().modifySchema();
-}
-function definePID() {
-
-       angular.element(document.getElementById('navbar')).scope().definePID();
-}
 function defineServiceAcronym() {
 
        angular.element(document.getElementById('navbar')).scope()
index 826e187..36070de 100644 (file)
@@ -30,7 +30,6 @@ var list_model_test_sets={};
 var list_model_path_details={};
 var list_model_schema_extensions={};
 var list_model_test_management_details={};
-var isImportSchema=false;
 var selected_decison_element='';
 var selected_element_name = '';
 var list_model_repeatable_heirarchical_elements={};
index 044b21e..f1ab1e1 100644 (file)
  * 
  */
 
-function updateMsProperties(type, form) {
+function updateMsProperties(type, newMsProperties) {
     var newMsProperties = cl_props["microServicePolicies"];
     for (p in newMsProperties) {
         if (newMsProperties[p]["name"] == type) {
-               cl_props["microServicePolicies"][p] = form;
+               cl_props["microServicePolicies"][p] = newMsProperties;
         }
     }
 }
 
-function updateGlobalProperties(form) {
-    cl_props["globalPropertiesJson"] = form;
+function updateGlobalProperties(newGlobalProperties) {
+    cl_props["globalPropertiesJson"] = newGlobalProperties;
 }
 
-function updateOpPolicyProperties(form) {      
+function updateOpPolicyProperties(newOpProperties) {   
    cl_props["operationalPolicies"] = newOpProperties;
 }
 
diff --git a/src/main/resources/META-INF/resources/designer/scripts/soapRequestService.js b/src/main/resources/META-INF/resources/designer/scripts/soapRequestService.js
deleted file mode 100644 (file)
index 25a0b47..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * ONAP CLAMP
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights
- *                             reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License"); 
- * you may not use this file except in compliance with the License. 
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software 
- * distributed under the License is distributed on an "AS IS" BASIS, 
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
- * See the License for the specific language governing permissions and 
- * limitations under the License.
- * ============LICENSE_END============================================
- * ===================================================================
- * 
- */
-
-app.service('soapRequestService', ['$http', '$q', function ($http, $q) {
-    console.log("////////////soapRequestService");
-       this.changetimeoutMode = function(timeoutMode){
-        console.log("changetimeoutMode");
-               console.log("timeoutmode:"+timeoutMode);
-               if(timeoutMode == "Default")
-                       return false;
-               else
-                       return true;
-       };
-       
-       
-       this.generateTst = function(tstInput, generateTSTUrl){
-        console.log("generateTst");
-               var def = $q.defer();
-       
-        $http.post(generateTSTUrl, tstInput)
-        .success(function(data){
-            console.log("success");
-               def.resolve(data);              
-               
-        })
-        .error(function(data){ 
-        console.log("error");                        
-                       def.reject("GenerateTST not successful");
-        });
-        
-        return def.promise;
-       };
-       
-       
-       this.generateTSTMultiple = function(tstInputList, generateTSTUrl){
-        console.log("generateTSTMultiple");
-               var def = $q.defer();
-       
-        $http.post(generateTSTUrl, tstInputList)
-        .success(function(data){
-            console.log("success");
-               def.resolve(data);              
-               
-        })
-        .error(function(data){ 
-        console.log("error");                        
-                       def.reject("GenerateTST multiple not successful");
-        });
-        
-        return def.promise;
-       };
-       
-       this.downloadTst = function(tstId, tstName,downloadTSTUrl){
-        console.log("downloadTst");
-               var def = $q.defer();
-               
-               var downloadInput={};
-               
-               downloadInput.tstId=tstId;
-               downloadInput.tstName=tstName;
-       
-               $http({
-            url: downloadTSTUrl,     method: "POST",     data: downloadInput,
-             responseType: 'arraybuffer' }).success(function (data, status, headers, config) {
-             console.log("success");                    
-                var results = [];
-                
-                
-                results.data = new Blob([data], {type: 'application/octet-stream'});
-                 console.log( results.data);
-                 results.headers = headers();
-                 results.status = status;
-                 results.config = config;
-                 def.resolve(results); 
-                 console.log( "Result From UTM Server : " + results.data);
-        })
-        .error(function(data){
-        console.log("error");                        
-                       def.reject("DownloadTST not successful");
-        });
-        
-        return def.promise;
-       };
-       
-}]);
index 50858f7..97b33e1 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP CLAMP
  * ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights
  *                             reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -150,7 +150,7 @@ public class CldsDaoItCase {
     @Test
     public void testGetCldsMonitoringDetails() {
         List<CldsMonitoringDetails> cldsMonitoringDetailsList = new ArrayList<CldsMonitoringDetails>();
-        cldsMonitoringDetailsList = cldsDao.getCLDSMonitoringDetails();
+        cldsMonitoringDetailsList = cldsDao.getCldsMonitoringDetails();
         cldsMonitoringDetailsList.forEach(clName -> {
             logger.info(clName.getCloseloopName());
             assertNotNull(clName.getCloseloopName());
index 571986c..699cffd 100644 (file)
@@ -8,7 +8,7 @@ policy_types:
         version: 1.0.0
         properties:
             tca_policy:
-                type: list
+                type: map
                 description: TCA Policy JSON
                 entry_schema:
                     type: onap.datatypes.monitoring.tca_policy