Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge pull request #335 from ckeditor/i/4504
Browse files Browse the repository at this point in the history
Fix: Improved markup operation performance of the editor with the image plugin enabled. See ckeditor/ckeditor5#4504.
  • Loading branch information
Reinmar authored Nov 20, 2019
2 parents 11c9f39 + 07b1b28 commit 6c7fc94
Showing 1 changed file with 7 additions and 62 deletions.
69 changes: 7 additions & 62 deletions src/image/imageloadobserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,65 +20,18 @@ import Observer from '@ckeditor/ckeditor5-engine/src/view/observer/observer';
* @extends module:engine/view/observer/observer~Observer
*/
export default class ImageLoadObserver extends Observer {
constructor( view ) {
super( view );

/**
* List of img DOM elements that are observed by this observer.
*
* @private
* @type {Set.<HTMLElement>}
*/
this._observedElements = new Set();
}

/**
* @inheritDoc
*/
observe( domRoot, name ) {
const viewRoot = this.document.getRoot( name );

// When there is a change in one of the view element
// we need to check if there are any new `<img/>` elements to observe.
viewRoot.on( 'change:children', ( evt, node ) => {
// Wait for the render to be sure that `<img/>` elements are rendered in the DOM root.
this.view.once( 'render', () => this._updateObservedElements( domRoot, node ) );
} );
}

/**
* Updates the list of observed `<img/>` elements.
*
* @private
* @param {HTMLElement} domRoot DOM root element.
* @param {module:engine/view/element~Element} viewNode View element where children have changed.
*/
_updateObservedElements( domRoot, viewNode ) {
if ( !viewNode.is( 'element' ) || viewNode.is( 'attributeElement' ) ) {
return;
}

const domNode = this.view.domConverter.mapViewToDom( viewNode );
observe( domRoot ) {
this.listenTo( domRoot, 'load', ( event, domEvent ) => {
const domElement = domEvent.target;

// If there is no `domNode` it means that it was removed from the DOM in the meanwhile.
if ( !domNode ) {
return;
}

for ( const domElement of domNode.querySelectorAll( 'img' ) ) {
if ( !this._observedElements.has( domElement ) ) {
this.listenTo( domElement, 'load', ( evt, domEvt ) => this._fireEvents( domEvt ) );
this._observedElements.add( domElement );
}
}

// Clean up the list of observed elements from elements that has been removed from the root.
for ( const domElement of this._observedElements ) {
if ( !domRoot.contains( domElement ) ) {
this.stopListening( domElement );
this._observedElements.delete( domElement );
if ( domElement.tagName == 'IMG' ) {
this._fireEvents( domEvent );
}
}
// Use capture phase for better performance (#4504).
}, { useCapture: true } );
}

/**
Expand All @@ -95,14 +48,6 @@ export default class ImageLoadObserver extends Observer {
this.document.fire( 'imageLoaded', domEvent );
}
}

/**
* @inheritDoc
*/
destroy() {
this._observedElements.clear();
super.destroy();
}
}

/**
Expand Down

0 comments on commit 6c7fc94

Please sign in to comment.