|
1 |
| -//@ sourceURL=patternkit.jsoneditor.js |
| 1 | +/*globals JSONEditor:false */ |
2 | 2 | /**
|
3 | 3 | * @file
|
4 | 4 | * Provides Twig Pattern Library Editing Functionality.
|
|
13 | 13 | */
|
14 | 14 |
|
15 | 15 | (function ($, Drupal) {
|
| 16 | + 'use strict'; |
| 17 | + |
16 | 18 | Drupal.behaviors.patternkitEditor = {
|
17 | 19 | attach: function (context, settings) {
|
| 20 | + if (!window.JSONEditor) { |
| 21 | + return; |
| 22 | + } |
| 23 | + |
| 24 | + // Ajax command response to allow updating Editor field values. |
| 25 | + Drupal.AjaxCommands.prototype.patternkitEditorUpdate = function(ajax, response, status) { |
| 26 | + window.patternkitEditor.getEditor(response.selector).setValue(response.value); |
| 27 | + }; |
| 28 | + |
| 29 | + // This forces Drupal to re-attach |
| 30 | + $(window).on('dialog:afterclose', function (e, dialog, $element) { |
| 31 | + Drupal.attachBehaviors($(':root'), settings); |
| 32 | + }); |
| 33 | + |
18 | 34 | var $target = $('#editor-shadow-injection-target', context);
|
19 | 35 | $target.once('patternkit-editor').each(function () {
|
20 | 36 | var shadow = this.attachShadow({mode: 'open'});
|
21 |
| - var theme_js = drupalSettings.patternkitEditor.themeJS; |
22 |
| - if (typeof theme_js == 'string') { |
| 37 | + var theme_js = settings.patternkitEditor.themeJS; |
| 38 | + if (typeof theme_js === 'string') { |
23 | 39 | theme_js = [theme_js];
|
24 | 40 | }
|
25 | 41 | for (var i = 0; theme_js && i < theme_js.length; i++) {
|
|
28 | 44 | script_element.src = theme_js[i];
|
29 | 45 | document.getElementsByTagName('head')[0].appendChild(script_element);
|
30 | 46 | }
|
31 |
| - if (drupalSettings.patternkitEditor.themeStylesheet) { |
32 |
| - var editor_dom = '<link rel="stylesheet" id="theme_stylesheet" href="' + drupalSettings.patternkitEditor.themeStylesheet + '">'; |
| 47 | + var editor_dom = ''; |
| 48 | + if (settings.patternkitEditor.themeStylesheet) { |
| 49 | + editor_dom = '<link rel="stylesheet" id="theme_stylesheet" href="' + settings.patternkitEditor.themeStylesheet + '">'; |
33 | 50 | }
|
34 | 51 | // @todo Re-eval with this shadow dom webfont bug: https://bugs.chromium.org/p/chromium/issues/detail?id=336876
|
35 |
| - if (drupalSettings.patternkitEditor.iconStylesheet) { |
| 52 | + if (settings.patternkitEditor.iconStylesheet) { |
36 | 53 | var icons_element = document.createElement('link');
|
37 | 54 | icons_element.rel = "stylesheet";
|
38 | 55 | icons_element.id = "icon_stylesheet";
|
39 |
| - icons_element.href = drupalSettings.patternkitEditor.iconStylesheet; |
| 56 | + icons_element.href = settings.patternkitEditor.iconStylesheet; |
40 | 57 | document.getElementsByTagName('head')[0].appendChild(icons_element);
|
41 |
| - editor_dom += '<link rel="stylesheet" id="icon_stylesheet" href="' + drupalSettings.patternkitEditor.iconStylesheet + '">'; |
| 58 | + editor_dom += '<link rel="stylesheet" id="icon_stylesheet" href="' + settings.patternkitEditor.iconStylesheet + '">'; |
42 | 59 | }
|
43 | 60 | editor_dom += '<div id="editor_holder"></div>';
|
44 | 61 | shadow.innerHTML += editor_dom;
|
45 | 62 |
|
46 | 63 | var data = {};
|
47 |
| - data.schema = JSON.parse(drupalSettings.patternkitEditor.schemaJson); |
48 |
| - data.starting = JSON.parse(drupalSettings.patternkitEditor.startingJson); |
| 64 | + data.schema = JSON.parse(settings.patternkitEditor.schemaJson); |
| 65 | + data.starting = JSON.parse(settings.patternkitEditor.startingJson); |
49 | 66 |
|
50 |
| - JSONEditor.defaults.options.theme = drupalSettings.patternkitEditor.theme; |
51 |
| - JSONEditor.defaults.options.iconlib = drupalSettings.patternkitEditor.icons; |
| 67 | + JSONEditor.defaults.options.theme = settings.patternkitEditor.theme; |
| 68 | + JSONEditor.defaults.options.iconlib = settings.patternkitEditor.icons; |
52 | 69 | JSONEditor.defaults.options.keep_oneof_values = false;
|
53 | 70 | JSONEditor.defaults.options.disable_edit_json = true;
|
54 | 71 | JSONEditor.defaults.options.disable_collapse = false;
|
55 | 72 | JSONEditor.defaults.options.collapse = false;
|
56 | 73 | JSONEditor.defaults.options.ajax = true;
|
57 | 74 |
|
| 75 | + // Drupal Image Editor. |
| 76 | + JSONEditor.defaults.editors.drupal_image = JSONEditor.AbstractEditor.extend({ |
| 77 | + getNumColumns: function() { |
| 78 | + return 4; |
| 79 | + }, |
| 80 | + build: function() { |
| 81 | + var self = this; |
| 82 | + this.title = this.header = this.label = this.theme.getFormInputLabel(this.getTitle(), this.isRequired()); |
| 83 | + // Don't show uploader if this is readonly |
| 84 | + if(!this.schema.readOnly && !this.schema.readonly) { |
| 85 | + this.urlfield = this.theme.getFormInputField('text'); |
| 86 | + this.button = this.getButton(this.path + '-media', 'upload', Drupal.t('Select/Upload Media')); |
| 87 | + // @todo: Add support for multiple file/image URL editors. |
| 88 | + var media_library_settings = 'media_library_opener_id=patternkit.opener.jsonlibrary' + |
| 89 | + '&' + encodeURIComponent('media_library_allowed_types[0]') + '=image' + |
| 90 | + '&media_library_selected_type=image' + |
| 91 | + '&media_library_remaining=1' + |
| 92 | + '&' + encodeURIComponent('media_library_opener_parameters[field_widget_id]') + '=' + this.path; |
| 93 | + |
| 94 | + this.button.addEventListener('click', function(e) { |
| 95 | + e.preventDefault(); |
| 96 | + e.stopPropagation(); |
| 97 | + |
| 98 | + this.dialog = Drupal.dialog($('#drupal-modal').append($('<span>', {id: 'patternkit_image_dialog_loading'})), { title: Drupal.t('Choose Image'), width: 900, height: 900 }).showModal(); |
| 99 | + Drupal.ajax({ url: settings.patternkitEditor.imageUrl + '?' + media_library_settings, base: 'drupal-modal', wrapper: 'patternkit_image_dialog_loading' }).execute(); |
| 100 | + }); |
| 101 | + } |
| 102 | + |
| 103 | + var description = this.schema.description; |
| 104 | + if (!description) { |
| 105 | + description = ''; |
| 106 | + } |
| 107 | + |
| 108 | + this.preview = this.theme.getFormInputDescription(description); |
| 109 | + this.container.appendChild(this.preview); |
| 110 | + |
| 111 | + this.control = this.theme.getFormControl(this.label, this.urlfield||this.input, this.preview); |
| 112 | + this.container.appendChild(this.control); |
| 113 | + |
| 114 | + if (this.button) { |
| 115 | + this.container.appendChild(this.button); |
| 116 | + } |
| 117 | + |
| 118 | + window.requestAnimationFrame(function() { |
| 119 | + if (self.value) { |
| 120 | + var img = document.createElement('img'); |
| 121 | + img.style.maxWidth = '100%'; |
| 122 | + img.style.maxHeight = '100px'; |
| 123 | + img.onload = function (event) { |
| 124 | + self.preview.appendChild(img); |
| 125 | + }; |
| 126 | + img.onerror = function(error) { |
| 127 | + window.console.error('upload error', error); |
| 128 | + }; |
| 129 | + img.src = self.container.querySelector('a').href; |
| 130 | + } |
| 131 | + }); |
| 132 | + |
| 133 | + }, |
| 134 | + refreshPreview: function() { |
| 135 | + if (this.last_preview === this.preview_value) { |
| 136 | + return; |
| 137 | + } |
| 138 | + this.last_preview = this.preview_value; |
| 139 | + |
| 140 | + this.preview.innerHTML = ''; |
| 141 | + |
| 142 | + if (!this.preview_value) { |
| 143 | + return; |
| 144 | + } |
| 145 | + |
| 146 | + var self = this; |
| 147 | + |
| 148 | + var mime = this.preview_value.match(/^data:([^;,]+)[;,]/); |
| 149 | + if (mime) { |
| 150 | + mime = mime[1]; |
| 151 | + } |
| 152 | + else { |
| 153 | + mime = 'unknown'; |
| 154 | + } |
| 155 | + |
| 156 | + var file = this.urlfield.files[0]; |
| 157 | + |
| 158 | + this.preview.innerHTML = '<strong>Type:</strong> '+mime+', <strong>Size:</strong> '+file.size+' bytes'; |
| 159 | + if(mime.substr(0,5)==="image") { |
| 160 | + this.preview.innerHTML += '<br>'; |
| 161 | + var img = document.createElement('img'); |
| 162 | + img.style.maxWidth = '100%'; |
| 163 | + img.style.maxHeight = '100px'; |
| 164 | + img.src = this.preview_value; |
| 165 | + this.preview.appendChild(img); |
| 166 | + } |
| 167 | + |
| 168 | + this.preview.innerHTML += '<br>'; |
| 169 | + var uploadButton = this.getButton('Upload', 'upload', 'Upload'); |
| 170 | + this.preview.appendChild(uploadButton); |
| 171 | + uploadButton.addEventListener('click',function(event) { |
| 172 | + event.preventDefault(); |
| 173 | + |
| 174 | + uploadButton.setAttribute("disabled", "disabled"); |
| 175 | + self.theme.removeInputError(self.uploader); |
| 176 | + |
| 177 | + if (self.theme.getProgressBar) { |
| 178 | + self.progressBar = self.theme.getProgressBar(); |
| 179 | + self.preview.appendChild(self.progressBar); |
| 180 | + } |
| 181 | + |
| 182 | + self.jsoneditor.options.upload(self.path, file, { |
| 183 | + success: function(url) { |
| 184 | + self.setValue(url); |
| 185 | + |
| 186 | + if (self.parent) { |
| 187 | + self.parent.onChildEditorChange(self); |
| 188 | + } |
| 189 | + else { |
| 190 | + self.jsoneditor.onChange(); |
| 191 | + } |
| 192 | + |
| 193 | + if (self.progressBar) { |
| 194 | + self.preview.removeChild(self.progressBar); |
| 195 | + } |
| 196 | + uploadButton.removeAttribute("disabled"); |
| 197 | + }, |
| 198 | + failure: function(error) { |
| 199 | + self.theme.addInputError(self.uploader, error); |
| 200 | + if (self.progressBar) { |
| 201 | + self.preview.removeChild(self.progressBar); |
| 202 | + } |
| 203 | + uploadButton.removeAttribute("disabled"); |
| 204 | + }, |
| 205 | + updateProgress: function(progress) { |
| 206 | + if (self.progressBar) { |
| 207 | + if (progress) { |
| 208 | + self.theme.updateProgressBar(self.progressBar, progress); |
| 209 | + } |
| 210 | + else { |
| 211 | + self.theme.updateProgressBarUnknown(self.progressBar); |
| 212 | + } |
| 213 | + } |
| 214 | + } |
| 215 | + }); |
| 216 | + }); |
| 217 | + |
| 218 | + if(this.jsoneditor.options.auto_upload || this.schema.options.auto_upload) { |
| 219 | + uploadButton.dispatchEvent(new MouseEvent('click')); |
| 220 | + this.preview.removeChild(uploadButton); |
| 221 | + } |
| 222 | + }, |
| 223 | + enable: function() { |
| 224 | + if(!this.always_disabled) { |
| 225 | + if(this.urlfield) { |
| 226 | + this.urlfield.disabled = false; |
| 227 | + } |
| 228 | + this._super(); |
| 229 | + } |
| 230 | + }, |
| 231 | + disable: function(always_disabled) { |
| 232 | + if(always_disabled) { |
| 233 | + this.always_disabled = true; |
| 234 | + } |
| 235 | + if(this.urlfield) { |
| 236 | + this.urlfield.disabled = true; |
| 237 | + } |
| 238 | + this._super(); |
| 239 | + }, |
| 240 | + setValue: function(val) { |
| 241 | + if(this.value !== val) { |
| 242 | + this.value = val; |
| 243 | + this.urlfield.value = this.value; |
| 244 | + this.onChange(); |
| 245 | + } |
| 246 | + }, |
| 247 | + destroy: function() { |
| 248 | + if(this.preview && this.preview.parentNode) { |
| 249 | + this.preview.parentNode.removeChild(this.preview); |
| 250 | + } |
| 251 | + if(this.title && this.title.parentNode) { |
| 252 | + this.title.parentNode.removeChild(this.title); |
| 253 | + } |
| 254 | + if(this.input && this.input.parentNode) { |
| 255 | + this.input.parentNode.removeChild(this.input); |
| 256 | + } |
| 257 | + if(this.urlfield && this.urlfield.parentNode) { |
| 258 | + this.urlfield.parentNode.removeChild(this.urlfield); |
| 259 | + } |
| 260 | + |
| 261 | + this._super(); |
| 262 | + } |
| 263 | + }); |
| 264 | + JSONEditor.defaults.resolvers.unshift(function(schema) { |
| 265 | + if (schema.type === 'string' && schema.format === 'image') { |
| 266 | + return 'drupal_image'; |
| 267 | + } |
| 268 | + }); |
| 269 | + |
58 | 270 | // Override how references are resolved.
|
59 | 271 | JSONEditor.prototype._loadExternalRefs = function (schema, callback) {
|
60 | 272 | var self = this;
|
|
73 | 285 | waiting++;
|
74 | 286 |
|
75 | 287 | var r = new XMLHttpRequest();
|
76 |
| - var uri = drupalSettings.path.baseUrl + url + '/schema'; |
| 288 | + var uri = settings.path.baseUrl + url + '/schema'; |
77 | 289 |
|
78 | 290 | r.open("GET", uri, true);
|
79 | 291 | r.onreadystatechange = function () {
|
|
125 | 337 | if (typeof data.starting === 'object' && !$.isEmptyObject(data.starting)) {
|
126 | 338 | config.startval = data.starting;
|
127 | 339 | }
|
128 |
| - var editor = new JSONEditor($target[0].shadowRoot.getElementById('editor_holder'), config); |
| 340 | + window.patternkitEditor = new JSONEditor($target[0].shadowRoot.getElementById('editor_holder'), config); |
129 | 341 | JSONEditor.plugins.sceditor.emoticonsEnabled = false;
|
130 | 342 | var saveSchema = function () {
|
131 |
| - $('#schema_instance_config').val(JSON.stringify(editor.getValue())); |
| 343 | + $('#schema_instance_config').val(JSON.stringify(window.patternkitEditor.getValue())); |
132 | 344 | if (window.M) {
|
133 | 345 | window.M.updateTextFields();
|
134 | 346 | }
|
135 | 347 | };
|
136 | 348 |
|
137 |
| - editor.on('ready', function () { |
| 349 | + window.patternkitEditor.on('ready', function () { |
138 | 350 | if (window.M) {
|
139 | 351 | window.M.updateTextFields();
|
140 | 352 | }
|
141 | 353 | });
|
142 |
| - editor.on('change', saveSchema); |
| 354 | + window.patternkitEditor.on('change', saveSchema); |
143 | 355 | $('[data-drupal-selector="edit-actions-submit"]').on('input', function (e) {
|
144 | 356 | saveSchema();
|
145 | 357 | });
|
146 | 358 | // Drupal triggers Ajax submit via input events.
|
147 | 359 | // This is before allowing other events, so we need to add a pre-hook
|
148 | 360 | // to trigger the editor update with latest field values.
|
149 | 361 | // @TODO Add handling for AJAX errors and re-attach.
|
| 362 | + var beforeSubmitHandler = Drupal.Ajax.prototype.beforeSubmit; |
150 | 363 | Drupal.Ajax.prototype.beforeSubmit = function(formValues, element, options) {
|
151 |
| - editor.disable(); |
| 364 | + if ( $(element).parents("#editor_holder").length !== 1 ) { |
| 365 | + return beforeSubmitHandler(formValues, element, options); |
| 366 | + } |
| 367 | + window.patternkitEditor.disable(); |
152 | 368 | saveSchema();
|
153 | 369 | for (var v = 0; v < formValues.length; v++) {
|
154 |
| - if (formValues[v]['name'] === 'settings[instance_config]') { |
155 |
| - formValues[v]['value'] = JSON.stringify(editor.getValue()); |
| 370 | + if (formValues[v].name === 'settings[instance_config]') { |
| 371 | + formValues[v].value = JSON.stringify(window.patternkitEditor.getValue()); |
156 | 372 | }
|
157 | 373 | }
|
158 |
| - editor.destroy(); |
| 374 | + window.patternkitEditor.destroy(); |
159 | 375 | };
|
160 | 376 | });
|
161 | 377 | }
|
|
0 commit comments