UNPKG

@pepperi/lib

Version:

This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.0.1.

441 lines (440 loc) 62.8 kB
import { Component, ContentChild, ElementRef, EventEmitter, Input, NgModule, NgZone, Output, ViewChild } from '@angular/core'; import * as tween from '@tweenjs/tween.js'; import * as i0 from "@angular/core"; const _c0 = ["container"]; const _c1 = ["content"]; const _c2 = ["shim"]; const _c3 = ["*"]; export class VirtualScrollComponent { constructor(element, renderer, zone) { this.element = element; this.renderer = renderer; this.zone = zone; //@Input() //items: any[] = []; this.totalRows = 0; this.bufferAmount = 0; this.scrollAnimationTime = 1500; this.doNotCheckAngularZone = false; this.refreshHandler = () => { this.refresh(true); }; this.isTable = false; //@Output() //update: EventEmitter<any[]> = new EventEmitter<any[]>(); //viewPortItems: any[]; this.change = new EventEmitter(); this.load = new EventEmitter(); this.start = new EventEmitter(); this.end = new EventEmitter(); this.startupLoop = true; /** Cache of the last scroll height to prevent setting CSS when not needed. */ this.lastScrollHeight = -1; /** Cache of the last top padding to prevent setting CSS when not needed. */ this.lastTopPadding = -1; } set parentScroll(element) { if (this._parentScroll === element) { return; } this._parentScroll = element; this.addParentEventHandlers(this._parentScroll); } get parentScroll() { return this._parentScroll; } ngOnInit() { this.scrollbarWidth = 0; // this.element.nativeElement.offsetWidth - this.element.nativeElement.clientWidth; this.scrollbarHeight = 0; // this.element.nativeElement.offsetHeight - this.element.nativeElement.clientHeight; if (!this.parentScroll) { this.addParentEventHandlers(this.element.nativeElement); } } ngOnDestroy() { this.removeParentEventHandlers(); } ngOnChanges(changes) { this.previousStart = undefined; this.previousEnd = undefined; const totalRows = changes.totalRows || {}; if ((changes.totalRows !== undefined && totalRows.previousValue === undefined) || totalRows.previousValue !== undefined) { this.startupLoop = true; } var ieVer = this.detectIE(); var headerRowHeight = '34px'; // Set padding top for the table view because the header row. //this.renderer.setStyle(this.contentElementRef.nativeElement, 'padding-top', this.isTable ? headerRowHeight : '0'); if (!ieVer || ieVer >= 16) { // not IE and version < 16 this.renderer.setStyle(this.element.nativeElement, 'top', '0'); } else { this.renderer.setStyle(this.element.nativeElement, 'top', headerRowHeight); } //Only for IE browsers /* let ua = navigator.userAgent; if (this.isTable && (ua.indexOf('MSIE ') >= 0 || ua.indexOf('Trident/') >= 0 || ua.indexOf('Edge/') >= 0)) { this.renderer.setStyle(this.element.nativeElement, 'top', headerRowHeight); } else { this.renderer.setStyle(this.element.nativeElement, 'top', '0'); }*/ this.refresh(); } detectIE() { var ua = window.navigator.userAgent; // Test values; Uncomment to check result … // IE 10 // ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)'; // IE 11 // ua = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko'; // Edge 12 (Spartan) // ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0'; // Edge 13 // ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586'; var msie = ua.indexOf('MSIE '); if (msie > 0) { // IE 10 or older => return version number return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10); } var trident = ua.indexOf('Trident/'); if (trident > 0) { // IE 11 => return version number var rv = ua.indexOf('rv:'); return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10); } var edge = ua.indexOf('Edge/'); if (edge > 0) { // Edge (IE 12+) => return version number return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10); } // other browser return false; } refresh(forceViewportUpdate = false) { this.zone.runOutsideAngular(() => { requestAnimationFrame(() => this.calculateItems(forceViewportUpdate)); }); } scrollInto(index) { let el = this.parentScroll instanceof Window ? document.body : this.parentScroll || this.element.nativeElement; let offsetTop = this.getElementsOffset(); //let index: number = (this.items || []).indexOf(item); if (index < 0 || index >= this.totalRows) return; let d = this.calculateDimensions(); let scrollTop = Math.floor(index / d.itemsPerRow) * d.childHeight - d.childHeight * Math.min(index, this.bufferAmount); let animationRequest; if (this.currentTween !== undefined) { this.currentTween.stop(); } // totally disable animate if (!this.scrollAnimationTime) { el.scrollTop = scrollTop; return; } this.currentTween = new tween.Tween({ scrollTop: el.scrollTop }) .to({ scrollTop }, this.scrollAnimationTime) .easing(tween.Easing.Quadratic.Out) .onUpdate(data => { if (isNaN(data.scrollTop)) { return; } this.renderer.setProperty(el, 'scrollTop', data.scrollTop); this.refresh(true); }) .onStop(() => { cancelAnimationFrame(animationRequest); }) .start(); const animate = (time) => { this.currentTween.update(time); if (this.currentTween._object.scrollTop !== scrollTop) { this.zone.runOutsideAngular(() => { animationRequest = requestAnimationFrame(animate); }); } }; animate(); } addParentEventHandlers(parentScroll) { this.removeParentEventHandlers(); if (parentScroll) { this.zone.runOutsideAngular(() => { this.disposeScrollHandler = this.renderer.listen(parentScroll, 'mousewheel', _.throttle(this.refreshHandler, 20, { leading: false, trailing: true })); this.renderer.listen(parentScroll, 'scroll', _.debounce(this.refreshHandler, 150)); //this.renderer.listen(parentScroll, 'scroll', _.debounce(_.throttle(this.refreshHandler, 150), 50)); if (parentScroll instanceof Window) { this.disposeScrollHandler = this.renderer.listen('window', 'resize', _.debounce(this.refreshHandler, 250)); } }); } } removeParentEventHandlers() { if (this.disposeScrollHandler) { this.disposeScrollHandler(); this.disposeScrollHandler = undefined; } if (this.disposeResizeHandler) { this.disposeResizeHandler(); this.disposeResizeHandler = undefined; } } countItemsPerRow() { let offsetTop; let itemsPerRow; let children = this.contentElementRef.nativeElement.children; for (itemsPerRow = 0; itemsPerRow < children.length; itemsPerRow++) { if (offsetTop != undefined && offsetTop !== children[itemsPerRow].offsetTop) break; offsetTop = children[itemsPerRow].offsetTop; } return itemsPerRow; } getElementsOffset() { let offsetTop = 0; if (this.containerElementRef && this.containerElementRef.nativeElement) { offsetTop += this.containerElementRef.nativeElement.offsetTop; } if (this.parentScroll) { offsetTop += this.element.nativeElement.offsetTop; } return offsetTop; } calculateDimensions() { let el = this.parentScroll instanceof Window ? document.body : this.parentScroll || this.element.nativeElement; let itemCount = this.totalRows; let viewWidth = el.clientWidth - this.scrollbarWidth; let viewHeight = el.clientHeight - this.scrollbarHeight; let contentDimensions; if (this.childWidth == undefined || this.childHeight == undefined) { let content = this.contentElementRef.nativeElement; if (this.containerElementRef && this.containerElementRef.nativeElement) { content = this.containerElementRef.nativeElement; } contentDimensions = content.children[0] ? content.children[0].getBoundingClientRect() : { width: viewWidth, height: viewHeight }; } let childWidth = this.childWidth || contentDimensions.width; let childHeight = this.childHeight || contentDimensions.height; let itemsPerRow = Math.max(1, this.countItemsPerRow()); let itemsPerRowByCalc = Math.max(1, Math.floor(viewWidth / childWidth)); let itemsPerCol = Math.max(1, Math.floor(viewHeight / childHeight)); let elScrollTop = this.parentScroll instanceof Window ? window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0 : el.scrollTop; let scrollTop = Math.max(0, elScrollTop); var scrollHeight = childHeight * Math.floor(itemCount / itemsPerRow) + (itemCount % itemsPerRow != 0 ? childHeight : 0); let ua = navigator.userAgent; /*if (this.isTable && (ua.indexOf('MSIE ') >= 0 || ua.indexOf('Trident/') >= 0 || ua.indexOf('Edge/') >= 0)) { scrollHeight += 34; }*/ if (itemsPerCol === 1 && Math.floor((scrollTop / scrollHeight) * itemCount) + itemsPerRowByCalc >= itemCount) { itemsPerRow = itemsPerRowByCalc; } if (scrollHeight !== this.lastScrollHeight) { this.renderer.setStyle(this.shimElementRef.nativeElement, 'height', `${scrollHeight}px`); this.lastScrollHeight = scrollHeight; } return { itemCount: itemCount, viewWidth: viewWidth, viewHeight: viewHeight, childWidth: childWidth, childHeight: childHeight, itemsPerRow: itemsPerRow, itemsPerCol: itemsPerCol, itemsPerRowByCalc: itemsPerRowByCalc, scrollHeight }; } calculateItems(forceViewportUpdate = false) { if (!this.doNotCheckAngularZone) { NgZone.assertNotInAngularZone(); } let el = this.parentScroll instanceof Window ? document.body : this.parentScroll || this.element.nativeElement; let d = this.calculateDimensions(); //let items = this.items || []; let offsetTop = this.getElementsOffset(); let elScrollTop = this.parentScroll instanceof Window ? window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0 : el.scrollTop; if (elScrollTop > d.scrollHeight) { elScrollTop = d.scrollHeight + offsetTop; } let scrollTop = Math.max(0, elScrollTop - offsetTop); let indexByScrollTop = ((scrollTop / d.scrollHeight) * d.itemCount) / d.itemsPerRow; let end = Math.min(d.itemCount, Math.ceil(indexByScrollTop) * d.itemsPerRow + d.itemsPerRow * (d.itemsPerCol + 1)); let maxStartEnd = end; const modEnd = end % d.itemsPerRow; if (modEnd) { maxStartEnd = end + d.itemsPerRow - modEnd; } let maxStart = Math.max(0, maxStartEnd - d.itemsPerCol * d.itemsPerRow - d.itemsPerRow); let start = Math.min(maxStart, Math.floor(indexByScrollTop) * d.itemsPerRow); let startRow = Math.ceil(start / d.itemsPerRow); const topPadding = this.totalRows === 0 ? 0 : d.childHeight * startRow - d.childHeight * Math.min(startRow, this.bufferAmount); if (topPadding !== this.lastTopPadding) { this.renderer.setStyle(this.contentElementRef.nativeElement, 'transform', `translateY(${topPadding}px)`); this.renderer.setStyle(this.contentElementRef.nativeElement, 'webkitTransform', `translateY(${topPadding}px)`); this.lastTopPadding = topPadding; } let buffer = this.bufferAmount * d.itemsPerRow; start = !isNaN(start) ? start : -1; end = !isNaN(end) ? end : -1; start -= buffer; start = Math.max(0, start); end += buffer; end = Math.min(this.totalRows, end); if (start !== this.previousStart || end !== this.previousEnd || forceViewportUpdate === true) { this.zone.run(() => { // update the scroll list end = end >= 0 ? end : 0; // To prevent from accidentally selecting the entire array with a negative 1 (-1) in the end position. //this.viewPortItems = this.items.slice(start, end); //this.update.emit(this.viewPortItems); // emit 'start' event //if (start !== this.previousStart && this.startupLoop === false) { // this.start.emit({ start, end }); //} // emit 'end' event //if (end !== this.previousEnd && this.startupLoop === false) { // this.end.emit({ start, end }); //} // To know if to add at the start of the list or at the end. let addAtStart = this.previousEnd >= end; this.previousStart = start; this.previousEnd = end; if (this.startupLoop === true) { this.refresh(); } else { let calculatedChildHeight = d.childHeight; this.change.emit({ start, end, addAtStart, calculatedChildHeight }); } }); } else if (this.startupLoop === true) { this.startupLoop = false; // Added to know when the scroll is ready (UI elements are displayed already). this.load.emit(); this.refresh(); } } } VirtualScrollComponent.ɵfac = function VirtualScrollComponent_Factory(t) { return new (t || VirtualScrollComponent)(i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i0.Renderer2), i0.ɵɵdirectiveInject(i0.NgZone)); }; VirtualScrollComponent.ɵcmp = i0.ɵɵdefineComponent({ type: VirtualScrollComponent, selectors: [["virtual-scroll"], ["", "virtualScroll", ""]], contentQueries: function VirtualScrollComponent_ContentQueries(rf, ctx, dirIndex) { if (rf & 1) { i0.ɵɵcontentQuery(dirIndex, _c0, true); } if (rf & 2) { var _t; i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.containerElementRef = _t.first); } }, viewQuery: function VirtualScrollComponent_Query(rf, ctx) { if (rf & 1) { i0.ɵɵviewQuery(_c1, true, ElementRef); i0.ɵɵviewQuery(_c2, true, ElementRef); } if (rf & 2) { var _t; i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.contentElementRef = _t.first); i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.shimElementRef = _t.first); } }, hostVars: 2, hostBindings: function VirtualScrollComponent_HostBindings(rf, ctx) { if (rf & 2) { i0.ɵɵstyleProp("overflow-y", ctx.parentScroll ? "hidden" : "auto"); } }, inputs: { totalRows: "totalRows", scrollbarWidth: "scrollbarWidth", scrollbarHeight: "scrollbarHeight", childWidth: "childWidth", childHeight: "childHeight", bufferAmount: "bufferAmount", scrollAnimationTime: "scrollAnimationTime", doNotCheckAngularZone: "doNotCheckAngularZone", parentScroll: "parentScroll", isTable: "isTable" }, outputs: { change: "change", load: "load", start: "start", end: "end" }, exportAs: ["virtualScroll"], features: [i0.ɵɵNgOnChangesFeature], ngContentSelectors: _c3, decls: 5, vars: 0, consts: [[1, "total-padding"], ["shim", ""], [1, "scrollable-content"], ["content", ""]], template: function VirtualScrollComponent_Template(rf, ctx) { if (rf & 1) { i0.ɵɵprojectionDef(); i0.ɵɵelement(0, "div", 0, 1); i0.ɵɵelementStart(2, "div", 2, 3); i0.ɵɵprojection(4); i0.ɵɵelementEnd(); } }, styles: ["[_nghost-%COMP%] {\n overflow: hidden;\n position: relative;\n display: block;\n -webkit-overflow-scrolling: touch;\n }\n .scrollable-content[_ngcontent-%COMP%] {\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n position: absolute;\n // z-index:495;\n }\n .total-padding[_ngcontent-%COMP%] {\n width: 1px;\n opacity: 0;\n }\n\n .rtl[_ngcontent-%COMP%] {\n .scrollable-content {\n left: unset;\n right: 0;\n }\n }"] }); /*@__PURE__*/ (function () { i0.ɵsetClassMetadata(VirtualScrollComponent, [{ type: Component, args: [{ selector: 'virtual-scroll,[virtualScroll]', exportAs: 'virtualScroll', template: ` <div class="total-padding" #shim></div> <div class="scrollable-content" #content> <ng-content></ng-content> </div> `, host: { '[style.overflow-y]': "parentScroll ? 'hidden' : 'auto'" }, styles: [ ` :host { overflow: hidden; position: relative; display: block; -webkit-overflow-scrolling: touch; } .scrollable-content { top: 0; left: 0; width: 100%; height: 100%; position: absolute; // z-index:495; } .total-padding { width: 1px; opacity: 0; } .rtl { .scrollable-content { left: unset; right: 0; } } ` ] }] }], function () { return [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.NgZone }]; }, { totalRows: [{ type: Input }], scrollbarWidth: [{ type: Input }], scrollbarHeight: [{ type: Input }], childWidth: [{ type: Input }], childHeight: [{ type: Input }], bufferAmount: [{ type: Input }], scrollAnimationTime: [{ type: Input }], doNotCheckAngularZone: [{ type: Input }], parentScroll: [{ type: Input }], isTable: [{ type: Input }], change: [{ type: Output }], load: [{ type: Output }], start: [{ type: Output }], end: [{ type: Output }], contentElementRef: [{ type: ViewChild, args: ['content', { read: ElementRef }] }], shimElementRef: [{ type: ViewChild, args: ['shim', { read: ElementRef }] }], containerElementRef: [{ type: ContentChild, args: ['container'] }] }); })(); export class VirtualScrollModule { } VirtualScrollModule.ɵmod = i0.ɵɵdefineNgModule({ type: VirtualScrollModule }); VirtualScrollModule.ɵinj = i0.ɵɵdefineInjector({ factory: function VirtualScrollModule_Factory(t) { return new (t || VirtualScrollModule)(); } }); (function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(VirtualScrollModule, { declarations: [VirtualScrollComponent], exports: [VirtualScrollComponent] }); })(); /*@__PURE__*/ (function () { i0.ɵsetClassMetadata(VirtualScrollModule, [{ type: NgModule, args: [{ exports: [VirtualScrollComponent], declarations: [VirtualScrollComponent] }] }], null, null); })(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlydHVhbC1zY3JvbGwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvcGVwcGVyaS1saWIvbGlzdC92aXJ0dWFsLXNjcm9sbC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFDNUQsTUFBTSxFQUE0QixTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFMUYsT0FBTyxLQUFLLEtBQUssTUFBTSxtQkFBbUIsQ0FBQzs7Ozs7O0FBc0QzQyxNQUFNLE9BQU8sc0JBQXNCO0lBdUYvQixZQUFtQixPQUFtQixFQUFVLFFBQW1CLEVBQVUsSUFBWTtRQUF0RSxZQUFPLEdBQVAsT0FBTyxDQUFZO1FBQVUsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQUFVLFNBQUksR0FBSixJQUFJLENBQVE7UUF0RnpGLFVBQVU7UUFDVixvQkFBb0I7UUFHcEIsY0FBUyxHQUFXLENBQUMsQ0FBQztRQWV0QixpQkFBWSxHQUFXLENBQUMsQ0FBQztRQUd6Qix3QkFBbUIsR0FBVyxJQUFJLENBQUM7UUFHbkMsMEJBQXFCLEdBQVksS0FBSyxDQUFDO1FBRS9CLG1CQUFjLEdBQUcsR0FBRyxFQUFFO1lBQzFCLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdkIsQ0FBQyxDQUFBO1FBZ0JELFlBQU8sR0FBWSxLQUFLLENBQUM7UUFFekIsV0FBVztRQUNYLDBEQUEwRDtRQUMxRCx1QkFBdUI7UUFHdkIsV0FBTSxHQUE4QixJQUFJLFlBQVksRUFBZSxDQUFDO1FBR3BFLFNBQUksR0FBc0IsSUFBSSxZQUFZLEVBQU8sQ0FBQztRQUdsRCxVQUFLLEdBQThCLElBQUksWUFBWSxFQUFlLENBQUM7UUFHbkUsUUFBRyxHQUE4QixJQUFJLFlBQVksRUFBZSxDQUFD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QU07a0JBREwsTUFBTTtZQUlQLElBQUk7a0JBREgsTUFBTTtZQUlQLEtBQUs7a0JBREosTUFBTTtZQUlQLEdBQUc7a0JBREYsTUFBTTtZQUlQLGlCQUFpQjtrQkFEaEIsU0FBUzttQkFBQyxTQUFTLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFO1lBSTFDLGNBQWM7a0JBRGIsU0FBUzttQkFBQyxNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFO1lBSXZDLG1CQUFtQjtrQkFEbEIsWUFBWTttQkFBQyxXQUFXOztBQWlXN0IsTUFBTSxPQUFPLG1CQUFtQjs7dURBQW5CLG1CQUFtQjtxSEFBbkIsbUJBQW1CO3dGQUFuQixtQkFBbUIsbUJBdmFuQixzQkFBc0IsYUFBdEIsc0JBQXNCO2tEQXVhdEIsbUJBQW1CO2NBSi9CLFFBQVE7ZUFBQztnQkFDTixPQUFPLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQztnQkFDakMsWUFBWSxFQUFFLENBQUMsc0JBQXNCLENBQUM7YUFDekMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIENvbnRlbnRDaGlsZCwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgTmdNb2R1bGUsIE5nWm9uZSwgT25DaGFuZ2VzLFxyXG4gICAgT25EZXN0cm95LCBPbkluaXQsIE91dHB1dCwgUmVuZGVyZXIyLCBTaW1wbGVDaGFuZ2VzLCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbmltcG9ydCAqIGFzIHR3ZWVuIGZyb20gJ0B0d2VlbmpzL3R3ZWVuLmpzJztcclxuZGVjbGFyZSB2YXIgXzogYW55O1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBDaGFuZ2VFdmVudCB7XHJcbiAgICBzdGFydD86IG51bWJlcjtcclxuICAgIGVuZD86IG51bWJlcjtcclxuICAgIGZyb21JbmRleD86IG51bWJlcjtcclxuICAgIHRvSW5kZXg/OiBudW1iZXI7XHJcbiAgICBhZGRBdFN0YXJ0PzogYm9vbGVhbjtcclxuICAgIGNhbGN1bGF0ZWRDaGlsZEhlaWdodD86IG51bWJlcjtcclxufVxyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ3ZpcnR1YWwtc2Nyb2xsLFt2aXJ0dWFsU2Nyb2xsXScsXHJcbiAgICBleHBvcnRBczogJ3ZpcnR1YWxTY3JvbGwnLFxyXG4gICAgdGVtcGxhdGU6IGBcclxuICAgICAgICA8ZGl2IGNsYXNzPVwidG90YWwtcGFkZGluZ1wiICNzaGltPjwvZGl2PlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzY3JvbGxhYmxlLWNvbnRlbnRcIiAjY29udGVudD5cclxuICAgICAgICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgYCxcclxuICAgIGhvc3Q6IHtcclxuICAgICAgICAnW3N0eWxlLm92ZXJmbG93LXldJzogXCJwYXJlbnRTY3JvbGwgPyAnaGlkZGVuJyA6ICdhdXRvJ1wiXHJcbiAgICB9LFxyXG4gICAgc3R5bGVzOiBbXHJcbiAgICAgICAgYFxyXG4gICAgOmhvc3Qge1xyXG4gICAgICAgIG92ZXJmbG93OiBoaWRkZW47XHJcbiAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICAgIGRpc3BsYXk6IGJsb2NrO1xyXG4gICAgICAgIC13ZWJraXQtb3ZlcmZsb3ctc2Nyb2xsaW5nOiB0b3VjaDtcclxuICAgIH1cclxuICAgIC5zY3JvbGxhYmxlLWNvbnRlbnQge1xyXG4gICAgICAgIHRvcDogMDtcclxuICAgICAgICBsZWZ0OiAwO1xyXG4gICAgICAgIHdpZHRoOiAxMDAlO1xyXG4gICAgICAgIGhlaWdodDogMTAwJTtcclxuICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgICAgLy8gICB6LWluZGV4OjQ5NTtcclxuICAgIH1cclxuICAgIC50b3RhbC1wYWRkaW5nIHtcclxuICAgICAgICB3aWR0aDogMXB4O1xyXG4gICAgICAgIG9wYWNpdHk6IDA7XHJcbiAgICB9XHJcblxyXG4gICAgLnJ0bCB7XHJcbiAgICAgICAgLnNjcm9sbGFibGUtY29udGVudCB7XHJcbiAgICAgICAgICAgIGxlZnQ6IHVuc2V0O1xyXG4gICAgICAgICAgICByaWdodDogMDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgYFxyXG4gICAgXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgVmlydHVhbFNjcm9sbENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xyXG4gICAgLy9ASW5wdXQoKVxyXG4gICAgLy9pdGVtczogYW55W10gPSBbXTtcclxuXHJcbiAgICBASW5wdXQoKVxyXG4gICAgdG90YWxSb3dzOiBudW1iZXIgPSAwO1xyXG5cclxuICAgIEBJbnB1dCgpXHJcbiAgICBzY3JvbGxiYXJXaWR0aDogbnVtYmVyO1xyXG5cclxuICAgIEBJbnB1dCgpXHJcbiAgICBzY3JvbGxiYXJIZWlnaHQ6IG51bWJlcjtcclxuXHJcbiAgICBASW5wdXQoKVxyXG4gICAgY2hpbGRXaWR0aDogbnVtYmVyO1xyXG5cclxuICAgIEBJbnB1dCgpXHJcbiAgICBjaGlsZEhlaWdodDogbnVtYmVyO1xyXG5cclxuICAgIEBJbnB1dCgpXHJcbiAgICBidWZmZXJBbW91bnQ6IG51bWJlciA9IDA7XHJcblxyXG4gICAgQElucHV0KClcclxuICAgIHNjcm9sbEFuaW1hdGlvblRpbWU6IG51bWJlciA9IDE1MDA7XHJcblxyXG4gICAgQElucHV0KClcclxuICAgIGRvTm90Q2hlY2tBbmd1bGFyWm9uZTogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAgIHByaXZhdGUgcmVmcmVzaEhhbmRsZXIgPSAoKSA9PiB7XHJcbiAgICAgICAgdGhpcy5yZWZyZXNoKHRydWUpO1xyXG4gICAgfVxyXG4gICAgcHJpdmF0ZSBfcGFyZW50U2Nyb2xsOiBFbGVtZW50IHwgV2luZG93O1xyXG4gICAgQElucHV0KClcclxuICAgIHNldCBwYXJlbnRTY3JvbGwoZWxlbWVudDogRWxlbWVudCB8IFdpbmRvdykge1xyXG4gICAgICAgIGlmICh0aGlzLl9wYXJlbnRTY3JvbGwgPT09IGVsZW1lbnQpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLl9wYXJlbnRTY3JvbGwgPSBlbGVtZW50O1xyXG4gICAgICAgIHRoaXMuYWRkUGFyZW50RXZlbnRIYW5kbGVycyh0aGlzLl9wYXJlbnRTY3JvbGwpO1xyXG4gICAgfVxyXG5cclxuICAgIGdldCBwYXJlbnRTY3JvbGwoKTogRWxlbWVudCB8IFdpbmRvdyB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BhcmVudFNjcm9sbDtcclxuICAgIH1cclxuXHJcbiAgICBASW5wdXQoKVxyXG4gICAgaXNUYWJsZTogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAgIC8vQE91dHB1dCgpXHJcbiAgICAvL3VwZGF0ZTogRXZlbnRFbWl0dGVyPGFueVtdPiA9IG5ldyBFdmVudEVtaXR0ZXI8YW55W10+KCk7XHJcbiAgICAvL3ZpZXdQb3J0SXRlbXM6IGFueVtdO1xyXG5cclxuICAgIEBPdXRwdXQoKVxyXG4gICAgY2hhbmdlOiBFdmVudEVtaXR0ZXI8Q2hhbmdlRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxDaGFuZ2VFdmVudD4oKTtcclxuXHJcbiAgICBAT3V0cHV0KClcclxuICAgIGxvYWQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcblxyXG4gICAgQE91dHB1dCgpXHJcbiAgICBzdGFydDogRXZlbnRFbWl0dGVyPENoYW5nZUV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hhbmdlRXZlbnQ+KCk7XHJcblxyXG4gICAgQE91dHB1dCgpXHJcbiAgICBlbmQ6IEV2ZW50RW1pdHRlcjxDaGFuZ2VFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyPENoYW5nZUV2ZW50PigpO1xyXG5cclxuICAgIEBWaWV3Q2hpbGQoJ2NvbnRlbnQnLCB7IHJlYWQ6IEVsZW1lbnRSZWYgfSlcclxuICAgIGNvbnRlbnRFbGVtZW50UmVmOiBFbGVtZW50UmVmO1xyXG5cclxuICAgIEBWaWV3Q2hpbGQoJ3NoaW0nLCB7IHJlYWQ6IEVsZW1lbnRSZWYgfSlcclxuICAgIHNoaW1FbGVtZW50UmVmOiBFbGVtZW50UmVmO1xyXG5cclxuICAgIEBDb250ZW50Q2hpbGQoJ2NvbnRhaW5lcicpXHJcbiAgICBjb250YWluZXJFbGVtZW50UmVmOiBFbGVtZW50UmVmO1xyXG5cclxuICAgIHByZXZpb3VzU3RhcnQ6IG51bWJlcjtcclxuICAgIHByZXZpb3VzRW5kOiBudW1iZXI7XHJcbiAgICBzdGFydHVwTG9vcDogYm9vbGVhbiA9IHRydWU7XHJcbiAgICBjdXJyZW50VHdlZW46IGFueTtcclxuXHJcbiAgICBwcml2YXRlIGRpc3Bvc2VTY3JvbGxIYW5kbGVyOiAoKSA9PiB2b2lkIHwgdW5kZWZpbmVkO1xyXG4gICAgcHJpdmF0ZSBkaXNwb3NlUmVzaXplSGFuZGxlcjogKCkgPT4gdm9pZCB8IHVuZGVmaW5lZDtcclxuXHJcbiAgICAvKiogQ2FjaGUgb2YgdGhlIGxhc3Qgc2Nyb2xsIGhlaWdodCB0byBwcmV2ZW50IHNldHRpbmcgQ1NTIHdoZW4gbm90IG5lZWRlZC4gKi9cclxuICAgIHByaXZhdGUgbGFzdFNjcm9sbEhlaWdodCA9IC0xO1xyXG5cclxuICAgIC8qKiBDYWNoZSBvZiB0aGUgbGFzdCB0b3AgcGFkZGluZyB0byBwcmV2ZW50IHNldHRpbmcgQ1NTIHdoZW4gbm90IG5lZWRlZC4gKi9cclxuICAgIHByaXZhdGUgbGFzdFRvcFBhZGRpbmcgPSAtMTtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihwdWJsaWMgZWxlbWVudDogRWxlbWVudFJlZiwgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyLCBwcml2YXRlIHpvbmU6IE5nWm9uZSkgeyB9XHJcblxyXG4gICAgbmdPbkluaXQoKSB7XHJcbiAgICAgICAgdGhpcy5zY3JvbGxiYXJXaWR0aCA9IDA7IC8vIHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoIC0gdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQuY2xpZW50V2lkdGg7XHJcbiAgICAgICAgdGhpcy5zY3JvbGxiYXJIZWlnaHQgPSAwOyAvLyB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5vZmZzZXRIZWlnaHQgLSB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudC5jbGllbnRIZWlnaHQ7XHJcblxyXG4gICAgICAgIGlmICghdGhpcy5wYXJlbnRTY3JvbGwpIHtcclxuICAgICAgICAgICAgdGhpcy5hZGRQYXJlbnRFdmVudEhhbmRsZXJzKHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgbmdPbkRlc3Ryb3koKSB7XHJcbiAgICAgICAgdGhpcy5yZW1vdmVQYXJlbnRFdmVudEhhbmRsZXJzKCk7XHJcbiAgICB9XHJcblxyXG4gICAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xyXG4gICAgICAgIHRoaXMucHJldmlvdXNTdGFydCA9IHVuZGVmaW5lZDtcclxuICAgICAgICB0aGlzLnByZXZpb3VzRW5kID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIGNvbnN0IHRvdGFsUm93cyA9IChjaGFuZ2VzIGFzIGFueSkudG90YWxSb3dzIHx8IHt9O1xyXG4gICAgICAgIGlmICgoKGNoYW5nZXMgYXMgYW55KS50b3RhbFJvd3MgIT09IHVuZGVmaW5lZCAmJiB0b3RhbFJvd3MucHJldmlvdXNWYWx1ZSA9PT0gdW5kZWZpbmVkKSB8fFxyXG4gICAgICAgICAgICB0b3RhbFJvd3MucHJldmlvdXNWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc3RhcnR1cExvb3AgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdmFyIGllVmVyID0gdGhpcy5kZXRlY3RJRSgpO1xyXG4gICAgICAgIHZhciBoZWFkZXJSb3dIZWlnaHQgPSAnMzRweCc7XHJcblxyXG4gICAgICAgIC8vIFNldCBwYWRkaW5nIHRvcCBmb3IgdGhlIHRhYmxlIHZpZXcgYmVjYXVzZSB0aGUgaGVhZGVyIHJvdy5cclxuICAgICAgICAvL3RoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5jb250ZW50RWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAncGFkZGluZy10b3AnLCB0aGlzLmlzVGFibGUgPyBoZWFkZXJSb3dIZWlnaHQgOiAnMCcpO1xyXG5cclxuICAgICAgICBpZiAoIWllVmVyIHx8IGllVmVyID49IDE2KSB7XHJcbiAgICAgICAgICAgIC8vIG5vdCBJRSBhbmQgdmVyc2lvbiA8IDE2XHJcbiAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQsICd0b3AnLCAnMCcpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQsICd0b3AnLCBoZWFkZXJSb3dIZWlnaHQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy9Pbmx5IGZvciBJRSBicm93c2Vyc1xyXG4gICAgICAgIC8qICBsZXQgdWEgPSBuYXZpZ2F0b3IudXNlckFnZW50O1xyXG4gICAgICAgIGlmICh0aGlzLmlzVGFibGUgJiYgKHVhLmluZGV4T2YoJ01TSUUgJykgPj0gMCB8fCB1YS5pbmRleE9mKCdUcmlkZW50LycpID49IDAgfHwgdWEuaW5kZXhPZignRWRnZS8nKSA+PSAwKSkge1xyXG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LCAndG9wJywgaGVhZGVyUm93SGVpZ2h0KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQsICd0b3AnLCAnMCcpO1xyXG4gICAgICAgIH0qL1xyXG5cclxuICAgICAgICB0aGlzLnJlZnJlc2goKTtcclxuICAgIH1cclxuXHJcbiAgICBkZXRlY3RJRSgpOiBhbnkge1xyXG4gICAgICAgIHZhciB1YSA9IHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50O1xyXG5cclxuICAgICAgICAvLyBUZXN0IHZhbHVlczsgVW5jb21tZW50IHRvIGNoZWNrIHJlc3VsdCDigKZcclxuXHJcbiAgICAgICAgLy8gSUUgMTBcclxuICAgICAgICAvLyB1YSA9ICdNb3ppbGxhLzUuMCAoY29tcGF0aWJsZTsgTVNJRSAxMC4wOyBXaW5kb3dzIE5UIDYuMjsgVHJpZGVudC82LjApJztcclxuXHJcbiAgICAgICAgLy8gSUUgMTFcclxuICAgICAgICAvLyB1YSA9ICdNb3ppbGxhLzUuMCAoV2luZG93cyBOVCA2LjM7IFRyaWRlbnQvNy4wOyBydjoxMS4wKSBsaWtlIEdlY2tvJztcclxuXHJcbiAgICAgICAgLy8gRWRnZSAxMiAoU3BhcnRhbilcclxuICAgICAgICAvLyB1YSA9ICdNb3ppbGxhLzUuMCAoV2luZG93cyBOVCAxMC4wOyBXT1c2NCkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzM5LjAuMjE3MS43MSBTYWZhcmkvNTM3LjM2IEVkZ2UvMTIuMCc7XHJcblxyXG4gICAgICAgIC8vIEVkZ2UgMTNcclxuICAgICAgICAvLyB1YSA9ICdNb3ppbGxhLzUuMCAoV2luZG93cyBOVCAxMC4wOyBXaW42NDsgeDY0KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvNDYuMC4yNDg2LjAgU2FmYXJpLzUzNy4zNiBFZGdlLzEzLjEwNTg2JztcclxuXHJcbiAgICAgICAgdmFyIG1zaWUgPSB1YS5pbmRleE9mKCdNU0lFICcpO1xyXG4gICAgICAgIGlmIChtc2llID4gMCkge1xyXG4gICAgICAgICAgICAvLyBJRSAxMCBvciBvbGRlciA9PiByZXR1cm4gdmVyc2lvbiBudW1iZXJcclxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlSW50KHVhLnN1YnN0cmluZyhtc2llICsgNSwgdWEuaW5kZXhPZignLicsIG1zaWUpKSwgMTApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdmFyIHRyaWRlbnQgPSB1YS5pbmRleE9mKCdUcmlkZW50LycpO1xyXG4gICAgICAgIGlmICh0cmlkZW50ID4gMCkge1xyXG4gICAgICAgICAgICAvLyBJRSAxMSA9PiByZXR1cm4gdmVyc2lvbiBudW1iZXJcclxuICAgICAgICAgICAgdmFyIHJ2ID0gdWEuaW5kZXhPZigncnY6Jyk7XHJcbiAgICAgICAgICAgIHJldHVybiBwYXJzZUludCh1YS5zdWJzdHJpbmcocnYgKyAzLCB1YS5pbmRleE9mKCcuJywgcnYpKSwgMTApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdmFyIGVkZ2UgPSB1YS5pbmRleE9mKCdFZGdlLycpO1xyXG4gICAgICAgIGlmIChlZGdlID4gMCkge1xyXG4gICAgICAgICAgICAvLyBFZGdlIChJRSAxMispID0+IHJldHVybiB2ZXJzaW9uIG51bWJlclxyXG4gICAgICAgICAgICByZXR1cm4gcGFyc2VJbnQodWEuc3Vic3RyaW5nKGVkZ2UgKyA1LCB1YS5pbmRleE9mKCcuJywgZWRnZSkpLCAxMCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBvdGhlciBicm93c2VyXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIHJlZnJlc2goZm9yY2VWaWV3cG9ydFVwZGF0ZTogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICAgICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcclxuICAgICAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHRoaXMuY2FsY3VsYXRlSXRlbXMoZm9yY2VWaWV3cG9ydFVwZGF0ZSkpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHNjcm9sbEludG8oaW5kZXg6IGFueSkge1xyXG4gICAgICAgIGxldCBlbDogRWxlbWVudCA9IHRoaXMucGFyZW50U2Nyb2xsIGluc3RhbmNlb2YgV2luZG93ID8gZG9jdW1lbnQuYm9keSA6IHRoaXMucGFyZW50U2Nyb2xsIHx8IHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50O1xyXG4gICAgICAgIGxldCBvZmZzZXRUb3AgPSB0aGlzLmdldEVsZW1lbnRzT2Zmc2V0KCk7XHJcbiAgICAgICAgLy9sZXQgaW5kZXg6IG51bWJlciA9ICh0aGlzLml0ZW1zIHx8IFtdKS5pbmRleE9mKGl0ZW0pO1xyXG4gICAgICAgIGlmIChpbmRleCA8IDAgfHwgaW5kZXggPj0gdGhpcy50b3RhbFJvd3MpIHJldHVybjtcclxuXHJcbiAgICAgICAgbGV0IGQgPSB0aGlzLmNhbGN1bGF0ZURpbWVuc2lvbnMoKTtcclxuICAgICAgICBsZXQgc2Nyb2xsVG9wID0gTWF0aC5mbG9vcihpbmRleCAvIGQuaXRlbXNQZXJSb3cpICogZC5jaGlsZEhlaWdodCAtIGQuY2hpbGRIZWlnaHQgKiBNYXRoLm1pbihpbmRleCwgdGhpcy5idWZmZXJBbW91bnQpO1xyXG5cclxuICAgICAgICBsZXQgYW5pbWF0aW9uUmVxdWVzdDtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudFR3ZWVuICE9PSB1bmRlZmluZWQpIHsgdGhpcy5jdXJyZW50VHdlZW4uc3RvcCgpOyB9XHJcblxyXG4gICAgICAgIC8vIHRvdGFsbHkgZGlzYWJsZSBhbmltYXRlXHJcbiAgICAgICAgaWYgKCF0aGlzLnNjcm9sbEFuaW1hdGlvblRpbWUpIHtcclxuICAgICAgICAgICAgZWwuc2Nyb2xsVG9wID0gc2Nyb2xsVG9wO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLmN1cnJlbnRUd2VlbiA9IG5ldyB0d2Vlbi5Ud2Vlbih7IHNjcm9sbFRvcDogZWwuc2Nyb2xsVG9wIH0pXHJcbiAgICAgICAgICAgIC50byh7IHNjcm9sbFRvcCB9LCB0aGlzLnNjcm9sbEFuaW1hdGlvblRpbWUpXHJcbiAgICAgICAgICAgIC5lYXNpbmcodHdlZW4uRWFzaW5nLlF1YWRyYXRpYy5PdXQpXHJcbiAgICAgICAgICAgIC5vblVwZGF0ZShkYXRhID0+IHtcclxuICAgICAgICAgICAgICAgIGlmIChpc05hTihkYXRhLnNjcm9sbFRvcCkpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFByb3BlcnR5KGVsLCAnc2Nyb2xsVG9wJywgZGF0YS5zY3JvbGxUb3ApO1xyXG4gICAgICAgICAgICA