Mercurial > hg > cmmr2012-drupal-site
comparison core/modules/quickedit/js/views/EditorView.es6.js @ 4:a9cd425dd02b
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:11:55 +0000 |
parents | c75dbcec494b |
children |
comparison
equal
deleted
inserted
replaced
3:307d7a7fd348 | 4:a9cd425dd02b |
---|---|
1 /** | 1 /** |
2 * @file | 2 * @file |
3 * An abstract Backbone View that controls an in-place editor. | 3 * An abstract Backbone View that controls an in-place editor. |
4 */ | 4 */ |
5 | 5 |
6 (function ($, Backbone, Drupal) { | 6 (function($, Backbone, Drupal) { |
7 Drupal.quickedit.EditorView = Backbone.View.extend(/** @lends Drupal.quickedit.EditorView# */{ | 7 Drupal.quickedit.EditorView = Backbone.View.extend( |
8 | 8 /** @lends Drupal.quickedit.EditorView# */ { |
9 /** | 9 /** |
10 * A base implementation that outlines the structure for in-place editors. | 10 * A base implementation that outlines the structure for in-place editors. |
11 * | 11 * |
12 * Specific in-place editor implementations should subclass (extend) this | 12 * Specific in-place editor implementations should subclass (extend) this |
13 * View and override whichever method they deem necessary to override. | 13 * View and override whichever method they deem necessary to override. |
14 * | 14 * |
15 * Typically you would want to override this method to set the | 15 * Typically you would want to override this method to set the |
16 * originalValue attribute in the FieldModel to such a value that your | 16 * originalValue attribute in the FieldModel to such a value that your |
17 * in-place editor can revert to the original value when necessary. | 17 * in-place editor can revert to the original value when necessary. |
18 * | 18 * |
19 * @example | 19 * @example |
20 * <caption>If you override this method, you should call this | 20 * <caption>If you override this method, you should call this |
21 * method (the parent class' initialize()) first.</caption> | 21 * method (the parent class' initialize()) first.</caption> |
22 * Drupal.quickedit.EditorView.prototype.initialize.call(this, options); | 22 * Drupal.quickedit.EditorView.prototype.initialize.call(this, options); |
23 * | 23 * |
24 * @constructs | 24 * @constructs |
25 * | 25 * |
26 * @augments Backbone.View | 26 * @augments Backbone.View |
27 * | 27 * |
28 * @param {object} options | 28 * @param {object} options |
29 * An object with the following keys: | 29 * An object with the following keys: |
30 * @param {Drupal.quickedit.EditorModel} options.model | 30 * @param {Drupal.quickedit.EditorModel} options.model |
31 * The in-place editor state model. | 31 * The in-place editor state model. |
32 * @param {Drupal.quickedit.FieldModel} options.fieldModel | 32 * @param {Drupal.quickedit.FieldModel} options.fieldModel |
33 * The field model. | 33 * The field model. |
34 * | 34 * |
35 * @see Drupal.quickedit.EditorModel | 35 * @see Drupal.quickedit.EditorModel |
36 * @see Drupal.quickedit.editors.plain_text | 36 * @see Drupal.quickedit.editors.plain_text |
37 */ | 37 */ |
38 initialize(options) { | 38 initialize(options) { |
39 this.fieldModel = options.fieldModel; | 39 this.fieldModel = options.fieldModel; |
40 this.listenTo(this.fieldModel, 'change:state', this.stateChange); | 40 this.listenTo(this.fieldModel, 'change:state', this.stateChange); |
41 }, | |
42 | |
43 /** | |
44 * @inheritdoc | |
45 */ | |
46 remove() { | |
47 // The el property is the field, which should not be removed. Remove the | |
48 // pointer to it, then call Backbone.View.prototype.remove(). | |
49 this.setElement(); | |
50 Backbone.View.prototype.remove.call(this); | |
51 }, | |
52 | |
53 /** | |
54 * Returns the edited element. | |
55 * | |
56 * For some single cardinality fields, it may be necessary or useful to | |
57 * not in-place edit (and hence decorate) the DOM element with the | |
58 * data-quickedit-field-id attribute (which is the field's wrapper), but a | |
59 * specific element within the field's wrapper. | |
60 * e.g. using a WYSIWYG editor on a body field should happen on the DOM | |
61 * element containing the text itself, not on the field wrapper. | |
62 * | |
63 * @return {jQuery} | |
64 * A jQuery-wrapped DOM element. | |
65 * | |
66 * @see Drupal.quickedit.editors.plain_text | |
67 */ | |
68 getEditedElement() { | |
69 return this.$el; | |
70 }, | |
71 | |
72 /** | |
73 * | |
74 * @return {object} | |
75 * Returns 3 Quick Edit UI settings that depend on the in-place editor: | |
76 * - Boolean padding: indicates whether padding should be applied to the | |
77 * edited element, to guarantee legibility of text. | |
78 * - Boolean unifiedToolbar: provides the in-place editor with the ability | |
79 * to insert its own toolbar UI into Quick Edit's tightly integrated | |
80 * toolbar. | |
81 * - Boolean fullWidthToolbar: indicates whether Quick Edit's tightly | |
82 * integrated toolbar should consume the full width of the element, | |
83 * rather than being just long enough to accommodate a label. | |
84 */ | |
85 getQuickEditUISettings() { | |
86 return { | |
87 padding: false, | |
88 unifiedToolbar: false, | |
89 fullWidthToolbar: false, | |
90 popup: false, | |
91 }; | |
92 }, | |
93 | |
94 /** | |
95 * Determines the actions to take given a change of state. | |
96 * | |
97 * @param {Drupal.quickedit.FieldModel} fieldModel | |
98 * The quickedit `FieldModel` that holds the state. | |
99 * @param {string} state | |
100 * The state of the associated field. One of | |
101 * {@link Drupal.quickedit.FieldModel.states}. | |
102 */ | |
103 stateChange(fieldModel, state) { | |
104 const from = fieldModel.previous('state'); | |
105 const to = state; | |
106 switch (to) { | |
107 case 'inactive': | |
108 // An in-place editor view will not yet exist in this state, hence | |
109 // this will never be reached. Listed for sake of completeness. | |
110 break; | |
111 | |
112 case 'candidate': | |
113 // Nothing to do for the typical in-place editor: it should not be | |
114 // visible yet. Except when we come from the 'invalid' state, then we | |
115 // clean up. | |
116 if (from === 'invalid') { | |
117 this.removeValidationErrors(); | |
118 } | |
119 break; | |
120 | |
121 case 'highlighted': | |
122 // Nothing to do for the typical in-place editor: it should not be | |
123 // visible yet. | |
124 break; | |
125 | |
126 case 'activating': { | |
127 // The user has indicated he wants to do in-place editing: if | |
128 // something needs to be loaded (CSS/JavaScript/server data/…), then | |
129 // do so at this stage, and once the in-place editor is ready, | |
130 // set the 'active' state. A "loading" indicator will be shown in the | |
131 // UI for as long as the field remains in this state. | |
132 const loadDependencies = function(callback) { | |
133 // Do the loading here. | |
134 callback(); | |
135 }; | |
136 loadDependencies(() => { | |
137 fieldModel.set('state', 'active'); | |
138 }); | |
139 break; | |
140 } | |
141 | |
142 case 'active': | |
143 // The user can now actually use the in-place editor. | |
144 break; | |
145 | |
146 case 'changed': | |
147 // Nothing to do for the typical in-place editor. The UI will show an | |
148 // indicator that the field has changed. | |
149 break; | |
150 | |
151 case 'saving': | |
152 // When the user has indicated he wants to save his changes to this | |
153 // field, this state will be entered. If the previous saving attempt | |
154 // resulted in validation errors, the previous state will be | |
155 // 'invalid'. Clean up those validation errors while the user is | |
156 // saving. | |
157 if (from === 'invalid') { | |
158 this.removeValidationErrors(); | |
159 } | |
160 this.save(); | |
161 break; | |
162 | |
163 case 'saved': | |
164 // Nothing to do for the typical in-place editor. Immediately after | |
165 // being saved, a field will go to the 'candidate' state, where it | |
166 // should no longer be visible (after all, the field will then again | |
167 // just be a *candidate* to be in-place edited). | |
168 break; | |
169 | |
170 case 'invalid': | |
171 // The modified field value was attempted to be saved, but there were | |
172 // validation errors. | |
173 this.showValidationErrors(); | |
174 break; | |
175 } | |
176 }, | |
177 | |
178 /** | |
179 * Reverts the modified value to the original, before editing started. | |
180 */ | |
181 revert() { | |
182 // A no-op by default; each editor should implement reverting itself. | |
183 // Note that if the in-place editor does not cause the FieldModel's | |
184 // element to be modified, then nothing needs to happen. | |
185 }, | |
186 | |
187 /** | |
188 * Saves the modified value in the in-place editor for this field. | |
189 */ | |
190 save() { | |
191 const fieldModel = this.fieldModel; | |
192 const editorModel = this.model; | |
193 const backstageId = `quickedit_backstage-${this.fieldModel.id.replace( | |
194 /[/[\]_\s]/g, | |
195 '-', | |
196 )}`; | |
197 | |
198 function fillAndSubmitForm(value) { | |
199 const $form = $(`#${backstageId}`).find('form'); | |
200 // Fill in the value in any <input> that isn't hidden or a submit | |
201 // button. | |
202 $form | |
203 .find(':input[type!="hidden"][type!="submit"]:not(select)') | |
204 // Don't mess with the node summary. | |
205 .not('[name$="\\[summary\\]"]') | |
206 .val(value); | |
207 // Submit the form. | |
208 $form.find('.quickedit-form-submit').trigger('click.quickedit'); | |
209 } | |
210 | |
211 const formOptions = { | |
212 fieldID: this.fieldModel.get('fieldID'), | |
213 $el: this.$el, | |
214 nocssjs: true, | |
215 other_view_modes: fieldModel.findOtherViewModes(), | |
216 // Reset an existing entry for this entity in the PrivateTempStore (if | |
217 // any) when saving the field. Logically speaking, this should happen in | |
218 // a separate request because this is an entity-level operation, not a | |
219 // field-level operation. But that would require an additional request, | |
220 // that might not even be necessary: it is only when a user saves a | |
221 // first changed field for an entity that this needs to happen: | |
222 // precisely now! | |
223 reset: !this.fieldModel.get('entity').get('inTempStore'), | |
224 }; | |
225 | |
226 const self = this; | |
227 Drupal.quickedit.util.form.load(formOptions, (form, ajax) => { | |
228 // Create a backstage area for storing forms that are hidden from view | |
229 // (hence "backstage" — since the editing doesn't happen in the form, it | |
230 // happens "directly" in the content, the form is only used for saving). | |
231 const $backstage = $( | |
232 Drupal.theme('quickeditBackstage', { id: backstageId }), | |
233 ).appendTo('body'); | |
234 // Hidden forms are stuffed into the backstage container for this field. | |
235 const $form = $(form).appendTo($backstage); | |
236 // Disable the browser's HTML5 validation; we only care about server- | |
237 // side validation. (Not disabling this will actually cause problems | |
238 // because browsers don't like to set HTML5 validation errors on hidden | |
239 // forms.) | |
240 $form.prop('novalidate', true); | |
241 const $submit = $form.find('.quickedit-form-submit'); | |
242 self.formSaveAjax = Drupal.quickedit.util.form.ajaxifySaving( | |
243 formOptions, | |
244 $submit, | |
245 ); | |
246 | |
247 function removeHiddenForm() { | |
248 Drupal.quickedit.util.form.unajaxifySaving(self.formSaveAjax); | |
249 delete self.formSaveAjax; | |
250 $backstage.remove(); | |
251 } | |
252 | |
253 // Successfully saved. | |
254 self.formSaveAjax.commands.quickeditFieldFormSaved = function( | |
255 ajax, | |
256 response, | |
257 status, | |
258 ) { | |
259 removeHiddenForm(); | |
260 // First, transition the state to 'saved'. | |
261 fieldModel.set('state', 'saved'); | |
262 // Second, set the 'htmlForOtherViewModes' attribute, so that when | |
263 // this field is rerendered, the change can be propagated to other | |
264 // instances of this field, which may be displayed in different view | |
265 // modes. | |
266 fieldModel.set('htmlForOtherViewModes', response.other_view_modes); | |
267 // Finally, set the 'html' attribute on the field model. This will | |
268 // cause the field to be rerendered. | |
269 fieldModel.set('html', response.data); | |
270 }; | |
271 | |
272 // Unsuccessfully saved; validation errors. | |
273 self.formSaveAjax.commands.quickeditFieldFormValidationErrors = function( | |
274 ajax, | |
275 response, | |
276 status, | |
277 ) { | |
278 removeHiddenForm(); | |
279 editorModel.set('validationErrors', response.data); | |
280 fieldModel.set('state', 'invalid'); | |
281 }; | |
282 | |
283 // The quickeditFieldForm AJAX command is only called upon loading the | |
284 // form for the first time, and when there are validation errors in the | |
285 // form; Form API then marks which form items have errors. This is | |
286 // useful for the form-based in-place editor, but pointless for any | |
287 // other: the form itself won't be visible at all anyway! So, we just | |
288 // ignore it. | |
289 self.formSaveAjax.commands.quickeditFieldForm = function() {}; | |
290 | |
291 fillAndSubmitForm(editorModel.get('currentValue')); | |
292 }); | |
293 }, | |
294 | |
295 /** | |
296 * Shows validation error messages. | |
297 * | |
298 * Should be called when the state is changed to 'invalid'. | |
299 */ | |
300 showValidationErrors() { | |
301 const $errors = $( | |
302 '<div class="quickedit-validation-errors"></div>', | |
303 ).append(this.model.get('validationErrors')); | |
304 this.getEditedElement() | |
305 .addClass('quickedit-validation-error') | |
306 .after($errors); | |
307 }, | |
308 | |
309 /** | |
310 * Cleans up validation error messages. | |
311 * | |
312 * Should be called when the state is changed to 'candidate' or 'saving'. In | |
313 * the case of the latter: the user has modified the value in the in-place | |
314 * editor again to attempt to save again. In the case of the latter: the | |
315 * invalid value was discarded. | |
316 */ | |
317 removeValidationErrors() { | |
318 this.getEditedElement() | |
319 .removeClass('quickedit-validation-error') | |
320 .next('.quickedit-validation-errors') | |
321 .remove(); | |
322 }, | |
41 }, | 323 }, |
42 | 324 ); |
43 /** | 325 })(jQuery, Backbone, Drupal); |
44 * @inheritdoc | |
45 */ | |
46 remove() { | |
47 // The el property is the field, which should not be removed. Remove the | |
48 // pointer to it, then call Backbone.View.prototype.remove(). | |
49 this.setElement(); | |
50 Backbone.View.prototype.remove.call(this); | |
51 }, | |
52 | |
53 /** | |
54 * Returns the edited element. | |
55 * | |
56 * For some single cardinality fields, it may be necessary or useful to | |
57 * not in-place edit (and hence decorate) the DOM element with the | |
58 * data-quickedit-field-id attribute (which is the field's wrapper), but a | |
59 * specific element within the field's wrapper. | |
60 * e.g. using a WYSIWYG editor on a body field should happen on the DOM | |
61 * element containing the text itself, not on the field wrapper. | |
62 * | |
63 * @return {jQuery} | |
64 * A jQuery-wrapped DOM element. | |
65 * | |
66 * @see Drupal.quickedit.editors.plain_text | |
67 */ | |
68 getEditedElement() { | |
69 return this.$el; | |
70 }, | |
71 | |
72 /** | |
73 * | |
74 * @return {object} | |
75 * Returns 3 Quick Edit UI settings that depend on the in-place editor: | |
76 * - Boolean padding: indicates whether padding should be applied to the | |
77 * edited element, to guarantee legibility of text. | |
78 * - Boolean unifiedToolbar: provides the in-place editor with the ability | |
79 * to insert its own toolbar UI into Quick Edit's tightly integrated | |
80 * toolbar. | |
81 * - Boolean fullWidthToolbar: indicates whether Quick Edit's tightly | |
82 * integrated toolbar should consume the full width of the element, | |
83 * rather than being just long enough to accommodate a label. | |
84 */ | |
85 getQuickEditUISettings() { | |
86 return { padding: false, unifiedToolbar: false, fullWidthToolbar: false, popup: false }; | |
87 }, | |
88 | |
89 /** | |
90 * Determines the actions to take given a change of state. | |
91 * | |
92 * @param {Drupal.quickedit.FieldModel} fieldModel | |
93 * The quickedit `FieldModel` that holds the state. | |
94 * @param {string} state | |
95 * The state of the associated field. One of | |
96 * {@link Drupal.quickedit.FieldModel.states}. | |
97 */ | |
98 stateChange(fieldModel, state) { | |
99 const from = fieldModel.previous('state'); | |
100 const to = state; | |
101 switch (to) { | |
102 case 'inactive': | |
103 // An in-place editor view will not yet exist in this state, hence | |
104 // this will never be reached. Listed for sake of completeness. | |
105 break; | |
106 | |
107 case 'candidate': | |
108 // Nothing to do for the typical in-place editor: it should not be | |
109 // visible yet. Except when we come from the 'invalid' state, then we | |
110 // clean up. | |
111 if (from === 'invalid') { | |
112 this.removeValidationErrors(); | |
113 } | |
114 break; | |
115 | |
116 case 'highlighted': | |
117 // Nothing to do for the typical in-place editor: it should not be | |
118 // visible yet. | |
119 break; | |
120 | |
121 case 'activating': { | |
122 // The user has indicated he wants to do in-place editing: if | |
123 // something needs to be loaded (CSS/JavaScript/server data/…), then | |
124 // do so at this stage, and once the in-place editor is ready, | |
125 // set the 'active' state. A "loading" indicator will be shown in the | |
126 // UI for as long as the field remains in this state. | |
127 const loadDependencies = function (callback) { | |
128 // Do the loading here. | |
129 callback(); | |
130 }; | |
131 loadDependencies(() => { | |
132 fieldModel.set('state', 'active'); | |
133 }); | |
134 break; | |
135 } | |
136 | |
137 case 'active': | |
138 // The user can now actually use the in-place editor. | |
139 break; | |
140 | |
141 case 'changed': | |
142 // Nothing to do for the typical in-place editor. The UI will show an | |
143 // indicator that the field has changed. | |
144 break; | |
145 | |
146 case 'saving': | |
147 // When the user has indicated he wants to save his changes to this | |
148 // field, this state will be entered. If the previous saving attempt | |
149 // resulted in validation errors, the previous state will be | |
150 // 'invalid'. Clean up those validation errors while the user is | |
151 // saving. | |
152 if (from === 'invalid') { | |
153 this.removeValidationErrors(); | |
154 } | |
155 this.save(); | |
156 break; | |
157 | |
158 case 'saved': | |
159 // Nothing to do for the typical in-place editor. Immediately after | |
160 // being saved, a field will go to the 'candidate' state, where it | |
161 // should no longer be visible (after all, the field will then again | |
162 // just be a *candidate* to be in-place edited). | |
163 break; | |
164 | |
165 case 'invalid': | |
166 // The modified field value was attempted to be saved, but there were | |
167 // validation errors. | |
168 this.showValidationErrors(); | |
169 break; | |
170 } | |
171 }, | |
172 | |
173 /** | |
174 * Reverts the modified value to the original, before editing started. | |
175 */ | |
176 revert() { | |
177 // A no-op by default; each editor should implement reverting itself. | |
178 // Note that if the in-place editor does not cause the FieldModel's | |
179 // element to be modified, then nothing needs to happen. | |
180 }, | |
181 | |
182 /** | |
183 * Saves the modified value in the in-place editor for this field. | |
184 */ | |
185 save() { | |
186 const fieldModel = this.fieldModel; | |
187 const editorModel = this.model; | |
188 const backstageId = `quickedit_backstage-${this.fieldModel.id.replace(/[/[\]_\s]/g, '-')}`; | |
189 | |
190 function fillAndSubmitForm(value) { | |
191 const $form = $(`#${backstageId}`).find('form'); | |
192 // Fill in the value in any <input> that isn't hidden or a submit | |
193 // button. | |
194 $form.find(':input[type!="hidden"][type!="submit"]:not(select)') | |
195 // Don't mess with the node summary. | |
196 .not('[name$="\\[summary\\]"]').val(value); | |
197 // Submit the form. | |
198 $form.find('.quickedit-form-submit').trigger('click.quickedit'); | |
199 } | |
200 | |
201 const formOptions = { | |
202 fieldID: this.fieldModel.get('fieldID'), | |
203 $el: this.$el, | |
204 nocssjs: true, | |
205 other_view_modes: fieldModel.findOtherViewModes(), | |
206 // Reset an existing entry for this entity in the PrivateTempStore (if | |
207 // any) when saving the field. Logically speaking, this should happen in | |
208 // a separate request because this is an entity-level operation, not a | |
209 // field-level operation. But that would require an additional request, | |
210 // that might not even be necessary: it is only when a user saves a | |
211 // first changed field for an entity that this needs to happen: | |
212 // precisely now! | |
213 reset: !this.fieldModel.get('entity').get('inTempStore'), | |
214 }; | |
215 | |
216 const self = this; | |
217 Drupal.quickedit.util.form.load(formOptions, (form, ajax) => { | |
218 // Create a backstage area for storing forms that are hidden from view | |
219 // (hence "backstage" — since the editing doesn't happen in the form, it | |
220 // happens "directly" in the content, the form is only used for saving). | |
221 const $backstage = $(Drupal.theme('quickeditBackstage', { id: backstageId })).appendTo('body'); | |
222 // Hidden forms are stuffed into the backstage container for this field. | |
223 const $form = $(form).appendTo($backstage); | |
224 // Disable the browser's HTML5 validation; we only care about server- | |
225 // side validation. (Not disabling this will actually cause problems | |
226 // because browsers don't like to set HTML5 validation errors on hidden | |
227 // forms.) | |
228 $form.prop('novalidate', true); | |
229 const $submit = $form.find('.quickedit-form-submit'); | |
230 self.formSaveAjax = Drupal.quickedit.util.form.ajaxifySaving(formOptions, $submit); | |
231 | |
232 function removeHiddenForm() { | |
233 Drupal.quickedit.util.form.unajaxifySaving(self.formSaveAjax); | |
234 delete self.formSaveAjax; | |
235 $backstage.remove(); | |
236 } | |
237 | |
238 // Successfully saved. | |
239 self.formSaveAjax.commands.quickeditFieldFormSaved = function (ajax, response, status) { | |
240 removeHiddenForm(); | |
241 // First, transition the state to 'saved'. | |
242 fieldModel.set('state', 'saved'); | |
243 // Second, set the 'htmlForOtherViewModes' attribute, so that when | |
244 // this field is rerendered, the change can be propagated to other | |
245 // instances of this field, which may be displayed in different view | |
246 // modes. | |
247 fieldModel.set('htmlForOtherViewModes', response.other_view_modes); | |
248 // Finally, set the 'html' attribute on the field model. This will | |
249 // cause the field to be rerendered. | |
250 fieldModel.set('html', response.data); | |
251 }; | |
252 | |
253 // Unsuccessfully saved; validation errors. | |
254 self.formSaveAjax.commands.quickeditFieldFormValidationErrors = function (ajax, response, status) { | |
255 removeHiddenForm(); | |
256 editorModel.set('validationErrors', response.data); | |
257 fieldModel.set('state', 'invalid'); | |
258 }; | |
259 | |
260 // The quickeditFieldForm AJAX command is only called upon loading the | |
261 // form for the first time, and when there are validation errors in the | |
262 // form; Form API then marks which form items have errors. This is | |
263 // useful for the form-based in-place editor, but pointless for any | |
264 // other: the form itself won't be visible at all anyway! So, we just | |
265 // ignore it. | |
266 self.formSaveAjax.commands.quickeditFieldForm = function () {}; | |
267 | |
268 fillAndSubmitForm(editorModel.get('currentValue')); | |
269 }); | |
270 }, | |
271 | |
272 /** | |
273 * Shows validation error messages. | |
274 * | |
275 * Should be called when the state is changed to 'invalid'. | |
276 */ | |
277 showValidationErrors() { | |
278 const $errors = $('<div class="quickedit-validation-errors"></div>') | |
279 .append(this.model.get('validationErrors')); | |
280 this.getEditedElement() | |
281 .addClass('quickedit-validation-error') | |
282 .after($errors); | |
283 }, | |
284 | |
285 /** | |
286 * Cleans up validation error messages. | |
287 * | |
288 * Should be called when the state is changed to 'candidate' or 'saving'. In | |
289 * the case of the latter: the user has modified the value in the in-place | |
290 * editor again to attempt to save again. In the case of the latter: the | |
291 * invalid value was discarded. | |
292 */ | |
293 removeValidationErrors() { | |
294 this.getEditedElement() | |
295 .removeClass('quickedit-validation-error') | |
296 .next('.quickedit-validation-errors') | |
297 .remove(); | |
298 }, | |
299 | |
300 }); | |
301 }(jQuery, Backbone, Drupal)); |