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