|
|
@@ -14,97 +14,97 @@ import global from '@ckeditor/ckeditor5-utils/src/dom/global';
|
|
|
import Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';
|
|
|
import DomEmitterMixin from '@ckeditor/ckeditor5-utils/src/dom/emittermixin';
|
|
|
|
|
|
-let ExportedResizeObserver;
|
|
|
-
|
|
|
-// TODO: One day, the ResizeObserver API will be supported in all modern web browsers.
|
|
|
-// When it happens, this module will no longer make sense and should be removed and
|
|
|
-// the native implementation should be used across the project to save bytes.
|
|
|
-// Check out https://caniuse.com/#feat=resizeobserver.
|
|
|
-if ( typeof global.window.ResizeObserver === 'function' ) {
|
|
|
- ExportedResizeObserver = global.window.ResizeObserver;
|
|
|
-} else {
|
|
|
- const RESIZE_CHECK_INTERVAL = 500;
|
|
|
-
|
|
|
- ExportedResizeObserver = class {
|
|
|
- constructor( callback ) {
|
|
|
- this.callback = callback;
|
|
|
- this.elements = new Set();
|
|
|
-
|
|
|
- this._startPeriodicCheck();
|
|
|
- }
|
|
|
+const RESIZE_CHECK_INTERVAL = 500;
|
|
|
+
|
|
|
+export default function getResizeObserver( callback ) {
|
|
|
+ // TODO: One day, the ResizeObserver API will be supported in all modern web browsers.
|
|
|
+ // When it happens, this module will no longer make sense and should be removed and
|
|
|
+ // the native implementation should be used across the project to save bytes.
|
|
|
+ // Check out https://caniuse.com/#feat=resizeobserver.
|
|
|
+ if ( typeof global.window.ResizeObserver === 'function' ) {
|
|
|
+ return new global.window.ResizeObserver( callback );
|
|
|
+ } else {
|
|
|
+ return new ResizeObserverPolyfill( callback );
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- observe( element ) {
|
|
|
- this.elements.add( element );
|
|
|
- }
|
|
|
+class ResizeObserverPolyfill {
|
|
|
+ constructor( callback ) {
|
|
|
+ this.callback = callback;
|
|
|
+ this.elements = new Set();
|
|
|
|
|
|
- unobserve( element ) {
|
|
|
- this.elements.remove( element );
|
|
|
- this._previousRects.delete( element );
|
|
|
+ this._startPeriodicCheck();
|
|
|
+ }
|
|
|
|
|
|
- if ( !this.elements.size ) {
|
|
|
- this._stopPeriodicCheck();
|
|
|
- }
|
|
|
- }
|
|
|
+ observe( element ) {
|
|
|
+ this.elements.add( element );
|
|
|
+ }
|
|
|
|
|
|
- disconnect() {
|
|
|
- this.elements.forEach( element => this.unobserve( element ) );
|
|
|
+ unobserve( element ) {
|
|
|
+ this.elements.remove( element );
|
|
|
+ this._previousRects.delete( element );
|
|
|
|
|
|
+ if ( !this.elements.size ) {
|
|
|
this._stopPeriodicCheck();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- _startPeriodicCheck() {
|
|
|
- this._previousRects = new Map();
|
|
|
+ disconnect() {
|
|
|
+ this.elements.forEach( element => this.unobserve( element ) );
|
|
|
|
|
|
- const periodicCheck = () => {
|
|
|
- this._checkElementRectsAndExecuteCallbacks();
|
|
|
- this._periodicCheckTimeout = setTimeout( periodicCheck, RESIZE_CHECK_INTERVAL );
|
|
|
- };
|
|
|
+ this._stopPeriodicCheck();
|
|
|
+ }
|
|
|
|
|
|
- this.listenTo( global.window, 'resize', () => {
|
|
|
- this._checkElementRectsAndExecuteCallbacks();
|
|
|
- } );
|
|
|
+ _startPeriodicCheck() {
|
|
|
+ this._previousRects = new Map();
|
|
|
|
|
|
- periodicCheck();
|
|
|
- }
|
|
|
+ const periodicCheck = () => {
|
|
|
+ this._checkElementRectsAndExecuteCallbacks();
|
|
|
+ this._periodicCheckTimeout = setTimeout( periodicCheck, RESIZE_CHECK_INTERVAL );
|
|
|
+ };
|
|
|
|
|
|
- _stopPeriodicCheck() {
|
|
|
- clearTimeout( this._periodicCheckTimeout );
|
|
|
- this.stopListening();
|
|
|
- this._previousRects.clear();
|
|
|
- }
|
|
|
+ this.listenTo( global.window, 'resize', () => {
|
|
|
+ this._checkElementRectsAndExecuteCallbacks();
|
|
|
+ } );
|
|
|
|
|
|
- _checkElementRectsAndExecuteCallbacks() {
|
|
|
- const entries = [];
|
|
|
+ periodicCheck();
|
|
|
+ }
|
|
|
|
|
|
- for ( const element of this.elements ) {
|
|
|
- if ( this._hasRectChanged( element ) ) {
|
|
|
- entries.push( {
|
|
|
- target: element,
|
|
|
- contentRect: this._previousRects.get( element )
|
|
|
- } );
|
|
|
- }
|
|
|
- }
|
|
|
+ _stopPeriodicCheck() {
|
|
|
+ clearTimeout( this._periodicCheckTimeout );
|
|
|
+ this.stopListening();
|
|
|
+ this._previousRects.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ _checkElementRectsAndExecuteCallbacks() {
|
|
|
+ const entries = [];
|
|
|
|
|
|
- if ( entries.length ) {
|
|
|
- this.callback( entries );
|
|
|
+ for ( const element of this.elements ) {
|
|
|
+ if ( this._hasRectChanged( element ) ) {
|
|
|
+ entries.push( {
|
|
|
+ target: element,
|
|
|
+ contentRect: this._previousRects.get( element )
|
|
|
+ } );
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- _hasRectChanged( element ) {
|
|
|
- const currentRect = new Rect( element );
|
|
|
- const previousRect = this._previousRects.get( element );
|
|
|
+ if ( entries.length ) {
|
|
|
+ this.callback( entries );
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- // The first check should always yield true despite no Previous rect to compare to.
|
|
|
- // The native ResizeObserver does that and... that makes sense. Sort of.
|
|
|
- const hasChanged = !previousRect || !previousRect.isEqual( currentRect );
|
|
|
+ _hasRectChanged( element ) {
|
|
|
+ const currentRect = new Rect( element );
|
|
|
+ const previousRect = this._previousRects.get( element );
|
|
|
|
|
|
- this._previousRects.set( element, currentRect );
|
|
|
+ // The first check should always yield true despite no Previous rect to compare to.
|
|
|
+ // The native ResizeObserver does that and... that makes sense. Sort of.
|
|
|
+ const hasChanged = !previousRect || !previousRect.isEqual( currentRect );
|
|
|
|
|
|
- return hasChanged;
|
|
|
- }
|
|
|
- };
|
|
|
+ this._previousRects.set( element, currentRect );
|
|
|
|
|
|
- mix( ExportedResizeObserver, DomEmitterMixin );
|
|
|
+ return hasChanged;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-export default ExportedResizeObserver;
|
|
|
+mix( ResizeObserverPolyfill, DomEmitterMixin );
|