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