@progress/kendo-angular-gantt
Version:
Kendo UI Angular Gantt
84 lines (83 loc) • 4.03 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import { Injectable, NgZone } from '@angular/core';
import { Subscription, Subject, fromEvent } from 'rxjs';
import { distinctUntilChanged, map, take } from 'rxjs/operators';
import * as i0 from "@angular/core";
/**
* @hidden
*/
export class ScrollSyncService {
ngZone;
changes = new Subject();
elements = [];
subscriptions = new Subscription();
syncingTimeline;
syncingTreeList;
constructor(ngZone) {
this.ngZone = ngZone;
this.subscriptions.add(this.changes.subscribe(args => {
this.scroll(args);
}));
}
registerElement(el, sourceType) {
this.elements.push({ element: el, sourceType });
if (sourceType === "timeline" || sourceType === "treelist") {
this.ngZone.runOutsideAngular(() => {
const obs = fromEvent(el, 'scroll').pipe(map(({ target: { scrollTop, scrollLeft } }) => ({
scrollTop,
scrollLeft,
sourceType
})));
const comparisonFn = sourceType === 'timeline' ?
(x, y) => (x.scrollTop === y.scrollTop) && (x.scrollLeft === y.scrollLeft) :
(x, y) => (x.scrollTop === y.scrollTop);
this.subscriptions.add(obs.pipe(distinctUntilChanged(comparisonFn))
.subscribe((event) => this.changes.next(event)));
});
}
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
this.elements = null;
}
syncScrollTop(sourceType, targetType) {
const source = this.elements.find(element => element.sourceType === sourceType);
const target = this.elements.find(element => element.sourceType === targetType);
// Need to wait for the splitter pane's content to be rendered
this.ngZone.onStable.pipe(take(1)).subscribe(() => target.element.scrollTop = source.element.scrollTop);
}
resetTimelineScrollLeft() {
const source = this.elements.find(element => element.sourceType === 'timeline');
source.element.scrollLeft = 0;
}
scroll({ scrollTop, scrollLeft, sourceType }) {
this.ngZone.runOutsideAngular(() => {
if (sourceType === 'timeline') {
const header = this.elements.find(element => element.sourceType === 'header').element;
header.scrollLeft = scrollLeft;
if (!this.syncingTimeline) {
this.syncingTreeList = true;
const treelist = this.elements.find(element => element.sourceType === 'treelist').element;
treelist.scrollTop = scrollTop;
}
this.syncingTimeline = false;
}
if (sourceType === 'treelist') {
if (!this.syncingTreeList) {
this.syncingTimeline = true;
const timeline = this.elements.find(element => element.sourceType === 'timeline').element;
timeline.scrollTop = scrollTop;
}
this.syncingTreeList = false;
}
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScrollSyncService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScrollSyncService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScrollSyncService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i0.NgZone }] });