1jQuery(function() {
2    //Verify, if json-plugin is installed. Initialize it, if necessary.
3    if(typeof json_plugin !== 'object') {
4        return;
5    }
6    if(!json_plugin.initialized) {
7        json_plugin.init();
8    }
9
10    var JSONEditor_configured = false;
11
12    jQuery('.jsoneditor-plugin').each(function() {
13
14        var $tabs = jQuery(this),
15            $editor_error = $tabs.find('.json-editor-error'),
16            $editor = $tabs.find('.json-editor'),
17            options = $tabs.data('options'),
18            schema = $tabs.data('schema'),
19            saveall = $tabs.data('saveall'),
20            errors = [],
21            dataChanged = false,
22            o = $tabs.data('o'),    //object with interface, which was prepared by json_plugin
23            json_editor,
24            dataOriginal;
25
26        //configure JSONEditor library globally on the first pass
27        if (!JSONEditor_configured) {
28            JSONEditor_configured = true;
29            // add language to the jsoneditor.js library
30            if (LANG.plugins.jsoneditor.language.length > 0 && LANG.plugins.jsoneditor.language !== 'en') {
31                JSONEditor.defaults.language = LANG.plugins.jsoneditor.language;
32                JSONEditor.defaults.languages[LANG.plugins.jsoneditor.language] = {
33                    error_notset: LANG.plugins.jsoneditor.error_notset,
34                    error_notempty: LANG.plugins.jsoneditor.error_notempty,
35                    error_enum: LANG.plugins.jsoneditor.error_enum,
36                    error_const: LANG.plugins.jsoneditor.error_const,
37                    error_anyOf: LANG.plugins.jsoneditor.error_anyOf,
38                    error_oneOf: LANG.plugins.jsoneditor.error_oneOf,
39                    error_not: LANG.plugins.jsoneditor.error_not,
40                    error_type_union: LANG.plugins.jsoneditor.error_type_union,
41                    error_type: LANG.plugins.jsoneditor.error_type,
42                    error_disallow_union: LANG.plugins.jsoneditor.error_disallow_union,
43                    error_disallow: LANG.plugins.jsoneditor.error_disallow,
44                    error_multipleOf: LANG.plugins.jsoneditor.error_multipleOf,
45                    error_maximum_excl: LANG.plugins.jsoneditor.error_maximum_excl,
46                    error_maximum_incl: LANG.plugins.jsoneditor.error_maximum_incl,
47                    error_minimum_excl: LANG.plugins.jsoneditor.error_minimum_excl,
48                    error_minimum_incl: LANG.plugins.jsoneditor.error_minimum_incl,
49                    error_maxLength: LANG.plugins.jsoneditor.error_maxLength,
50                    error_minLength: LANG.plugins.jsoneditor.error_minLength,
51                    error_pattern: LANG.plugins.jsoneditor.error_pattern,
52                    error_additionalItems: LANG.plugins.jsoneditor.error_additionalItems,
53                    error_maxItems: LANG.plugins.jsoneditor.error_maxItems,
54                    error_minItems: LANG.plugins.jsoneditor.error_minItems,
55                    error_uniqueItems: LANG.plugins.jsoneditor.error_uniqueItems,
56                    error_maxProperties: LANG.plugins.jsoneditor.error_maxProperties,
57                    error_minProperties: LANG.plugins.jsoneditor.error_minProperties,
58                    error_required: LANG.plugins.jsoneditor.error_required,
59                    error_additional_properties: LANG.plugins.jsoneditor.error_additional_properties,
60                    error_property_names_exceeds_maxlength: LANG.plugins.jsoneditor.error_property_names_exceeds_maxlength,
61                    error_property_names_enum_mismatch: LANG.plugins.jsoneditor.error_property_names_enum_mismatch,
62                    error_property_names_const_mismatch: LANG.plugins.jsoneditor.error_property_names_const_mismatch,
63                    error_property_names_pattern_mismatch: LANG.plugins.jsoneditor.error_property_names_pattern_mismatch,
64                    error_property_names_false: LANG.plugins.jsoneditor.error_property_names_false,
65                    error_property_names_maxlength: LANG.plugins.jsoneditor.error_property_names_maxlength,
66                    error_property_names_enum: LANG.plugins.jsoneditor.error_property_names_enum,
67                    error_property_names_pattern: LANG.plugins.jsoneditor.error_property_names_pattern,
68                    error_property_names_unsupported: LANG.plugins.jsoneditor.error_property_names_unsupported,
69                    error_dependency: LANG.plugins.jsoneditor.error_dependency,
70                    error_date: LANG.plugins.jsoneditor.error_date,
71                    error_time: LANG.plugins.jsoneditor.error_time,
72                    error_datetime_local: LANG.plugins.jsoneditor.error_datetime_local,
73                    error_invalid_epoch: LANG.plugins.jsoneditor.error_invalid_epoch,
74                    error_ipv4: LANG.plugins.jsoneditor.error_ipv4,
75                    error_ipv6: LANG.plugins.jsoneditor.error_ipv6,
76                    error_hostname: LANG.plugins.jsoneditor.error_hostname,
77                    button_save: LANG.plugins.jsoneditor.button_save,
78                    button_copy: LANG.plugins.jsoneditor.button_copy,
79                    button_cancel: LANG.plugins.jsoneditor.button_cancel,
80                    button_add: LANG.plugins.jsoneditor.button_add,
81                    button_delete_all: LANG.plugins.jsoneditor.button_delete_all,
82                    button_delete_all_title: LANG.plugins.jsoneditor.button_delete_all_title,
83                    button_delete_last: LANG.plugins.jsoneditor.button_delete_last,
84                    button_delete_last_title: LANG.plugins.jsoneditor.button_delete_last_title,
85                    button_add_row_title: LANG.plugins.jsoneditor.button_add_row_title,
86                    button_move_down_title: LANG.plugins.jsoneditor.button_move_down_title,
87                    button_move_up_title: LANG.plugins.jsoneditor.button_move_up_title,
88                    button_properties: LANG.plugins.jsoneditor.button_properties,
89                    button_object_properties: LANG.plugins.jsoneditor.button_object_properties,
90                    button_copy_row_title: LANG.plugins.jsoneditor.button_copy_row_title,
91                    button_delete_row_title: LANG.plugins.jsoneditor.button_delete_row_title,
92                    button_delete_row_title_short: LANG.plugins.jsoneditor.button_delete_row_title_short,
93                    button_copy_row_title_short: LANG.plugins.jsoneditor.button_copy_row_title_short,
94                    button_collapse: LANG.plugins.jsoneditor.button_collapse,
95                    button_expand: LANG.plugins.jsoneditor.button_expand,
96                    button_edit_json: LANG.plugins.jsoneditor.button_edit_json,
97                    button_upload: LANG.plugins.jsoneditor.button_upload,
98                    flatpickr_toggle_button: LANG.plugins.jsoneditor.flatpickr_toggle_button,
99                    flatpickr_clear_button: LANG.plugins.jsoneditor.flatpickr_clear_button,
100                    choices_placeholder_text: LANG.plugins.jsoneditor.choices_placeholder_text,
101                    default_array_item_title: LANG.plugins.jsoneditor.default_array_item_title,
102                    button_delete_node_warning: LANG.plugins.jsoneditor.button_delete_node_warning
103                };
104            }
105
106            // set EJS template engine, if enabled by json plugin.
107            if(JSINFO.enable_ejs) {
108                //JSONEditor.defaults.options.template = 'ejs'; doesn't work, bug in JSONEditor? Workaround below:
109                const myEJS = {
110                    compile: function (template) {
111                        // Compile returns a render function
112                        return function(vars) {
113                            return ejs.render(template, vars);
114                        }
115                    }
116                };
117                JSONEditor.defaults.options.template = myEJS;
118            }
119        }
120
121
122        //prepare options, schema and data for jsoneditor
123        if(typeof options !== 'object') {
124            try {
125                options = JSON.parse(options);
126            }
127            catch(e) {
128                errors.push("'options' attribute: " + String(e));
129                options = {};
130            }
131        }
132        else if (options === null) {
133            options = {};
134        }
135        if(typeof schema !== 'object') {
136            try {
137                schema = JSON.parse(schema);
138            }
139            catch(e) {
140                errors.push("'schema' attribute: " + String(e));
141                schema = {};
142            }
143        }
144        else if (schema === null) {
145            schema = {};
146        }
147
148        options.schema = schema;
149        options.startval = JSON.parse(o.data_combined);
150
151
152        //display errors
153        if(errors.length) {
154            $editor_error.append(errors.join('<br/>'));
155        }
156
157
158        //initialize jsoneditor
159        json_editor = new JSONEditor($editor[0], options);
160
161        //add validate button to the header of the json_editor
162        var $button = jQuery('<button style="font-weight: bold;" class="json-editor-btn-collapse json-editor-btntype-toggle">'+LANG.plugins.jsoneditor.button_validate+'</button>');
163
164        json_editor.on('ready', function (event) {
165            var $header = $editor.find('> div > h3');
166            $header.append($button);
167        });
168
169        $button.on('click', function (event) {
170            var err_validator = json_editor.validate();
171            if(err_validator.length) {
172                if(errors.length) {
173                    $editor_error.append('<br/>');
174                }
175                errors = [];
176                for(var i = 0; i < err_validator.length; i++) {
177                    var e = err_validator[i];
178                    errors.push('Validation error in ' + e.path + ' - ' + e.property + ' - ' + e.message);
179                }
180                $editor_error.append(errors.join('<br/>'));
181            }
182            else {
183                //get data from editor
184                var value = json_editor.getValue(),
185                    dataToSave;
186
187                //write all or partial data into JSON data_inline (textarea)
188                if(saveall) {
189                    dataToSave = value;
190                }
191                else {
192                    if(dataOriginal === undefined) {
193                        dataOriginal = JSON.parse(o.data_original);
194                    }
195                    dataToSave = json_plugin.diff(dataOriginal, value);
196                }
197
198                //stringify JSON
199                if(Array.isArray(dataToSave) && typeof dataToSave === "object") {
200                    //if we have an array of objects on the first level, make output a little less compact
201                    o.data_inline = "[\n"
202                        + dataToSave.map(x => "  " + JSON.stringify(x)).join(",\n")
203                        + "\n]";
204                }
205                else {
206                    o.data_inline = JSON.stringify(dataToSave);
207                }
208
209                //show JSON save button
210                o.showButton();
211            }
212        });
213
214        //warn if browser window unloads and data has been changed
215        var ignoreFirstSignal = true;
216        json_editor.on('change', function() {
217            if (ignoreFirstSignal) {
218                ignoreFirstSignal = false;
219            }
220            else {
221                window.onbeforeunload = function(e) {
222                    e.preventDefault();
223                    e.returnValue = '';
224                };
225            }
226        });
227    });
228
229});
230