X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=blobdiff_plain;f=web%2Fcore%2Fmodules%2Fquickedit%2Fjs%2Fviews%2FEntityToolbarView.es6.js;fp=web%2Fcore%2Fmodules%2Fquickedit%2Fjs%2Fviews%2FEntityToolbarView.es6.js;h=0c9628d075228d063baaada3f1fc8dbdd315ab70;hp=9975ff353569da83c387c3306c94266f84f32433;hb=0bf8d09d2542548982e81a441b1f16e75873a04f;hpb=74df008bdbb3a11eeea356744f39b802369bda3c diff --git a/web/core/modules/quickedit/js/views/EntityToolbarView.es6.js b/web/core/modules/quickedit/js/views/EntityToolbarView.es6.js index 9975ff353..0c9628d07 100644 --- a/web/core/modules/quickedit/js/views/EntityToolbarView.es6.js +++ b/web/core/modules/quickedit/js/views/EntityToolbarView.es6.js @@ -3,523 +3,580 @@ * A Backbone View that provides an entity level toolbar. */ -(function ($, _, Backbone, Drupal, debounce) { - Drupal.quickedit.EntityToolbarView = Backbone.View.extend(/** @lends Drupal.quickedit.EntityToolbarView# */{ - - /** - * @type {jQuery} - */ - _fieldToolbarRoot: null, - - /** - * @return {object} - * A map of events. - */ - events() { - const map = { - 'click button.action-save': 'onClickSave', - 'click button.action-cancel': 'onClickCancel', - mouseenter: 'onMouseenter', - }; - return map; - }, +(function($, _, Backbone, Drupal, debounce) { + Drupal.quickedit.EntityToolbarView = Backbone.View.extend( + /** @lends Drupal.quickedit.EntityToolbarView# */ { + /** + * @type {jQuery} + */ + _fieldToolbarRoot: null, - /** - * @constructs - * - * @augments Backbone.View - * - * @param {object} options - * Options to construct the view. - * @param {Drupal.quickedit.AppModel} options.appModel - * A quickedit `AppModel` to use in the view. - */ - initialize(options) { - const that = this; - this.appModel = options.appModel; - this.$entity = $(this.model.get('el')); - - // Rerender whenever the entity state changes. - this.listenTo(this.model, 'change:isActive change:isDirty change:state', this.render); - // Also rerender whenever a different field is highlighted or activated. - this.listenTo(this.appModel, 'change:highlightedField change:activeField', this.render); - // Rerender when a field of the entity changes state. - this.listenTo(this.model.get('fields'), 'change:state', this.fieldStateChange); - - // Reposition the entity toolbar as the viewport and the position within - // the viewport changes. - $(window).on('resize.quickedit scroll.quickedit drupalViewportOffsetChange.quickedit', debounce($.proxy(this.windowChangeHandler, this), 150)); - - // Adjust the fence placement within which the entity toolbar may be - // positioned. - $(document).on('drupalViewportOffsetChange.quickedit', (event, offsets) => { - if (that.$fence) { - that.$fence.css(offsets); - } - }); + /** + * @return {object} + * A map of events. + */ + events() { + const map = { + 'click button.action-save': 'onClickSave', + 'click button.action-cancel': 'onClickCancel', + mouseenter: 'onMouseenter', + }; + return map; + }, + + /** + * @constructs + * + * @augments Backbone.View + * + * @param {object} options + * Options to construct the view. + * @param {Drupal.quickedit.AppModel} options.appModel + * A quickedit `AppModel` to use in the view. + */ + initialize(options) { + const that = this; + this.appModel = options.appModel; + this.$entity = $(this.model.get('el')); + + // Rerender whenever the entity state changes. + this.listenTo( + this.model, + 'change:isActive change:isDirty change:state', + this.render, + ); + // Also rerender whenever a different field is highlighted or activated. + this.listenTo( + this.appModel, + 'change:highlightedField change:activeField', + this.render, + ); + // Rerender when a field of the entity changes state. + this.listenTo( + this.model.get('fields'), + 'change:state', + this.fieldStateChange, + ); + + // Reposition the entity toolbar as the viewport and the position within + // the viewport changes. + $(window).on( + 'resize.quickedit scroll.quickedit drupalViewportOffsetChange.quickedit', + debounce($.proxy(this.windowChangeHandler, this), 150), + ); + + // Adjust the fence placement within which the entity toolbar may be + // positioned. + $(document).on( + 'drupalViewportOffsetChange.quickedit', + (event, offsets) => { + if (that.$fence) { + that.$fence.css(offsets); + } + }, + ); - // Set the entity toolbar DOM element as the el for this view. - const $toolbar = this.buildToolbarEl(); - this.setElement($toolbar); - this._fieldToolbarRoot = $toolbar.find('.quickedit-toolbar-field').get(0); + // Set the entity toolbar DOM element as the el for this view. + const $toolbar = this.buildToolbarEl(); + this.setElement($toolbar); + this._fieldToolbarRoot = $toolbar + .find('.quickedit-toolbar-field') + .get(0); - // Initial render. - this.render(); - }, + // Initial render. + this.render(); + }, - /** - * @inheritdoc - * - * @return {Drupal.quickedit.EntityToolbarView} - * The entity toolbar view. - */ - render() { - if (this.model.get('isActive')) { - // If the toolbar container doesn't exist, create it. - const $body = $('body'); - if ($body.children('#quickedit-entity-toolbar').length === 0) { - $body.append(this.$el); - } - // The fence will define a area on the screen that the entity toolbar - // will be position within. - if ($body.children('#quickedit-toolbar-fence').length === 0) { - this.$fence = $(Drupal.theme('quickeditEntityToolbarFence')) - .css(Drupal.displace()) - .appendTo($body); + /** + * @inheritdoc + * + * @return {Drupal.quickedit.EntityToolbarView} + * The entity toolbar view. + */ + render() { + if (this.model.get('isActive')) { + // If the toolbar container doesn't exist, create it. + const $body = $('body'); + if ($body.children('#quickedit-entity-toolbar').length === 0) { + $body.append(this.$el); + } + // The fence will define a area on the screen that the entity toolbar + // will be position within. + if ($body.children('#quickedit-toolbar-fence').length === 0) { + this.$fence = $(Drupal.theme('quickeditEntityToolbarFence')) + .css(Drupal.displace()) + .appendTo($body); + } + // Adds the entity title to the toolbar. + this.label(); + + // Show the save and cancel buttons. + this.show('ops'); + // If render is being called and the toolbar is already visible, just + // reposition it. + this.position(); } - // Adds the entity title to the toolbar. - this.label(); - // Show the save and cancel buttons. - this.show('ops'); - // If render is being called and the toolbar is already visible, just - // reposition it. - this.position(); - } - - // The save button text and state varies with the state of the entity - // model. - const $button = this.$el.find('.quickedit-button.action-save'); - const isDirty = this.model.get('isDirty'); - // Adjust the save button according to the state of the model. - switch (this.model.get('state')) { - // Quick editing is active, but no field is being edited. - case 'opened': - // The saving throbber is not managed by AJAX system. The - // EntityToolbarView manages this visual element. - $button - .removeClass('action-saving icon-throbber icon-end') - .text(Drupal.t('Save')) - .removeAttr('disabled') - .attr('aria-hidden', !isDirty); - break; - - // The changes to the fields of the entity are being committed. - case 'committing': - $button - .addClass('action-saving icon-throbber icon-end') - .text(Drupal.t('Saving')) - .attr('disabled', 'disabled'); - break; - - default: - $button.attr('aria-hidden', true); - break; - } - - return this; - }, + // The save button text and state varies with the state of the entity + // model. + const $button = this.$el.find('.quickedit-button.action-save'); + const isDirty = this.model.get('isDirty'); + // Adjust the save button according to the state of the model. + switch (this.model.get('state')) { + // Quick editing is active, but no field is being edited. + case 'opened': + // The saving throbber is not managed by AJAX system. The + // EntityToolbarView manages this visual element. + $button + .removeClass('action-saving icon-throbber icon-end') + .text(Drupal.t('Save')) + .removeAttr('disabled') + .attr('aria-hidden', !isDirty); + break; - /** - * @inheritdoc - */ - remove() { - // Remove additional DOM elements controlled by this View. - this.$fence.remove(); + // The changes to the fields of the entity are being committed. + case 'committing': + $button + .addClass('action-saving icon-throbber icon-end') + .text(Drupal.t('Saving')) + .attr('disabled', 'disabled'); + break; - // Stop listening to additional events. - $(window).off('resize.quickedit scroll.quickedit drupalViewportOffsetChange.quickedit'); - $(document).off('drupalViewportOffsetChange.quickedit'); + default: + $button.attr('aria-hidden', true); + break; + } - Backbone.View.prototype.remove.call(this); - }, + return this; + }, - /** - * Repositions the entity toolbar on window scroll and resize. - * - * @param {jQuery.Event} event - * The scroll or resize event. - */ - windowChangeHandler(event) { - this.position(); - }, + /** + * @inheritdoc + */ + remove() { + // Remove additional DOM elements controlled by this View. + this.$fence.remove(); - /** - * Determines the actions to take given a change of state. - * - * @param {Drupal.quickedit.FieldModel} model - * The `FieldModel` model. - * @param {string} state - * The state of the associated field. One of - * {@link Drupal.quickedit.FieldModel.states}. - */ - fieldStateChange(model, state) { - switch (state) { - case 'active': - this.render(); - break; - - case 'invalid': - this.render(); - break; - } - }, + // Stop listening to additional events. + $(window).off( + 'resize.quickedit scroll.quickedit drupalViewportOffsetChange.quickedit', + ); + $(document).off('drupalViewportOffsetChange.quickedit'); - /** - * Uses the jQuery.ui.position() method to position the entity toolbar. - * - * @param {HTMLElement} [element] - * The element against which the entity toolbar is positioned. - */ - position(element) { - clearTimeout(this.timer); - - const that = this; - // Vary the edge of the positioning according to the direction of language - // in the document. - const edge = (document.documentElement.dir === 'rtl') ? 'right' : 'left'; - // A time unit to wait until the entity toolbar is repositioned. - let delay = 0; - // Determines what check in the series of checks below should be - // evaluated. - let check = 0; - // When positioned against an active field that has padding, we should - // ignore that padding when positioning the toolbar, to not unnecessarily - // move the toolbar horizontally, which feels annoying. - let horizontalPadding = 0; - let of; - let activeField; - let highlightedField; - // There are several elements in the page that the entity toolbar might be - // positioned against. They are considered below in a priority order. - do { - switch (check) { - case 0: - // Position against a specific element. - of = element; - break; + Backbone.View.prototype.remove.call(this); + }, - case 1: - // Position against a form container. - activeField = Drupal.quickedit.app.model.get('activeField'); - of = activeField && activeField.editorView && activeField.editorView.$formContainer && activeField.editorView.$formContainer.find('.quickedit-form'); - break; - - case 2: - // Position against an active field. - of = activeField && activeField.editorView && activeField.editorView.getEditedElement(); - if (activeField && activeField.editorView && activeField.editorView.getQuickEditUISettings().padding) { - horizontalPadding = 5; - } - break; + /** + * Repositions the entity toolbar on window scroll and resize. + * + * @param {jQuery.Event} event + * The scroll or resize event. + */ + windowChangeHandler(event) { + this.position(); + }, - case 3: - // Position against a highlighted field. - highlightedField = Drupal.quickedit.app.model.get('highlightedField'); - of = highlightedField && highlightedField.editorView && highlightedField.editorView.getEditedElement(); - delay = 250; + /** + * Determines the actions to take given a change of state. + * + * @param {Drupal.quickedit.FieldModel} model + * The `FieldModel` model. + * @param {string} state + * The state of the associated field. One of + * {@link Drupal.quickedit.FieldModel.states}. + */ + fieldStateChange(model, state) { + switch (state) { + case 'active': + this.render(); break; - default: { - const fieldModels = this.model.get('fields').models; - let topMostPosition = 1000000; - let topMostField = null; - // Position against the topmost field. - for (let i = 0; i < fieldModels.length; i++) { - const pos = fieldModels[i].get('el').getBoundingClientRect().top; - if (pos < topMostPosition) { - topMostPosition = pos; - topMostField = fieldModels[i]; - } - } - of = topMostField.get('el'); - delay = 50; + case 'invalid': + this.render(); break; - } } - // Prepare to check the next possible element to position against. - check++; - } while (!of); + }, /** - * Refines the positioning algorithm of jquery.ui.position(). - * - * Invoked as the 'using' callback of jquery.ui.position() in - * positionToolbar(). + * Uses the jQuery.ui.position() method to position the entity toolbar. * - * @param {*} view - * The view the positions will be calculated from. - * @param {object} suggested - * A hash of top and left values for the position that should be set. It - * can be forwarded to .css() or .animate(). - * @param {object} info - * The position and dimensions of both the 'my' element and the 'of' - * elements, as well as calculations to their relative position. This - * object contains the following properties: - * @param {object} info.element - * A hash that contains information about the HTML element that will be - * positioned. Also known as the 'my' element. - * @param {object} info.target - * A hash that contains information about the HTML element that the - * 'my' element will be positioned against. Also known as the 'of' - * element. + * @param {HTMLElement} [element] + * The element against which the entity toolbar is positioned. */ - function refinePosition(view, suggested, info) { - // Determine if the pointer should be on the top or bottom. - const isBelow = suggested.top > info.target.top; - info.element.element.toggleClass('quickedit-toolbar-pointer-top', isBelow); - // Don't position the toolbar past the first or last editable field if - // the entity is the target. - if (view.$entity[0] === info.target.element[0]) { - // Get the first or last field according to whether the toolbar is - // above or below the entity. - const $field = view.$entity.find('.quickedit-editable').eq((isBelow) ? -1 : 0); - if ($field.length > 0) { - suggested.top = (isBelow) ? ($field.offset().top + $field.outerHeight(true)) : $field.offset().top - info.element.element.outerHeight(true); + position(element) { + clearTimeout(this.timer); + + const that = this; + // Vary the edge of the positioning according to the direction of language + // in the document. + const edge = document.documentElement.dir === 'rtl' ? 'right' : 'left'; + // A time unit to wait until the entity toolbar is repositioned. + let delay = 0; + // Determines what check in the series of checks below should be + // evaluated. + let check = 0; + // When positioned against an active field that has padding, we should + // ignore that padding when positioning the toolbar, to not unnecessarily + // move the toolbar horizontally, which feels annoying. + let horizontalPadding = 0; + let of; + let activeField; + let highlightedField; + // There are several elements in the page that the entity toolbar might be + // positioned against. They are considered below in a priority order. + do { + switch (check) { + case 0: + // Position against a specific element. + of = element; + break; + + case 1: + // Position against a form container. + activeField = Drupal.quickedit.app.model.get('activeField'); + of = + activeField && + activeField.editorView && + activeField.editorView.$formContainer && + activeField.editorView.$formContainer.find('.quickedit-form'); + break; + + case 2: + // Position against an active field. + of = + activeField && + activeField.editorView && + activeField.editorView.getEditedElement(); + if ( + activeField && + activeField.editorView && + activeField.editorView.getQuickEditUISettings().padding + ) { + horizontalPadding = 5; + } + break; + + case 3: + // Position against a highlighted field. + highlightedField = Drupal.quickedit.app.model.get( + 'highlightedField', + ); + of = + highlightedField && + highlightedField.editorView && + highlightedField.editorView.getEditedElement(); + delay = 250; + break; + + default: { + const fieldModels = this.model.get('fields').models; + let topMostPosition = 1000000; + let topMostField = null; + // Position against the topmost field. + for (let i = 0; i < fieldModels.length; i++) { + const pos = fieldModels[i].get('el').getBoundingClientRect() + .top; + if (pos < topMostPosition) { + topMostPosition = pos; + topMostField = fieldModels[i]; + } + } + of = topMostField.get('el'); + delay = 50; + break; + } } + // Prepare to check the next possible element to position against. + check++; + } while (!of); + + /** + * Refines the positioning algorithm of jquery.ui.position(). + * + * Invoked as the 'using' callback of jquery.ui.position() in + * positionToolbar(). + * + * @param {*} view + * The view the positions will be calculated from. + * @param {object} suggested + * A hash of top and left values for the position that should be set. It + * can be forwarded to .css() or .animate(). + * @param {object} info + * The position and dimensions of both the 'my' element and the 'of' + * elements, as well as calculations to their relative position. This + * object contains the following properties: + * @param {object} info.element + * A hash that contains information about the HTML element that will be + * positioned. Also known as the 'my' element. + * @param {object} info.target + * A hash that contains information about the HTML element that the + * 'my' element will be positioned against. Also known as the 'of' + * element. + */ + function refinePosition(view, suggested, info) { + // Determine if the pointer should be on the top or bottom. + const isBelow = suggested.top > info.target.top; + info.element.element.toggleClass( + 'quickedit-toolbar-pointer-top', + isBelow, + ); + // Don't position the toolbar past the first or last editable field if + // the entity is the target. + if (view.$entity[0] === info.target.element[0]) { + // Get the first or last field according to whether the toolbar is + // above or below the entity. + const $field = view.$entity + .find('.quickedit-editable') + .eq(isBelow ? -1 : 0); + if ($field.length > 0) { + suggested.top = isBelow + ? $field.offset().top + $field.outerHeight(true) + : $field.offset().top - info.element.element.outerHeight(true); + } + } + // Don't let the toolbar go outside the fence. + const fenceTop = view.$fence.offset().top; + const fenceHeight = view.$fence.height(); + const toolbarHeight = info.element.element.outerHeight(true); + if (suggested.top < fenceTop) { + suggested.top = fenceTop; + } else if (suggested.top + toolbarHeight > fenceTop + fenceHeight) { + suggested.top = fenceTop + fenceHeight - toolbarHeight; + } + // Position the toolbar. + info.element.element.css({ + left: Math.floor(suggested.left), + top: Math.floor(suggested.top), + }); } - // Don't let the toolbar go outside the fence. - const fenceTop = view.$fence.offset().top; - const fenceHeight = view.$fence.height(); - const toolbarHeight = info.element.element.outerHeight(true); - if (suggested.top < fenceTop) { - suggested.top = fenceTop; - } - else if ((suggested.top + toolbarHeight) > (fenceTop + fenceHeight)) { - suggested.top = (fenceTop + fenceHeight) - toolbarHeight; + + /** + * Calls the jquery.ui.position() method on the $el of this view. + */ + function positionToolbar() { + that.$el + .position({ + my: `${edge} bottom`, + // Move the toolbar 1px towards the start edge of the 'of' element, + // plus any horizontal padding that may have been added to the + // element that is being added, to prevent unwanted horizontal + // movement. + at: `${edge}+${1 + horizontalPadding} top`, + of, + collision: 'flipfit', + using: refinePosition.bind(null, that), + within: that.$fence, + }) + // Resize the toolbar to match the dimensions of the field, up to a + // maximum width that is equal to 90% of the field's width. + .css({ + 'max-width': + document.documentElement.clientWidth < 450 + ? document.documentElement.clientWidth + : 450, + // Set a minimum width of 240px for the entity toolbar, or the width + // of the client if it is less than 240px, so that the toolbar + // never folds up into a squashed and jumbled mess. + 'min-width': + document.documentElement.clientWidth < 240 + ? document.documentElement.clientWidth + : 240, + width: '100%', + }); } - // Position the toolbar. - info.element.element.css({ - left: Math.floor(suggested.left), - top: Math.floor(suggested.top), - }); - } + + // Uses the jQuery.ui.position() method. Use a timeout to move the toolbar + // only after the user has focused on an editable for 250ms. This prevents + // the toolbar from jumping around the screen. + this.timer = setTimeout(() => { + // Render the position in the next execution cycle, so that animations + // on the field have time to process. This is not strictly speaking, a + // guarantee that all animations will be finished, but it's a simple + // way to get better positioning without too much additional code. + _.defer(positionToolbar); + }, delay); + }, /** - * Calls the jquery.ui.position() method on the $el of this view. + * Set the model state to 'saving' when the save button is clicked. + * + * @param {jQuery.Event} event + * The click event. */ - function positionToolbar() { - that.$el - .position({ - my: `${edge} bottom`, - // Move the toolbar 1px towards the start edge of the 'of' element, - // plus any horizontal padding that may have been added to the - // element that is being added, to prevent unwanted horizontal - // movement. - at: `${edge}+${1 + horizontalPadding} top`, - of, - collision: 'flipfit', - using: refinePosition.bind(null, that), - within: that.$fence, - }) - // Resize the toolbar to match the dimensions of the field, up to a - // maximum width that is equal to 90% of the field's width. - .css({ - 'max-width': (document.documentElement.clientWidth < 450) ? document.documentElement.clientWidth : 450, - // Set a minimum width of 240px for the entity toolbar, or the width - // of the client if it is less than 240px, so that the toolbar - // never folds up into a squashed and jumbled mess. - 'min-width': (document.documentElement.clientWidth < 240) ? document.documentElement.clientWidth : 240, - width: '100%', - }); - } - - // Uses the jQuery.ui.position() method. Use a timeout to move the toolbar - // only after the user has focused on an editable for 250ms. This prevents - // the toolbar from jumping around the screen. - this.timer = setTimeout(() => { - // Render the position in the next execution cycle, so that animations - // on the field have time to process. This is not strictly speaking, a - // guarantee that all animations will be finished, but it's a simple - // way to get better positioning without too much additional code. - _.defer(positionToolbar); - }, delay); - }, + onClickSave(event) { + event.stopPropagation(); + event.preventDefault(); + // Save the model. + this.model.set('state', 'committing'); + }, - /** - * Set the model state to 'saving' when the save button is clicked. - * - * @param {jQuery.Event} event - * The click event. - */ - onClickSave(event) { - event.stopPropagation(); - event.preventDefault(); - // Save the model. - this.model.set('state', 'committing'); - }, - - /** - * Sets the model state to candidate when the cancel button is clicked. - * - * @param {jQuery.Event} event - * The click event. - */ - onClickCancel(event) { - event.preventDefault(); - this.model.set('state', 'deactivating'); - }, + /** + * Sets the model state to candidate when the cancel button is clicked. + * + * @param {jQuery.Event} event + * The click event. + */ + onClickCancel(event) { + event.preventDefault(); + this.model.set('state', 'deactivating'); + }, - /** - * Clears the timeout that will eventually reposition the entity toolbar. - * - * Without this, it may reposition itself, away from the user's cursor! - * - * @param {jQuery.Event} event - * The mouse event. - */ - onMouseenter(event) { - clearTimeout(this.timer); - }, + /** + * Clears the timeout that will eventually reposition the entity toolbar. + * + * Without this, it may reposition itself, away from the user's cursor! + * + * @param {jQuery.Event} event + * The mouse event. + */ + onMouseenter(event) { + clearTimeout(this.timer); + }, - /** - * Builds the entity toolbar HTML; attaches to DOM; sets starting position. - * - * @return {jQuery} - * The toolbar element. - */ - buildToolbarEl() { - const $toolbar = $(Drupal.theme('quickeditEntityToolbar', { - id: 'quickedit-entity-toolbar', - })); - - $toolbar - .find('.quickedit-toolbar-entity') - // Append the "ops" toolgroup into the toolbar. - .prepend(Drupal.theme('quickeditToolgroup', { - classes: ['ops'], - buttons: [ - { - label: Drupal.t('Save'), - type: 'submit', - classes: 'action-save quickedit-button icon', - attributes: { - 'aria-hidden': true, - }, - }, - { - label: Drupal.t('Close'), - classes: 'action-cancel quickedit-button icon icon-close icon-only', - }, - ], - })); - - // Give the toolbar a sensible starting position so that it doesn't - // animate on to the screen from a far off corner. - $toolbar - .css({ + /** + * Builds the entity toolbar HTML; attaches to DOM; sets starting position. + * + * @return {jQuery} + * The toolbar element. + */ + buildToolbarEl() { + const $toolbar = $( + Drupal.theme('quickeditEntityToolbar', { + id: 'quickedit-entity-toolbar', + }), + ); + + $toolbar + .find('.quickedit-toolbar-entity') + // Append the "ops" toolgroup into the toolbar. + .prepend( + Drupal.theme('quickeditToolgroup', { + classes: ['ops'], + buttons: [ + { + label: Drupal.t('Save'), + type: 'submit', + classes: 'action-save quickedit-button icon', + attributes: { + 'aria-hidden': true, + }, + }, + { + label: Drupal.t('Close'), + classes: + 'action-cancel quickedit-button icon icon-close icon-only', + }, + ], + }), + ); + + // Give the toolbar a sensible starting position so that it doesn't + // animate on to the screen from a far off corner. + $toolbar.css({ left: this.$entity.offset().left, top: this.$entity.offset().top, }); - return $toolbar; - }, + return $toolbar; + }, - /** - * Returns the DOM element that fields will attach their toolbars to. - * - * @return {jQuery} - * The DOM element that fields will attach their toolbars to. - */ - getToolbarRoot() { - return this._fieldToolbarRoot; - }, + /** + * Returns the DOM element that fields will attach their toolbars to. + * + * @return {jQuery} + * The DOM element that fields will attach their toolbars to. + */ + getToolbarRoot() { + return this._fieldToolbarRoot; + }, - /** - * Generates a state-dependent label for the entity toolbar. - */ - label() { - // The entity label. - let label = ''; - const entityLabel = this.model.get('label'); - - // Label of an active field, if it exists. - const activeField = Drupal.quickedit.app.model.get('activeField'); - const activeFieldLabel = activeField && activeField.get('metadata').label; - // Label of a highlighted field, if it exists. - const highlightedField = Drupal.quickedit.app.model.get('highlightedField'); - const highlightedFieldLabel = highlightedField && highlightedField.get('metadata').label; - // The label is constructed in a priority order. - if (activeFieldLabel) { - label = Drupal.theme('quickeditEntityToolbarLabel', { - entityLabel, - fieldLabel: activeFieldLabel, - }); - } - else if (highlightedFieldLabel) { - label = Drupal.theme('quickeditEntityToolbarLabel', { - entityLabel, - fieldLabel: highlightedFieldLabel, - }); - } - else { - // @todo Add XSS regression test coverage in https://www.drupal.org/node/2547437 - label = Drupal.checkPlain(entityLabel); - } - - this.$el - .find('.quickedit-toolbar-label') - .html(label); - }, + /** + * Generates a state-dependent label for the entity toolbar. + */ + label() { + // The entity label. + let label = ''; + const entityLabel = this.model.get('label'); + + // Label of an active field, if it exists. + const activeField = Drupal.quickedit.app.model.get('activeField'); + const activeFieldLabel = + activeField && activeField.get('metadata').label; + // Label of a highlighted field, if it exists. + const highlightedField = Drupal.quickedit.app.model.get( + 'highlightedField', + ); + const highlightedFieldLabel = + highlightedField && highlightedField.get('metadata').label; + // The label is constructed in a priority order. + if (activeFieldLabel) { + label = Drupal.theme('quickeditEntityToolbarLabel', { + entityLabel, + fieldLabel: activeFieldLabel, + }); + } else if (highlightedFieldLabel) { + label = Drupal.theme('quickeditEntityToolbarLabel', { + entityLabel, + fieldLabel: highlightedFieldLabel, + }); + } else { + // @todo Add XSS regression test coverage in https://www.drupal.org/node/2547437 + label = Drupal.checkPlain(entityLabel); + } - /** - * Adds classes to a toolgroup. - * - * @param {string} toolgroup - * A toolgroup name. - * @param {string} classes - * A string of space-delimited class names that will be applied to the - * wrapping element of the toolbar group. - */ - addClass(toolgroup, classes) { - this._find(toolgroup).addClass(classes); - }, + this.$el.find('.quickedit-toolbar-label').html(label); + }, - /** - * Removes classes from a toolgroup. - * - * @param {string} toolgroup - * A toolgroup name. - * @param {string} classes - * A string of space-delimited class names that will be removed from the - * wrapping element of the toolbar group. - */ - removeClass(toolgroup, classes) { - this._find(toolgroup).removeClass(classes); - }, + /** + * Adds classes to a toolgroup. + * + * @param {string} toolgroup + * A toolgroup name. + * @param {string} classes + * A string of space-delimited class names that will be applied to the + * wrapping element of the toolbar group. + */ + addClass(toolgroup, classes) { + this._find(toolgroup).addClass(classes); + }, - /** - * Finds a toolgroup. - * - * @param {string} toolgroup - * A toolgroup name. - * - * @return {jQuery} - * The toolgroup DOM element. - */ - _find(toolgroup) { - return this.$el.find(`.quickedit-toolbar .quickedit-toolgroup.${toolgroup}`); - }, + /** + * Removes classes from a toolgroup. + * + * @param {string} toolgroup + * A toolgroup name. + * @param {string} classes + * A string of space-delimited class names that will be removed from the + * wrapping element of the toolbar group. + */ + removeClass(toolgroup, classes) { + this._find(toolgroup).removeClass(classes); + }, - /** - * Shows a toolgroup. - * - * @param {string} toolgroup - * A toolgroup name. - */ - show(toolgroup) { - this.$el.removeClass('quickedit-animate-invisible'); - }, + /** + * Finds a toolgroup. + * + * @param {string} toolgroup + * A toolgroup name. + * + * @return {jQuery} + * The toolgroup DOM element. + */ + _find(toolgroup) { + return this.$el.find( + `.quickedit-toolbar .quickedit-toolgroup.${toolgroup}`, + ); + }, - }); -}(jQuery, _, Backbone, Drupal, Drupal.debounce)); + /** + * Shows a toolgroup. + * + * @param {string} toolgroup + * A toolgroup name. + */ + show(toolgroup) { + this.$el.removeClass('quickedit-animate-invisible'); + }, + }, + ); +})(jQuery, _, Backbone, Drupal, Drupal.debounce);