From ff011a58f992e7e2383bb2436dab98e52e4b2bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?"J.=20Rene=CC=81e=20Beach"?= Date: Sun, 5 May 2013 14:57:26 -0400 Subject: [PATCH] Issue #1678002-89 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f21dd7a7663723d477db8febd0edd91dbee04b74 Author: J. Renée Beach Date: Fri May 3 16:50:34 2013 -0400 Entity Toolbar now follows on hover. Signed-off-by: J. Renée Beach commit b31e8e966bdfde2bfb6eb70c4e87c9d2243076bd Author: J. Renée Beach Date: Fri May 3 15:17:12 2013 -0400 Moved field state handling out of EntityToolbarView Signed-off-by: J. Renée Beach commit 38378dfd9299e9948dfacc2132299fe7853957ac Author: J. Renée Beach Date: Fri May 3 14:24:21 2013 -0400 Introduced state to the EntityModel. Signed-off-by: J. Renée Beach commit 48cdae96253e83ad6fd3cbe6314404a904cf1456 Author: J. Renée Beach Date: Fri May 3 14:06:00 2013 -0400 Trying to make save work Signed-off-by: J. Renée Beach commit 23ac70132f6351b25d587c3fce2493779b1ccf62 Author: J. Renée Beach Date: Fri May 3 11:38:58 2013 -0400 Squashed commit of the following: commit c1d27c949c5f4519a2cdfe46934d1e90e07f2e33 Author: J. Renée Beach Date: Thu May 2 15:04:36 2013 -0400 Position the toolbar after a field closes. Signed-off-by: J. Renée Beach commit 39d7b9bccee5aff877120fe964fcdb226f516e7d Author: J. Renée Beach Date: Thu May 2 15:00:02 2013 -0400 The field label now attaches correctly. Signed-off-by: J. Renée Beach commit 4b1d1c33196f5ca784cd5e16146d16e1334a1c5c Author: J. Renée Beach Date: Thu May 2 14:35:42 2013 -0400 entity toolbar Signed-off-by: J. Renée Beach Signed-off-by: J. Renée Beach Signed-off-by: J. Renée Beach --- core/modules/edit/css/edit.css | 48 +-- core/modules/edit/edit.module | 3 + core/modules/edit/js/edit.js | 15 +- core/modules/edit/js/models/EntityModel.js | 81 ++++- core/modules/edit/js/theme.js | 29 +- core/modules/edit/js/views/AppView.js | 27 +- core/modules/edit/js/views/EditorDecorationView.js | 50 +++ core/modules/edit/js/views/EntityToolbarView.js | 360 ++++++++++++++++++++ core/modules/edit/js/views/FieldToolbarView.js | 247 ++------------ .../editor/js/editor.formattedTextEditor.js | 3 +- 10 files changed, 599 insertions(+), 264 deletions(-) create mode 100644 core/modules/edit/js/views/EntityToolbarView.js diff --git a/core/modules/edit/css/edit.css b/core/modules/edit/css/edit.css index 37e7578..b10d11f 100644 --- a/core/modules/edit/css/edit.css +++ b/core/modules/edit/css/edit.css @@ -61,17 +61,19 @@ transition: opacity .2s ease; } -.edit-animate-only-background-and-padding { - -webkit-transition: background, padding .2s ease; - -moz-transition: background, padding .2s ease; - -ms-transition: background, padding .2s ease; - -o-transition: background, padding .2s ease; - transition: background, padding .2s ease; +/** + * Entity toolbar. + */ +.edit-toolbar-container { + background-color: white; + border: 1px solid #ababab; + position: absolute; + -webkit-transition: all 0.2s; + transition: all 0.2s; + width: 20em; + z-index: 350; } - - - /** * Candidate editables + editables being edited. * @@ -214,8 +216,6 @@ .edit-toolbar-container, .edit-form-container { position: relative; - padding: 0; - border: 0; margin: 0; vertical-align: baseline; z-index: 310; @@ -229,38 +229,12 @@ user-select: none; } -.edit-toolbar-heightfaker { - height: auto; - position: absolute; - bottom: 1px; - box-shadow: 0 0 1px 1px #0199ff, 0 0 3px 3px rgba(153, 153, 153, .5); - background: #fff; - display: none; -} -.edit-highlighted .edit-toolbar-heightfaker { - display: block; -} - /* The toolbar; these are not necessarily visible. */ .edit-toolbar { position: relative; height: 100%; font-family: 'Droid sans', 'Lucida Grande', sans-serif; } -.edit-toolbar-heightfaker { - clip: rect(-1000px, 1000px, auto, -1000px); /* Remove bottom box-shadow. */ -} -/* Exception: when the toolbar is instructed to be "full width". */ -.edit-toolbar-fullwidth .edit-toolbar-heightfaker { - width: 100%; - clip: auto; -} - - -/* The toolbar contains toolgroups; these are visible. */ -.edit-toolgroup { - float: left; /* LTR */ -} /* Info toolgroup. */ .edit-toolgroup.info { diff --git a/core/modules/edit/edit.module b/core/modules/edit/edit.module index 2de3b37..c7fa4fb 100644 --- a/core/modules/edit/edit.module +++ b/core/modules/edit/edit.module @@ -78,6 +78,7 @@ function edit_library_info() { // Views. $path . '/js/views/AppView.js' => $options, $path . '/js/views/EditorDecorationView.js' => $options, + $path . '/js/views/EntityToolbarView.js' => $options, $path . '/js/views/ContextualLinkView.js' => $options, $path . '/js/views/ModalView.js' => $options, $path . '/js/views/FieldToolbarView.js' => $options, @@ -106,8 +107,10 @@ function edit_library_info() { array('system', 'underscore'), array('system', 'backbone'), array('system', 'jquery.form'), + array('system', 'jquery.ui.position'), array('system', 'drupal.form'), array('system', 'drupal.ajax'), + array('system', 'drupal.debounce'), array('system', 'drupalSettings'), ), ); diff --git a/core/modules/edit/js/edit.js b/core/modules/edit/js/edit.js index 0720e6e..1014280 100644 --- a/core/modules/edit/js/edit.js +++ b/core/modules/edit/js/edit.js @@ -193,7 +193,8 @@ Drupal.behaviors.edit = { var id = $this.data('edit-entity'); entityModel = new Drupal.edit.EntityModel({ - id: id + id: id, + el: this }); that.collections.entities.add(entityModel); @@ -278,6 +279,8 @@ Drupal.behaviors.edit = { // trigger an "update" method rather than a "create" method. id: editID || null, editID: editID || null, + // Store the field in a collection in its entity's model. + collection: entity.get('fields'), label: Drupal.edit.metadataCache[editID].label, editor: Drupal.edit.metadataCache[editID].editor, html: $element[0].outerHTML, @@ -291,7 +294,15 @@ Drupal.behaviors.edit = { // being edited, then transition it to the 'candidate' state. // (This happens when a field was modified and is re-rendered.) if (entity === activeEntity) { - Drupal.edit.app.decorate(field); + // @todo The signature to app.decorate has evovled into a poor design. + // It needs to many arguments to function. + var entityToolbar = entity.get('entityToolbar'); + + // Get the field toolbar DOM root from the entity toolbar. + var fieldToolbarRoot = entityToolbar.getToolbarRoot(); + var fieldLabelRoot = entityToolbar.getLabelRoot(); + + Drupal.edit.app.decorate(entity, field, {toolbar: fieldToolbarRoot, label: fieldLabelRoot}); field.set('state', 'candidate'); } }); diff --git a/core/modules/edit/js/models/EntityModel.js b/core/modules/edit/js/models/EntityModel.js index 047ffe7..4836bb5 100644 --- a/core/modules/edit/js/models/EntityModel.js +++ b/core/modules/edit/js/models/EntityModel.js @@ -16,11 +16,90 @@ $.extend(Drupal.edit, { // Indicates whether this instance of this entity is currently being // edited. isActive: false, + // The current processing state of an entity. + state: 'inactive', // A Drupal.edit.FieldCollection for all fields of this entity. - fields: null + fields: null, + // The model for the currently active field. The default is a stub object + // with an 'on' method so that it can be result to the default value + // when no fields are active on this entity without breaking listener + // attachment calls to this property's object. + fieldModel: (function () { + return { + on: function () {}, + off: function () {}, + get: function () {} + }; + }()) }, + + /** + * + */ initialize: function () { + this.set('fields', new Drupal.edit.FieldCollection()); + + // Instantiate configuration for state handling. + // @see Drupal.edit.FieldModel.states + this.activeEditorStates = ['activating', 'active']; + this.singleEditorStates = _.union(['highlighted'], this.activeEditorStates); + + this.on('viewChanged', this.viewChange, this); + + this.on('change:state', this.stateChange, this); + + // @todo This is probably a little too simplistic, but it works for the + // moment. The state of the entity toolbar will most likely be determined + // by considering the states of all the fields in the entity. + // + // The entity toolbar state mirrors the state of its fields. + this.get('fields').on('change:state', function (model, state, options) { + this.set('state', model.get('state'), {fieldModel: model}); + }, this); + }, + + /** + * Listens to FieldModel editor state changes. + * + * @param Drupal.edit.FieldModel model + * @param String state + * The state of an editable element. Used to determine display and behavior. + */ + stateChange: function (model, state, options) { + var from = model.previous('state'); + var to = state; + switch (to) { + case 'inactive': + break; + case 'candidate': + this.set('fieldModel', this.defaults.fieldModel); + break; + case 'highlighted': + this.set('fieldModel', options.fieldModel); + break; + case 'activating': + break; + case 'active': + break; + case 'changed': + break; + case 'saving': + break; + case 'saved': + break; + case 'invalid': + break; + default: + break; + } + }, + + /** + * + */ + viewChange: function (view) { + this.trigger('fieldViewChange', view); } }) }); diff --git a/core/modules/edit/js/theme.js b/core/modules/edit/js/theme.js index 7bef553..46d5a49 100644 --- a/core/modules/edit/js/theme.js +++ b/core/modules/edit/js/theme.js @@ -64,17 +64,31 @@ Drupal.theme.editModal = function(settings) { * @return * The corresponding HTML. */ -Drupal.theme.editToolbarContainer = function(settings) { +Drupal.theme.editEntityToolbar = function(settings) { var html = ''; - html += '
'; - html += '
'; - html += '
'; - html += '
'; + html += '
'; + html += '
'; + html += '
'; + html += '
'; + html += '
'; html += '
'; return html; }; /** + * Theme function for a toolbar container of the Edit module. + * + * @param settings + * An object with the following keys: + * - id: the id to apply to the toolbar container. + * @return + * The corresponding HTML. + */ +Drupal.theme.editFieldToolbar = function(settings) { + return '
'; +}; + +/** * Theme function for a toolbar toolgroup of the Edit module. * * @param settings @@ -86,9 +100,10 @@ Drupal.theme.editToolbarContainer = function(settings) { * The corresponding HTML. */ Drupal.theme.editToolgroup = function(settings) { - var classes = 'edit-toolgroup edit-animate-slow edit-animate-invisible edit-animate-delay-veryfast'; + var classes = (settings.classes || []); + classes.unshift('edit-toolgroup'); var html = ''; - html += '
-1; + }); + var $fieldElement = field && field.get('$el'); + // Prefer the specified element from the parameters, then the acive field + // and finally the entity itself to determine the position of the toolbar. + var of = element || $fieldElement || this.$entity; + // Uses the jQuery.ui.position() method. + this.$el + .position({ + my: edge + ' bottom', + at: edge + ' top', + of: of + }); + }, + + /** + * Determines the actions to take given a change of state. + * + * @param Drupal.edit.EntityModel model + * @param String state + * The state of the associated field. One of Drupal.edit.EntityModel.states. + */ + stateChange: function (model, state, options) { + var from = model.previous('state'); + var to = state; + switch (to) { + case 'inactive': + break; + case 'candidate': + // Position the toolbar against the entity. + this.position(); + break; + case 'highlighted': + this.position(); + break; + case 'activating': + this.setLoadingIndicator(true); + break; + case 'active': + this.setLoadingIndicator(false); + this.startEdit(); + // Position the toolbar against the active field. + this.position(); + break; + case 'changed': + this.$el + .find('button.save') + .addClass('blue-button') + .removeClass('gray-button'); + break; + case 'saving': + this.setLoadingIndicator(true); + break; + case 'saved': + this.setLoadingIndicator(false); + break; + case 'invalid': + this.setLoadingIndicator(false); + break; + default: + break; + } + }, + + /** + * Set the model state to 'saving' when the save button is clicked. + * + * @param jQuery event + */ + onClickSave: function (event) { + event.stopPropagation(); + event.preventDefault(); + var fieldModel = this.model.get('fieldModel'); + fieldModel.set('state', 'saving'); + this.model.set('state', 'saving'); + }, + + /** + * Sets the model state to candidate when the cancel button is clicked. + * + * @param jQuery event + */ + onClickClose: function (event) { + event.stopPropagation(); + event.preventDefault(); + var fields = this.model.get('fields'); + var activeFields = fields.where({'state': 'active'}); + var changedFieldds = fields.where({'state': 'changed'}); + // If a field is active, then set it back to highlighted state. If not, + // close the editing of this entity. + if (activeFields.length > 0) { + fields.each(function (fieldModel) { + fieldModel.set('state', 'candidate'); + }); + } + else { + this.model.set('isActive', false); + // Set all the fields back to candidate status. + fields.each(function (fieldModel) { + fieldModel.set('state', 'inactive'); + }); + } + }, + + + /** + * Redirects the click.edit-event to the editor DOM element. + * + * @param jQuery event + */ + onClickInfoLabel: function (event) { + event.stopPropagation(); + event.preventDefault(); + // Redirects the event to the editor DOM element. + this.$field.trigger('click.edit'); + }, + + /** + * Controls mouseleave events. + * + * A mouseleave to the editor doesn't matter; a mouseleave to something else + * counts as a mouseleave on the editor itself. + * + * @param jQuery event + */ + onMouseLeave: function (event) { + var fieldModel = this.model.get('fieldModel'); + if (fieldModel) { + var $field = this.model.get('fieldModel').get('$el'); + if (event.relatedTarget !== $field[0] && !$.contains($field, event.relatedTarget)) { + // @todo, this is triggered, but nothing is listening. This method was + // taken from ToolbarView.js + $field.trigger('mouseleave.edit'); + } + event.stopPropagation(); + } + }, + + /** + * + */ + buildToolbarEl: function () { + var $toolbar; + $toolbar = $(Drupal.theme('editEntityToolbar', { + id: 'edit-entity-toolbar' + })); + + $toolbar + .find('.edit-toolbar-entity') + // Append the "ops" toolgroup into the toolbar. + .append(Drupal.theme('editToolgroup', { + classes: ['ops'], + buttons: [ + { label: Drupal.t('Save'), type: 'submit', classes: 'field-save save gray-button' }, + { label: '' + Drupal.t('Close') + '', classes: 'field-close close gray-button' } + ] + })); + + // Give the toolbar a sensible starting position so that it doesn't + // animiate on to the screen from a far off corner. + $toolbar + .css({ + left: this.$entity.offset().left, + top: this.$entity.offset().top + }); + + this.setElement($toolbar); + }, + + /** + * + */ + getToolbarRoot: function () { + return this._fieldToolbarRoot; + }, + + /** + * + */ + getLabelRoot: function () { + return this._fieldLabelRoot; + }, + + /** + * + */ + startEdit: function () { + this.$el.addClass('edit-editing'); + }, + + /** + * Indicates in the 'info' toolgroup that we're waiting for a server reponse. + * + * Prevents flickering loading indicator by only showing it after 0.6 seconds + * and if it is shown, only hiding it after another 0.6 seconds. + * + * @param Boolean enabled + * Whether the loading indicator should be displayed or not. + */ + setLoadingIndicator: function (enabled) { + var that = this; + if (enabled) { + this._loader = setTimeout(function() { + that.addClass('info', 'loading'); + that._loaderVisibleStart = new Date().getTime(); + }, 600); + } + else { + var currentTime = new Date().getTime(); + clearTimeout(this._loader); + if (this._loaderVisibleStart) { + setTimeout(function() { + that.removeClass('info', 'loading'); + }, this._loaderVisibleStart + 600 - currentTime); + } + this._loader = null; + this._loaderVisibleStart = 0; + } + }, + + /** + * Adds classes to a toolgroup. + * + * @param String toolgroup + * A toolgroup name. + */ + addClass: function (toolgroup, classes) { + this._find(toolgroup).addClass(classes); + }, + + /** + * Removes classes from a toolgroup. + * + * @param String toolgroup + * A toolgroup name. + */ + removeClass: function (toolgroup, classes) { + this._find(toolgroup).removeClass(classes); + }, + + /** + * Finds a toolgroup. + * + * @param String toolgroup + * A toolgroup name. + */ + _find: function (toolgroup) { + return this.$el.find('.edit-toolbar .edit-toolgroup.' + toolgroup); + }, + + /** + * Shows a toolgroup. + * + * @param String toolgroup + * A toolgroup name. + */ + show: function (toolgroup) { + this.$el.removeClass('edit-animate-invisible'); + } +}); + +})(jQuery, Backbone, Drupal, Drupal.debounce); diff --git a/core/modules/edit/js/views/FieldToolbarView.js b/core/modules/edit/js/views/FieldToolbarView.js index a854312..20e7ae5 100644 --- a/core/modules/edit/js/views/FieldToolbarView.js +++ b/core/modules/edit/js/views/FieldToolbarView.js @@ -12,32 +12,20 @@ Drupal.edit.FieldToolbarView = Backbone.View.extend({ $field: null, - _loader: null, - _loaderVisibleStart: 0, - _id: null, - events: { - 'click.edit button.label': 'onClickInfoLabel', - 'mouseleave.edit': 'onMouseLeave', - 'click.edit button.field-save': 'onClickSave', - 'click.edit button.field-close': 'onClickClose' - }, - /** * Implements Backbone.View.prototype.initialize(). */ initialize: function (options) { this.$field = options.$field; this.editorView = options.editorView; + this.entityModel = options.entityModel; - this._loader = null; - this._loaderVisibleStart = 0; + this.model.on('change:state', this.stateChange, this); // Generate a DOM-compatible ID for the form container DOM element. this._id = 'edit-toolbar-for-' + this.model.get('editID').replace(/\//g, '_'); - - this.model.on('change:state', this.stateChange, this); }, /** @@ -48,18 +36,16 @@ Drupal.edit.FieldToolbarView = Backbone.View.extend({ */ render: function () { // Render toolbar. - this.setElement($(Drupal.theme('editToolbarContainer', { + this.$toolbar = $(Drupal.theme('editFieldToolbar', { id: this._id - }))); + })); // Insert in DOM. if (this.$field.css('display') === 'inline') { - this.$el.prependTo(this.$field.offsetParent()); - var pos = this.$field.position(); - this.$el.css('left', pos.left).css('top', pos.top); + this.$toolbar.prependTo(this.el); } else { - this.$el.insertBefore(this.$field); + this.$toolbar.insertBefore(this.$field); } return this; @@ -72,45 +58,17 @@ Drupal.edit.FieldToolbarView = Backbone.View.extend({ * @param String state * The state of the associated field. One of Drupal.edit.FieldModel.states. */ - stateChange: function (model, state) { + stateChange: function (model, state, options) { var from = model.previous('state'); var to = state; switch (to) { case 'inactive': - if (from) { - this.remove(); - if (this.model.get('editor') !== 'form') { - Backbone.syncDirectCleanUp(); - } - } break; case 'candidate': - if (from === 'inactive') { - this.render(); - } - else { - if (this.model.get('editor') !== 'form') { - Backbone.syncDirectCleanUp(); - } - // Remove all toolgroups; they're no longer necessary. - this.$el - .removeClass('edit-highlighted edit-editing') - .find('.edit-toolbar .edit-toolgroup').remove(); - if (from !== 'highlighted' && this.getEditUISetting('padding')) { - this._unpad(); - } - } break; case 'highlighted': - // As soon as we highlight, make sure we have a toolbar in the DOM (with at least a title). - this.startHighlight(); break; case 'activating': - this.setLoadingIndicator(true); - break; - case 'active': - this.startEdit(); - this.setLoadingIndicator(false); if (this.getEditUISetting('fullWidthToolbar')) { this.$el.addClass('edit-toolbar-fullwidth'); } @@ -122,147 +80,20 @@ Drupal.edit.FieldToolbarView = Backbone.View.extend({ this.insertWYSIWYGToolGroups(); } break; + case 'active': + break; case 'changed': - this.$el - .find('button.save') - .addClass('blue-button') - .removeClass('gray-button'); break; case 'saving': - this.setLoadingIndicator(true); break; case 'saved': - this.setLoadingIndicator(false); break; case 'invalid': - this.setLoadingIndicator(false); break; } }, /** - * Redirects the click.edit-event to the editor DOM element. - * - * @param jQuery event - */ - onClickInfoLabel: function (event) { - event.stopPropagation(); - event.preventDefault(); - // Redirects the event to the editor DOM element. - this.$field.trigger('click.edit'); - }, - - /** - * Controls mouseleave events. - * - * A mouseleave to the editor doesn't matter; a mouseleave to something else - * counts as a mouseleave on the editor itself. - * - * @param jQuery event - */ - onMouseLeave: function (event) { - if (event.relatedTarget !== this.$field[0] && !$.contains(this.$field, event.relatedTarget)) { - this.$field.trigger('mouseleave.edit'); - } - event.stopPropagation(); - }, - - /** - * Set the model state to 'saving' when the save button is clicked. - * - * @param jQuery event - */ - onClickSave: function (event) { - event.stopPropagation(); - event.preventDefault(); - this.model.set('state', 'saving'); - }, - - /** - * Sets the model state to candidate when the cancel button is clicked. - * - * @param jQuery event - */ - onClickClose: function (event) { - event.stopPropagation(); - event.preventDefault(); - this.model.set('state', 'candidate', { reason: 'cancel' }); - }, - - /** - * Indicates in the 'info' toolgroup that we're waiting for a server reponse. - * - * Prevents flickering loading indicator by only showing it after 0.6 seconds - * and if it is shown, only hiding it after another 0.6 seconds. - * - * @param Boolean enabled - * Whether the loading indicator should be displayed or not. - */ - setLoadingIndicator: function (enabled) { - var that = this; - if (enabled) { - this._loader = setTimeout(function() { - that.addClass('info', 'loading'); - that._loaderVisibleStart = new Date().getTime(); - }, 600); - } - else { - var currentTime = new Date().getTime(); - clearTimeout(this._loader); - if (this._loaderVisibleStart) { - setTimeout(function() { - that.removeClass('info', 'loading'); - }, this._loaderVisibleStart + 600 - currentTime); - } - this._loader = null; - this._loaderVisibleStart = 0; - } - }, - - /** - * - */ - startHighlight: function () { - // Retrieve the lavel to show for this field. - var label = this.model.get('label'); - - this.$el - .addClass('edit-highlighted') - .find('.edit-toolbar') - // Append the "info" toolgroup into the toolbar. - .append(Drupal.theme('editToolgroup', { - classes: 'info edit-animate-only-background-and-padding', - buttons: [ - { label: label, classes: 'blank-button label' } - ] - })); - - // Animations. - var that = this; - setTimeout(function () { - that.show('info'); - }, 0); - }, - - /** - * - */ - startEdit: function () { - this.$el - .addClass('edit-editing') - .find('.edit-toolbar') - // Append the "ops" toolgroup into the toolbar. - .append(Drupal.theme('editToolgroup', { - classes: 'ops', - buttons: [ - { label: Drupal.t('Save'), type: 'submit', classes: 'field-save save gray-button' }, - { label: '' + Drupal.t('Close') + '', classes: 'field-close close gray-button' } - ] - })); - this.show('ops'); - }, - - /** * Retrieves a setting of the editor-specific Edit UI integration. * * @param String setting @@ -279,6 +110,7 @@ Drupal.edit.FieldToolbarView = Backbone.View.extend({ * @see EditorDecorationView._pad(). */ _pad: function () { + return; // The whole toolbar must move to the top when the property's DOM element // is displayed inline. if (this.$field.css('display') === 'inline') { @@ -300,6 +132,7 @@ Drupal.edit.FieldToolbarView = Backbone.View.extend({ * @see EditorDecorationView._unpad(). */ _unpad: function () { + return; // Move the toolbar back to its original position. var $hf = this.$el.find('.edit-toolbar-heightfaker'); $hf.css({ bottom: '1px', left: '' }); @@ -314,24 +147,20 @@ Drupal.edit.FieldToolbarView = Backbone.View.extend({ */ insertWYSIWYGToolGroups: function () { this.$el - .find('.edit-toolbar') .append(Drupal.theme('editToolgroup', { id: this.getFloatedWysiwygToolgroupId(), - classes: 'wysiwyg-floated', + classes: ['wysiwyg-floated', 'edit-animate-slow', 'edit-animate-invisible', 'edit-animate-delay-veryfast'], buttons: [] })) .append(Drupal.theme('editToolgroup', { id: this.getMainWysiwygToolgroupId(), - classes: 'wysiwyg-main', + classes: ['wysiwyg-main', 'edit-animate-slow', 'edit-animate-invisible', 'edit-animate-delay-veryfast'], buttons: [] })); // Animate the toolgroups into visibility. - var that = this; - setTimeout(function () { - that.show('wysiwyg-floated'); - that.show('wysiwyg-main'); - }, 0); + this.show('wysiwyg-floated'); + this.show('wysiwyg-main'); }, /** @@ -371,43 +200,37 @@ Drupal.edit.FieldToolbarView = Backbone.View.extend({ }, /** - * Shows a toolgroup. - * - * @param String toolgroup - * A toolgroup name. - */ - show: function (toolgroup) { - this._find(toolgroup).removeClass('edit-animate-invisible'); - }, - - /** - * Adds classes to a toolgroup. - * - * @param String toolgroup - * A toolgroup name. - */ - addClass: function (toolgroup, classes) { - this._find(toolgroup).addClass(classes); - }, - - /** - * Removes classes from a toolgroup. + * Finds a toolgroup. * * @param String toolgroup * A toolgroup name. */ - removeClass: function (toolgroup, classes) { - this._find(toolgroup).removeClass(classes); + _find: function (toolgroup) { + return this.$el.find('.edit-toolgroup.' + toolgroup); }, /** - * Finds a toolgroup. + * Shows a toolgroup. * * @param String toolgroup * A toolgroup name. */ - _find: function (toolgroup) { - return this.$el.find('.edit-toolbar .edit-toolgroup.' + toolgroup); + show: function (toolgroup) { + var that = this; + var $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.edit.util.constants.transitionEnd, function (event) { + that.entityModel.trigger('viewChanged', that); + $group.off(Drupal.edit.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(function () { + $group.removeClass('edit-animate-invisible'); + }, 0); } }); diff --git a/core/modules/editor/js/editor.formattedTextEditor.js b/core/modules/editor/js/editor.formattedTextEditor.js index 2dcdf92..016310f 100644 --- a/core/modules/editor/js/editor.formattedTextEditor.js +++ b/core/modules/editor/js/editor.formattedTextEditor.js @@ -51,8 +51,8 @@ Drupal.edit.editors.editor = Drupal.edit.EditorView.extend({ var to = state; switch (to) { case 'inactive': + this.model.off(); break; - case 'candidate': // Detach the text editor when entering the 'candidate' state from one // of the states where it could have been attached. @@ -68,6 +68,7 @@ Drupal.edit.editors.editor = Drupal.edit.EditorView.extend({ break; case 'activating': + console.log(this.cid); // When transformation filters have been been applied to the processed // text of this field, then we'll need to load a re-processed version of // it without the transformation filters. -- 1.7.10.4