diff options
author | vempo <vitaliy.emporopulo@amdocs.com> | 2018-07-24 17:34:04 +0300 |
---|---|---|
committer | vempo <vitaliy.emporopulo@amdocs.com> | 2018-07-25 11:39:10 +0300 |
commit | a52d50e788792a63e97a9176ab319d53db7a2853 (patch) | |
tree | b1c2222cacf4b8192aea16d1e0315b1f005c5347 /deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll | |
parent | 3c2665debb400aef7f0ed9e235698d2ff9f859db (diff) |
Replaced old implementation at root
Old project files and directories has been moved
under 'deprecated-workflow-designer'. The old project
is not built by the CI anymore, but can be still built manually.
New modules/directories have been moved up and integrated with
the CI system.
Change-Id: I1528c792bcbcce9e50bfc294a1328a20e72c91cf
Issue-ID: SDC-1559
Signed-off-by: vempo <vitaliy.emporopulo@amdocs.com>
Diffstat (limited to 'deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll')
9 files changed, 567 insertions, 0 deletions
diff --git a/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/block-scroll-strategy.ts b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/block-scroll-strategy.ts new file mode 100644 index 00000000..d1c1d401 --- /dev/null +++ b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/block-scroll-strategy.ts @@ -0,0 +1,77 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/* tslint:disable:array-type member-access variable-name typedef + only-arrow-functions directive-class-suffix component-class-suffix + component-selector*/ +import {ViewportRuler} from '../position/viewport-ruler'; + +import {ScrollStrategy} from './scroll-strategy'; + +/** + * Strategy that will prevent the user from scrolling while the overlay is + * visible. + */ +export class BlockScrollStrategy implements ScrollStrategy { + private _previousHTMLStyles = {top: '', left: ''}; + private _previousScrollPosition: {top: number, left: number}; + private _isEnabled = false; + + constructor(private _viewportRuler: ViewportRuler) {} + + attach() { + // + } + + enable() { + if (this._canBeEnabled()) { + const root = document.documentElement; + + this._previousScrollPosition = + this._viewportRuler.getViewportScrollPosition(); + + // Cache the previous inline styles in case the user had set them. + this._previousHTMLStyles.left = root.style.left || ''; + this._previousHTMLStyles.top = root.style.top || ''; + + // Note: we're using the `html` node, instead of the `body`, because the + // `body` may have the user agent margin, whereas the `html` is guaranteed + // not to have one. + root.style.left = `${- this._previousScrollPosition.left}px`; + root.style.top = `${- this._previousScrollPosition.top}px`; + root.classList.add('cdk-global-scrollblock'); + this._isEnabled = true; + } + } + + disable() { + if (this._isEnabled) { + this._isEnabled = false; + document.documentElement.style.left = this._previousHTMLStyles.left; + document.documentElement.style.top = this._previousHTMLStyles.top; + document.documentElement.classList.remove('cdk-global-scrollblock'); + window.scroll( + this._previousScrollPosition.left, this._previousScrollPosition.top); + } + } + + private _canBeEnabled(): boolean { + // Since the scroll strategies can't be singletons, we have to use a global + // CSS class + // (`cdk-global-scrollblock`) to make sure that we don't try to disable + // global scrolling multiple times. + if (document.documentElement.classList.contains('cdk-global-scrollblock') || + this._isEnabled) { + return false; + } + + const body = document.body; + const viewport = this._viewportRuler.getViewportRect(); + return body.scrollHeight > viewport.height || + body.scrollWidth > viewport.width; + } +} diff --git a/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/close-scroll-strategy.ts b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/close-scroll-strategy.ts new file mode 100644 index 00000000..51189dc1 --- /dev/null +++ b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/close-scroll-strategy.ts @@ -0,0 +1,54 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/* tslint:disable:array-type member-access variable-name typedef + only-arrow-functions directive-class-suffix component-class-suffix + component-selector*/ +import {Subscription} from 'rxjs/Subscription'; + +import {OverlayRef} from '../overlay-ref'; + +import {ScrollDispatcher} from './scroll-dispatcher'; +import {getMdScrollStrategyAlreadyAttachedError, ScrollStrategy} from './scroll-strategy'; + + +/** + * Strategy that will close the overlay as soon as the user starts scrolling. + */ +export class CloseScrollStrategy implements ScrollStrategy { + private _scrollSubscription: Subscription|null = null; + private _overlayRef: OverlayRef; + + constructor(private _scrollDispatcher: ScrollDispatcher) {} + + attach(overlayRef: OverlayRef) { + if (this._overlayRef) { + throw getMdScrollStrategyAlreadyAttachedError(); + } + + this._overlayRef = overlayRef; + } + + enable() { + if (!this._scrollSubscription) { + this._scrollSubscription = this._scrollDispatcher.scrolled(0, () => { + if (this._overlayRef.hasAttached()) { + this._overlayRef.detach(); + } + + this.disable(); + }); + } + } + + disable() { + if (this._scrollSubscription) { + this._scrollSubscription.unsubscribe(); + this._scrollSubscription = null; + } + } +} diff --git a/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/index.ts b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/index.ts new file mode 100644 index 00000000..e386770b --- /dev/null +++ b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/index.ts @@ -0,0 +1,35 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/* tslint:disable:array-type member-access variable-name typedef + only-arrow-functions directive-class-suffix component-class-suffix + component-selector*/ +import {PlatformModule} from '@angular/cdk'; +import {NgModule} from '@angular/core'; + +import {SCROLL_DISPATCHER_PROVIDER} from './scroll-dispatcher'; +import {ScrollStrategyOptions} from './scroll-strategy-options'; +import {Scrollable} from './scrollable'; + +export {BlockScrollStrategy} from './block-scroll-strategy'; +export {CloseScrollStrategy} from './close-scroll-strategy'; +export {NoopScrollStrategy} from './noop-scroll-strategy'; +export {RepositionScrollStrategy} from './reposition-scroll-strategy'; +export {ScrollDispatcher} from './scroll-dispatcher'; +// Export pre-defined scroll strategies and interface to build custom ones. +export {ScrollStrategy} from './scroll-strategy'; +export {ScrollStrategyOptions} from './scroll-strategy-options'; +export {Scrollable} from './scrollable'; + +@NgModule({ + imports: [PlatformModule], + exports: [Scrollable], + declarations: [Scrollable], + providers: [SCROLL_DISPATCHER_PROVIDER, ScrollStrategyOptions], +}) +export class ScrollDispatchModule { +} diff --git a/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/noop-scroll-strategy.ts b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/noop-scroll-strategy.ts new file mode 100644 index 00000000..9b92ab49 --- /dev/null +++ b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/noop-scroll-strategy.ts @@ -0,0 +1,24 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {ScrollStrategy} from './scroll-strategy'; + +/** + * Scroll strategy that doesn't do anything. + */ +export class NoopScrollStrategy implements ScrollStrategy { + enable() { + // + } + disable() { + // + } + attach() { + // + } +} diff --git a/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/reposition-scroll-strategy.ts b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/reposition-scroll-strategy.ts new file mode 100644 index 00000000..b15d5dea --- /dev/null +++ b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/reposition-scroll-strategy.ts @@ -0,0 +1,59 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/* tslint:disable:array-type member-access variable-name typedef + only-arrow-functions directive-class-suffix component-class-suffix + component-selector*/ +import {Subscription} from 'rxjs/Subscription'; + +import {OverlayRef} from '../overlay-ref'; + +import {ScrollDispatcher} from './scroll-dispatcher'; +import {getMdScrollStrategyAlreadyAttachedError, ScrollStrategy} from './scroll-strategy'; + +/** + * Config options for the RepositionScrollStrategy. + */ +export interface RepositionScrollStrategyConfig { scrollThrottle?: number; } + +/** + * Strategy that will update the element position as the user is scrolling. + */ +export class RepositionScrollStrategy implements ScrollStrategy { + private _scrollSubscription: Subscription|null = null; + private _overlayRef: OverlayRef; + + constructor( + private _scrollDispatcher: ScrollDispatcher, + private _config?: RepositionScrollStrategyConfig) {} + + attach(overlayRef: OverlayRef) { + if (this._overlayRef) { + throw getMdScrollStrategyAlreadyAttachedError(); + } + + this._overlayRef = overlayRef; + } + + enable() { + if (!this._scrollSubscription) { + const throttle = this._config ? this._config.scrollThrottle : 0; + + this._scrollSubscription = + this._scrollDispatcher.scrolled(throttle, () => { + this._overlayRef.updatePosition(); + }); + } + } + + disable() { + if (this._scrollSubscription) { + this._scrollSubscription.unsubscribe(); + this._scrollSubscription = null; + } + } +} diff --git a/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/scroll-dispatcher.ts b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/scroll-dispatcher.ts new file mode 100644 index 00000000..2c145af5 --- /dev/null +++ b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/scroll-dispatcher.ts @@ -0,0 +1,174 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/* tslint:disable:array-type member-access variable-name typedef + only-arrow-functions directive-class-suffix component-class-suffix + component-selector*/ +import {Platform} from '@angular/cdk'; +import {auditTime} from 'rxjs/operator/auditTime'; +import {ElementRef, Injectable, NgZone, Optional, SkipSelf} from '@angular/core'; +import {fromEvent} from 'rxjs/observable/fromEvent'; +import {merge} from 'rxjs/observable/merge'; +import {Subject} from 'rxjs/Subject'; +import {Subscription} from 'rxjs/Subscription'; + +import {Scrollable} from './scrollable'; + + +/** Time in ms to throttle the scrolling events by default. */ +export const DEFAULT_SCROLL_TIME = 20; + +/** + * Service contained all registered Scrollable references and emits an event + * when any one of the Scrollable references emit a scrolled event. + */ +@Injectable() +export class ScrollDispatcher { + /** Subject for notifying that a registered scrollable reference element has + * been scrolled. */ + _scrolled: Subject<void> = new Subject<void>(); + + /** Keeps track of the global `scroll` and `resize` subscriptions. */ + _globalSubscription: Subscription|null = null; + + /** Keeps track of the amount of subscriptions to `scrolled`. Used for + * cleaning up afterwards. */ + private _scrolledCount = 0; + + /** + * Map of all the scrollable references that are registered with the service + * and their scroll event subscriptions. + */ + scrollableReferences: Map<Scrollable, Subscription> = new Map(); + + constructor(private _ngZone: NgZone, private _platform: Platform) {} + + /** + * Registers a Scrollable with the service and listens for its scrolled + * events. When the scrollable is scrolled, the service emits the event in its + * scrolled observable. + * @param scrollable Scrollable instance to be registered. + */ + register(scrollable: Scrollable): void { + const scrollSubscription = + scrollable.elementScrolled().subscribe(() => this._notify()); + + this.scrollableReferences.set(scrollable, scrollSubscription); + } + + /** + * Deregisters a Scrollable reference and unsubscribes from its scroll event + * observable. + * @param scrollable Scrollable instance to be deregistered. + */ + deregister(scrollable: Scrollable): void { + const scrollableReference = this.scrollableReferences.get(scrollable); + + if (scrollableReference) { + scrollableReference.unsubscribe(); + this.scrollableReferences.delete(scrollable); + } + } + + /** + * Subscribes to an observable that emits an event whenever any of the + * registered Scrollable references (or window, document, or body) fire a + * scrolled event. Can provide a time in ms to override the default "throttle" + * time. + */ + scrolled(auditTimeInMs: number = DEFAULT_SCROLL_TIME, callback: () => any): + Subscription { + // Scroll events can only happen on the browser, so do nothing if we're not + // on the browser. + if (!this._platform.isBrowser) { + return Subscription.EMPTY; + } + + // In the case of a 0ms delay, use an observable without auditTime + // since it does add a perceptible delay in processing overhead. + const observable = auditTimeInMs > 0 ? + auditTime.call(this._scrolled.asObservable(), auditTimeInMs) : + this._scrolled.asObservable(); + + this._scrolledCount++; + + if (!this._globalSubscription) { + this._globalSubscription = this._ngZone.runOutsideAngular(() => { + return merge( + fromEvent(window.document, 'scroll'), + fromEvent(window, 'resize')) + .subscribe(() => this._notify()); + }); + } + + // Note that we need to do the subscribing from here, in order to be able to + // remove the global event listeners once there are no more subscriptions. + const subscription = observable.subscribe(callback); + + subscription.add(() => { + this._scrolledCount--; + + if (this._globalSubscription && !this.scrollableReferences.size && + !this._scrolledCount) { + this._globalSubscription.unsubscribe(); + this._globalSubscription = null; + } + }); + + return subscription; + } + + /** Returns all registered Scrollables that contain the provided element. */ + getScrollContainers(elementRef: ElementRef): Scrollable[] { + const scrollingContainers: Scrollable[] = []; + + this.scrollableReferences.forEach( + (_subscription: Subscription, scrollable: Scrollable) => { + if (this.scrollableContainsElement(scrollable, elementRef)) { + scrollingContainers.push(scrollable); + } + }); + + return scrollingContainers; + } + + /** Returns true if the element is contained within the provided Scrollable. + */ + scrollableContainsElement(scrollable: Scrollable, elementRef: ElementRef): + boolean { + let element = elementRef.nativeElement; + const scrollableElement = scrollable.getElementRef().nativeElement; + + // Traverse through the element parents until we reach null, checking if any + // of the elements are the scrollable's element. + do { + if (element === scrollableElement) { + return true; + } + } while (element = element.parentElement); + + return false; + } + + /** Sends a notification that a scroll event has been fired. */ + _notify() { + this._scrolled.next(); + } +} + +export function SCROLL_DISPATCHER_PROVIDER_FACTORY( + parentDispatcher: ScrollDispatcher, ngZone: NgZone, platform: Platform) { + return parentDispatcher || new ScrollDispatcher(ngZone, platform); +} + +export const SCROLL_DISPATCHER_PROVIDER = { + // If there is already a ScrollDispatcher available, use that. Otherwise, + // provide a new one. + provide: ScrollDispatcher, + deps: [[new Optional(), new SkipSelf(), ScrollDispatcher], NgZone, Platform], + useFactory: SCROLL_DISPATCHER_PROVIDER_FACTORY +}; diff --git a/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/scroll-strategy-options.ts b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/scroll-strategy-options.ts new file mode 100644 index 00000000..f6270388 --- /dev/null +++ b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/scroll-strategy-options.ts @@ -0,0 +1,52 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/* tslint:disable:array-type member-access variable-name typedef + only-arrow-functions directive-class-suffix component-class-suffix + component-selector no-unused-expression*/ +import {Injectable} from '@angular/core'; + +import {ViewportRuler} from '../position/viewport-ruler'; + +import {BlockScrollStrategy} from './block-scroll-strategy'; +import {CloseScrollStrategy} from './close-scroll-strategy'; +import {NoopScrollStrategy} from './noop-scroll-strategy'; +import {RepositionScrollStrategy, RepositionScrollStrategyConfig} from './reposition-scroll-strategy'; +import {ScrollDispatcher} from './scroll-dispatcher'; +// import {ScrollStrategy} from './scroll-strategy'; + + +/** + * Options for how an overlay will handle scrolling. + * + * Users can provide a custom value for `ScrollStrategyOptions` to replace the + * default behaviors. This class primarily acts as a factory for ScrollStrategy + * instances. + */ +@Injectable() +export class ScrollStrategyOptions { + constructor( + private _scrollDispatcher: ScrollDispatcher, + private _viewportRuler: ViewportRuler) {} + + /** Do nothing on scroll. */ + noop = () => new NoopScrollStrategy(); + + /** Close the overlay as soon as the user scrolls. */ + close = () => new CloseScrollStrategy(this._scrollDispatcher); + + /** Block scrolling. */ + block = () => new BlockScrollStrategy(this._viewportRuler); + + /** + * Update the overlay's position on scroll. + * @param config Configuration to be used inside the scroll strategy. + * Allows debouncing the reposition calls. + */ + reposition = (config?: RepositionScrollStrategyConfig) => + new RepositionScrollStrategy(this._scrollDispatcher, config) +} diff --git a/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/scroll-strategy.ts b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/scroll-strategy.ts new file mode 100644 index 00000000..d59651a7 --- /dev/null +++ b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/scroll-strategy.ts @@ -0,0 +1,29 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/* tslint:disable:array-type member-access variable-name typedef + only-arrow-functions directive-class-suffix component-class-suffix + component-selector*/ +import {OverlayRef} from '../overlay-ref'; + +/** + * Describes a strategy that will be used by an overlay + * to handle scroll events while it is open. + */ +export abstract class ScrollStrategy { + enable: () => void; + disable: () => void; + attach: (overlayRef: OverlayRef) => void; +} + +/** + * Returns an error to be thrown when attempting to attach an already-attached + * scroll strategy. + */ +export function getMdScrollStrategyAlreadyAttachedError(): Error { + return Error(`Scroll strategy has already been attached.`); +} diff --git a/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/scrollable.ts b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/scrollable.ts new file mode 100644 index 00000000..fe7b041c --- /dev/null +++ b/deprecated-workflow-designer/sdc-workflow-designer-ui/src/app/paletx/core/overlay/scroll/scrollable.ts @@ -0,0 +1,63 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +/* tslint:disable:array-type member-access variable-name typedef + only-arrow-functions directive-class-suffix component-class-suffix + component-selector*/ +import {Directive, ElementRef, NgZone, OnDestroy, OnInit, Renderer2} from '@angular/core'; +import {Observable} from 'rxjs/Observable'; +import {Subject} from 'rxjs/Subject'; + +import {ScrollDispatcher} from './scroll-dispatcher'; + + +/** + * Sends an event when the directive's element is scrolled. Registers itself + * with the ScrollDispatcher service to include itself as part of its collection + * of scrolling events that it can be listened to through the service. + */ +@Directive({selector: '[cdk-scrollable], [cdkScrollable]'}) +export class Scrollable implements OnInit, OnDestroy { + private _elementScrolled: Subject<Event> = new Subject(); + private _scrollListener: Function|null; + + constructor( + private _elementRef: ElementRef, private _scroll: ScrollDispatcher, + private _ngZone: NgZone, private _renderer: Renderer2) {} + + ngOnInit() { + this._scrollListener = this._ngZone.runOutsideAngular(() => { + return this._renderer.listen( + this.getElementRef().nativeElement, 'scroll', (event: Event) => { + this._elementScrolled.next(event); + }); + }); + + this._scroll.register(this); + } + + ngOnDestroy() { + this._scroll.deregister(this); + + if (this._scrollListener) { + this._scrollListener(); + this._scrollListener = null; + } + } + + /** + * Returns observable that emits when a scroll event is fired on the host + * element. + */ + elementScrolled(): Observable<any> { + return this._elementScrolled.asObservable(); + } + + getElementRef(): ElementRef { + return this._elementRef; + } +} |