2 * DO NOT EDIT THIS FILE.
3 * See the following change record for more information,
4 * https://www.drupal.org/node/2815083
8 (function (_, $, Backbone, Drupal) {
9 Drupal.quickedit.EntityModel = Drupal.quickedit.BaseModel.extend({
15 entityInstanceID: null,
33 fieldsInTempStore: [],
38 initialize: function initialize() {
39 this.set('fields', new Drupal.quickedit.FieldCollection());
41 this.listenTo(this, 'change:state', this.stateChange);
43 this.listenTo(this.get('fields'), 'change:state', this.fieldStateChange);
45 Drupal.quickedit.BaseModel.prototype.initialize.call(this);
47 stateChange: function stateChange(entityModel, state, options) {
62 entityModel.get('fields').each(function (fieldModel) {
63 fieldModel.set('state', 'candidate', options);
68 this.set('isActive', true);
73 var fields = this.get('fields');
75 fields.chain().filter(function (fieldModel) {
76 return _.intersection([fieldModel.get('state')], ['active']).length;
77 }).each(function (fieldModel) {
78 fieldModel.set('state', 'candidate');
81 fields.chain().filter(function (fieldModel) {
82 return _.intersection([fieldModel.get('state')], Drupal.quickedit.app.changedFieldStates).length;
83 }).each(function (fieldModel) {
84 fieldModel.set('state', 'saving');
91 var changedFields = this.get('fields').filter(function (fieldModel) {
92 return _.intersection([fieldModel.get('state')], ['changed', 'invalid']).length;
95 if ((changedFields.length || this.get('fieldsInTempStore').length) && !options.saved && !options.confirmed) {
96 this.set('state', 'opened', { confirming: true });
99 Drupal.quickedit.app.confirmEntityDeactivation(entityModel);
102 var invalidFields = this.get('fields').filter(function (fieldModel) {
103 return _.intersection([fieldModel.get('state')], ['invalid']).length;
106 entityModel.set('reload', this.get('fieldsInTempStore').length || invalidFields.length);
108 entityModel.get('fields').each(function (fieldModel) {
109 if (_.intersection([fieldModel.get('state')], ['candidate', 'highlighted']).length) {
110 fieldModel.trigger('change:state', fieldModel, fieldModel.get('state'), options);
112 fieldModel.set('state', 'candidate', options);
120 options.reason = 'stop';
121 this.get('fields').each(function (fieldModel) {
130 _updateInTempStoreAttributes: function _updateInTempStoreAttributes(entityModel, fieldModel) {
131 var current = fieldModel.get('state');
132 var previous = fieldModel.previous('state');
133 var fieldsInTempStore = entityModel.get('fieldsInTempStore');
135 if (current === 'saved') {
136 entityModel.set('inTempStore', true);
138 fieldModel.set('inTempStore', true);
140 fieldsInTempStore.push(fieldModel.get('fieldID'));
141 fieldsInTempStore = _.uniq(fieldsInTempStore);
142 entityModel.set('fieldsInTempStore', fieldsInTempStore);
143 } else if (current === 'candidate' && previous === 'inactive') {
144 fieldModel.set('inTempStore', _.intersection([fieldModel.get('fieldID')], fieldsInTempStore).length > 0);
147 fieldStateChange: function fieldStateChange(fieldModel, state) {
148 var entityModel = this;
149 var fieldState = state;
151 switch (this.get('state')) {
157 _.defer(function () {
158 entityModel.set('state', 'opened', {
159 'accept-field-states': Drupal.quickedit.app.readyFieldStates
165 if (fieldState === 'changed') {
166 entityModel.set('isDirty', true);
168 this._updateInTempStoreAttributes(entityModel, fieldModel);
174 if (fieldState === 'invalid') {
175 _.defer(function () {
176 entityModel.set('state', 'opened', { reason: 'invalid' });
179 this._updateInTempStoreAttributes(entityModel, fieldModel);
183 'accept-field-states': Drupal.quickedit.app.readyFieldStates
185 if (entityModel.set('isCommitting', true, options)) {
187 success: function success() {
189 state: 'deactivating',
193 error: function error() {
194 entityModel.set('isCommitting', false);
196 entityModel.set('state', 'opened', { reason: 'networkerror' });
198 var message = Drupal.t('Your changes to <q>@entity-title</q> could not be saved, either due to a website problem or a network connection problem.<br>Please try again.', { '@entity-title': entityModel.get('label') });
199 Drupal.quickedit.util.networkErrorModal(Drupal.t('Network problem!'), message);
207 _.defer(function () {
208 entityModel.set('state', 'closing', {
209 'accept-field-states': Drupal.quickedit.app.readyFieldStates
215 _.defer(function () {
216 entityModel.set('state', 'closed', {
217 'accept-field-states': ['inactive']
223 save: function save(options) {
224 var entityModel = this;
226 var entitySaverAjax = Drupal.ajax({
227 url: Drupal.url('quickedit/entity/' + entityModel.get('entityID')),
228 error: function error() {
229 options.error.call(entityModel);
233 entitySaverAjax.commands.quickeditEntitySaved = function (ajax, response, status) {
234 entityModel.get('fields').each(function (fieldModel) {
235 fieldModel.set('inTempStore', false);
237 entityModel.set('inTempStore', false);
238 entityModel.set('fieldsInTempStore', []);
240 if (options.success) {
241 options.success.call(entityModel);
245 entitySaverAjax.execute();
247 validate: function validate(attrs, options) {
248 var acceptedFieldStates = options['accept-field-states'] || [];
250 var currentState = this.get('state');
251 var nextState = attrs.state;
252 if (currentState !== nextState) {
253 if (_.indexOf(this.constructor.states, nextState) === -1) {
254 return '"' + nextState + '" is an invalid state';
257 if (!this._acceptStateChange(currentState, nextState, options)) {
258 return 'state change not accepted';
259 } else if (!this._fieldsHaveAcceptableStates(acceptedFieldStates)) {
260 return 'state change not accepted because fields are not in acceptable state';
264 var currentIsCommitting = this.get('isCommitting');
265 var nextIsCommitting = attrs.isCommitting;
266 if (currentIsCommitting === false && nextIsCommitting === true) {
267 if (!this._fieldsHaveAcceptableStates(acceptedFieldStates)) {
268 return 'isCommitting change not accepted because fields are not in acceptable state';
270 } else if (currentIsCommitting === true && nextIsCommitting === true) {
271 return 'isCommitting is a mutex, hence only changes are allowed';
274 _acceptStateChange: function _acceptStateChange(from, to, context) {
277 if (!this.constructor.followsStateSequence(from, to)) {
280 if (from === 'closing' && to === 'closed') {
282 } else if (from === 'committing' && to === 'opened' && context.reason && (context.reason === 'invalid' || context.reason === 'networkerror')) {
284 } else if (from === 'deactivating' && to === 'opened' && context.confirming) {
286 } else if (from === 'opened' && to === 'deactivating' && context.confirmed) {
293 _fieldsHaveAcceptableStates: function _fieldsHaveAcceptableStates(acceptedFieldStates) {
296 if (acceptedFieldStates.length > 0) {
297 var fieldStates = this.get('fields').pluck('state') || [];
299 if (_.difference(fieldStates, acceptedFieldStates).length) {
306 destroy: function destroy(options) {
307 Drupal.quickedit.BaseModel.prototype.destroy.call(this, options);
309 this.stopListening();
311 this.get('fields').reset();
313 sync: function sync() {}
315 states: ['closed', 'launching', 'opening', 'opened', 'committing', 'deactivating', 'closing'],
317 followsStateSequence: function followsStateSequence(from, to) {
318 return _.indexOf(this.states, from) < _.indexOf(this.states, to);
322 Drupal.quickedit.EntityCollection = Backbone.Collection.extend({
323 model: Drupal.quickedit.EntityModel
325 })(_, jQuery, Backbone, Drupal);