ng-beautiful-gauges
Version:
Angular 6+ component wrapper for the canvas-gauges lib written by @Mikhus
334 lines • 30.3 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/*!
* The MIT License (MIT)
*
* Copyright (c) 2017 Vlad Martynenko <vladimir.martynenko.work@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import { ViewChild, Input, ElementRef } from '@angular/core';
import * as CanvasGauges from 'canvas-gauges';
import * as Rx from 'rx-dom-html';
/**
* Base gauge component for the Gauges rendering
* T - Type of the Gauge to be rendered (Currently RadialGauge, LinearGauge from the original library)
* T2 - Type of config options used by the particular gauge (RadialGaugeOptions, LinearGaugeOptions)
* @abstract
* @template T, T2
*/
export class BaseGauge {
/**
*
* @param {?} el - reference to the element of the whole component, used to scrape options declared on the component itself
* @param {?} zone - required to redraw gauge outside of Angular, due to animation lags caused by the ovewritten function of the ngZone
*/
constructor(el, zone) {
this.el = el;
this.zone = zone;
/**
* Flag indicating that OnViewInit life-cycle has completed
*/
this.isInited = false;
}
/**
* Returns gauges properties as an options object.
* Option properties consist of the attribute-based properties and those
* explicitly set.
* @return {?} <T2>
*/
get options() {
/** @type {?} */
const options = (/** @type {?} */ ({}));
options.renderTo = this.canvas.nativeElement;
// Map attribute-based options onto options.
// Requries converting kebab style attribute names to camelCase property names
for (const attr of this.el.nativeElement.attributes) {
/** @type {?} */
const prop = attributeName2PropertyName(attr.name);
options[prop] = CanvasGauges.DomObserver.parse(attr.value);
}
// merge preOptons with attribute-based properties
// tslint:disable-next-line:forin
for (const prop in this.preInitOptions) {
options[prop] = this.preInitOptions[prop];
}
// clear the preInitOptions as they have already been merged
// with the attribute-based properties
if (this.isInited) {
this.preInitOptions = null;
}
return options;
}
/**
* Assign gauge options at anytime in the lifecycle.
* @param {?} newOptions - assign the style and size properties
* @return {?}
*/
set options(newOptions) {
// cache newOptions as preInitOptions until gauge is ready
if (!this.isInited) {
this.preInitOptions = newOptions;
return;
}
this.update(newOptions);
}
/**
* Assign the value of the gauge visual indicator such as a needle or pointer
* @param {?} newValue the guage new value
* @return {?}
*/
set value(newValue) {
// case new gauge value as preInitValue until the gauge is ready
if (!this.isInited) {
this.preInitValue = newValue;
return;
}
this.zone.runOutsideAngular((/**
* @return {?}
*/
() => {
this.gauge.value = newValue;
}));
}
/**
* Update the gauge options. Do not use until after OnViewInit() before using.
*
* Special implementation note - options.properties are maintained as
* attribute name->value on this component's elementRef. Thus this method
* maps each newOptions property onto the property's corresponding attribute.
* The attribute update triggers a DOM mutation event which "this" listens for.
* See #listenForDOMEvents()
*
* @param {?} newOptions - the options to update the gauge
* @return {?}
*/
update(newOptions) {
// map all options onto this element's attributes
// Then attribute changes will be detected and pushed to the gauge.update()
if (!newOptions) {
return;
}
// tslint:disable-next-line:forin
for (const prop in newOptions) {
/** @type {?} */
const val = newOptions[prop].toString();
if (prop === 'value') {
// short circuit the value property update by calling
// the gauge.value api directly for efficient animated update
this.value = CanvasGauges.DomObserver.parse(val);
}
else {
/** @type {?} */
const attrName = toKebabCase(prop);
this.el.nativeElement.setAttribute(attrName, val);
}
}
}
/**
* Perform gauge initialization.
* Subclasses that override this method must this super version
* for proper operation.
* @return {?}
*/
ngAfterViewInit() {
// initial update of gauge properties
this.initGauge();
this.listenForDOMEvents();
this.isInited = true;
}
/**
* Listen for attribute-change events that are created when updating
* the options of this gauge.
* @protected
* @return {?}
*/
listenForDOMEvents() {
// Listen to gauge element for attribute changes
// Convert all changed attribtues into a GenericOptions or subclass
// Update the gauge with the new options.
this.domListener =
Rx.DOM.fromMutationObserver(this.el.nativeElement, { attributes: true }).
subscribe((/**
* @param {?} changes
* @return {?}
*/
changes => {
/** @type {?} */
const newOptions = (/** @type {?} */ ({}));
changes.forEach((/**
* @param {?} change
* @return {?}
*/
change => {
if ('attributes' === change.type) {
// console.log('DOM, change', change.attributeName);
newOptions[attributeName2PropertyName(change.attributeName)] =
CanvasGauges.DomObserver.parse(this.el.nativeElement.getAttribute(change.attributeName));
}
}));
this.basicUpdate(newOptions);
}));
}
/**
* Discontinue listening for attribute change events.
* @protected
* @return {?}
*/
stopListeningForDOMEvents() {
if (this.domListener) {
this.domListener.disconnect();
this.domListener = null;
}
}
/**
* Initalize the gauge with all options defined by attributes and
* parent component options.
* @protected
* @return {?}
*/
initGauge() {
/** @type {?} */
const options = this.options;
if (this.preInitValue) {
options.value = this.preInitValue;
}
// init options.renderTo if needed
if (!options.hasOwnProperty('renderTo') || !options.renderTo) {
options.renderTo = this.canvas.nativeElement;
}
this.basicUpdate(options);
}
/**
* Performs the gauge update using the current options
* @protected
* @param {?} options The options for the guage
* @return {?}
*/
basicUpdate(options) {
// treat the value property special and update it through the
// value getter.
if (typeof options.value === 'number') {
// use gauge api directly for most efficient update method
this.value = options.value;
// filter value property from options to avoid redundant
// processing by gauge
delete options.value;
}
// do nothing if no option properties to update
if (Object.keys(options).length) {
this.gauge.update(options);
}
}
}
BaseGauge.propDecorators = {
canvas: [{ type: ViewChild, args: ['gauge',] }],
options: [{ type: Input }],
value: [{ type: Input }]
};
if (false) {
/**
* Canvas element on the template used by the library to draw gauge element
* @type {?}
* @protected
*/
BaseGauge.prototype.canvas;
/**
* A gauge instance responsible for rendering and updates on the canvas.
* Subclasses should initialize in their ngOnInit implementation.
* @type {?}
* @protected
*/
BaseGauge.prototype.gauge;
/**
* Flag indicating that OnViewInit life-cycle has completed
* @type {?}
* @private
*/
BaseGauge.prototype.isInited;
/**
* value property of gauge prior to component view initialization
* @type {?}
* @private
*/
BaseGauge.prototype.preInitValue;
/**
* options property of gauge prior to component view initialization
* @type {?}
* @private
*/
BaseGauge.prototype.preInitOptions;
/**
* Listen for attribute changes, i.e., options properties that are stored
* as attributes on this ElementRef
* @type {?}
* @private
*/
BaseGauge.prototype.domListener;
/**
* @type {?}
* @private
*/
BaseGauge.prototype.el;
/** @type {?} */
BaseGauge.prototype.zone;
/**
* Subclasses should instantiate the CanvasGauge object in the child component
* @abstract
* @return {?}
*/
BaseGauge.prototype.ngOnInit = function () { };
}
// String utils
/** @type {?} */
const attributeName2PropertyName = (/**
* @param {?} attrName
* @return {?}
*/
(attrName) => toCamelCase(attrName));
const ɵ0 = attributeName2PropertyName;
/** @type {?} */
const propertyName2AttrName = (/**
* @param {?} propName
* @return {?}
*/
(propName) => toKebabCase(propName));
const ɵ1 = propertyName2AttrName;
/** @type {?} */
const toCamelCase = (/**
* @param {?} str
* @return {?}
*/
(str) => str.replace(/(\-\w)/g, (/**
* @param {?} m
* @return {?}
*/
(m) => m[1].toUpperCase())));
const ɵ2 = toCamelCase;
/** @type {?} */
const toKebabCase = (/**
* @param {?} str
* @return {?}
*/
(str) => str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase());
const ɵ3 = toKebabCase;
export { ɵ0, ɵ1, ɵ2, ɵ3 };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1nYXVnZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25nLWJlYXV0aWZ1bC1nYXVnZXMvIiwic291cmNlcyI6WyJsaWIvYmFzZS1nYXVnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF3QkEsT0FBTyxFQUFhLFNBQVMsRUFBRSxLQUFLLEVBQVUsVUFBVSxFQUF5QixNQUFNLGVBQWUsQ0FBQztBQUN2RyxPQUFPLEtBQUssWUFBWSxNQUFNLGVBQWUsQ0FBQztBQUM5QyxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQzs7Ozs7Ozs7QUFPbEMsTUFBTSxPQUFnQixTQUFTOzs7Ozs7SUE0QzNCLFlBQW9CLEVBQWMsRUFBUyxJQUFZO1FBQW5DLE9BQUUsR0FBRixFQUFFLENBQVk7UUFBUyxTQUFJLEdBQUosSUFBSSxDQUFROzs7O1FBekIvQyxhQUFRLEdBQUcsS0FBSyxDQUFDO0lBMEJ6QixDQUFDOzs7Ozs7O0lBZUQsSUFBVyxPQUFPOztjQUVSLE9BQU8sR0FBRyxtQkFBQSxFQUFFLEVBQU07UUFDeEIsT0FBTyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQztRQUU3Qyw0Q0FBNEM7UUFDNUMsOEVBQThFO1FBQzlFLEtBQUssTUFBTSxJQUFJLElBQUksSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsVUFBVSxFQUFFOztrQkFDM0MsSUFBSSxHQUFHLDBCQUEwQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7WUFDbEQsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLFlBQVksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUM5RDtRQUVELGtEQUFrRDtRQUNsRCxpQ0FBaUM7UUFDakMsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsY0FBYyxFQUFFO1lBQ3BDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENB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Ozs7Ozs7O0lBdkdOLDJCQUM2Qjs7Ozs7OztJQU03QiwwQkFBbUI7Ozs7OztJQU1uQiw2QkFBeUI7Ozs7OztJQUt6QixpQ0FBNkI7Ozs7OztJQUs3QixtQ0FBMkI7Ozs7Ozs7SUFPM0IsZ0NBQXNDOzs7OztJQVExQix1QkFBc0I7O0lBQUUseUJBQW1COzs7Ozs7SUFPdkQsK0NBQTBCOzs7O01BNk14QiwwQkFBMEI7Ozs7QUFBRyxDQUFDLFFBQWdCLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQTs7O01BRXhFLHFCQUFxQjs7OztBQUFHLENBQUMsUUFBZ0IsRUFBRSxFQUFFLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFBOzs7TUFFbkUsV0FBVzs7OztBQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLFNBQVM7Ozs7QUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFDLENBQUE7OztNQUV4RSxXQUFXOzs7O0FBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsb0JBQW9CLEVBQUUsT0FBTyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIFRoZSBNSVQgTGljZW5zZSAoTUlUKVxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxNyBWbGFkIE1hcnR5bmVua28gPHZsYWRpbWlyLm1hcnR5bmVua28ud29ya0BnbWFpbC5jb20+XG4gKlxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuICogb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuICogaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuICogdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4gKiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4gKiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gKiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuICogQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbiAqIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG4gKiBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgeyBDb21wb25lbnQsIFZpZXdDaGlsZCwgSW5wdXQsIE5nWm9uZSwgRWxlbWVudFJlZiwgT25Jbml0LCBBZnRlclZpZXdJbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgKiBhcyBDYW52YXNHYXVnZXMgZnJvbSAnY2FudmFzLWdhdWdlcyc7XG5pbXBvcnQgKiBhcyBSeCBmcm9tICdyeC1kb20taHRtbCc7XG5cbi8qKlxuICogQmFzZSBnYXVnZSBjb21wb25lbnQgZm9yIHRoZSBHYXVnZXMgcmVuZGVyaW5nXG4gKiBUIC0gVHlwZSBvZiB0aGUgR2F1Z2UgdG8gYmUgcmVuZGVyZWQgKEN1cnJlbnRseSBSYWRpYWxHYXVnZSwgTGluZWFyR2F1Z2UgZnJvbSB0aGUgb3JpZ2luYWwgbGlicmFyeSlcbiAqIFQyIC0gVHlwZSBvZiBjb25maWcgb3B0aW9ucyB1c2VkIGJ5IHRoZSBwYXJ0aWN1bGFyIGdhdWdlIChSYWRpYWxHYXVnZU9wdGlvbnMsIExpbmVhckdhdWdlT3B0aW9ucylcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VHYXVnZTxUIGV4dGVuZHMgQ2FudmFzR2F1Z2VzLkJhc2VHYXVnZSwgVDIgZXh0ZW5kcyBDYW52YXNHYXVnZXMuR2VuZXJpY09wdGlvbnM+XG4gICAgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQge1xuXG4gICAgLyoqXG4gICAgICogQ2FudmFzIGVsZW1lbnQgb24gdGhlIHRlbXBsYXRlIHVzZWQgYnkgdGhlIGxpYnJhcnkgdG8gZHJhdyBnYXVnZSBlbGVtZW50XG4gICAgICovXG4gICAgQFZpZXdDaGlsZCgnZ2F1Z2UnKVxuICAgIHByb3RlY3RlZCBjYW52YXM6IEVsZW1lbnRSZWY7XG5cbiAgICAvKipcbiAgICAgKiBBIGdhdWdlIGluc3RhbmNlIHJlc3BvbnNpYmxlIGZvciByZW5kZXJpbmcgYW5kIHVwZGF0ZXMgb24gdGhlIGNhbnZhcy5cbiAgICAgKiBTdWJjbGFzc2VzIHNob3VsZCBpbml0aWFsaXplIGluIHRoZWlyIG5nT25Jbml0IGltcGxlbWVudGF0aW9uLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBnYXVnZTogVDtcblxuXG4gICAgLyoqXG4gICAgICogRmxhZyBpbmRpY2F0aW5nIHRoYXQgT25WaWV3SW5pdCBsaWZlLWN5Y2xlIGhhcyBjb21wbGV0ZWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGlzSW5pdGVkID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiB2YWx1ZSBwcm9wZXJ0eSBvZiBnYXVnZSBwcmlvciB0byBjb21wb25lbnQgdmlldyBpbml0aWFsaXphdGlvblxuICAgICAqL1xuICAgIHByaXZhdGUgcHJlSW5pdFZhbHVlOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBvcHRpb25zIHByb3BlcnR5IG9mIGdhdWdlIHByaW9yIHRvIGNvbXBvbmVudCB2aWV3IGluaXRpYWxpemF0aW9uXG4gICAgICovXG4gICAgcHJpdmF0ZSBwcmVJbml0T3B0aW9uczogVDI7XG5cblxuICAgIC8qKlxuICAgICAqIExpc3RlbiBmb3IgYXR0cmlidXRlIGNoYW5nZXMsIGkuZS4sIG9wdGlvbnMgcHJvcGVydGllcyB0aGF0IGFyZSBzdG9yZWRcbiAgICAgKiBhcyBhdHRyaWJ1dGVzIG9uIHRoaXMgRWxlbWVudFJlZlxuICAgICAqL1xuICAgIHByaXZhdGUgZG9tTGlzdGVuZXI6IE11dGF0aW9uT2JzZXJ2ZXI7XG5cblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIGVsIC0gcmVmZXJlbmNlIHRvIHRoZSBlbGVtZW50IG9mIHRoZSB3aG9sZSBjb21wb25lbnQsIHVzZWQgdG8gc2NyYXBlIG9wdGlvbnMgZGVjbGFyZWQgb24gdGhlIGNvbXBvbmVudCBpdHNlbGZcbiAgICAgKiBAcGFyYW0gem9uZSAtIHJlcXVpcmVkIHRvIHJlZHJhdyBnYXVnZSBvdXRzaWRlIG9mIEFuZ3VsYXIsIGR1ZSB0byBhbmltYXRpb24gbGFncyBjYXVzZWQgYnkgdGhlIG92ZXdyaXR0ZW4gZnVuY3Rpb24gb2YgdGhlIG5nWm9uZVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgZWw6IEVsZW1lbnRSZWYsIHB1YmxpYyB6b25lOiBOZ1pvbmUpIHtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFN1YmNsYXNzZXMgc2hvdWxkIGluc3RhbnRpYXRlIHRoZSBDYW52YXNHYXVnZSBvYmplY3QgaW4gdGhlIGNoaWxkIGNvbXBvbmVudFxuICAgICAqL1xuICAgIGFic3RyYWN0IG5nT25Jbml0KCk6IHZvaWQ7XG5cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgZ2F1Z2VzIHByb3BlcnRpZXMgYXMgYW4gb3B0aW9ucyBvYmplY3QuXG4gICAgICogT3B0aW9uIHByb3BlcnRpZXMgY29uc2lzdCBvZiB0aGUgYXR0cmlidXRlLWJhc2VkIHByb3BlcnRpZXMgYW5kIHRob3NlXG4gICAgICogZXhwbGljaXRseSBzZXQuXG4gICAgICogQHJldHVybnMgPFQyPlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgb3B0aW9ucygpOiBUMiB7XG5cbiAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHt9IGFzIFQyO1xuICAgICAgICBvcHRpb25zLnJlbmRlclRvID0gdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudDtcblxuICAgICAgICAvLyBNYXAgYXR0cmlidXRlLWJhc2VkIG9wdGlvbnMgb250byBvcHRpb25zLlxuICAgICAgICAvLyBSZXF1cmllcyBjb252ZXJ0aW5nIGtlYmFiIHN0eWxlIGF0dHJpYnV0ZSBuYW1lcyB0byBjYW1lbENhc2UgcHJvcGVydHkgbmFtZXNcbiAgICAgICAgZm9yIChjb25zdCBhdHRyIG9mIHRoaXMuZWwubmF0aXZlRWxlbWVudC5hdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgICBjb25zdCBwcm9wID0gYXR0cmlidXRlTmFtZTJQcm9wZXJ0eU5hbWUoYXR0ci5uYW1lKTtcbiAgICAgICAgICAgIG9wdGlvbnNbcHJvcF0gPSBDYW52YXNHYXVnZXMuRG9tT2JzZXJ2ZXIucGFyc2UoYXR0ci52YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBtZXJnZSBwcmVPcHRvbnMgd2l0aCBhdHRyaWJ1dGUtYmFzZWQgcHJvcGVydGllc1xuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6Zm9yaW5cbiAgICAgICAgZm9yIChjb25zdCBwcm9wIGluIHRoaXMucHJlSW5pdE9wdGlvbnMpIHtcbiAgICAgICAgICAgIG9wdGlvbnNbcHJvcF0gPSB0aGlzLnByZUluaXRPcHRpb25zW3Byb3BdO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY2xlYXIgdGhlIHByZUluaXRPcHRpb25zIGFzIHRoZXkgaGF2ZSBhbHJlYWR5IGJlZW4gbWVyZ2VkXG4gICAgICAgIC8vIHdpdGggdGhlIGF0dHJpYnV0ZS1iYXNlZCBwcm9wZXJ0aWVzXG4gICAgICAgIGlmICh0aGlzLmlzSW5pdGVkKSB7XG4gICAgICAgICAgICB0aGlzLnByZUluaXRPcHRpb25zID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvcHRpb25zO1xuICAgIH1cblxuICAgIFxuICAgIC8qKlxuICAgICAqIEFzc2lnbiBnYXVnZSBvcHRpb25zIGF0IGFueXRpbWUgaW4gdGhlIGxpZmVjeWNsZS5cbiAgICAgKiBAcGFyYW0gbmV3T3B0aW9ucyAtIGFzc2lnbiB0aGUgc3R5bGUgYW5kIHNpemUgcHJvcGVydGllc1xuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIHNldCBvcHRpb25zKG5ld09wdGlvbnM6IFQyKSB7XG5cbiAgICAgICAgLy8gY2FjaGUgbmV3T3B0aW9ucyBhcyBwcmVJbml0T3B0aW9ucyB1bnRpbCBnYXVnZSBpcyByZWFkeVxuICAgICAgICBpZiAoIXRoaXMuaXNJbml0ZWQpIHtcbiAgICAgICAgICAgIHRoaXMucHJlSW5pdE9wdGlvbnMgPSBuZXdPcHRpb25zO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy51cGRhdGUobmV3T3B0aW9ucyk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBBc3NpZ24gdGhlIHZhbHVlIG9mIHRoZSBnYXVnZSB2aXN1YWwgaW5kaWNhdG9yIHN1Y2ggYXMgYSBuZWVkbGUgb3IgcG9pbnRlclxuICAgICAqIEBwYXJhbSBuZXdWYWx1ZSAgdGhlIGd1YWdlIG5ldyB2YWx1ZVxuICAgICAqL1xuICAgIEBJbnB1dCgpXG4gICAgcHVibGljIHNldCB2YWx1ZShuZXdWYWx1ZTogbnVtYmVyKSB7XG5cbiAgICAgICAgLy8gY2FzZSBuZXcgZ2F1Z2UgdmFsdWUgYXMgcHJlSW5pdFZhbHVlIHVudGlsIHRoZSBnYXVnZSBpcyByZWFkeVxuICAgICAgICBpZiAoIXRoaXMuaXNJbml0ZWQpIHtcbiAgICAgICAgICAgIHRoaXMucHJlSW5pdFZhbHVlID0gbmV3VmFsdWU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnpvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5nYXVnZS52YWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgZ2F1Z2Ugb3B0aW9ucy4gRG8gbm90IHVzZSB1bnRpbCBhZnRlciBPblZpZXdJbml0KCkgYmVmb3JlIHVzaW5nLlxuICAgICAqXG4gICAgICogU3BlY2lhbCBpbXBsZW1lbnRhdGlvbiBub3RlIC0gb3B0aW9ucy5wcm9wZXJ0aWVzIGFyZSBtYWludGFpbmVkIGFzXG4gICAgICogYXR0cmlidXRlIG5hbWUtPnZhbHVlIG9uIHRoaXMgY29tcG9uZW50J3MgZWxlbWVudFJlZi4gIFRodXMgdGhpcyBtZXRob2RcbiAgICAgKiBtYXBzIGVhY2ggbmV3T3B0aW9ucyBwcm9wZXJ0eSBvbnRvIHRoZSBwcm9wZXJ0eSdzIGNvcnJlc3BvbmRpbmcgYXR0cmlidXRlLlxuICAgICAqIFRoZSBhdHRyaWJ1dGUgdXBkYXRlIHRyaWdnZXJzIGEgRE9NIG11dGF0aW9uIGV2ZW50IHdoaWNoICBcInRoaXNcIiBsaXN0ZW5zIGZvci5cbiAgICAgKiBTZWUgI2xpc3RlbkZvckRPTUV2ZW50cygpXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbmV3T3B0aW9ucyAgLSB0aGUgb3B0aW9ucyB0byB1cGRhdGUgdGhlIGdhdWdlXG4gICAgICovXG4gICAgcHVibGljIHVwZGF0ZShuZXdPcHRpb25zOiBUMiB8IHt9KSB7XG5cbiAgICAgICAgLy8gbWFwIGFsbCBvcHRpb25zIG9udG8gdGhpcyBlbGVtZW50J3MgYXR0cmlidXRlc1xuICAgICAgICAvLyBUaGVuIGF0dHJpYnV0ZSBjaGFuZ2VzIHdpbGwgYmUgZGV0ZWN0ZWQgYW5kIHB1c2hlZCB0byB0aGUgZ2F1Z2UudXBkYXRlKClcbiAgICAgICAgaWYgKCFuZXdPcHRpb25zKSB7IHJldHVybjsgfVxuXG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpmb3JpblxuICAgICAgICBmb3IgKGNvbnN0IHByb3AgaW4gbmV3T3B0aW9ucykge1xuICAgICAgICAgICAgY29uc3QgdmFsID0gbmV3T3B0aW9uc1twcm9wXS50b1N0cmluZygpO1xuXG4gICAgICAgICAgICBpZiAocHJvcCA9PT0gJ3ZhbHVlJykge1xuICAgICAgICAgICAgICAgIC8vIHNob3J0IGNpcmN1aXQgdGhlIHZhbHVlIHByb3BlcnR5IHVwZGF0ZSBieSBjYWxsaW5nXG4gICAgICAgICAgICAgICAgLy8gdGhlIGdhdWdlLnZhbHVlIGFwaSBkaXJlY3RseSBmb3IgZWZmaWNpZW50IGFuaW1hdGVkIHVwZGF0ZVxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSBDYW52YXNHYXVnZXMuRG9tT2JzZXJ2ZXIucGFyc2UodmFsKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYXR0ck5hbWUgPSB0b0tlYmFiQ2FzZShwcm9wKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCB2YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtIGdhdWdlIGluaXRpYWxpemF0aW9uLlxuICAgICAqIFN1YmNsYXNzZXMgdGhhdCBvdmVycmlkZSB0aGlzIG1ldGhvZCBtdXN0IHRoaXMgc3VwZXIgdmVyc2lvblxuICAgICAqIGZvciBwcm9wZXIgb3BlcmF0aW9uLlxuICAgICAqL1xuICAgIHB1YmxpYyBuZ0FmdGVyVmlld0luaXQoKSB7XG5cbiAgICAgICAgLy8gaW5pdGlhbCB1cGRhdGUgb2YgZ2F1Z2UgcHJvcGVydGllc1xuICAgICAgICB0aGlzLmluaXRHYXVnZSgpO1xuXG4gICAgICAgIHRoaXMubGlzdGVuRm9yRE9NRXZlbnRzKCk7XG5cbiAgICAgICAgdGhpcy5pc0luaXRlZCA9IHRydWU7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBMaXN0ZW4gZm9yIGF0dHJpYnV0ZS1jaGFuZ2UgZXZlbnRzIHRoYXQgYXJlIGNyZWF0ZWQgd2hlbiB1cGRhdGluZ1xuICAgICAqIHRoZSBvcHRpb25zIG9mIHRoaXMgZ2F1Z2UuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGxpc3RlbkZvckRPTUV2ZW50cygpIHtcbiAgICAgICAgLy8gTGlzdGVuIHRvIGdhdWdlIGVsZW1lbnQgZm9yIGF0dHJpYnV0ZSBjaGFuZ2VzXG4gICAgICAgIC8vIENvbnZlcnQgYWxsIGNoYW5nZWQgYXR0cmlidHVlcyBpbnRvIGEgR2VuZXJpY09wdGlvbnMgb3Igc3ViY2xhc3NcbiAgICAgICAgLy8gVXBkYXRlIHRoZSBnYXVnZSB3aXRoIHRoZSBuZXcgb3B0aW9ucy5cbiAgICAgICAgdGhpcy5kb21MaXN0ZW5lciA9XG4gICAgICAgICAgICBSeC5ET00uZnJvbU11dGF0aW9uT2JzZXJ2ZXIodGhpcy5lbC5uYXRpdmVFbGVtZW50LCB7IGF0dHJpYnV0ZXM6IHRydWUgfSkuXG4gICAgICAgICAgICAgICAgc3Vic2NyaWJlKGNoYW5nZXMgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdPcHRpb25zID0ge30gYXMgVDI7XG4gICAgICAgICAgICAgICAgICAgIGNoYW5nZXMuZm9yRWFjaChjaGFuZ2UgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCdhdHRyaWJ1dGVzJyA9PT0gY2hhbmdlLnR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnRE9NLCBjaGFuZ2UnLCBjaGFuZ2UuYXR0cmlidXRlTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3T3B0aW9uc1thdHRyaWJ1dGVOYW1lMlByb3BlcnR5TmFtZShjaGFuZ2UuYXR0cmlidXRlTmFtZSldID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2FudmFzR2F1Z2VzLkRvbU9ic2VydmVyLnBhcnNlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbC5uYXRpdmVFbGVtZW50LmdldEF0dHJpYnV0ZShjaGFuZ2UuYXR0cmlidXRlTmFtZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmJhc2ljVXBkYXRlKG5ld09wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogRGlzY29udGludWUgbGlzdGVuaW5nIGZvciBhdHRyaWJ1dGUgY2hhbmdlIGV2ZW50cy5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgc3RvcExpc3RlbmluZ0ZvckRPTUV2ZW50cygpIHtcbiAgICAgICAgaWYgKHRoaXMuZG9tTGlzdGVuZXIpIHtcbiAgICAgICAgICAgIHRoaXMuZG9tTGlzdGVuZXIuZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgdGhpcy5kb21MaXN0ZW5lciA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEluaXRhbGl6ZSB0aGUgZ2F1Z2Ugd2l0aCBhbGwgb3B0aW9ucyBkZWZpbmVkIGJ5IGF0dHJpYnV0ZXMgYW5kXG4gICAgICogcGFyZW50IGNvbXBvbmVudCBvcHRpb25zLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBpbml0R2F1Z2UoKSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG4gICAgICAgIGlmICh0aGlzLnByZUluaXRWYWx1ZSkge1xuICAgICAgICAgICAgb3B0aW9ucy52YWx1ZSA9IHRoaXMucHJlSW5pdFZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gaW5pdCBvcHRpb25zLnJlbmRlclRvIGlmIG5lZWRlZFxuICAgICAgICBpZiAoIW9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ3JlbmRlclRvJykgfHwgIW9wdGlvbnMucmVuZGVyVG8pIHtcbiAgICAgICAgICAgIG9wdGlvbnMucmVuZGVyVG8gPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5iYXNpY1VwZGF0ZShvcHRpb25zKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIFBlcmZvcm1zIHRoZSBnYXVnZSB1cGRhdGUgdXNpbmcgdGhlIGN1cnJlbnQgb3B0aW9uc1xuICAgICAqIEBwYXJhbSBvcHRpb25zICBUaGUgb3B0aW9ucyBmb3IgdGhlIGd1YWdlXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGJhc2ljVXBkYXRlKG9wdGlvbnM6IFQyKSB7XG5cbiAgICAgICAgLy8gdHJlYXQgdGhlIHZhbHVlIHByb3BlcnR5IHNwZWNpYWwgYW5kIHVwZGF0ZSBpdCB0aHJvdWdoIHRoZVxuICAgICAgICAvLyB2YWx1ZSBnZXR0ZXIuXG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy52YWx1ZSA9PT0gJ251bWJlcicpIHtcblxuICAgICAgICAgICAgLy8gdXNlIGdhdWdlIGFwaSBkaXJlY3RseSBmb3IgbW9zdCBlZmZpY2llbnQgdXBkYXRlIG1ldGhvZFxuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IG9wdGlvbnMudmFsdWU7XG5cbiAgICAgICAgICAgIC8vIGZpbHRlciB2YWx1ZSBwcm9wZXJ0eSBmcm9tIG9wdGlvbnMgdG8gYXZvaWQgcmVkdW5kYW50XG4gICAgICAgICAgICAvLyBwcm9jZXNzaW5nIGJ5IGdhdWdlXG4gICAgICAgICAgICBkZWxldGUgb3B0aW9ucy52YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGRvIG5vdGhpbmcgaWYgbm8gb3B0aW9uIHByb3BlcnRpZXMgdG8gdXBkYXRlXG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhvcHRpb25zKS5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMuZ2F1Z2UudXBkYXRlKG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfVxuXG59XG5cbi8vIFN0cmluZyB1dGlsc1xuY29uc3QgYXR0cmlidXRlTmFtZTJQcm9wZXJ0eU5hbWUgPSAoYXR0ck5hbWU6IHN0cmluZykgPT4gdG9DYW1lbENhc2UoYXR0ck5hbWUpO1xuXG5jb25zdCBwcm9wZXJ0eU5hbWUyQXR0ck5hbWUgPSAocHJvcE5hbWU6IHN0cmluZykgPT4gdG9LZWJhYkNhc2UocHJvcE5hbWUpO1xuXG5jb25zdCB0b0NhbWVsQ2FzZSA9IChzdHIpID0+IHN0ci5yZXBsYWNlKC8oXFwtXFx3KS9nLCAobSkgPT4gbVsxXS50b1VwcGVyQ2FzZSgpKTtcblxuY29uc3QgdG9LZWJhYkNhc2UgPSAoc3RyKSA9PiBzdHIucmVwbGFjZSgvKFthLXowLTldKShbQS1aXSkvZywgJyQxLSQyJykudG9Mb3dlckNhc2UoKTtcblxuXG4iXX0=