blob: db9ac75cd7498b20a2be031229914667c2a943aa [file] [log] [blame]
{"version":3,"file":"cdk-observers.umd.min.js","sources":["../../src/cdk/observers/observe-content.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {coerceBooleanProperty, coerceNumberProperty, coerceElement} from '@angular/cdk/coercion';\nimport {\n AfterContentInit,\n Directive,\n ElementRef,\n EventEmitter,\n Injectable,\n Input,\n NgModule,\n NgZone,\n OnDestroy,\n Output,\n} from '@angular/core';\nimport {Observable, Subject, Subscription, Observer} from 'rxjs';\nimport {debounceTime} from 'rxjs/operators';\n\n/**\n * Factory that creates a new MutationObserver and allows us to stub it out in unit tests.\n * @docs-private\n */\n@Injectable({providedIn: 'root'})\nexport class MutationObserverFactory {\n create(callback: MutationCallback): MutationObserver | null {\n return typeof MutationObserver === 'undefined' ? null : new MutationObserver(callback);\n }\n}\n\n\n/** An injectable service that allows watching elements for changes to their content. */\n@Injectable({providedIn: 'root'})\nexport class ContentObserver implements OnDestroy {\n /** Keeps track of the existing MutationObservers so they can be reused. */\n private _observedElements = new Map<Element, {\n observer: MutationObserver | null,\n stream: Subject<MutationRecord[]>,\n count: number\n }>();\n\n constructor(private _mutationObserverFactory: MutationObserverFactory) {}\n\n ngOnDestroy() {\n this._observedElements.forEach((_, element) => this._cleanupObserver(element));\n }\n\n /**\n * Observe content changes on an element.\n * @param element The element to observe for content changes.\n */\n observe(element: Element): Observable<MutationRecord[]>;\n\n /**\n * Observe content changes on an element.\n * @param element The element to observe for content changes.\n */\n observe(element: ElementRef<Element>): Observable<MutationRecord[]>;\n\n observe(elementOrRef: Element | ElementRef<Element>): Observable<MutationRecord[]> {\n const element = coerceElement(elementOrRef);\n\n return new Observable((observer: Observer<MutationRecord[]>) => {\n const stream = this._observeElement(element);\n const subscription = stream.subscribe(observer);\n\n return () => {\n subscription.unsubscribe();\n this._unobserveElement(element);\n };\n });\n }\n\n /**\n * Observes the given element by using the existing MutationObserver if available, or creating a\n * new one if not.\n */\n private _observeElement(element: Element): Subject<MutationRecord[]> {\n if (!this._observedElements.has(element)) {\n const stream = new Subject<MutationRecord[]>();\n const observer = this._mutationObserverFactory.create(mutations => stream.next(mutations));\n if (observer) {\n observer.observe(element, {\n characterData: true,\n childList: true,\n subtree: true\n });\n }\n this._observedElements.set(element, {observer, stream, count: 1});\n } else {\n this._observedElements.get(element)!.count++;\n }\n return this._observedElements.get(element)!.stream;\n }\n\n /**\n * Un-observes the given element and cleans up the underlying MutationObserver if nobody else is\n * observing this element.\n */\n private _unobserveElement(element: Element) {\n if (this._observedElements.has(element)) {\n this._observedElements.get(element)!.count--;\n if (!this._observedElements.get(element)!.count) {\n this._cleanupObserver(element);\n }\n }\n }\n\n /** Clean up the underlying MutationObserver for the specified element. */\n private _cleanupObserver(element: Element) {\n if (this._observedElements.has(element)) {\n const {observer, stream} = this._observedElements.get(element)!;\n if (observer) {\n observer.disconnect();\n }\n stream.complete();\n this._observedElements.delete(element);\n }\n }\n}\n\n\n/**\n * Directive that triggers a callback whenever the content of\n * its associated element has changed.\n */\n@Directive({\n selector: '[cdkObserveContent]',\n exportAs: 'cdkObserveContent',\n})\nexport class CdkObserveContent implements AfterContentInit, OnDestroy {\n /** Event emitted for each change in the element's content. */\n @Output('cdkObserveContent') event = new EventEmitter<MutationRecord[]>();\n\n /**\n * Whether observing content is disabled. This option can be used\n * to disconnect the underlying MutationObserver until it is needed.\n */\n @Input('cdkObserveContentDisabled')\n get disabled() { return this._disabled; }\n set disabled(value: any) {\n this._disabled = coerceBooleanProperty(value);\n this._disabled ? this._unsubscribe() : this._subscribe();\n }\n private _disabled = false;\n\n /** Debounce interval for emitting the changes. */\n @Input()\n get debounce(): number { return this._debounce; }\n set debounce(value: number) {\n this._debounce = coerceNumberProperty(value);\n this._subscribe();\n }\n private _debounce: number;\n\n private _currentSubscription: Subscription | null = null;\n\n constructor(private _contentObserver: ContentObserver,\n private _elementRef: ElementRef<HTMLElement>,\n private _ngZone: NgZone) {}\n\n ngAfterContentInit() {\n if (!this._currentSubscription && !this.disabled) {\n this._subscribe();\n }\n }\n\n ngOnDestroy() {\n this._unsubscribe();\n }\n\n private _subscribe() {\n this._unsubscribe();\n const stream = this._contentObserver.observe(this._elementRef);\n\n // TODO(mmalerba): We shouldn't be emitting on this @Output() outside the zone.\n // Consider brining it back inside the zone next time we're making breaking changes.\n // Bringing it back inside can cause things like infinite change detection loops and changed\n // after checked errors if people's code isn't handling it properly.\n this._ngZone.runOutsideAngular(() => {\n this._currentSubscription =\n (this.debounce ? stream.pipe(debounceTime(this.debounce)) : stream).subscribe(this.event);\n });\n }\n\n private _unsubscribe() {\n if (this._currentSubscription) {\n this._currentSubscription.unsubscribe();\n }\n }\n}\n\n\n@NgModule({\n exports: [CdkObserveContent],\n declarations: [CdkObserveContent],\n providers: [MutationObserverFactory]\n})\nexport class ObserversModule {}\n"],"names":["MutationObserverFactory","prototype","create","callback","MutationObserver","type","Injectable","args","providedIn","ContentObserver","_mutationObserverFactory","this","_observedElements","Map","ngOnDestroy","_this","forEach","_","element","_cleanupObserver","observe","elementOrRef","coerceElement","Observable","observer","stream","_observeElement","subscription","subscribe","unsubscribe","_unobserveElement","has","get","count","stream_1","Subject","mutations","next","characterData","childList","subtree","set","_a","disconnect","complete","delete","CdkObserveContent","_contentObserver","_elementRef","_ngZone","event","EventEmitter","_disabled","_currentSubscription","Object","defineProperty","value","coerceBooleanProperty","_unsubscribe","_subscribe","_debounce","coerceNumberProperty","ngAfterContentInit","disabled","runOutsideAngular","debounce","pipe","debounceTime","Directive","selector","exportAs","ElementRef","NgZone","Output","Input","ObserversModule","NgModule","exports","declarations","providers"],"mappings":"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"}