Chris@0: /** Chris@0: * DO NOT EDIT THIS FILE. Chris@0: * See the following change record for more information, Chris@0: * https://www.drupal.org/node/2815083 Chris@0: * @preserve Chris@0: **/ Chris@0: Chris@0: (function ($, _, Backbone, Drupal, debounce) { Chris@0: Drupal.quickedit.EntityToolbarView = Backbone.View.extend({ Chris@0: _fieldToolbarRoot: null, Chris@0: Chris@0: events: function events() { Chris@0: var map = { Chris@0: 'click button.action-save': 'onClickSave', Chris@0: 'click button.action-cancel': 'onClickCancel', Chris@0: mouseenter: 'onMouseenter' Chris@0: }; Chris@0: return map; Chris@0: }, Chris@0: initialize: function initialize(options) { Chris@0: var that = this; Chris@0: this.appModel = options.appModel; Chris@0: this.$entity = $(this.model.get('el')); Chris@0: Chris@0: this.listenTo(this.model, 'change:isActive change:isDirty change:state', this.render); Chris@0: Chris@0: this.listenTo(this.appModel, 'change:highlightedField change:activeField', this.render); Chris@0: Chris@0: this.listenTo(this.model.get('fields'), 'change:state', this.fieldStateChange); Chris@0: Chris@0: $(window).on('resize.quickedit scroll.quickedit drupalViewportOffsetChange.quickedit', debounce($.proxy(this.windowChangeHandler, this), 150)); Chris@0: Chris@0: $(document).on('drupalViewportOffsetChange.quickedit', function (event, offsets) { Chris@0: if (that.$fence) { Chris@0: that.$fence.css(offsets); Chris@0: } Chris@0: }); Chris@0: Chris@0: var $toolbar = this.buildToolbarEl(); Chris@0: this.setElement($toolbar); Chris@0: this._fieldToolbarRoot = $toolbar.find('.quickedit-toolbar-field').get(0); Chris@0: Chris@0: this.render(); Chris@0: }, Chris@0: render: function render() { Chris@0: if (this.model.get('isActive')) { Chris@0: var $body = $('body'); Chris@0: if ($body.children('#quickedit-entity-toolbar').length === 0) { Chris@0: $body.append(this.$el); Chris@0: } Chris@0: Chris@0: if ($body.children('#quickedit-toolbar-fence').length === 0) { Chris@0: this.$fence = $(Drupal.theme('quickeditEntityToolbarFence')).css(Drupal.displace()).appendTo($body); Chris@0: } Chris@0: Chris@0: this.label(); Chris@0: Chris@0: this.show('ops'); Chris@0: Chris@0: this.position(); Chris@0: } Chris@0: Chris@0: var $button = this.$el.find('.quickedit-button.action-save'); Chris@0: var isDirty = this.model.get('isDirty'); Chris@0: Chris@0: switch (this.model.get('state')) { Chris@0: case 'opened': Chris@0: $button.removeClass('action-saving icon-throbber icon-end').text(Drupal.t('Save')).removeAttr('disabled').attr('aria-hidden', !isDirty); Chris@0: break; Chris@0: Chris@0: case 'committing': Chris@0: $button.addClass('action-saving icon-throbber icon-end').text(Drupal.t('Saving')).attr('disabled', 'disabled'); Chris@0: break; Chris@0: Chris@0: default: Chris@0: $button.attr('aria-hidden', true); Chris@0: break; Chris@0: } Chris@0: Chris@0: return this; Chris@0: }, Chris@0: remove: function remove() { Chris@0: this.$fence.remove(); Chris@0: Chris@0: $(window).off('resize.quickedit scroll.quickedit drupalViewportOffsetChange.quickedit'); Chris@0: $(document).off('drupalViewportOffsetChange.quickedit'); Chris@0: Chris@0: Backbone.View.prototype.remove.call(this); Chris@0: }, Chris@0: windowChangeHandler: function windowChangeHandler(event) { Chris@0: this.position(); Chris@0: }, Chris@0: fieldStateChange: function fieldStateChange(model, state) { Chris@0: switch (state) { Chris@0: case 'active': Chris@0: this.render(); Chris@0: break; Chris@0: Chris@0: case 'invalid': Chris@0: this.render(); Chris@0: break; Chris@0: } Chris@0: }, Chris@0: position: function position(element) { Chris@0: clearTimeout(this.timer); Chris@0: Chris@0: var that = this; Chris@0: Chris@0: var edge = document.documentElement.dir === 'rtl' ? 'right' : 'left'; Chris@0: Chris@0: var delay = 0; Chris@0: Chris@0: var check = 0; Chris@0: Chris@0: var horizontalPadding = 0; Chris@0: var of = void 0; Chris@0: var activeField = void 0; Chris@0: var highlightedField = void 0; Chris@0: Chris@0: do { Chris@0: switch (check) { Chris@0: case 0: Chris@0: of = element; Chris@0: break; Chris@0: Chris@0: case 1: Chris@0: activeField = Drupal.quickedit.app.model.get('activeField'); Chris@0: of = activeField && activeField.editorView && activeField.editorView.$formContainer && activeField.editorView.$formContainer.find('.quickedit-form'); Chris@0: break; Chris@0: Chris@0: case 2: Chris@0: of = activeField && activeField.editorView && activeField.editorView.getEditedElement(); Chris@0: if (activeField && activeField.editorView && activeField.editorView.getQuickEditUISettings().padding) { Chris@0: horizontalPadding = 5; Chris@0: } Chris@0: break; Chris@0: Chris@0: case 3: Chris@0: highlightedField = Drupal.quickedit.app.model.get('highlightedField'); Chris@0: of = highlightedField && highlightedField.editorView && highlightedField.editorView.getEditedElement(); Chris@0: delay = 250; Chris@0: break; Chris@0: Chris@0: default: Chris@14: { Chris@14: var fieldModels = this.model.get('fields').models; Chris@14: var topMostPosition = 1000000; Chris@14: var topMostField = null; Chris@0: Chris@14: for (var i = 0; i < fieldModels.length; i++) { Chris@14: var pos = fieldModels[i].get('el').getBoundingClientRect().top; Chris@14: if (pos < topMostPosition) { Chris@14: topMostPosition = pos; Chris@14: topMostField = fieldModels[i]; Chris@14: } Chris@0: } Chris@14: of = topMostField.get('el'); Chris@14: delay = 50; Chris@14: break; Chris@0: } Chris@0: } Chris@0: Chris@0: check++; Chris@0: } while (!of); Chris@0: Chris@0: function refinePosition(view, suggested, info) { Chris@0: var isBelow = suggested.top > info.target.top; Chris@0: info.element.element.toggleClass('quickedit-toolbar-pointer-top', isBelow); Chris@0: Chris@0: if (view.$entity[0] === info.target.element[0]) { Chris@0: var $field = view.$entity.find('.quickedit-editable').eq(isBelow ? -1 : 0); Chris@0: if ($field.length > 0) { Chris@0: suggested.top = isBelow ? $field.offset().top + $field.outerHeight(true) : $field.offset().top - info.element.element.outerHeight(true); Chris@0: } Chris@0: } Chris@0: Chris@0: var fenceTop = view.$fence.offset().top; Chris@0: var fenceHeight = view.$fence.height(); Chris@0: var toolbarHeight = info.element.element.outerHeight(true); Chris@0: if (suggested.top < fenceTop) { Chris@0: suggested.top = fenceTop; Chris@0: } else if (suggested.top + toolbarHeight > fenceTop + fenceHeight) { Chris@0: suggested.top = fenceTop + fenceHeight - toolbarHeight; Chris@0: } Chris@0: Chris@0: info.element.element.css({ Chris@0: left: Math.floor(suggested.left), Chris@0: top: Math.floor(suggested.top) Chris@0: }); Chris@0: } Chris@0: Chris@0: function positionToolbar() { Chris@0: that.$el.position({ Chris@0: my: edge + ' bottom', Chris@0: Chris@0: at: edge + '+' + (1 + horizontalPadding) + ' top', Chris@0: of: of, Chris@0: collision: 'flipfit', Chris@0: using: refinePosition.bind(null, that), Chris@0: within: that.$fence Chris@0: }).css({ Chris@0: 'max-width': document.documentElement.clientWidth < 450 ? document.documentElement.clientWidth : 450, Chris@0: Chris@0: 'min-width': document.documentElement.clientWidth < 240 ? document.documentElement.clientWidth : 240, Chris@0: width: '100%' Chris@0: }); Chris@0: } Chris@0: Chris@0: this.timer = setTimeout(function () { Chris@0: _.defer(positionToolbar); Chris@0: }, delay); Chris@0: }, Chris@0: onClickSave: function onClickSave(event) { Chris@0: event.stopPropagation(); Chris@0: event.preventDefault(); Chris@0: Chris@0: this.model.set('state', 'committing'); Chris@0: }, Chris@0: onClickCancel: function onClickCancel(event) { Chris@0: event.preventDefault(); Chris@0: this.model.set('state', 'deactivating'); Chris@0: }, Chris@0: onMouseenter: function onMouseenter(event) { Chris@0: clearTimeout(this.timer); Chris@0: }, Chris@0: buildToolbarEl: function buildToolbarEl() { Chris@0: var $toolbar = $(Drupal.theme('quickeditEntityToolbar', { Chris@0: id: 'quickedit-entity-toolbar' Chris@0: })); Chris@0: Chris@0: $toolbar.find('.quickedit-toolbar-entity').prepend(Drupal.theme('quickeditToolgroup', { Chris@0: classes: ['ops'], Chris@0: buttons: [{ Chris@0: label: Drupal.t('Save'), Chris@0: type: 'submit', Chris@0: classes: 'action-save quickedit-button icon', Chris@0: attributes: { Chris@0: 'aria-hidden': true Chris@0: } Chris@0: }, { Chris@0: label: Drupal.t('Close'), Chris@0: classes: 'action-cancel quickedit-button icon icon-close icon-only' Chris@0: }] Chris@0: })); Chris@0: Chris@0: $toolbar.css({ Chris@0: left: this.$entity.offset().left, Chris@0: top: this.$entity.offset().top Chris@0: }); Chris@0: Chris@0: return $toolbar; Chris@0: }, Chris@0: getToolbarRoot: function getToolbarRoot() { Chris@0: return this._fieldToolbarRoot; Chris@0: }, Chris@0: label: function label() { Chris@0: var label = ''; Chris@0: var entityLabel = this.model.get('label'); Chris@0: Chris@0: var activeField = Drupal.quickedit.app.model.get('activeField'); Chris@0: var activeFieldLabel = activeField && activeField.get('metadata').label; Chris@0: Chris@0: var highlightedField = Drupal.quickedit.app.model.get('highlightedField'); Chris@0: var highlightedFieldLabel = highlightedField && highlightedField.get('metadata').label; Chris@0: Chris@0: if (activeFieldLabel) { Chris@0: label = Drupal.theme('quickeditEntityToolbarLabel', { Chris@0: entityLabel: entityLabel, Chris@0: fieldLabel: activeFieldLabel Chris@0: }); Chris@0: } else if (highlightedFieldLabel) { Chris@0: label = Drupal.theme('quickeditEntityToolbarLabel', { Chris@0: entityLabel: entityLabel, Chris@0: fieldLabel: highlightedFieldLabel Chris@0: }); Chris@0: } else { Chris@0: label = Drupal.checkPlain(entityLabel); Chris@0: } Chris@0: Chris@0: this.$el.find('.quickedit-toolbar-label').html(label); Chris@0: }, Chris@0: addClass: function addClass(toolgroup, classes) { Chris@0: this._find(toolgroup).addClass(classes); Chris@0: }, Chris@0: removeClass: function removeClass(toolgroup, classes) { Chris@0: this._find(toolgroup).removeClass(classes); Chris@0: }, Chris@0: _find: function _find(toolgroup) { Chris@0: return this.$el.find('.quickedit-toolbar .quickedit-toolgroup.' + toolgroup); Chris@0: }, Chris@0: show: function show(toolgroup) { Chris@0: this.$el.removeClass('quickedit-animate-invisible'); Chris@0: } Chris@0: }); Chris@0: })(jQuery, _, Backbone, Drupal, Drupal.debounce);