AppView.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /**
  2. * DO NOT EDIT THIS FILE.
  3. * See the following change record for more information,
  4. * https://www.drupal.org/node/2815083
  5. * @preserve
  6. **/
  7. (function ($, _, Backbone, Drupal) {
  8. var reload = false;
  9. Drupal.quickedit.AppView = Backbone.View.extend({
  10. initialize: function initialize(options) {
  11. this.activeFieldStates = ['activating', 'active'];
  12. this.singleFieldStates = ['highlighted', 'activating', 'active'];
  13. this.changedFieldStates = ['changed', 'saving', 'saved', 'invalid'];
  14. this.readyFieldStates = ['candidate', 'highlighted'];
  15. this.listenTo(options.entitiesCollection, 'change:state', this.appStateChange);
  16. this.listenTo(options.entitiesCollection, 'change:isActive', this.enforceSingleActiveEntity);
  17. this.listenTo(options.fieldsCollection, 'change:state', this.editorStateChange);
  18. this.listenTo(options.fieldsCollection, 'change:html', this.renderUpdatedField);
  19. this.listenTo(options.fieldsCollection, 'change:html', this.propagateUpdatedField);
  20. this.listenTo(options.fieldsCollection, 'add', this.rerenderedFieldToCandidate);
  21. this.listenTo(options.fieldsCollection, 'destroy', this.teardownEditor);
  22. },
  23. appStateChange: function appStateChange(entityModel, state) {
  24. var app = this;
  25. var entityToolbarView = void 0;
  26. switch (state) {
  27. case 'launching':
  28. reload = false;
  29. entityToolbarView = new Drupal.quickedit.EntityToolbarView({
  30. model: entityModel,
  31. appModel: this.model
  32. });
  33. entityModel.toolbarView = entityToolbarView;
  34. entityModel.get('fields').each(function (fieldModel) {
  35. app.setupEditor(fieldModel);
  36. });
  37. _.defer(function () {
  38. entityModel.set('state', 'opening');
  39. });
  40. break;
  41. case 'closed':
  42. entityToolbarView = entityModel.toolbarView;
  43. entityModel.get('fields').each(function (fieldModel) {
  44. app.teardownEditor(fieldModel);
  45. });
  46. if (entityToolbarView) {
  47. entityToolbarView.remove();
  48. delete entityModel.toolbarView;
  49. }
  50. if (reload) {
  51. reload = false;
  52. location.reload();
  53. }
  54. break;
  55. }
  56. },
  57. acceptEditorStateChange: function acceptEditorStateChange(from, to, context, fieldModel) {
  58. var accept = true;
  59. if (context && (context.reason === 'stop' || context.reason === 'rerender')) {
  60. if (from === 'candidate' && to === 'inactive') {
  61. accept = true;
  62. }
  63. } else {
  64. if (!Drupal.quickedit.FieldModel.followsStateSequence(from, to)) {
  65. accept = false;
  66. if (_.indexOf(this.activeFieldStates, from) !== -1 && to === 'candidate') {
  67. accept = true;
  68. } else if ((from === 'changed' || from === 'invalid') && to === 'candidate') {
  69. accept = true;
  70. } else if (from === 'highlighted' && to === 'candidate') {
  71. accept = true;
  72. } else if (from === 'saved' && to === 'candidate') {
  73. accept = true;
  74. } else if (from === 'invalid' && to === 'saving') {
  75. accept = true;
  76. } else if (from === 'invalid' && to === 'activating') {
  77. accept = true;
  78. }
  79. }
  80. if (accept) {
  81. var activeField = void 0;
  82. var activeFieldState = void 0;
  83. if ((this.readyFieldStates.indexOf(from) !== -1 || from === 'invalid') && this.activeFieldStates.indexOf(to) !== -1) {
  84. activeField = this.model.get('activeField');
  85. if (activeField && activeField !== fieldModel) {
  86. activeFieldState = activeField.get('state');
  87. if (this.activeFieldStates.indexOf(activeFieldState) !== -1) {
  88. activeField.set('state', 'candidate');
  89. } else if (activeFieldState === 'changed' || activeFieldState === 'invalid') {
  90. activeField.set('state', 'saving');
  91. }
  92. if (from === 'invalid') {
  93. this.model.set('activeField', fieldModel);
  94. accept = false;
  95. }
  96. }
  97. } else if (_.indexOf(this.activeFieldStates, from) !== -1 && to === 'candidate') {
  98. if (context && context.reason === 'mouseleave') {
  99. accept = false;
  100. }
  101. } else if ((from === 'changed' || from === 'invalid') && to === 'candidate') {
  102. if (context && context.reason === 'mouseleave') {
  103. accept = false;
  104. } else if (context && context.confirmed) {
  105. accept = true;
  106. }
  107. }
  108. }
  109. }
  110. return accept;
  111. },
  112. setupEditor: function setupEditor(fieldModel) {
  113. var entityModel = fieldModel.get('entity');
  114. var entityToolbarView = entityModel.toolbarView;
  115. var fieldToolbarRoot = entityToolbarView.getToolbarRoot();
  116. var editorName = fieldModel.get('metadata').editor;
  117. var editorModel = new Drupal.quickedit.EditorModel();
  118. var editorView = new Drupal.quickedit.editors[editorName]({
  119. el: $(fieldModel.get('el')),
  120. model: editorModel,
  121. fieldModel: fieldModel
  122. });
  123. var toolbarView = new Drupal.quickedit.FieldToolbarView({
  124. el: fieldToolbarRoot,
  125. model: fieldModel,
  126. $editedElement: $(editorView.getEditedElement()),
  127. editorView: editorView,
  128. entityModel: entityModel
  129. });
  130. var decorationView = new Drupal.quickedit.FieldDecorationView({
  131. el: $(editorView.getEditedElement()),
  132. model: fieldModel,
  133. editorView: editorView
  134. });
  135. fieldModel.editorView = editorView;
  136. fieldModel.toolbarView = toolbarView;
  137. fieldModel.decorationView = decorationView;
  138. },
  139. teardownEditor: function teardownEditor(fieldModel) {
  140. if (typeof fieldModel.editorView === 'undefined') {
  141. return;
  142. }
  143. fieldModel.toolbarView.remove();
  144. delete fieldModel.toolbarView;
  145. fieldModel.decorationView.remove();
  146. delete fieldModel.decorationView;
  147. fieldModel.editorView.remove();
  148. delete fieldModel.editorView;
  149. },
  150. confirmEntityDeactivation: function confirmEntityDeactivation(entityModel) {
  151. var that = this;
  152. var discardDialog = void 0;
  153. function closeDiscardDialog(action) {
  154. discardDialog.close(action);
  155. that.model.set('activeModal', null);
  156. if (action === 'save') {
  157. entityModel.set('state', 'committing', { confirmed: true });
  158. } else {
  159. entityModel.set('state', 'deactivating', { confirmed: true });
  160. if (entityModel.get('reload')) {
  161. reload = true;
  162. entityModel.set('reload', false);
  163. }
  164. }
  165. }
  166. if (!this.model.get('activeModal')) {
  167. var $unsavedChanges = $('<div>' + Drupal.t('You have unsaved changes') + '</div>');
  168. discardDialog = Drupal.dialog($unsavedChanges.get(0), {
  169. title: Drupal.t('Discard changes?'),
  170. dialogClass: 'quickedit-discard-modal',
  171. resizable: false,
  172. buttons: [{
  173. text: Drupal.t('Save'),
  174. click: function click() {
  175. closeDiscardDialog('save');
  176. },
  177. primary: true
  178. }, {
  179. text: Drupal.t('Discard changes'),
  180. click: function click() {
  181. closeDiscardDialog('discard');
  182. }
  183. }],
  184. closeOnEscape: false,
  185. create: function create() {
  186. $(this).parent().find('.ui-dialog-titlebar-close').remove();
  187. },
  188. beforeClose: false,
  189. close: function close(event) {
  190. $(event.target).remove();
  191. }
  192. });
  193. this.model.set('activeModal', discardDialog);
  194. discardDialog.showModal();
  195. }
  196. },
  197. editorStateChange: function editorStateChange(fieldModel, state) {
  198. var from = fieldModel.previous('state');
  199. var to = state;
  200. if (_.indexOf(this.singleFieldStates, to) !== -1 && this.model.get('highlightedField') !== fieldModel) {
  201. this.model.set('highlightedField', fieldModel);
  202. } else if (this.model.get('highlightedField') === fieldModel && to === 'candidate') {
  203. this.model.set('highlightedField', null);
  204. }
  205. if (_.indexOf(this.activeFieldStates, to) !== -1 && this.model.get('activeField') !== fieldModel) {
  206. this.model.set('activeField', fieldModel);
  207. } else if (this.model.get('activeField') === fieldModel && to === 'candidate') {
  208. if (from === 'changed' || from === 'invalid') {
  209. fieldModel.editorView.revert();
  210. }
  211. this.model.set('activeField', null);
  212. }
  213. },
  214. renderUpdatedField: function renderUpdatedField(fieldModel, html, options) {
  215. var $fieldWrapper = $(fieldModel.get('el'));
  216. var $context = $fieldWrapper.parent();
  217. var renderField = function renderField() {
  218. fieldModel.destroy();
  219. $fieldWrapper.replaceWith(html);
  220. Drupal.attachBehaviors($context.get(0));
  221. };
  222. if (!options.propagation) {
  223. _.defer(function () {
  224. fieldModel.set('state', 'candidate');
  225. _.defer(function () {
  226. fieldModel.set('state', 'inactive', { reason: 'rerender' });
  227. renderField();
  228. });
  229. });
  230. } else {
  231. renderField();
  232. }
  233. },
  234. propagateUpdatedField: function propagateUpdatedField(updatedField, html, options) {
  235. if (options.propagation) {
  236. return;
  237. }
  238. var htmlForOtherViewModes = updatedField.get('htmlForOtherViewModes');
  239. Drupal.quickedit.collections.fields.where({ logicalFieldID: updatedField.get('logicalFieldID') }).forEach(function (field) {
  240. if (field === updatedField) {} else if (field.getViewMode() === updatedField.getViewMode()) {
  241. field.set('html', updatedField.get('html'));
  242. } else if (field.getViewMode() in htmlForOtherViewModes) {
  243. field.set('html', htmlForOtherViewModes[field.getViewMode()], { propagation: true });
  244. }
  245. });
  246. },
  247. rerenderedFieldToCandidate: function rerenderedFieldToCandidate(fieldModel) {
  248. var activeEntity = Drupal.quickedit.collections.entities.findWhere({ isActive: true });
  249. if (!activeEntity) {
  250. return;
  251. }
  252. if (fieldModel.get('entity') === activeEntity) {
  253. this.setupEditor(fieldModel);
  254. fieldModel.set('state', 'candidate');
  255. }
  256. },
  257. enforceSingleActiveEntity: function enforceSingleActiveEntity(changedEntityModel) {
  258. if (changedEntityModel.get('isActive') === false) {
  259. return;
  260. }
  261. changedEntityModel.collection.chain().filter(function (entityModel) {
  262. return entityModel.get('isActive') === true && entityModel !== changedEntityModel;
  263. }).each(function (entityModel) {
  264. entityModel.set('state', 'deactivating');
  265. });
  266. }
  267. });
  268. })(jQuery, _, Backbone, Drupal);