Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / modules / quickedit / js / util.es6.js
1 /**
2  * @file
3  * Provides utility functions for Quick Edit.
4  */
5
6 (function($, Drupal) {
7   /**
8    * @namespace
9    */
10   Drupal.quickedit.util = Drupal.quickedit.util || {};
11
12   /**
13    * @namespace
14    */
15   Drupal.quickedit.util.constants = {};
16
17   /**
18    *
19    * @type {string}
20    */
21   Drupal.quickedit.util.constants.transitionEnd =
22     'transitionEnd.quickedit webkitTransitionEnd.quickedit transitionend.quickedit msTransitionEnd.quickedit oTransitionEnd.quickedit';
23
24   /**
25    * Converts a field id into a formatted url path.
26    *
27    * @example
28    * Drupal.quickedit.util.buildUrl(
29    *   'node/1/body/und/full',
30    *   '/quickedit/form/!entity_type/!id/!field_name/!langcode/!view_mode'
31    * );
32    *
33    * @param {string} id
34    *   The id of an editable field.
35    * @param {string} urlFormat
36    *   The Controller route for field processing.
37    *
38    * @return {string}
39    *   The formatted URL.
40    */
41   Drupal.quickedit.util.buildUrl = function(id, urlFormat) {
42     const parts = id.split('/');
43     return Drupal.formatString(decodeURIComponent(urlFormat), {
44       '!entity_type': parts[0],
45       '!id': parts[1],
46       '!field_name': parts[2],
47       '!langcode': parts[3],
48       '!view_mode': parts[4],
49     });
50   };
51
52   /**
53    * Shows a network error modal dialog.
54    *
55    * @param {string} title
56    *   The title to use in the modal dialog.
57    * @param {string} message
58    *   The message to use in the modal dialog.
59    */
60   Drupal.quickedit.util.networkErrorModal = function(title, message) {
61     const $message = $(`<div>${message}</div>`);
62     const networkErrorModal = Drupal.dialog($message.get(0), {
63       title,
64       dialogClass: 'quickedit-network-error',
65       buttons: [
66         {
67           text: Drupal.t('OK'),
68           click() {
69             networkErrorModal.close();
70           },
71           primary: true,
72         },
73       ],
74       create() {
75         $(this)
76           .parent()
77           .find('.ui-dialog-titlebar-close')
78           .remove();
79       },
80       close(event) {
81         // Automatically destroy the DOM element that was used for the dialog.
82         $(event.target).remove();
83       },
84     });
85     networkErrorModal.showModal();
86   };
87
88   /**
89    * @namespace
90    */
91   Drupal.quickedit.util.form = {
92     /**
93      * Loads a form, calls a callback to insert.
94      *
95      * Leverages {@link Drupal.Ajax}' ability to have scoped (per-instance)
96      * command implementations to be able to call a callback.
97      *
98      * @param {object} options
99      *   An object with the following keys:
100      * @param {string} options.fieldID
101      *   The field ID that uniquely identifies the field for which this form
102      *   will be loaded.
103      * @param {bool} options.nocssjs
104      *   Boolean indicating whether no CSS and JS should be returned (necessary
105      *   when the form is invisible to the user).
106      * @param {bool} options.reset
107      *   Boolean indicating whether the data stored for this field's entity in
108      *   PrivateTempStore should be used or reset.
109      * @param {function} callback
110      *   A callback function that will receive the form to be inserted, as well
111      *   as the ajax object, necessary if the callback wants to perform other
112      *   Ajax commands.
113      */
114     load(options, callback) {
115       const fieldID = options.fieldID;
116
117       // Create a Drupal.ajax instance to load the form.
118       const formLoaderAjax = Drupal.ajax({
119         url: Drupal.quickedit.util.buildUrl(
120           fieldID,
121           Drupal.url(
122             'quickedit/form/!entity_type/!id/!field_name/!langcode/!view_mode',
123           ),
124         ),
125         submit: {
126           nocssjs: options.nocssjs,
127           reset: options.reset,
128         },
129         error(xhr, url) {
130           // Show a modal to inform the user of the network error.
131           const fieldLabel = Drupal.quickedit.metadata.get(fieldID, 'label');
132           const message = Drupal.t(
133             'Could not load the form for <q>@field-label</q>, either due to a website problem or a network connection problem.<br>Please try again.',
134             { '@field-label': fieldLabel },
135           );
136           Drupal.quickedit.util.networkErrorModal(
137             Drupal.t('Network problem!'),
138             message,
139           );
140
141           // Change the state back to "candidate", to allow the user to start
142           // in-place editing of the field again.
143           const fieldModel = Drupal.quickedit.app.model.get('activeField');
144           fieldModel.set('state', 'candidate');
145         },
146       });
147       // Implement a scoped quickeditFieldForm AJAX command: calls the callback.
148       formLoaderAjax.commands.quickeditFieldForm = function(
149         ajax,
150         response,
151         status,
152       ) {
153         callback(response.data, ajax);
154         Drupal.ajax.instances[this.instanceIndex] = null;
155       };
156       // This will ensure our scoped quickeditFieldForm AJAX command gets
157       // called.
158       formLoaderAjax.execute();
159     },
160
161     /**
162      * Creates a {@link Drupal.Ajax} instance that is used to save a form.
163      *
164      * @param {object} options
165      *   Submit options to the form.
166      * @param {bool} options.nocssjs
167      *   Boolean indicating whether no CSS and JS should be returned (necessary
168      *   when the form is invisible to the user).
169      * @param {Array.<string>} options.other_view_modes
170      *   Array containing view mode IDs (of other instances of this field on the
171      *   page).
172      * @param {jQuery} $submit
173      *   The submit element.
174      *
175      * @return {Drupal.Ajax}
176      *   A {@link Drupal.Ajax} instance.
177      */
178     ajaxifySaving(options, $submit) {
179       // Re-wire the form to handle submit.
180       const settings = {
181         url: $submit.closest('form').attr('action'),
182         setClick: true,
183         event: 'click.quickedit',
184         progress: false,
185         submit: {
186           nocssjs: options.nocssjs,
187           other_view_modes: options.other_view_modes,
188         },
189
190         /**
191          * Reimplement the success handler.
192          *
193          * Ensure {@link Drupal.attachBehaviors} does not get called on the
194          * form.
195          *
196          * @param {Drupal.AjaxCommands~commandDefinition} response
197          *   The Drupal AJAX response.
198          * @param {number} [status]
199          *   The HTTP status code.
200          */
201         success(response, status) {
202           Object.keys(response || {}).forEach(i => {
203             if (response[i].command && this.commands[response[i].command]) {
204               this.commands[response[i].command](this, response[i], status);
205             }
206           });
207         },
208         base: $submit.attr('id'),
209         element: $submit[0],
210       };
211
212       return Drupal.ajax(settings);
213     },
214
215     /**
216      * Cleans up the {@link Drupal.Ajax} instance that is used to save the form.
217      *
218      * @param {Drupal.Ajax} ajax
219      *   A {@link Drupal.Ajax} instance that was returned by
220      *   {@link Drupal.quickedit.form.ajaxifySaving}.
221      */
222     unajaxifySaving(ajax) {
223       $(ajax.element).off('click.quickedit');
224     },
225   };
226 })(jQuery, Drupal);