@q149/angular-scrollspy
Version:
A simple lightweight library for Angular which automatically updates links to indicate the currently active section in the viewport
400 lines (391 loc) • 30 kB
JavaScript
import { Directive, Input, HostBinding, ChangeDetectorRef, Injectable, ContentChildren, Component, NgModule } from '@angular/core';
import { __spread } from 'tslib';
import { InViewportModule } from '@q149/angular-inviewport';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* A directive used to add an `active` class to a nav item
* when the section is in the viewport
*
* \@example
* ```html
* <a snScrollSpyItem for="foo" href="#section1">Section 1</a>
* ```
*
*/
var ScrollSpyItemDirective = /** @class */ (function () {
/**
* Creates an instance of ScrollSpyItemDirective.
* @memberof ScrollSpyItemDirective
*/
function ScrollSpyItemDirective(cdRef) {
this.cdRef = cdRef;
/**
* True if the nav item is the active item in the `items` list
* for `ScrollSpyDirective` instance
*
* \@memberof ScrollSpyItemDirective
*/
this.active = false;
/**
* If true means the section is in the viewport
*
* \@memberof ScrollSpyItemDirective
*/
this.inViewport = false;
}
Object.defineProperty(ScrollSpyItemDirective.prototype, "section", {
get: /**
* Id of section that links navigates to
*
* \@readonly
* \@memberof ScrollSpyItemDirective
* @return {?}
*/
function () {
return this.href.replace('#', '');
},
enumerable: true,
configurable: true
});
/**
* Manually trigger change detection
*
* \@memberof ScrollSpyItemDirective
* @return {?}
*/
ScrollSpyItemDirective.prototype.detectChanges = /**
* Manually trigger change detection
*
* \@memberof ScrollSpyItemDirective
* @return {?}
*/
function () {
this.cdRef.detectChanges();
};
ScrollSpyItemDirective.decorators = [
{ type: Directive, args: [{
selector: '[snScrollSpyItem]'
},] },
];
/** @nocollapse */
ScrollSpyItemDirective.ctorParameters = function () { return [
{ type: ChangeDetectorRef, },
]; };
ScrollSpyItemDirective.propDecorators = {
"active": [{ type: HostBinding, args: ['class.active',] },],
"for": [{ type: Input },],
"href": [{ type: Input },],
};
return ScrollSpyItemDirective;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* Service that stores a list of `Spy`'s and the state
* of their nav items `inViewport` and `active` state
*
*/
var ScrollSpyService = /** @class */ (function () {
function ScrollSpyService() {
/**
* List of `Spy`'s
*
* \@memberof ScrollSpyService
*/
this.spys = [];
/**
* Stores requests to add items to spy when spy hasn't been created
* yet. Once spy has been added then request will be made again.
*
* \@memberof ScrollSpyService
*/
this.buffer = [];
}
/**
* Add spy to list of `spys`
*
* \@memberof ScrollSpyService
* @param {?} id
* @param {?} items
* @return {?}
*/
ScrollSpyService.prototype.addSpy = /**
* Add spy to list of `spys`
*
* \@memberof ScrollSpyService
* @param {?} id
* @param {?} items
* @return {?}
*/
function (id, items) {
var _this = this;
this.spys.push({ id: id, items: items });
var /** @type {?} */ buffer = this.buffer.filter(function (i) { return i.spyId === id; });
this.buffer = this.buffer.filter(function (i) { return i.spyId !== id; });
buffer.forEach(function (i) {
return _this.setSpySectionStatus(i.sectionId, i.spyId, i.inViewport);
});
};
/**
* Remove spy from list of `spys`
*
* \@memberof ScrollSpyService
* @param {?} id
* @return {?}
*/
ScrollSpyService.prototype.removeSpy = /**
* Remove spy from list of `spys`
*
* \@memberof ScrollSpyService
* @param {?} id
* @return {?}
*/
function (id) {
var /** @type {?} */ i = this.spys.findIndex(function (s) { return s.id === id; });
this.spys.splice(i, 1);
};
/**
* Set the `inViewport` status for a spy item then sets the active
* to true for the first item in the list that has `inViewport`
* set to true
*
* \@memberof ScrollSpyService
* @param {?} sectionId
* @param {?} spyId
* @param {?} inViewport
* @return {?}
*/
ScrollSpyService.prototype.setSpySectionStatus = /**
* Set the `inViewport` status for a spy item then sets the active
* to true for the first item in the list that has `inViewport`
* set to true
*
* \@memberof ScrollSpyService
* @param {?} sectionId
* @param {?} spyId
* @param {?} inViewport
* @return {?}
*/
function (sectionId, spyId, inViewport) {
var /** @type {?} */ spy = this.spys.find(function (s) { return s.id === spyId; });
if (!spy) {
this.buffer.push({ sectionId: sectionId, spyId: spyId, inViewport: inViewport });
return;
}
var /** @type {?} */ item = spy.items.find(function (i) { return i.section === sectionId; });
if (!item) {
return;
}
item.inViewport = inViewport;
var /** @type {?} */ firstInViewport = spy.items.filter(function (i) { return i.inViewport; })[0];
spy.items.forEach(function (i) { return (i.active = false); });
if (firstInViewport) {
firstInViewport.active = true;
firstInViewport.detectChanges();
}
};
ScrollSpyService.decorators = [
{ type: Injectable },
];
return ScrollSpyService;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* Adds `active` class to navigation links when section is in the viewport.
* Used in conjuction with `snScrollItem` directive which should be added
* to anchor links in the nav
*
* \@example
* ```
* <ul role="navigation" snScrollSpy id="foo">
* <li><a snScrollSpyItem for="foo" href="#section1">Section 1</a></li>
* <li><a snScrollSpyItem for="foo" href="#section2">Section 2</a></li>
* <li><a snScrollSpyItem for="foo" href="#section3">Section 3</a></li>
* <li><a snScrollSpyItem for="foo" href="#section4">Section 4</a></li>
* </ul>
* ```
*
*/
var ScrollSpyDirective = /** @class */ (function () {
/**
* Creates an instance of ScrollSpyDirective.
* @memberof ScrollSpyDirective
*/
function ScrollSpyDirective(scrollSpySvc) {
this.scrollSpySvc = scrollSpySvc;
}
/**
* Adds spy to list of spys in `ScrollSpyService`
*
* \@memberof ScrollSpyDirective
* @return {?}
*/
ScrollSpyDirective.prototype.ngAfterViewInit = /**
* Adds spy to list of spys in `ScrollSpyService`
*
* \@memberof ScrollSpyDirective
* @return {?}
*/
function () {
this.scrollSpySvc.addSpy(this.id, this.items);
};
/**
* Remove spy from list of spys when directive is destroyed
*
* \@memberof ScrollSpyDirective
* @return {?}
*/
ScrollSpyDirective.prototype.ngOnDestroy = /**
* Remove spy from list of spys when directive is destroyed
*
* \@memberof ScrollSpyDirective
* @return {?}
*/
function () {
this.scrollSpySvc.removeSpy(this.id);
};
ScrollSpyDirective.decorators = [
{ type: Directive, args: [{
selector: '[snScrollSpy]'
},] },
];
/** @nocollapse */
ScrollSpyDirective.ctorParameters = function () { return [
{ type: ScrollSpyService, },
]; };
ScrollSpyDirective.propDecorators = {
"items": [{ type: ContentChildren, args: [ScrollSpyItemDirective,] },],
"id": [{ type: Input },],
};
return ScrollSpyDirective;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* A component to wrap section content within that will update the
* `ScrollSpyService` when it's in view
*
* \@example
* ```html
* <sn-scroll-spy-section id="section1" for="foo">
* ...
* </sn-scroll-spy-section>
* ```
*/
var ScrollSpySectionComponent = /** @class */ (function () {
/**
* Creates an instance of ScrollSpySectionComponent.
* @memberof ScrollSpySectionComponent
*/
function ScrollSpySectionComponent(scrollSpySvc) {
this.scrollSpySvc = scrollSpySvc;
/**
* Amount of time in ms to wait for other scroll events
* before running event handler
*
* \@default 0
* \@memberof ScrollSpySectionComponent
*/
this.debounce = 0;
}
/**
* Updates `ScrollSpy` section when element enters/leaves viewport
*
* \@memberof ScrollSpySectionComponent
* @param {?} inViewport
* @return {?}
*/
ScrollSpySectionComponent.prototype.onInViewportChange = /**
* Updates `ScrollSpy` section when element enters/leaves viewport
*
* \@memberof ScrollSpySectionComponent
* @param {?} inViewport
* @return {?}
*/
function (inViewport) {
this.scrollSpySvc.setSpySectionStatus(this.id, this.for, inViewport);
};
ScrollSpySectionComponent.decorators = [
{ type: Component, args: [{
selector: 'sn-scroll-spy-section',
template: "<div\n class=\"sn-hidden\"\n snInViewport\n [offsetTop]=\"500\"\n (inViewportChange)=\"onInViewportChange($event)\"\n [debounce]=\"debounce\">\n</div>\n<ng-content></ng-content>\n",
styles: [":host{display:block;position:relative}.sn-hidden{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0;z-index:-1}"]
},] },
];
/** @nocollapse */
ScrollSpySectionComponent.ctorParameters = function () { return [
{ type: ScrollSpyService, },
]; };
ScrollSpySectionComponent.propDecorators = {
"id": [{ type: Input },],
"for": [{ type: Input },],
"debounce": [{ type: Input },],
};
return ScrollSpySectionComponent;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
var /** @type {?} */ directives = [ScrollSpyDirective, ScrollSpyItemDirective];
var /** @type {?} */ components = [ScrollSpySectionComponent];
var /** @type {?} */ providers = [ScrollSpyService];
/**
* A simple lightweight library for Angular which automatically
* updates links to indicate the currently active section in the viewport
*
*/
var ScrollSpyModule = /** @class */ (function () {
function ScrollSpyModule() {
}
/**
* Specify a static method for root module to ensure providers are
* only provided once but allows the module to still be imported
* into other modules without reproviding services.
*
* \@memberof ScrollSpyModule
* @return {?}
*/
ScrollSpyModule.forRoot = /**
* Specify a static method for root module to ensure providers are
* only provided once but allows the module to still be imported
* into other modules without reproviding services.
*
* \@memberof ScrollSpyModule
* @return {?}
*/
function () {
return {
ngModule: ScrollSpyModule,
providers: __spread(providers)
};
};
ScrollSpyModule.decorators = [
{ type: NgModule, args: [{
imports: [InViewportModule],
declarations: __spread(directives, components),
exports: __spread(directives, components)
},] },
];
return ScrollSpyModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
export { ScrollSpyDirective, ScrollSpyItemDirective, ScrollSpySectionComponent, ScrollSpyService, ScrollSpyModule };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicTE0OS1hbmd1bGFyLXNjcm9sbHNweS5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQHExNDkvYW5ndWxhci1zY3JvbGxzcHkvYXBwL3Njcm9sbC1zcHkvc2Nyb2xsLXNweS1pdGVtL3Njcm9sbC1zcHktaXRlbS5kaXJlY3RpdmUudHMiLCJuZzovL0BxMTQ5L2FuZ3VsYXItc2Nyb2xsc3B5L2FwcC9zY3JvbGwtc3B5L3Njcm9sbC1zcHktc2VydmljZS9zY3JvbGwtc3B5LnNlcnZpY2UudHMiLCJuZzovL0BxMTQ5L2FuZ3VsYXItc2Nyb2xsc3B5L2FwcC9zY3JvbGwtc3B5L3Njcm9sbC1zcHkvc2Nyb2xsLXNweS5kaXJlY3RpdmUudHMiLCJuZzovL0BxMTQ5L2FuZ3VsYXItc2Nyb2xsc3B5L2FwcC9zY3JvbGwtc3B5L3Njcm9sbC1zcHktc2VjdGlvbi9zY3JvbGwtc3B5LXNlY3Rpb24uY29tcG9uZW50LnRzIiwibmc6Ly9AcTE0OS9hbmd1bGFyLXNjcm9sbHNweS9hcHAvc2Nyb2xsLXNweS9zY3JvbGwtc3B5Lm1vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIERpcmVjdGl2ZSxcclxuICBJbnB1dCxcclxuICBIb3N0QmluZGluZyxcclxuICBDaGFuZ2VEZXRlY3RvclJlZlxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuLyoqXHJcbiAqIEEgZGlyZWN0aXZlIHVzZWQgdG8gYWRkIGFuIGBhY3RpdmVgIGNsYXNzIHRvIGEgbmF2IGl0ZW1cclxuICogd2hlbiB0aGUgc2VjdGlvbiBpcyBpbiB0aGUgdmlld3BvcnRcclxuICpcclxuICogQGV4YW1wbGVcclxuICogYGBgaHRtbFxyXG4gKiA8YSBzblNjcm9sbFNweUl0ZW0gZm9yPVwiZm9vXCIgaHJlZj1cIiNzZWN0aW9uMVwiPlNlY3Rpb24gMTwvYT5cclxuICogYGBgXHJcbiAqXHJcbiAqL1xyXG5ARGlyZWN0aXZlKHtcclxuICBzZWxlY3RvcjogJ1tzblNjcm9sbFNweUl0ZW1dJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZSB7XHJcbiAgLyoqXHJcbiAgICogVHJ1ZSBpZiB0aGUgbmF2IGl0ZW0gaXMgdGhlIGFjdGl2ZSBpdGVtIGluIHRoZSBgaXRlbXNgIGxpc3RcclxuICAgKiBmb3IgYFNjcm9sbFNweURpcmVjdGl2ZWAgaW5zdGFuY2VcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlXHJcbiAgICovXHJcbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5hY3RpdmUnKSBwdWJsaWMgYWN0aXZlID0gZmFsc2U7XHJcbiAgLyoqXHJcbiAgICogSUQgb2YgYFNjcm9sbFNweURpcmVjdGl2ZWAgaW5zdGFuY2VcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlXHJcbiAgICovXHJcbiAgQElucHV0KCkgcHVibGljIGZvcjogc3RyaW5nO1xyXG4gIC8qKlxyXG4gICAqIEhhc2ggZm9yIHNlY3Rpb24gdG8gbGluayB0b1xyXG4gICAqXHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweUl0ZW1EaXJlY3RpdmVcclxuICAgKi9cclxuICBASW5wdXQoKSBwdWJsaWMgaHJlZjogc3RyaW5nO1xyXG4gIC8qKlxyXG4gICAqIElmIHRydWUgbWVhbnMgdGhlIHNlY3Rpb24gaXMgaW4gdGhlIHZpZXdwb3J0XHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBpblZpZXdwb3J0ID0gZmFsc2U7XHJcbiAgLyoqXHJcbiAgICogSWQgb2Ygc2VjdGlvbiB0aGF0IGxpbmtzIG5hdmlnYXRlcyB0b1xyXG4gICAqXHJcbiAgICogQHJlYWRvbmx5XHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweUl0ZW1EaXJlY3RpdmVcclxuICAgKi9cclxuICBwdWJsaWMgZ2V0IHNlY3Rpb24oKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aGlzLmhyZWYucmVwbGFjZSgnIycsICcnKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlLlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjZFJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYpIHt9XHJcbiAgLyoqXHJcbiAgICogTWFudWFsbHkgdHJpZ2dlciBjaGFuZ2UgZGV0ZWN0aW9uXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBkZXRlY3RDaGFuZ2VzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5jZFJlZi5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IEluamVjdGFibGUsIFF1ZXJ5TGlzdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuaW1wb3J0IHsgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZSB9IGZyb20gJy4uL3Njcm9sbC1zcHktaXRlbS9zY3JvbGwtc3B5LWl0ZW0uZGlyZWN0aXZlJztcclxuaW1wb3J0IHsgU3B5IH0gZnJvbSAnLi4vc2hhcmVkL3NweS5tb2RlbCc7XHJcblxyXG4vKipcclxuICogU2VydmljZSB0aGF0IHN0b3JlcyBhIGxpc3Qgb2YgYFNweWAncyBhbmQgdGhlIHN0YXRlXHJcbiAqIG9mIHRoZWlyIG5hdiBpdGVtcyBgaW5WaWV3cG9ydGAgYW5kIGBhY3RpdmVgIHN0YXRlXHJcbiAqXHJcbiAqL1xyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBTY3JvbGxTcHlTZXJ2aWNlIHtcclxuICAvKipcclxuICAgKiBMaXN0IG9mIGBTcHlgJ3NcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZXJ2aWNlXHJcbiAgICovXHJcbiAgcHVibGljIHNweXM6IFNweVtdID0gW107XHJcbiAgLyoqXHJcbiAgICogU3RvcmVzIHJlcXVlc3RzIHRvIGFkZCBpdGVtcyB0byBzcHkgd2hlbiBzcHkgaGFzbid0IGJlZW4gY3JlYXRlZFxyXG4gICAqIHlldC4gT25jZSBzcHkgaGFzIGJlZW4gYWRkZWQgdGhlbiByZXF1ZXN0IHdpbGwgYmUgbWFkZSBhZ2Fpbi5cclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZXJ2aWNlXHJcbiAgICovXHJcbiAgcHVibGljIGJ1ZmZlcjogYW55W10gPSBbXTtcclxuICAvKipcclxuICAgKiBBZGQgc3B5IHRvIGxpc3Qgb2YgYHNweXNgXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5U2VydmljZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBhZGRTcHkoaWQ6IHN0cmluZywgaXRlbXM6IFF1ZXJ5TGlzdDxTY3JvbGxTcHlJdGVtRGlyZWN0aXZlPik6IHZvaWQge1xyXG4gICAgdGhpcy5zcHlzLnB1c2goeyBpZCwgaXRlbXMgfSk7XHJcbiAgICBjb25zdCBidWZmZXIgPSB0aGlzLmJ1ZmZlci5maWx0ZXIoaSA9PiBpLnNweUlkID09PSBpZCk7XHJcbiAgICB0aGlzLmJ1ZmZlciA9IHRoaXMuYnVmZmVyLmZpbHRlcihpID0+IGkuc3B5SWQgIT09IGlkKTtcclxuICAgIGJ1ZmZlci5mb3JFYWNoKGkgPT5cclxuICAgICAgdGhpcy5zZXRTcHlTZWN0aW9uU3RhdHVzKGkuc2VjdGlvbklkLCBpLnNweUlkLCBpLmluVmlld3BvcnQpXHJcbiAgICApO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBSZW1vdmUgc3B5IGZyb20gbGlzdCBvZiBgc3B5c2BcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZXJ2aWNlXHJcbiAgICovXHJcbiAgcHVibGljIHJlbW92ZVNweShpZDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBpID0gdGhpcy5zcHlzLmZpbmRJbmRleChzID0+IHMuaWQgPT09IGlkKTtcclxuICAgIHRoaXMuc3B5cy5zcGxpY2UoaSwgMSk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIFNldCB0aGUgYGluVmlld3BvcnRgIHN0YXR1cyBmb3IgYSBzcHkgaXRlbSB0aGVuIHNldHMgdGhlIGFjdGl2ZVxyXG4gICAqIHRvIHRydWUgZm9yIHRoZSBmaXJzdCBpdGVtIGluIHRoZSBsaXN0IHRoYXQgaGFzIGBpblZpZXdwb3J0YFxyXG4gICAqIHNldCB0byB0cnVlXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5U2VydmljZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBzZXRTcHlTZWN0aW9uU3RhdHVzKFxyXG4gICAgc2VjdGlvbklkOiBzdHJpbmcsXHJcbiAgICBzcHlJZDogc3RyaW5nLFxyXG4gICAgaW5WaWV3cG9ydDogYm9vbGVhblxyXG4gICk6IHZvaWQge1xyXG4gICAgY29uc3Qgc3B5ID0gdGhpcy5zcHlzLmZpbmQocyA9PiBzLmlkID09PSBzcHlJZCk7XHJcbiAgICBpZiAoIXNweSkge1xyXG4gICAgICB0aGlzLmJ1ZmZlci5wdXNoKHsgc2VjdGlvbklkLCBzcHlJZCwgaW5WaWV3cG9ydCB9KTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgY29uc3QgaXRlbSA9IHNweS5pdGVtcy5maW5kKGkgPT4gaS5zZWN0aW9uID09PSBzZWN0aW9uSWQpO1xyXG4gICAgaWYgKCFpdGVtKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBpdGVtLmluVmlld3BvcnQgPSBpblZpZXdwb3J0O1xyXG4gICAgY29uc3QgZmlyc3RJblZpZXdwb3J0ID0gc3B5Lml0ZW1zLmZpbHRlcihpID0+IGkuaW5WaWV3cG9ydClbMF07XHJcbiAgICBzcHkuaXRlbXMuZm9yRWFjaChpID0+IChpLmFjdGl2ZSA9IGZhbHNlKSk7XHJcblxyXG4gICAgaWYgKGZpcnN0SW5WaWV3cG9ydCkge1xyXG4gICAgICBmaXJzdEluVmlld3BvcnQuYWN0aXZlID0gdHJ1ZTtcclxuICAgICAgZmlyc3RJblZpZXdwb3J0LmRldGVjdENoYW5nZXMoKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHtcclxuICBEaXJlY3RpdmUsXHJcbiAgQ29udGVudENoaWxkcmVuLFxyXG4gIFF1ZXJ5TGlzdCxcclxuICBBZnRlclZpZXdJbml0LFxyXG4gIElucHV0LFxyXG4gIE9uRGVzdHJveVxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuaW1wb3J0IHsgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZSB9IGZyb20gJy4uL3Njcm9sbC1zcHktaXRlbS9zY3JvbGwtc3B5LWl0ZW0uZGlyZWN0aXZlJztcclxuaW1wb3J0IHsgU2Nyb2xsU3B5U2VydmljZSB9IGZyb20gJy4uL3Njcm9sbC1zcHktc2VydmljZS9zY3JvbGwtc3B5LnNlcnZpY2UnO1xyXG5cclxuLyoqXHJcbiAqIEFkZHMgYGFjdGl2ZWAgY2xhc3MgdG8gbmF2aWdhdGlvbiBsaW5rcyB3aGVuIHNlY3Rpb24gaXMgaW4gdGhlIHZpZXdwb3J0LlxyXG4gKiBVc2VkIGluIGNvbmp1Y3Rpb24gd2l0aCBgc25TY3JvbGxJdGVtYCBkaXJlY3RpdmUgd2hpY2ggc2hvdWxkIGJlIGFkZGVkXHJcbiAqIHRvIGFuY2hvciBsaW5rcyBpbiB0aGUgbmF2XHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIGBgYFxyXG4gKiA8dWwgcm9sZT1cIm5hdmlnYXRpb25cIiBzblNjcm9sbFNweSBpZD1cImZvb1wiPlxyXG4gKiAgPGxpPjxhIHNuU2Nyb2xsU3B5SXRlbSBmb3I9XCJmb29cIiBocmVmPVwiI3NlY3Rpb24xXCI+U2VjdGlvbiAxPC9hPjwvbGk+XHJcbiAqICA8bGk+PGEgc25TY3JvbGxTcHlJdGVtIGZvcj1cImZvb1wiIGhyZWY9XCIjc2VjdGlvbjJcIj5TZWN0aW9uIDI8L2E+PC9saT5cclxuICogIDxsaT48YSBzblNjcm9sbFNweUl0ZW0gZm9yPVwiZm9vXCIgaHJlZj1cIiNzZWN0aW9uM1wiPlNlY3Rpb24gMzwvYT48L2xpPlxyXG4gKiAgPGxpPjxhIHNuU2Nyb2xsU3B5SXRlbSBmb3I9XCJmb29cIiBocmVmPVwiI3NlY3Rpb240XCI+U2VjdGlvbiA0PC9hPjwvbGk+XHJcbiAqIDwvdWw+XHJcbiAqIGBgYFxyXG4gKlxyXG4gKi9cclxuQERpcmVjdGl2ZSh7XHJcbiAgc2VsZWN0b3I6ICdbc25TY3JvbGxTcHldJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgU2Nyb2xsU3B5RGlyZWN0aXZlIGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcclxuICAvKipcclxuICAgKiBDb2xsZWN0aW9uIG9mIGBTY3JvbGxTcHlJdGVtYC4gVGhleSBhcmUgdGhlIGxpc3Qgb2ZcclxuICAgKiBuYXYgaXRlbXMuXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5RGlyZWN0aXZlXHJcbiAgICovXHJcbiAgQENvbnRlbnRDaGlsZHJlbihTY3JvbGxTcHlJdGVtRGlyZWN0aXZlKVxyXG4gIHB1YmxpYyBpdGVtczogUXVlcnlMaXN0PFNjcm9sbFNweUl0ZW1EaXJlY3RpdmU+O1xyXG4gIC8qKlxyXG4gICAqIElEIG9mIHNjcm9sbFNweSBpbnN0YW5jZVxyXG4gICAqXHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweURpcmVjdGl2ZVxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyBpZDogc3RyaW5nO1xyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgU2Nyb2xsU3B5RGlyZWN0aXZlLlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlEaXJlY3RpdmVcclxuICAgKi9cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNjcm9sbFNweVN2YzogU2Nyb2xsU3B5U2VydmljZSkge31cclxuICAvKipcclxuICAgKiBBZGRzIHNweSB0byBsaXN0IG9mIHNweXMgaW4gYFNjcm9sbFNweVNlcnZpY2VgXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5RGlyZWN0aXZlXHJcbiAgICovXHJcbiAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuc2Nyb2xsU3B5U3ZjLmFkZFNweSh0aGlzLmlkLCB0aGlzLml0ZW1zKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogUmVtb3ZlIHNweSBmcm9tIGxpc3Qgb2Ygc3B5cyB3aGVuIGRpcmVjdGl2ZSBpcyBkZXN0cm95ZWRcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlEaXJlY3RpdmVcclxuICAgKi9cclxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLnNjcm9sbFNweVN2Yy5yZW1vdmVTcHkodGhpcy5pZCk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgU2Nyb2xsU3B5U2VydmljZSB9IGZyb20gJy4uL3Njcm9sbC1zcHktc2VydmljZS9zY3JvbGwtc3B5LnNlcnZpY2UnO1xyXG5cclxuLyoqXHJcbiAqIEEgY29tcG9uZW50IHRvIHdyYXAgc2VjdGlvbiBjb250ZW50IHdpdGhpbiB0aGF0IHdpbGwgdXBkYXRlIHRoZVxyXG4gKiBgU2Nyb2xsU3B5U2VydmljZWAgd2hlbiBpdCdzIGluIHZpZXdcclxuICpcclxuICogQGV4YW1wbGVcclxuICogYGBgaHRtbFxyXG4gKiAgPHNuLXNjcm9sbC1zcHktc2VjdGlvbiBpZD1cInNlY3Rpb24xXCIgZm9yPVwiZm9vXCI+XHJcbiAqICAgIC4uLlxyXG4gKiAgPC9zbi1zY3JvbGwtc3B5LXNlY3Rpb24+XHJcbiAqIGBgYFxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdzbi1zY3JvbGwtc3B5LXNlY3Rpb24nLFxyXG4gIHRlbXBsYXRlOiBgPGRpdlxuICBjbGFzcz1cInNuLWhpZGRlblwiXG4gIHNuSW5WaWV3cG9ydFxuICBbb2Zmc2V0VG9wXT1cIjUwMFwiXG4gIChpblZpZXdwb3J0Q2hhbmdlKT1cIm9uSW5WaWV3cG9ydENoYW5nZSgkZXZlbnQpXCJcbiAgW2RlYm91bmNlXT1cImRlYm91bmNlXCI+XG48L2Rpdj5cbjxuZy1jb250ZW50PjwvbmctY29udGVudD5cbmAsXHJcbiAgc3R5bGVzOiBbYDpob3N0e2Rpc3BsYXk6YmxvY2s7cG9zaXRpb246cmVsYXRpdmV9LnNuLWhpZGRlbntib3R0b206MDtsZWZ0OjA7b3BhY2l0eTowO3Bvc2l0aW9uOmFic29sdXRlO3JpZ2h0OjA7dG9wOjA7ei1pbmRleDotMX1gXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgU2Nyb2xsU3B5U2VjdGlvbkNvbXBvbmVudCB7XHJcbiAgLyoqXHJcbiAgICogSWRlbnRpZmllcyB0aGUgc2VjdGlvblxyXG4gICAqXHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweVNlY3Rpb25Db21wb25lbnRcclxuICAgKi9cclxuICBASW5wdXQoKSBwdWJsaWMgaWQ6IHN0cmluZztcclxuICAvKipcclxuICAgKiBTcGVjaWZpZXMgd2hpY2ggYFNjcm9sbFNweWAgaW5zdGFuY2UgdG8gdXBkYXRlXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5U2VjdGlvbkNvbXBvbmVudFxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyBmb3I6IHN0cmluZztcclxuICAvKipcclxuICAgKiBBbW91bnQgb2YgdGltZSBpbiBtcyB0byB3YWl0IGZvciBvdGhlciBzY3JvbGwgZXZlbnRzXHJcbiAgICogYmVmb3JlIHJ1bm5pbmcgZXZlbnQgaGFuZGxlclxyXG4gICAqXHJcbiAgICogQGRlZmF1bHQgMFxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZWN0aW9uQ29tcG9uZW50XHJcbiAgICovXHJcbiAgQElucHV0KCkgcHVibGljIGRlYm91bmNlID0gMDtcclxuICAvKipcclxuICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIFNjcm9sbFNweVNlY3Rpb25Db21wb25lbnQuXHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweVNlY3Rpb25Db21wb25lbnRcclxuICAgKi9cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNjcm9sbFNweVN2YzogU2Nyb2xsU3B5U2VydmljZSkge31cclxuICAvKipcclxuICAgKiBVcGRhdGVzIGBTY3JvbGxTcHlgIHNlY3Rpb24gd2hlbiBlbGVtZW50IGVudGVycy9sZWF2ZXMgdmlld3BvcnRcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZWN0aW9uQ29tcG9uZW50XHJcbiAgICovXHJcbiAgcHVibGljIG9uSW5WaWV3cG9ydENoYW5nZShpblZpZXdwb3J0OiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLnNjcm9sbFNweVN2Yy5zZXRTcHlTZWN0aW9uU3RhdHVzKHRoaXMuaWQsIHRoaXMuZm9yLCBpblZpZXdwb3J0KTtcclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHsgTmdNb2R1bGUsIE1vZHVsZVdpdGhQcm92aWRlcnMsIFByb3ZpZGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBJblZpZXdwb3J0TW9kdWxlIH0gZnJvbSAnQHExNDkvYW5ndWxhci1pbnZpZXdwb3J0JztcblxuaW1wb3J0IHsgU2Nyb2xsU3B5RGlyZWN0aXZlIH0gZnJvbSAnLi9zY3JvbGwtc3B5L3Njcm9sbC1zcHkuZGlyZWN0aXZlJztcbmltcG9ydCB7IFNjcm9sbFNweVNlY3Rpb25Db21wb25lbnQgfSBmcm9tICcuL3Njcm9sbC1zcHktc2VjdGlvbi9zY3JvbGwtc3B5LXNlY3Rpb24uY29tcG9uZW50JztcbmltcG9ydCB7IFNjcm9sbFNweUl0ZW1EaXJlY3RpdmUgfSBmcm9tICcuL3Njcm9sbC1zcHktaXRlbS9zY3JvbGwtc3B5LWl0ZW0uZGlyZWN0aXZlJztcbmltcG9ydCB7IFNjcm9sbFNweVNlcnZpY2UgfSBmcm9tICcuL3Njcm9sbC1zcHktc2VydmljZS9zY3JvbGwtc3B5LnNlcnZpY2UnO1xuXG5jb25zdCBkaXJlY3RpdmVzOiBhbnlbXSA9IFtTY3JvbGxTcHlEaXJlY3RpdmUsIFNjcm9sbFNweUl0ZW1EaXJlY3RpdmVdO1xuXG5jb25zdCBjb21wb25lbnRzOiBhbnlbXSA9IFtTY3JvbGxTcHlTZWN0aW9uQ29tcG9uZW50XTtcblxuY29uc3QgcHJvdmlkZXJzOiBQcm92aWRlcltdID0gW1Njcm9sbFNweVNlcnZpY2VdO1xuXG4vKipcbiAqIEEgc2ltcGxlIGxpZ2h0d2VpZ2h0IGxpYnJhcnkgZm9yIEFuZ3VsYXIgd2hpY2ggYXV0b21hdGljYWxseVxuICogdXBkYXRlcyBsaW5rcyB0byBpbmRpY2F0ZSB0aGUgY3VycmVudGx5IGFjdGl2ZSBzZWN0aW9uIGluIHRoZSB2aWV3cG9ydFxuICpcbiAqL1xuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW0luVmlld3BvcnRNb2R1bGVdLFxuICBkZWNsYXJhdGlvbnM6IFsuLi5kaXJlY3RpdmVzLCAuLi5jb21wb25lbnRzXSxcbiAgZXhwb3J0czogWy4uLmRpcmVjdGl2ZXMsIC4uLmNvbXBvbmVudHNdXG59KVxuZXhwb3J0IGNsYXNzIFNjcm9sbFNweU1vZHVsZSB7XG4gIC8qKlxuICAgKiBTcGVjaWZ5IGEgc3RhdGljIG1ldGhvZCBmb3Igcm9vdCBtb2R1bGUgdG8gZW5zdXJlIHByb3ZpZGVycyBhcmVcbiAgICogb25seSBwcm92aWRlZCBvbmNlIGJ1dCBhbGxvd3MgdGhlIG1vZHVsZSB0byBzdGlsbCBiZSBpbXBvcnRlZFxuICAgKiBpbnRvIG90aGVyIG1vZHVsZXMgd2l0aG91dCByZXByb3ZpZGluZyBzZXJ2aWNlcy5cbiAgICpcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweU1vZHVsZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmb3JSb290KCk6IE1vZHVsZVdpdGhQcm92aWRlcnMge1xuICAgIHJldHVybiB7XG4gICAgICBuZ01vZHVsZTogU2Nyb2xsU3B5TW9kdWxlLFxuICAgICAgcHJvdmlkZXJzOiBbLi4ucHJvdmlkZXJzXVxuICAgIH07XG4gIH1cbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQUFBOzs7Ozs7Ozs7Ozs7Ozs7SUEyREUsZ0NBQW9C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