Skip to content

Commit

Permalink
feat: control if to use native resize observable unless explicitly sp…
Browse files Browse the repository at this point in the history
…ecified via options object

The injection token {USE_NATIVE_RESIZE_OBSERVER} can be provided to control if to use native resize observable by default.
The flag has no effect if not supported by the user agent, or if explicitly specified via options object when creating the resize observable.

fixes: #156
  • Loading branch information
danielwiehl committed Jul 26, 2019
1 parent 42ba260 commit 2fa2ac8
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 4 deletions.
3 changes: 3 additions & 0 deletions projects/scion/dimension/src/lib/dimension.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import { SciDimensionDirective } from './dimension.directive';
* Web Performance Working Group is working on a W3C recommendation for natively observing changes to Element’s size.
* The Web API draft is still work in progress and support limited to Google Chrome and Opera.
*
* You can control if to use the native {ResizeObserver} by default with {USE_NATIVE_RESIZE_OBSERVER} DI injection token.
* If not provided, the native resize observable is used, unless explicitly set via options object when creating the resize observable.
*
* @see https://wicg.github.io/ResizeObserver/
* @see https://caniuse.com/#feat=resizeobserver
*/
Expand Down
23 changes: 20 additions & 3 deletions projects/scion/dimension/src/lib/dimension.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,21 @@

import { concat, fromEvent, Observable, Observer, of, ReplaySubject, Subject, TeardownLogic } from 'rxjs';
import { map, multicast, refCount, switchMap, takeUntil, tap } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { Injectable, InjectionToken, Injector } from '@angular/core';

/**
* CSS class added to the HTML <object> element emitting resize events if not using the native {ResizeObserver}.
*/
const SYNTH_RESIZE_OBSERVABLE_OBJECT_MARKER = 'synth-resize-observable';

/**
* DI injection token to control if to use the native {ResizeObserver} by default.
* If not provided, the native resize observable is used, unless explicitly set via options object when creating the resize observable.
*
* This flag is only evaluated if the user agent supports {ResizeObserver}.
*/
export const USE_NATIVE_RESIZE_OBSERVER = new InjectionToken<boolean>('USE_NATIVE_RESIZE_OBSERVER');

/**
* Allows observing the dimension of an element.
*
Expand All @@ -37,6 +48,9 @@ export class SciDimensionService {
*/
public _objectObservableRegistry = new Map<HTMLElement, Observable<SciDimension>>();

constructor(private _injector: Injector) {
}

/**
* Upon subscription, it emits the element's dimension, and then continuously emits when the dimension of the element changes. It never completes.
*
Expand All @@ -48,9 +62,12 @@ export class SciDimensionService {
* By default, this flag is enabled.
*/
public dimension$(target: HTMLElement, options?: { useNativeResizeObserver: boolean }): Observable<SciDimension> {
const useNativeResizeObserver = !options || options.useNativeResizeObserver === undefined || options.useNativeResizeObserver === true;
options = {
useNativeResizeObserver: this._injector.get(USE_NATIVE_RESIZE_OBSERVER, true),
...options,
};

if (useNativeResizeObserver && supportsNativeResizeObserver()) {
if (options.useNativeResizeObserver && supportsNativeResizeObserver()) {
return createNativeResizeObservable$(target);
}

Expand Down
2 changes: 1 addition & 1 deletion projects/scion/dimension/src/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
export { SciDimensionModule } from './lib/dimension.module';
export { SciDimensionDirective } from './lib/dimension.directive';
export { SciMutationService } from './lib/mutation.service';
export { SciDimensionService, SciDimension } from './lib/dimension.service';
export { SciDimensionService, SciDimension, USE_NATIVE_RESIZE_OBSERVER } from './lib/dimension.service';
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Injectable, ModuleWithProviders, NgModule } from '@angular/core';
import { ViewActivationInstantProvider } from '../view-activation-instant-provider.service';
import { WorkbenchModule } from '../workbench.module';
import { WorkbenchConfig } from '../workbench.config';
import { USE_NATIVE_RESIZE_OBSERVER } from '@scion/dimension';

@Injectable()
export class ViewActivationTestingInstantProvider implements ViewActivationInstantProvider {
Expand All @@ -27,6 +28,14 @@ export class WorkbenchTestingModule {
providers: [
WorkbenchModule.forRoot(config).providers,
{provide: ViewActivationInstantProvider, useClass: ViewActivationTestingInstantProvider},
/**
* Disable native `ResizeObserver` in tests because it sometimes throws 'loop limit exceeded' error which can safely be ignored.
*
* Comment from the specification authors:
* This error means that `ResizeObserver` was not able to deliver all observations within a single animation frame. It is benign and the site will not break.
* See https://stackoverflow.com/a/50387233
*/
{provide: USE_NATIVE_RESIZE_OBSERVER, useValue: false},
],
};
}
Expand Down

0 comments on commit 2fa2ac8

Please sign in to comment.