/** * @file * A Backbone View that provides an interactive toolbar (1 per in-place editor). */ (function ($, _, Backbone, Drupal) { Drupal.quickedit.FieldToolbarView = Backbone.View.extend(/** @lends Drupal.quickedit.FieldToolbarView# */{ /** * The edited element, as indicated by EditorView.getEditedElement. * * @type {jQuery} */ $editedElement: null, /** * A reference to the in-place editor. * * @type {Drupal.quickedit.EditorView} */ editorView: null, /** * @type {string} */ _id: null, /** * @constructs * * @augments Backbone.View * * @param {object} options * Options object to construct the field toolbar. * @param {jQuery} options.$editedElement * The element being edited. * @param {Drupal.quickedit.EditorView} options.editorView * The EditorView the toolbar belongs to. */ initialize(options) { this.$editedElement = options.$editedElement; this.editorView = options.editorView; /** * @type {jQuery} */ this.$root = this.$el; // Generate a DOM-compatible ID for the form container DOM element. this._id = `quickedit-toolbar-for-${this.model.id.replace(/[/[\]]/g, '_')}`; this.listenTo(this.model, 'change:state', this.stateChange); }, /** * @inheritdoc * * @return {Drupal.quickedit.FieldToolbarView} * The current FieldToolbarView. */ render() { // Render toolbar and set it as the view's element. this.setElement($(Drupal.theme('quickeditFieldToolbar', { id: this._id, }))); // Attach to the field toolbar $root element in the entity toolbar. this.$el.prependTo(this.$root); return this; }, /** * Determines the actions to take given a change of state. * * @param {Drupal.quickedit.FieldModel} model * The quickedit FieldModel * @param {string} state * The state of the associated field. One of * {@link Drupal.quickedit.FieldModel.states}. */ stateChange(model, state) { const from = model.previous('state'); const to = state; switch (to) { case 'inactive': break; case 'candidate': // Remove the view's existing element if we went to the 'activating' // state or later, because it will be recreated. Not doing this would // result in memory leaks. if (from !== 'inactive' && from !== 'highlighted') { this.$el.remove(); this.setElement(); } break; case 'highlighted': break; case 'activating': this.render(); if (this.editorView.getQuickEditUISettings().fullWidthToolbar) { this.$el.addClass('quickedit-toolbar-fullwidth'); } if (this.editorView.getQuickEditUISettings().unifiedToolbar) { this.insertWYSIWYGToolGroups(); } break; case 'active': break; case 'changed': break; case 'saving': break; case 'saved': break; case 'invalid': break; } }, /** * Insert WYSIWYG markup into the associated toolbar. */ insertWYSIWYGToolGroups() { this.$el .append(Drupal.theme('quickeditToolgroup', { id: this.getFloatedWysiwygToolgroupId(), classes: ['wysiwyg-floated', 'quickedit-animate-slow', 'quickedit-animate-invisible', 'quickedit-animate-delay-veryfast'], buttons: [], })) .append(Drupal.theme('quickeditToolgroup', { id: this.getMainWysiwygToolgroupId(), classes: ['wysiwyg-main', 'quickedit-animate-slow', 'quickedit-animate-invisible', 'quickedit-animate-delay-veryfast'], buttons: [], })); // Animate the toolgroups into visibility. this.show('wysiwyg-floated'); this.show('wysiwyg-main'); }, /** * Retrieves the ID for this toolbar's container. * * Only used to make sane hovering behavior possible. * * @return {string} * A string that can be used as the ID for this toolbar's container. */ getId() { return `quickedit-toolbar-for-${this._id}`; }, /** * Retrieves the ID for this toolbar's floating WYSIWYG toolgroup. * * Used to provide an abstraction for any WYSIWYG editor to plug in. * * @return {string} * A string that can be used as the ID. */ getFloatedWysiwygToolgroupId() { return `quickedit-wysiwyg-floated-toolgroup-for-${this._id}`; }, /** * Retrieves the ID for this toolbar's main WYSIWYG toolgroup. * * Used to provide an abstraction for any WYSIWYG editor to plug in. * * @return {string} * A string that can be used as the ID. */ getMainWysiwygToolgroupId() { return `quickedit-wysiwyg-main-toolgroup-for-${this._id}`; }, /** * Finds a toolgroup. * * @param {string} toolgroup * A toolgroup name. * * @return {jQuery} * The toolgroup element. */ _find(toolgroup) { return this.$el.find(`.quickedit-toolgroup.${toolgroup}`); }, /** * Shows a toolgroup. * * @param {string} toolgroup * A toolgroup name. */ show(toolgroup) { const $group = this._find(toolgroup); // Attach a transitionEnd event handler to the toolbar group so that // update events can be triggered after the animations have ended. $group.on(Drupal.quickedit.util.constants.transitionEnd, (event) => { $group.off(Drupal.quickedit.util.constants.transitionEnd); }); // The call to remove the class and start the animation must be started in // the next animation frame or the event handler attached above won't be // triggered. window.setTimeout(() => { $group.removeClass('quickedit-animate-invisible'); }, 0); }, }); }(jQuery, _, Backbone, Drupal));