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