FieldToolbarView.es6.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /**
  2. * @file
  3. * A Backbone View that provides an interactive toolbar (1 per in-place editor).
  4. */
  5. (function ($, _, Backbone, Drupal) {
  6. Drupal.quickedit.FieldToolbarView = Backbone.View.extend(/** @lends Drupal.quickedit.FieldToolbarView# */{
  7. /**
  8. * The edited element, as indicated by EditorView.getEditedElement.
  9. *
  10. * @type {jQuery}
  11. */
  12. $editedElement: null,
  13. /**
  14. * A reference to the in-place editor.
  15. *
  16. * @type {Drupal.quickedit.EditorView}
  17. */
  18. editorView: null,
  19. /**
  20. * @type {string}
  21. */
  22. _id: null,
  23. /**
  24. * @constructs
  25. *
  26. * @augments Backbone.View
  27. *
  28. * @param {object} options
  29. * Options object to construct the field toolbar.
  30. * @param {jQuery} options.$editedElement
  31. * The element being edited.
  32. * @param {Drupal.quickedit.EditorView} options.editorView
  33. * The EditorView the toolbar belongs to.
  34. */
  35. initialize(options) {
  36. this.$editedElement = options.$editedElement;
  37. this.editorView = options.editorView;
  38. /**
  39. * @type {jQuery}
  40. */
  41. this.$root = this.$el;
  42. // Generate a DOM-compatible ID for the form container DOM element.
  43. this._id = `quickedit-toolbar-for-${this.model.id.replace(/[/[\]]/g, '_')}`;
  44. this.listenTo(this.model, 'change:state', this.stateChange);
  45. },
  46. /**
  47. * @inheritdoc
  48. *
  49. * @return {Drupal.quickedit.FieldToolbarView}
  50. * The current FieldToolbarView.
  51. */
  52. render() {
  53. // Render toolbar and set it as the view's element.
  54. this.setElement($(Drupal.theme('quickeditFieldToolbar', {
  55. id: this._id,
  56. })));
  57. // Attach to the field toolbar $root element in the entity toolbar.
  58. this.$el.prependTo(this.$root);
  59. return this;
  60. },
  61. /**
  62. * Determines the actions to take given a change of state.
  63. *
  64. * @param {Drupal.quickedit.FieldModel} model
  65. * The quickedit FieldModel
  66. * @param {string} state
  67. * The state of the associated field. One of
  68. * {@link Drupal.quickedit.FieldModel.states}.
  69. */
  70. stateChange(model, state) {
  71. const from = model.previous('state');
  72. const to = state;
  73. switch (to) {
  74. case 'inactive':
  75. break;
  76. case 'candidate':
  77. // Remove the view's existing element if we went to the 'activating'
  78. // state or later, because it will be recreated. Not doing this would
  79. // result in memory leaks.
  80. if (from !== 'inactive' && from !== 'highlighted') {
  81. this.$el.remove();
  82. this.setElement();
  83. }
  84. break;
  85. case 'highlighted':
  86. break;
  87. case 'activating':
  88. this.render();
  89. if (this.editorView.getQuickEditUISettings().fullWidthToolbar) {
  90. this.$el.addClass('quickedit-toolbar-fullwidth');
  91. }
  92. if (this.editorView.getQuickEditUISettings().unifiedToolbar) {
  93. this.insertWYSIWYGToolGroups();
  94. }
  95. break;
  96. case 'active':
  97. break;
  98. case 'changed':
  99. break;
  100. case 'saving':
  101. break;
  102. case 'saved':
  103. break;
  104. case 'invalid':
  105. break;
  106. }
  107. },
  108. /**
  109. * Insert WYSIWYG markup into the associated toolbar.
  110. */
  111. insertWYSIWYGToolGroups() {
  112. this.$el
  113. .append(Drupal.theme('quickeditToolgroup', {
  114. id: this.getFloatedWysiwygToolgroupId(),
  115. classes: ['wysiwyg-floated', 'quickedit-animate-slow', 'quickedit-animate-invisible', 'quickedit-animate-delay-veryfast'],
  116. buttons: [],
  117. }))
  118. .append(Drupal.theme('quickeditToolgroup', {
  119. id: this.getMainWysiwygToolgroupId(),
  120. classes: ['wysiwyg-main', 'quickedit-animate-slow', 'quickedit-animate-invisible', 'quickedit-animate-delay-veryfast'],
  121. buttons: [],
  122. }));
  123. // Animate the toolgroups into visibility.
  124. this.show('wysiwyg-floated');
  125. this.show('wysiwyg-main');
  126. },
  127. /**
  128. * Retrieves the ID for this toolbar's container.
  129. *
  130. * Only used to make sane hovering behavior possible.
  131. *
  132. * @return {string}
  133. * A string that can be used as the ID for this toolbar's container.
  134. */
  135. getId() {
  136. return `quickedit-toolbar-for-${this._id}`;
  137. },
  138. /**
  139. * Retrieves the ID for this toolbar's floating WYSIWYG toolgroup.
  140. *
  141. * Used to provide an abstraction for any WYSIWYG editor to plug in.
  142. *
  143. * @return {string}
  144. * A string that can be used as the ID.
  145. */
  146. getFloatedWysiwygToolgroupId() {
  147. return `quickedit-wysiwyg-floated-toolgroup-for-${this._id}`;
  148. },
  149. /**
  150. * Retrieves the ID for this toolbar's main WYSIWYG toolgroup.
  151. *
  152. * Used to provide an abstraction for any WYSIWYG editor to plug in.
  153. *
  154. * @return {string}
  155. * A string that can be used as the ID.
  156. */
  157. getMainWysiwygToolgroupId() {
  158. return `quickedit-wysiwyg-main-toolgroup-for-${this._id}`;
  159. },
  160. /**
  161. * Finds a toolgroup.
  162. *
  163. * @param {string} toolgroup
  164. * A toolgroup name.
  165. *
  166. * @return {jQuery}
  167. * The toolgroup element.
  168. */
  169. _find(toolgroup) {
  170. return this.$el.find(`.quickedit-toolgroup.${toolgroup}`);
  171. },
  172. /**
  173. * Shows a toolgroup.
  174. *
  175. * @param {string} toolgroup
  176. * A toolgroup name.
  177. */
  178. show(toolgroup) {
  179. const $group = this._find(toolgroup);
  180. // Attach a transitionEnd event handler to the toolbar group so that
  181. // update events can be triggered after the animations have ended.
  182. $group.on(Drupal.quickedit.util.constants.transitionEnd, (event) => {
  183. $group.off(Drupal.quickedit.util.constants.transitionEnd);
  184. });
  185. // The call to remove the class and start the animation must be started in
  186. // the next animation frame or the event handler attached above won't be
  187. // triggered.
  188. window.setTimeout(() => {
  189. $group.removeClass('quickedit-animate-invisible');
  190. }, 0);
  191. },
  192. });
  193. }(jQuery, _, Backbone, Drupal));