EntityToolbarView.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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, debounce) {
  8. Drupal.quickedit.EntityToolbarView = Backbone.View.extend({
  9. _fieldToolbarRoot: null,
  10. events: function events() {
  11. var map = {
  12. 'click button.action-save': 'onClickSave',
  13. 'click button.action-cancel': 'onClickCancel',
  14. mouseenter: 'onMouseenter'
  15. };
  16. return map;
  17. },
  18. initialize: function initialize(options) {
  19. var that = this;
  20. this.appModel = options.appModel;
  21. this.$entity = $(this.model.get('el'));
  22. this.listenTo(this.model, 'change:isActive change:isDirty change:state', this.render);
  23. this.listenTo(this.appModel, 'change:highlightedField change:activeField', this.render);
  24. this.listenTo(this.model.get('fields'), 'change:state', this.fieldStateChange);
  25. $(window).on('resize.quickedit scroll.quickedit drupalViewportOffsetChange.quickedit', debounce($.proxy(this.windowChangeHandler, this), 150));
  26. $(document).on('drupalViewportOffsetChange.quickedit', function (event, offsets) {
  27. if (that.$fence) {
  28. that.$fence.css(offsets);
  29. }
  30. });
  31. var $toolbar = this.buildToolbarEl();
  32. this.setElement($toolbar);
  33. this._fieldToolbarRoot = $toolbar.find('.quickedit-toolbar-field').get(0);
  34. this.render();
  35. },
  36. render: function render() {
  37. if (this.model.get('isActive')) {
  38. var $body = $('body');
  39. if ($body.children('#quickedit-entity-toolbar').length === 0) {
  40. $body.append(this.$el);
  41. }
  42. if ($body.children('#quickedit-toolbar-fence').length === 0) {
  43. this.$fence = $(Drupal.theme('quickeditEntityToolbarFence')).css(Drupal.displace()).appendTo($body);
  44. }
  45. this.label();
  46. this.show('ops');
  47. this.position();
  48. }
  49. var $button = this.$el.find('.quickedit-button.action-save');
  50. var isDirty = this.model.get('isDirty');
  51. switch (this.model.get('state')) {
  52. case 'opened':
  53. $button.removeClass('action-saving icon-throbber icon-end').text(Drupal.t('Save')).removeAttr('disabled').attr('aria-hidden', !isDirty);
  54. break;
  55. case 'committing':
  56. $button.addClass('action-saving icon-throbber icon-end').text(Drupal.t('Saving')).attr('disabled', 'disabled');
  57. break;
  58. default:
  59. $button.attr('aria-hidden', true);
  60. break;
  61. }
  62. return this;
  63. },
  64. remove: function remove() {
  65. this.$fence.remove();
  66. $(window).off('resize.quickedit scroll.quickedit drupalViewportOffsetChange.quickedit');
  67. $(document).off('drupalViewportOffsetChange.quickedit');
  68. Backbone.View.prototype.remove.call(this);
  69. },
  70. windowChangeHandler: function windowChangeHandler(event) {
  71. this.position();
  72. },
  73. fieldStateChange: function fieldStateChange(model, state) {
  74. switch (state) {
  75. case 'active':
  76. this.render();
  77. break;
  78. case 'invalid':
  79. this.render();
  80. break;
  81. }
  82. },
  83. position: function position(element) {
  84. clearTimeout(this.timer);
  85. var that = this;
  86. var edge = document.documentElement.dir === 'rtl' ? 'right' : 'left';
  87. var delay = 0;
  88. var check = 0;
  89. var horizontalPadding = 0;
  90. var of = void 0;
  91. var activeField = void 0;
  92. var highlightedField = void 0;
  93. do {
  94. switch (check) {
  95. case 0:
  96. of = element;
  97. break;
  98. case 1:
  99. activeField = Drupal.quickedit.app.model.get('activeField');
  100. of = activeField && activeField.editorView && activeField.editorView.$formContainer && activeField.editorView.$formContainer.find('.quickedit-form');
  101. break;
  102. case 2:
  103. of = activeField && activeField.editorView && activeField.editorView.getEditedElement();
  104. if (activeField && activeField.editorView && activeField.editorView.getQuickEditUISettings().padding) {
  105. horizontalPadding = 5;
  106. }
  107. break;
  108. case 3:
  109. highlightedField = Drupal.quickedit.app.model.get('highlightedField');
  110. of = highlightedField && highlightedField.editorView && highlightedField.editorView.getEditedElement();
  111. delay = 250;
  112. break;
  113. default:
  114. {
  115. var fieldModels = this.model.get('fields').models;
  116. var topMostPosition = 1000000;
  117. var topMostField = null;
  118. for (var i = 0; i < fieldModels.length; i++) {
  119. var pos = fieldModels[i].get('el').getBoundingClientRect().top;
  120. if (pos < topMostPosition) {
  121. topMostPosition = pos;
  122. topMostField = fieldModels[i];
  123. }
  124. }
  125. of = topMostField.get('el');
  126. delay = 50;
  127. break;
  128. }
  129. }
  130. check++;
  131. } while (!of);
  132. function refinePosition(view, suggested, info) {
  133. var isBelow = suggested.top > info.target.top;
  134. info.element.element.toggleClass('quickedit-toolbar-pointer-top', isBelow);
  135. if (view.$entity[0] === info.target.element[0]) {
  136. var $field = view.$entity.find('.quickedit-editable').eq(isBelow ? -1 : 0);
  137. if ($field.length > 0) {
  138. suggested.top = isBelow ? $field.offset().top + $field.outerHeight(true) : $field.offset().top - info.element.element.outerHeight(true);
  139. }
  140. }
  141. var fenceTop = view.$fence.offset().top;
  142. var fenceHeight = view.$fence.height();
  143. var toolbarHeight = info.element.element.outerHeight(true);
  144. if (suggested.top < fenceTop) {
  145. suggested.top = fenceTop;
  146. } else if (suggested.top + toolbarHeight > fenceTop + fenceHeight) {
  147. suggested.top = fenceTop + fenceHeight - toolbarHeight;
  148. }
  149. info.element.element.css({
  150. left: Math.floor(suggested.left),
  151. top: Math.floor(suggested.top)
  152. });
  153. }
  154. function positionToolbar() {
  155. that.$el.position({
  156. my: edge + ' bottom',
  157. at: edge + '+' + (1 + horizontalPadding) + ' top',
  158. of: of,
  159. collision: 'flipfit',
  160. using: refinePosition.bind(null, that),
  161. within: that.$fence
  162. }).css({
  163. 'max-width': document.documentElement.clientWidth < 450 ? document.documentElement.clientWidth : 450,
  164. 'min-width': document.documentElement.clientWidth < 240 ? document.documentElement.clientWidth : 240,
  165. width: '100%'
  166. });
  167. }
  168. this.timer = setTimeout(function () {
  169. _.defer(positionToolbar);
  170. }, delay);
  171. },
  172. onClickSave: function onClickSave(event) {
  173. event.stopPropagation();
  174. event.preventDefault();
  175. this.model.set('state', 'committing');
  176. },
  177. onClickCancel: function onClickCancel(event) {
  178. event.preventDefault();
  179. this.model.set('state', 'deactivating');
  180. },
  181. onMouseenter: function onMouseenter(event) {
  182. clearTimeout(this.timer);
  183. },
  184. buildToolbarEl: function buildToolbarEl() {
  185. var $toolbar = $(Drupal.theme('quickeditEntityToolbar', {
  186. id: 'quickedit-entity-toolbar'
  187. }));
  188. $toolbar.find('.quickedit-toolbar-entity').prepend(Drupal.theme('quickeditToolgroup', {
  189. classes: ['ops'],
  190. buttons: [{
  191. label: Drupal.t('Save'),
  192. type: 'submit',
  193. classes: 'action-save quickedit-button icon',
  194. attributes: {
  195. 'aria-hidden': true
  196. }
  197. }, {
  198. label: Drupal.t('Close'),
  199. classes: 'action-cancel quickedit-button icon icon-close icon-only'
  200. }]
  201. }));
  202. $toolbar.css({
  203. left: this.$entity.offset().left,
  204. top: this.$entity.offset().top
  205. });
  206. return $toolbar;
  207. },
  208. getToolbarRoot: function getToolbarRoot() {
  209. return this._fieldToolbarRoot;
  210. },
  211. label: function label() {
  212. var label = '';
  213. var entityLabel = this.model.get('label');
  214. var activeField = Drupal.quickedit.app.model.get('activeField');
  215. var activeFieldLabel = activeField && activeField.get('metadata').label;
  216. var highlightedField = Drupal.quickedit.app.model.get('highlightedField');
  217. var highlightedFieldLabel = highlightedField && highlightedField.get('metadata').label;
  218. if (activeFieldLabel) {
  219. label = Drupal.theme('quickeditEntityToolbarLabel', {
  220. entityLabel: entityLabel,
  221. fieldLabel: activeFieldLabel
  222. });
  223. } else if (highlightedFieldLabel) {
  224. label = Drupal.theme('quickeditEntityToolbarLabel', {
  225. entityLabel: entityLabel,
  226. fieldLabel: highlightedFieldLabel
  227. });
  228. } else {
  229. label = Drupal.checkPlain(entityLabel);
  230. }
  231. this.$el.find('.quickedit-toolbar-label').html(label);
  232. },
  233. addClass: function addClass(toolgroup, classes) {
  234. this._find(toolgroup).addClass(classes);
  235. },
  236. removeClass: function removeClass(toolgroup, classes) {
  237. this._find(toolgroup).removeClass(classes);
  238. },
  239. _find: function _find(toolgroup) {
  240. return this.$el.find('.quickedit-toolbar .quickedit-toolgroup.' + toolgroup);
  241. },
  242. show: function show(toolgroup) {
  243. this.$el.removeClass('quickedit-animate-invisible');
  244. }
  245. });
  246. })(jQuery, _, Backbone, Drupal, Drupal.debounce);