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