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