UNPKG

@foblex/drag-toolkit

Version:

A TypeScript library providing foundational classes and utilities for implementing drag-and-drop functionality in Angular applications, with support for both mouse and touch events, and designed to work with or without Angular’s NgZone (zoneless applicati

162 lines 27 kB
import { IMouseEvent, ITouchDownEvent, ITouchMoveEvent } from './pointer-events'; import { EventExtensions } from './event.extensions'; import { IPointerUpEvent } from './pointer-events/i-pointer-up-event'; export const MOUSE_EVENT_IGNORE_TIME = 800; export class DragAndDropBase { constructor(ngZone) { this.ngZone = ngZone; this.mouseListeners = EventExtensions.emptyListener(); this.touchListeners = EventExtensions.emptyListener(); this.startListeners = EventExtensions.emptyListener(); this.lastTouchEventTime = 0; this.isDragStarted = false; this.dragStartThreshold = 3; this.dragStartDelay = 0; this.dragStartTime = 0; this.dragStartPosition = { x: 0, y: 0 }; this.moveHandler = this.checkDragSequenceToStart; this.pointerDownElement = null; this.onMouseDown = (event) => { var _a; const isSyntheticEvent = this.isSyntheticEvent(event); const isFakeEvent = isFakeMousedownFromScreenReader(event); const mouseEvent = new IMouseEvent(event); this.pointerDownElement = mouseEvent.targetElement; if (isSyntheticEvent || isFakeEvent || this.disabled) { return; } let result = this.onPointerDown(mouseEvent); if (result) { this.dragStartTime = Date.now(); this.dragStartPosition = mouseEvent.getPosition(); (_a = this.ngZone) === null || _a === void 0 ? void 0 : _a.runOutsideAngular(() => { var _a, _b, _c; (_a = this.document) === null || _a === void 0 ? void 0 : _a.addEventListener('selectstart', this.onSelectStart, EventExtensions.activeListener()); (_b = this.document) === null || _b === void 0 ? void 0 : _b.addEventListener('mousemove', this.onMouseMove); (_c = this.document) === null || _c === void 0 ? void 0 : _c.addEventListener('pointerup', this.onPointerUpEvent); }); this.mouseListeners = () => { var _a, _b, _c; (_a = this.document) === null || _a === void 0 ? void 0 : _a.removeEventListener('selectstart', this.onSelectStart, EventExtensions.activeListener()); (_b = this.document) === null || _b === void 0 ? void 0 : _b.removeEventListener('mousemove', this.onMouseMove); (_c = this.document) === null || _c === void 0 ? void 0 : _c.removeEventListener('pointerup', this.onPointerUpEvent); }; } }; this.onTouchDown = (event) => { var _a; const isFakeEvent = isFakeTouchstartFromScreenReader(event); const touchEvent = new ITouchDownEvent(event); this.pointerDownElement = touchEvent.targetElement; if (isFakeEvent || this.disabled) { return; } let result = this.onPointerDown(touchEvent); if (result) { this.dragStartTime = Date.now(); this.dragStartPosition = touchEvent.getPosition(); (_a = this.ngZone) === null || _a === void 0 ? void 0 : _a.runOutsideAngular(() => { var _a, _b, _c; (_a = this.document) === null || _a === void 0 ? void 0 : _a.addEventListener('selectstart', this.onSelectStart, EventExtensions.activeListener()); (_b = this.document) === null || _b === void 0 ? void 0 : _b.addEventListener('touchmove', this.onTouchMove); (_c = this.document) === null || _c === void 0 ? void 0 : _c.addEventListener('pointerup', this.onPointerUpEvent); }); this.touchListeners = () => { var _a, _b, _c; (_a = this.document) === null || _a === void 0 ? void 0 : _a.removeEventListener('selectstart', this.onSelectStart, EventExtensions.activeListener()); (_b = this.document) === null || _b === void 0 ? void 0 : _b.removeEventListener('touchmove', this.onTouchMove); (_c = this.document) === null || _c === void 0 ? void 0 : _c.removeEventListener('pointerup', this.onPointerUpEvent); }; } }; this.onSelectStart = (event) => { this.onSelect(event); }; this.onMouseMove = (event) => { this.moveHandler(new IMouseEvent(event)); }; this.onTouchMove = (event) => { this.moveHandler(new ITouchMoveEvent(event)); }; this.onPointerUpEvent = (event) => { if (this.isDragStarted) { this.onPointerUp(new IPointerUpEvent(event)); } this.endDragSequence(); }; } isSyntheticEvent(event) { return !!this.lastTouchEventTime && (this.lastTouchEventTime + MOUSE_EVENT_IGNORE_TIME > Date.now()); } checkDragSequenceToStart(event) { const pointerPosition = event.getPosition(); if (!this.isDragStarted && this.pointerDownElement) { event.setTarget(this.pointerDownElement); const distanceX = Math.abs(pointerPosition.x - this.dragStartPosition.x); const distanceY = Math.abs(pointerPosition.y - this.dragStartPosition.y); const isOverThreshold = distanceX + distanceY >= this.dragStartThreshold; if (isOverThreshold) { const isDelayElapsed = Date.now() >= this.dragStartTime + this.dragStartDelay; if (!isDelayElapsed) { this.endDragSequence(); return; } event.preventDefault(); this.prepareDragSequence(event); this.isDragStarted = true; this.moveHandler = this.onPointerMove; if (isTouchEvent(event.originalEvent)) { this.lastTouchEventTime = Date.now(); } } } } endDragSequence() { this.isDragStarted = false; this.pointerDownElement = null; this.moveHandler = this.checkDragSequenceToStart; this.mouseListeners(); this.mouseListeners = EventExtensions.emptyListener(); this.touchListeners(); this.touchListeners = EventExtensions.emptyListener(); this.finalizeDragSequence(); } subscribe(fDocument) { var _a; if (this.document) { this.unsubscribe(); } this.document = fDocument; (_a = this.ngZone) === null || _a === void 0 ? void 0 : _a.runOutsideAngular(() => { fDocument.addEventListener('mousedown', this.onMouseDown, EventExtensions.activeListener()); fDocument.addEventListener('touchstart', this.onTouchDown, EventExtensions.passiveListener()); }); this.startListeners = () => { fDocument.removeEventListener('mousedown', this.onMouseDown, EventExtensions.activeListener()); fDocument.removeEventListener('touchstart', this.onTouchDown, EventExtensions.passiveListener()); }; } unsubscribe() { this.startListeners(); this.startListeners = EventExtensions.emptyListener(); this.touchListeners(); this.touchListeners = EventExtensions.emptyListener(); this.mouseListeners(); this.mouseListeners = EventExtensions.emptyListener(); } } function isTouchEvent(event) { return event.type[0] === 't'; } function isFakeMousedownFromScreenReader(event) { return event.buttons === 0 || (event.offsetX === 0 && event.offsetY === 0); } function isFakeTouchstartFromScreenReader(event) { const touch = (event.touches && event.touches[0]) || (event.changedTouches && event.changedTouches[0]); return (!!touch && touch.identifier === -1 && (touch.radiusX == null || touch.radiusX === 1) && (touch.radiusY == null || touch.radiusY === 1)); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJhZy1hbmQtZHJvcC1iYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vcHJvamVjdHMvZi1kcmFnLXRvb2xraXQvc3JjL2RyYWctYW5kLWRyb3AtYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsV0FBVyxFQUFpQixlQUFlLEVBQUUsZUFBZSxFQUFpQixNQUFNLGtCQUFrQixDQUFDO0FBQy9HLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFFdEUsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsR0FBRyxDQUFDO0FBRTNDLE1BQU0sT0FBZ0IsZUFBZTtJQStCbkMsWUFDWSxNQUF5QztRQUF6QyxXQUFNLEdBQU4sTUFBTSxDQUFtQztRQTFCN0MsbUJBQWMsR0FBYSxlQUFlLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDM0QsbUJBQWMsR0FBYSxlQUFlLENBQUMsYUFBYSxFQUFFLENBQUM7UUFFM0QsbUJBQWMsR0FBYSxlQUFlLENBQUMsYUFBYSxFQUFFLENBQUM7UUFPM0QsdUJBQWtCLEdBQVcsQ0FBQyxDQUFDO1FBRWhDLGtCQUFhLEdBQVksS0FBSyxDQUFDO1FBQzlCLHVCQUFrQixHQUFXLENBQUMsQ0FBQztRQUMvQixtQkFBYyxHQUFXLENBQUMsQ0FBQztRQUUzQixrQkFBYSxHQUFXLENBQUMsQ0FBQztRQUMxQixzQkFBaUIsR0FBNkIsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUk3RCxnQkFBVyxHQUFhLElBQUksQ0FBQyx3QkFBd0IsQ0FBQztRQUV0RCx1QkFBa0IsR0FBdUIsSUFBSSxDQUFDO1FBTzlDLGdCQUFXLEdBQUcsQ0FBQyxLQUFpQixFQUFFLEVBQUU7O1lBQzFDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFD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QUFDLGNBQWMsQ0FBRSxDQUFDLENBQUUsQ0FBQyxDQUFDO0lBQy9GLE9BQU8sQ0FDTCxDQUFDLENBQUMsS0FBSztRQUNQLEtBQUssQ0FBQyxVQUFVLEtBQUssQ0FBQyxDQUFDO1FBQ3ZCLENBQUMsS0FBSyxDQUFDLE9BQU8sSUFBSSxJQUFJLElBQUksS0FBSyxDQUFDLE9BQU8sS0FBSyxDQUFDLENBQUM7UUFDOUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxJQUFJLElBQUksSUFBSSxLQUFLLENBQUMsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUMvQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IElDYW5SdW5PdXRzaWRlQW5ndWxhciB9IGZyb20gJy4vaS1jYW4tcnVuLW91dHNpZGUtYW5ndWxhcic7XG5pbXBvcnQgeyBJTW91c2VFdmVudCwgSVBvaW50ZXJFdmVudCwgSVRvdWNoRG93bkV2ZW50LCBJVG91Y2hNb3ZlRXZlbnQsIElUb3VjaFVwRXZlbnQgfSBmcm9tICcuL3BvaW50ZXItZXZlbnRzJztcbmltcG9ydCB7IEV2ZW50RXh0ZW5zaW9ucyB9IGZyb20gJy4vZXZlbnQuZXh0ZW5zaW9ucyc7XG5pbXBvcnQgeyBJUG9pbnRlclVwRXZlbnQgfSBmcm9tICcuL3BvaW50ZXItZXZlbnRzL2ktcG9pbnRlci11cC1ldmVudCc7XG5cbmV4cG9ydCBjb25zdCBNT1VTRV9FVkVOVF9JR05PUkVfVElNRSA9IDgwMDtcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIERyYWdBbmREcm9wQmFzZSB7XG5cbiAgcHVibGljIGFic3RyYWN0IGhvc3RFbGVtZW50OiBIVE1MRWxlbWVudDtcblxuICBwcml2YXRlIGRvY3VtZW50OiBEb2N1bWVudCB8IHVuZGVmaW5lZDtcblxuICBwcml2YXRlIG1vdXNlTGlzdGVuZXJzOiBGdW5jdGlvbiA9IEV2ZW50RXh0ZW5zaW9ucy5lbXB0eUxpc3RlbmVyKCk7XG4gIHByaXZhdGUgdG91Y2hMaXN0ZW5lcnM6IEZ1bmN0aW9uID0gRXZlbnRFeHRlbnNpb25zLmVtcHR5TGlzdGVuZXIoKTtcblxuICBwcml2YXRlIHN0YXJ0TGlzdGVuZXJzOiBGdW5jdGlvbiA9IEV2ZW50RXh0ZW5zaW9ucy5lbXB0eUxpc3RlbmVyKCk7XG5cbiAgcHVibGljIGlzU3ludGhldGljRXZlbnQoZXZlbnQ6IE1vdXNlRXZlbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLmxhc3RUb3VjaEV2ZW50VGltZSAmJlxuICAgICAgKHRoaXMubGFzdFRvdWNoRXZlbnRUaW1lICsgTU9VU0VfRVZFTlRfSUdOT1JFX1RJTUUgPiBEYXRlLm5vdygpKTtcbiAgfVxuXG4gIHByaXZhdGUgbGFzdFRvdWNoRXZlbnRUaW1lOiBudW1iZXIgPSAwO1xuXG4gIHB1YmxpYyBpc0RyYWdTdGFydGVkOiBib29sZWFuID0gZmFsc2U7XG4gIHByaXZhdGUgZHJhZ1N0YXJ0VGhyZXNob2xkOiBudW1iZXIgPSAzO1xuICBwcml2YXRlIGRyYWdTdGFydERlbGF5OiBudW1iZXIgPSAwO1xuXG4gIHByaXZhdGUgZHJhZ1N0YXJ0VGltZTogbnVtYmVyID0gMDtcbiAgcHJpdmF0ZSBkcmFnU3RhcnRQb3NpdGlvbjogeyB4OiBudW1iZXIsIHk6IG51bWJlciB9ID0geyB4OiAwLCB5OiAwIH07XG5cbiAgcHVibGljIGFic3RyYWN0IGRpc2FibGVkOiBib29sZWFuO1xuXG4gIHByaXZhdGUgbW92ZUhhbmRsZXI6IEZ1bmN0aW9uID0gdGhpcy5jaGVja0RyYWdTZXF1ZW5jZVRvU3RhcnQ7XG5cbiAgcHJpdmF0ZSBwb2ludGVyRG93bkVsZW1lbnQ6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBuZ1pvbmU6IElDYW5SdW5PdXRzaWRlQW5ndWxhciB8IHVuZGVmaW5lZFxuICApIHtcbiAgfVxuXG4gIHByaXZhdGUgb25Nb3VzZURvd24gPSAoZXZlbnQ6IE1vdXNlRXZlbnQpID0+IHtcbiAgICBjb25zdCBpc1N5bnRoZXRpY0V2ZW50ID0gdGhpcy5pc1N5bnRoZXRpY0V2ZW50KGV2ZW50KTtcbiAgICBjb25zdCBpc0Zha2VFdmVudCA9IGlzRmFrZU1vdXNlZG93bkZyb21TY3JlZW5SZWFkZXIoZXZlbnQpO1xuICAgIGNvbnN0IG1vdXNlRXZlbnQgPSBuZXcgSU1vdXNlRXZlbnQoZXZlbnQpO1xuICAgIHRoaXMucG9pbnRlckRvd25FbGVtZW50ID0gbW91c2VFdmVudC50YXJnZXRFbGVtZW50O1xuXG4gICAgaWYgKGlzU3ludGhldGljRXZlbnQgfHwgaXNGYWtlRXZlbnQgfHwgdGhpcy5kaXNhYmxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgcmVzdWx0ID0gdGhpcy5vblBvaW50ZXJEb3duKG1vdXNlRXZlbnQpO1xuICAgIGlmIChyZXN1bHQpIHtcblxuICAgICAgdGhpcy5kcmFnU3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgIHRoaXMuZHJhZ1N0YXJ0UG9zaXRpb24gPSBtb3VzZUV2ZW50LmdldFBvc2l0aW9uKCk7XG5cbiAgICAgIHRoaXMubmdab25lPy5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgIHRoaXMuZG9jdW1lbnQ/LmFkZEV2ZW50TGlzdGVuZXIoJ3NlbGVjdHN0YXJ0JywgdGhpcy5vblNlbGVjdFN0YXJ0LCBFdmVudEV4dGVuc2lvbnMuYWN0aXZlTGlzdGVuZXIoKSk7XG4gICAgICAgIHRoaXMuZG9jdW1lbnQ/LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMub25Nb3VzZU1vdmUpO1xuICAgICAgICB0aGlzLmRvY3VtZW50Py5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVydXAnLCB0aGlzLm9uUG9pbnRlclVwRXZlbnQpO1xuICAgICAgfSk7XG5cbiAgICAgIHRoaXMubW91c2VMaXN0ZW5lcnMgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMuZG9jdW1lbnQ/LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3NlbGVjdHN0YXJ0JywgdGhpcy5vblNlbGVjdFN0YXJ0LCBFdmVudEV4dGVuc2lvbnMuYWN0aXZlTGlzdGVuZXIoKSk7XG4gICAgICAgIHRoaXMuZG9jdW1lbnQ/LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMub25Nb3VzZU1vdmUpO1xuICAgICAgICB0aGlzLmRvY3VtZW50Py5yZW1vdmVFdmVudExpc3RlbmVyKCdwb2ludGVydXAnLCB0aGlzLm9uUG9pbnRlclVwRXZlbnQpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG9uVG91Y2hEb3duID0gKGV2ZW50OiBUb3VjaEV2ZW50KSA9PiB7XG4gICAgY29uc3QgaXNGYWtlRXZlbnQgPSBpc0Zha2VUb3VjaHN0YXJ0RnJvbVNjcmVlblJlYWRlcihldmVudCBhcyBUb3VjaEV2ZW50KVxuICAgIGNvbnN0IHRvdWNoRXZlbnQgPSBuZXcgSVRvdWNoRG93bkV2ZW50KGV2ZW50KTtcbiAgICB0aGlzLnBvaW50ZXJEb3duRWxlbWVudCA9IHRvdWNoRXZlbnQudGFyZ2V0RWxlbWVudDtcblxuICAgIGlmIChpc0Zha2VFdmVudCB8fCB0aGlzLmRpc2FibGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCByZXN1bHQgPSB0aGlzLm9uUG9pbnRlckRvd24odG91Y2hFdmVudCk7XG4gICAgaWYgKHJlc3VsdCkge1xuXG4gICAgICB0aGlzLmRyYWdTdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgdGhpcy5kcmFnU3RhcnRQb3NpdGlvbiA9IHRvdWNoRXZlbnQuZ2V0UG9zaXRpb24oKTtcblxuICAgICAgdGhpcy5uZ1pvbmU/LnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgICAgdGhpcy5kb2N1bWVudD8uYWRkRXZlbnRMaXN0ZW5lcignc2VsZWN0c3RhcnQnLCB0aGlzLm9uU2VsZWN0U3RhcnQsIEV2ZW50RXh0ZW5zaW9ucy5hY3RpdmVMaXN0ZW5lcigpKTtcbiAgICAgICAgdGhpcy5kb2N1bWVudD8uYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5vblRvdWNoTW92ZSk7XG4gICAgICAgIHRoaXMuZG9jdW1lbnQ/LmFkZEV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJ1cCcsIHRoaXMub25Qb2ludGVyVXBFdmVudCk7XG4gICAgICB9KTtcblxuICAgICAgdGhpcy50b3VjaExpc3RlbmVycyA9ICgpID0+IHtcbiAgICAgICAgdGhpcy5kb2N1bWVudD8ucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2VsZWN0c3RhcnQnLCB0aGlzLm9uU2VsZWN0U3RhcnQsIEV2ZW50RXh0ZW5zaW9ucy5hY3RpdmVMaXN0ZW5lcigpKTtcbiAgICAgICAgdGhpcy5kb2N1bWVudD8ucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5vblRvdWNoTW92ZSk7XG4gICAgICAgIHRoaXMuZG9jdW1lbnQ/LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3BvaW50ZXJ1cCcsIHRoaXMub25Qb2ludGVyVXBFdmVudCk7XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgb25TZWxlY3RTdGFydCA9IChldmVudDogRXZlbnQpID0+IHtcbiAgICB0aGlzLm9uU2VsZWN0KGV2ZW50KTtcbiAgfVxuXG4gIHByaXZhdGUgb25Nb3VzZU1vdmUgPSAoZXZlbnQ6IE1vdXNlRXZlbnQpID0+IHtcbiAgICB0aGlzLm1vdmVIYW5kbGVyKG5ldyBJTW91c2VFdmVudChldmVudCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBvblRvdWNoTW92ZSA9IChldmVudDogVG91Y2hFdmVudCkgPT4ge1xuICAgIHRoaXMubW92ZUhhbmRsZXIobmV3IElUb3VjaE1vdmVFdmVudChldmVudCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBjaGVja0RyYWdTZXF1ZW5jZVRvU3RhcnQoZXZlbnQ6IElQb2ludGVyRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBwb2ludGVyUG9zaXRpb24gPSBldmVudC5nZXRQb3NpdGlvbigpO1xuXG4gICAgaWYgKCF0aGlzLmlzRHJhZ1N0YXJ0ZWQgJiYgdGhpcy5wb2ludGVyRG93bkVsZW1lbnQpIHtcbiAgICAgIGV2ZW50LnNldFRhcmdldCh0aGlzLnBvaW50ZXJEb3duRWxlbWVudCk7XG4gICAgICBjb25zdCBkaXN0YW5jZVggPSBNYXRoLmFicyhwb2ludGVyUG9zaXRpb24ueCAtIHRoaXMuZHJhZ1N0YXJ0UG9zaXRpb24ueCk7XG4gICAgICBjb25zdCBkaXN0YW5jZVkgPSBNYXRoLmFicyhwb2ludGVyUG9zaXRpb24ueSAtIHRoaXMuZHJhZ1N0YXJ0UG9zaXRpb24ueSk7XG4gICAgICBjb25zdCBpc092ZXJUaHJlc2hvbGQgPSBkaXN0YW5jZVggKyBkaXN0YW5jZVkgPj0gdGhpcy5kcmFnU3RhcnRUaHJlc2hvbGQ7XG5cbiAgICAgIGlmIChpc092ZXJUaHJlc2hvbGQpIHtcbiAgICAgICAgY29uc3QgaXNEZWxheUVsYXBzZWQgPSBEYXRlLm5vdygpID49IHRoaXMuZHJhZ1N0YXJ0VGltZSArIHRoaXMuZHJhZ1N0YXJ0RGVsYXk7XG5cbiAgICAgICAgaWYgKCFpc0RlbGF5RWxhcHNlZCkge1xuICAgICAgICAgIHRoaXMuZW5kRHJhZ1NlcXVlbmNlKCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdGhpcy5wcmVwYXJlRHJhZ1NlcXVlbmNlKGV2ZW50KTtcbiAgICAgICAgdGhpcy5pc0RyYWdTdGFydGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5tb3ZlSGFuZGxlciA9IHRoaXMub25Qb2ludGVyTW92ZTtcbiAgICAgICAgaWYgKGlzVG91Y2hFdmVudChldmVudC5vcmlnaW5hbEV2ZW50KSkge1xuICAgICAgICAgIHRoaXMubGFzdFRvdWNoRXZlbnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBwcmVwYXJlRHJhZ1NlcXVlbmNlKGV2ZW50OiBJUG9pbnRlckV2ZW50KTogdm9pZDtcblxuICBwcml2YXRlIG9uUG9pbnRlclVwRXZlbnQgPSAoZXZlbnQ6IFBvaW50ZXJFdmVudCkgPT4ge1xuICAgIGlmICh0aGlzLmlzRHJhZ1N0YXJ0ZWQpIHtcbiAgICAgIHRoaXMub25Qb2ludGVyVXAobmV3IElQb2ludGVyVXBFdmVudChldmVudCkpO1xuICAgIH1cbiAgICB0aGlzLmVuZERyYWdTZXF1ZW5jZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBlbmREcmFnU2VxdWVuY2UoKTogdm9pZCB7XG4gICAgdGhpcy5pc0RyYWdTdGFydGVkID0gZmFsc2U7XG4gICAgdGhpcy5wb2ludGVyRG93bkVsZW1lbnQgPSBudWxsO1xuXG4gICAgdGhpcy5tb3ZlSGFuZGxlciA9IHRoaXMuY2hlY2tEcmFnU2VxdWVuY2VUb1N0YXJ0O1xuICAgIHRoaXMubW91c2VMaXN0ZW5lcnMoKTtcbiAgICB0aGlzLm1vdXNlTGlzdGVuZXJzID0gRXZlbnRFeHRlbnNpb25zLmVtcHR5TGlzdGVuZXIoKTtcbiAgICB0aGlzLnRvdWNoTGlzdGVuZXJzKCk7XG4gICAgdGhpcy50b3VjaExpc3RlbmVycyA9IEV2ZW50RXh0ZW5zaW9ucy5lbXB0eUxpc3RlbmVyKCk7XG4gICAgdGhpcy5maW5hbGl6ZURyYWdTZXF1ZW5jZSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGZpbmFsaXplRHJhZ1NlcXVlbmNlKCk6IHZvaWQ7XG5cbiAgcHJvdGVjdGVkIGFic3RyYWN0IG9uU2VsZWN0KGV2ZW50OiBFdmVudCk6IHZvaWQ7XG5cbiAgcHVibGljIGFic3RyYWN0IG9uUG9pbnRlckRvd24oZXZlbnQ6IElQb2ludGVyRXZlbnQpOiBib29sZWFuO1xuXG4gIHB1YmxpYyBhYnN0cmFjdCBvblBvaW50ZXJNb3ZlKGV2ZW50OiBJUG9pbnRlckV2ZW50KTogdm9pZDtcblxuICBwdWJsaWMgYWJzdHJhY3Qgb25Qb2ludGVyVXAoZXZlbnQ6IElQb2ludGVyRXZlbnQpOiB2b2lkO1xuXG4gIHB1YmxpYyBzdWJzY3JpYmUoZkRvY3VtZW50OiBEb2N1bWVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRvY3VtZW50KSB7XG4gICAgICB0aGlzLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICAgIHRoaXMuZG9jdW1lbnQgPSBmRG9jdW1lbnQ7XG5cbiAgICB0aGlzLm5nWm9uZT8ucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgZkRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMub25Nb3VzZURvd24sIEV2ZW50RXh0ZW5zaW9ucy5hY3RpdmVMaXN0ZW5lcigpKTtcbiAgICAgIGZEb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5vblRvdWNoRG93biwgRXZlbnRFeHRlbnNpb25zLnBhc3NpdmVMaXN0ZW5lcigpKTtcbiAgICB9KTtcblxuICAgIHRoaXMuc3RhcnRMaXN0ZW5lcnMgPSAoKSA9PiB7XG4gICAgICBmRG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5vbk1vdXNlRG93biwgRXZlbnRFeHRlbnNpb25zLmFjdGl2ZUxpc3RlbmVyKCkpO1xuICAgICAgZkRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCB0aGlzLm9uVG91Y2hEb3duLCBFdmVudEV4dGVuc2lvbnMucGFzc2l2ZUxpc3RlbmVyKCkpO1xuICAgIH07XG4gIH1cblxuICBwdWJsaWMgdW5zdWJzY3JpYmUoKTogdm9pZCB7XG5cbiAgICB0aGlzLnN0YXJ0TGlzdGVuZXJzKCk7XG4gICAgdGhpcy5zdGFydExpc3RlbmVycyA9IEV2ZW50RXh0ZW5zaW9ucy5lbXB0eUxpc3RlbmVyKCk7XG4gICAgdGhpcy50b3VjaExpc3RlbmVycygpO1xuICAgIHRoaXMudG91Y2hMaXN0ZW5lcnMgPSBFdmVudEV4dGVuc2lvbnMuZW1wdHlMaXN0ZW5lcigpO1xuICAgIHRoaXMubW91c2VMaXN0ZW5lcnMoKTtcbiAgICB0aGlzLm1vdXNlTGlzdGVuZXJzID0gRXZlbnRFeHRlbnNpb25zLmVtcHR5TGlzdGVuZXIoKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpc1RvdWNoRXZlbnQoZXZlbnQ6IE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50KTogZXZlbnQgaXMgVG91Y2hFdmVudCB7XG4gIHJldHVybiBldmVudC50eXBlWyAwIF0gPT09ICd0Jztcbn1cblxuZnVuY3Rpb24gaXNGYWtlTW91c2Vkb3duRnJvbVNjcmVlblJlYWRlcihldmVudDogTW91c2VFdmVudCk6IGJvb2xlYW4ge1xuICByZXR1cm4gZXZlbnQuYnV0dG9ucyA9PT0gMCB8fCAoZXZlbnQub2Zmc2V0WCA9PT0gMCAmJiBldmVudC5vZmZzZXRZID09PSAwKTtcbn1cblxuZnVuY3Rpb24gaXNGYWtlVG91Y2hzdGFydEZyb21TY3JlZW5SZWFkZXIoZXZlbnQ6IFRvdWNoRXZlbnQpOiBib29sZWFuIHtcbiAgY29uc3QgdG91Y2g6IFRvdWNoIHwgdW5kZWZpbmVkID1cbiAgICAoZXZlbnQudG91Y2hlcyAmJiBldmVudC50b3VjaGVzWyAwIF0pIHx8IChldmVudC5jaGFuZ2VkVG91Y2hlcyAmJiBldmVudC5jaGFuZ2VkVG91Y2hlc1sgMCBdKTtcbiAgcmV0dXJuIChcbiAgICAhIXRvdWNoICYmXG4gICAgdG91Y2guaWRlbnRpZmllciA9PT0gLTEgJiZcbiAgICAodG91Y2gucmFkaXVzWCA9PSBudWxsIHx8IHRvdWNoLnJhZGl1c1ggPT09IDEpICYmXG4gICAgKHRvdWNoLnJhZGl1c1kgPT0gbnVsbCB8fCB0b3VjaC5yYWRpdXNZID09PSAxKVxuICApO1xufVxuIl19