From 2d70a8b8423847ed1fea2ab360c4ec632354f4b2 Mon Sep 17 00:00:00 2001 From: Szymon Cofalik Date: Wed, 4 Oct 2017 10:18:06 +0200 Subject: [PATCH] Change: Force rendering view document after `selectionchange` event instead of doing this in asynchronous timeout callback. --- src/view/observer/focusobserver.js | 23 ++++------------------- src/view/observer/selectionobserver.js | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/view/observer/focusobserver.js b/src/view/observer/focusobserver.js index e2fd03fcb..ee21c503a 100644 --- a/src/view/observer/focusobserver.js +++ b/src/view/observer/focusobserver.js @@ -7,9 +7,8 @@ * @module engine/view/observer/focusobserver */ -/* globals setTimeout, clearTimeout */ - import DomEventObserver from './domeventobserver'; +import SelectionObserver from './selectionobserver'; /** * {@link module:engine/view/document~Document#event:focus Focus} @@ -28,14 +27,11 @@ export default class FocusObserver extends DomEventObserver { this.domEventType = [ 'focus', 'blur' ]; this.useCapture = true; + const selectionObserver = document.getObserver( SelectionObserver ); + document.on( 'focus', () => { document.isFocused = true; - - // Unfortunately native `selectionchange` event is fired asynchronously. - // We need to wait until `SelectionObserver` handle the event and then render. Otherwise rendering will - // overwrite new DOM selection with selection from the view. - // See https://github.com/ckeditor/ckeditor5-engine/issues/795 for more details. - this._renderTimeoutId = setTimeout( () => document.render(), 0 ); + selectionObserver._forceRenderAfterNextChange = true; } ); document.on( 'blur', ( evt, data ) => { @@ -48,13 +44,6 @@ export default class FocusObserver extends DomEventObserver { document.render(); } } ); - - /** - * Identifier of the timeout currently used by focus listener to delay rendering execution. - * - * @private - * @member {Number} #_renderTimeoutId - */ } onDomEvent( domEvent ) { @@ -65,10 +54,6 @@ export default class FocusObserver extends DomEventObserver { * @inheritDoc */ destroy() { - if ( this._renderTimeoutId ) { - clearTimeout( this._renderTimeoutId ); - } - super.destroy(); } } diff --git a/src/view/observer/selectionobserver.js b/src/view/observer/selectionobserver.js index 239db6130..3c1182b77 100644 --- a/src/view/observer/selectionobserver.js +++ b/src/view/observer/selectionobserver.js @@ -94,6 +94,17 @@ export default class SelectionObserver extends Observer { * @member {Number} module:engine/view/observer/selectionobserver~SelectionObserver#_loopbackCounter */ this._loopbackCounter = 0; + + /** + * Property used to force view render after the next `selectionchange` event. + * + * Because `selectionchange` is an asynchronous event, other parts of code may use this property to + * force rendering view document after DOM selection is changed. + * + * @protected + * @member {Boolean} module:engine/view/observer/selectionobserver~SelectionObserver#_forceRenderAfterNextChange + */ + this._forceRenderAfterNextChange = false; } /** @@ -109,6 +120,11 @@ export default class SelectionObserver extends Observer { this.listenTo( domDocument, 'selectionchange', () => { this._handleSelectionChange( domDocument ); + + if ( this._forceRenderAfterNextChange ) { + this._forceRenderAfterNextChange = false; + this.document.render(); + } } ); this._documents.add( domDocument );