ng-canvas-gauges
Version:
Angular 6+ component wrapper for the canvas-gauges lib written by @Mikhus
327 lines • 30 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';
// String utils
/** @type {?} */
const toCamelCase = (/**
* @param {?} str
* @return {?}
*/
(str) => str.replace(/(\-\w)/g, (/**
* @param {?} matches
* @return {?}
*/
(matches) => matches[1].toUpperCase())));
const ɵ0 = toCamelCase;
/** @type {?} */
const toKebabCase = (/**
* @param {?} str
* @return {?}
*/
(str) => str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase());
const ɵ1 = toKebabCase;
/** @type {?} */
const attributeName2PropertyName = (/**
* @param {?} attrName
* @return {?}
*/
(attrName) => toCamelCase(attrName));
const ɵ2 = attributeName2PropertyName;
/**
* 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 () { };
}
export { ɵ0, ɵ1, ɵ2 };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1nYXVnZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25nLWNhbnZhcy1nYXVnZXMvIiwic291cmNlcyI6WyJsaWIvYmFzZS1nYXVnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF3QkEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQVUsVUFBVSxFQUF5QixNQUFNLGVBQWUsQ0FBQztBQUM1RixPQUFPLEtBQUssWUFBWSxNQUFNLGVBQWUsQ0FBQztBQUM5QyxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQzs7O01BSzVCLFdBQVc7Ozs7QUFBRyxDQUFDLEdBQVcsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxTQUFTOzs7O0FBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBQyxDQUFBOzs7TUFFNUYsV0FBVzs7OztBQUFHLENBQUMsR0FBVyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLG9CQUFvQixFQUFFLE9BQU8sQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFBOzs7TUFFdkYsMEJBQTBCOzs7O0FBQUcsQ0FBQyxRQUFnQixFQUFFLEVBQUUsQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUE7Ozs7Ozs7OztBQVU5RSxNQUFNLE9BQWdCLFNBQVM7Ozs7OztJQTRDM0IsWUFBb0IsRUFBYyxFQUFTLElBQVk7UUFBbkMsT0FBRSxHQUFGLEVBQUUsQ0FBWTtRQUFTLFNBQUksR0FBSixJQUFJLENBQVE7Ozs7UUF6Qi9DLGFBQVEsR0FBRyxLQUFLLENBQUM7SUEwQnpCLENBQUM7Ozs7Ozs7SUFlRCxJQUFXLE9BQU87O2NBRVIsT0FBTyxHQUFHLG1CQUFBLEVBQUUsRUFBTTtRQUN4QixPQUFPLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDO1FBRTdDLDRDQUE0QztR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QUMsS0FBSyxLQUFLLFFBQVEsRUFBRTtZQUVuQywwREFBMEQ7WUFDMUQsSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO1lBRTNCLHdEQUF3RDtZQUN4RCxzQkFBc0I7WUFDdEIsT0FBTyxPQUFPLENBQUMsS0FBSyxDQUFDO1NBQ3hCO1FBRUQsK0NBQStDO1FBQy9DLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUU7WUFDN0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDOUI7SUFDTCxDQUFDOzs7cUJBclBBLFNBQVMsU0FBQyxPQUFPO3NCQXNGakIsS0FBSztvQkFpQkwsS0FBSzs7Ozs7Ozs7SUF2R04sMkJBQzZCOzs7Ozs7O0lBTTdCLDBCQUFtQjs7Ozs7O0lBTW5CLDZCQUF5Qjs7Ozs7O0lBS3pCLGlDQUE2Qjs7Ozs7O0lBSzdCLG1DQUEyQjs7Ozs7OztJQU8zQixnQ0FBc0M7Ozs7O0lBUTFCLHVCQUFzQjs7SUFBRSx5QkFBbUI7Ozs7OztJQU92RCwrQ0FBMEIiLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIFRoZSBNSVQgTGljZW5zZSAoTUlUKVxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxNyBWbGFkIE1hcnR5bmVua28gPHZsYWRpbWlyLm1hcnR5bmVua28ud29ya0BnbWFpbC5jb20+XG4gKlxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuICogb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuICogaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuICogdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4gKiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4gKiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gKiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuICogQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbiAqIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG4gKiBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgeyBWaWV3Q2hpbGQsIElucHV0LCBOZ1pvbmUsIEVsZW1lbnRSZWYsIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0ICogYXMgQ2FudmFzR2F1Z2VzIGZyb20gJ2NhbnZhcy1nYXVnZXMnO1xuaW1wb3J0ICogYXMgUnggZnJvbSAncngtZG9tLWh0bWwnO1xuXG5cblxuLy8gU3RyaW5nIHV0aWxzXG5jb25zdCB0b0NhbWVsQ2FzZSA9IChzdHI6IHN0cmluZykgPT4gc3RyLnJlcGxhY2UoLyhcXC1cXHcpL2csIChtYXRjaGVzKSA9PiBtYXRjaGVzWzFdLnRvVXBwZXJDYXNlKCkpO1xuXG5jb25zdCB0b0tlYmFiQ2FzZSA9IChzdHI6IHN0cmluZykgPT4gc3RyLnJlcGxhY2UoLyhbYS16MC05XSkoW0EtWl0pL2csICckMS0kMicpLnRvTG93ZXJDYXNlKCk7XG5cbmNvbnN0IGF0dHJpYnV0ZU5hbWUyUHJvcGVydHlOYW1lID0gKGF0dHJOYW1lOiBzdHJpbmcpID0+IHRvQ2FtZWxDYXNlKGF0dHJOYW1lKTtcblxuXG5cblxuLyoqXG4gKiBCYXNlIGdhdWdlIGNvbXBvbmVudCBmb3IgdGhlIEdhdWdlcyByZW5kZXJpbmdcbiAqIFQgLSBUeXBlIG9mIHRoZSBHYXVnZSB0byBiZSByZW5kZXJlZCAoQ3VycmVudGx5IFJhZGlhbEdhdWdlLCBMaW5lYXJHYXVnZSBmcm9tIHRoZSBvcmlnaW5hbCBsaWJyYXJ5KVxuICogVDIgLSBUeXBlIG9mIGNvbmZpZyBvcHRpb25zIHVzZWQgYnkgdGhlIHBhcnRpY3VsYXIgZ2F1Z2UgKFJhZGlhbEdhdWdlT3B0aW9ucywgTGluZWFyR2F1Z2VPcHRpb25zKVxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQmFzZUdhdWdlPFQgZXh0ZW5kcyBDYW52YXNHYXVnZXMuQmFzZUdhdWdlLCBUMiBleHRlbmRzIENhbnZhc0dhdWdlcy5HZW5lcmljT3B0aW9ucz5cbiAgICBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG5cbiAgICAvKipcbiAgICAgKiBDYW52YXMgZWxlbWVudCBvbiB0aGUgdGVtcGxhdGUgdXNlZCBieSB0aGUgbGlicmFyeSB0byBkcmF3IGdhdWdlIGVsZW1lbnRcbiAgICAgKi9cbiAgICBAVmlld0NoaWxkKCdnYXVnZScpXG4gICAgcHJvdGVjdGVkIGNhbnZhczogRWxlbWVudFJlZjtcblxuICAgIC8qKlxuICAgICAqIEEgZ2F1Z2UgaW5zdGFuY2UgcmVzcG9uc2libGUgZm9yIHJlbmRlcmluZyBhbmQgdXBkYXRlcyBvbiB0aGUgY2FudmFzLlxuICAgICAqIFN1YmNsYXNzZXMgc2hvdWxkIGluaXRpYWxpemUgaW4gdGhlaXIgbmdPbkluaXQgaW1wbGVtZW50YXRpb24uXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGdhdWdlOiBUO1xuXG5cbiAgICAvKipcbiAgICAgKiBGbGFnIGluZGljYXRpbmcgdGhhdCBPblZpZXdJbml0IGxpZmUtY3ljbGUgaGFzIGNvbXBsZXRlZFxuICAgICAqL1xuICAgIHByaXZhdGUgaXNJbml0ZWQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIHZhbHVlIHByb3BlcnR5IG9mIGdhdWdlIHByaW9yIHRvIGNvbXBvbmVudCB2aWV3IGluaXRpYWxpemF0aW9uXG4gICAgICovXG4gICAgcHJpdmF0ZSBwcmVJbml0VmFsdWU6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIG9wdGlvbnMgcHJvcGVydHkgb2YgZ2F1Z2UgcHJpb3IgdG8gY29tcG9uZW50IHZpZXcgaW5pdGlhbGl6YXRpb25cbiAgICAgKi9cbiAgICBwcml2YXRlIHByZUluaXRPcHRpb25zOiBUMjtcblxuXG4gICAgLyoqXG4gICAgICogTGlzdGVuIGZvciBhdHRyaWJ1dGUgY2hhbmdlcywgaS5lLiwgb3B0aW9ucyBwcm9wZXJ0aWVzIHRoYXQgYXJlIHN0b3JlZFxuICAgICAqIGFzIGF0dHJpYnV0ZXMgb24gdGhpcyBFbGVtZW50UmVmXG4gICAgICovXG4gICAgcHJpdmF0ZSBkb21MaXN0ZW5lcjogTXV0YXRpb25PYnNlcnZlcjtcblxuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZWwgLSByZWZlcmVuY2UgdG8gdGhlIGVsZW1lbnQgb2YgdGhlIHdob2xlIGNvbXBvbmVudCwgdXNlZCB0byBzY3JhcGUgb3B0aW9ucyBkZWNsYXJlZCBvbiB0aGUgY29tcG9uZW50IGl0c2VsZlxuICAgICAqIEBwYXJhbSB6b25lIC0gcmVxdWlyZWQgdG8gcmVkcmF3IGdhdWdlIG91dHNpZGUgb2YgQW5ndWxhciwgZHVlIHRvIGFuaW1hdGlvbiBsYWdzIGNhdXNlZCBieSB0aGUgb3Zld3JpdHRlbiBmdW5jdGlvbiBvZiB0aGUgbmdab25lXG4gICAgICovXG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBlbDogRWxlbWVudFJlZiwgcHVibGljIHpvbmU6IE5nWm9uZSkge1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogU3ViY2xhc3NlcyBzaG91bGQgaW5zdGFudGlhdGUgdGhlIENhbnZhc0dhdWdlIG9iamVjdCBpbiB0aGUgY2hpbGQgY29tcG9uZW50XG4gICAgICovXG4gICAgYWJzdHJhY3QgbmdPbkluaXQoKTogdm9pZDtcblxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBnYXVnZXMgcHJvcGVydGllcyBhcyBhbiBvcHRpb25zIG9iamVjdC5cbiAgICAgKiBPcHRpb24gcHJvcGVydGllcyBjb25zaXN0IG9mIHRoZSBhdHRyaWJ1dGUtYmFzZWQgcHJvcGVydGllcyBhbmQgdGhvc2VcbiAgICAgKiBleHBsaWNpdGx5IHNldC5cbiAgICAgKiBAcmV0dXJucyA8VDI+XG4gICAgICovXG4gICAgcHVibGljIGdldCBvcHRpb25zKCk6IFQyIHtcblxuICAgICAgICBjb25zdCBvcHRpb25zID0ge30gYXMgVDI7XG4gICAgICAgIG9wdGlvbnMucmVuZGVyVG8gPSB0aGlzLmNhbnZhcy5uYXRpdmVFbGVtZW50O1xuXG4gICAgICAgIC8vIE1hcCBhdHRyaWJ1dGUtYmFzZWQgb3B0aW9ucyBvbnRvIG9wdGlvbnMuXG4gICAgICAgIC8vIFJlcXVyaWVzIGNvbnZlcnRpbmcga2ViYWIgc3R5bGUgYXR0cmlidXRlIG5hbWVzIHRvIGNhbWVsQ2FzZSBwcm9wZXJ0eSBuYW1lc1xuICAgICAgICBmb3IgKGNvbnN0IGF0dHIgb2YgdGhpcy5lbC5uYXRpdmVFbGVtZW50LmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHByb3AgPSBhdHRyaWJ1dGVOYW1lMlByb3BlcnR5TmFtZShhdHRyLm5hbWUpO1xuICAgICAgICAgICAgb3B0aW9uc1twcm9wXSA9IENhbnZhc0dhdWdlcy5Eb21PYnNlcnZlci5wYXJzZShhdHRyLnZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG1lcmdlIHByZU9wdG9ucyB3aXRoIGF0dHJpYnV0ZS1iYXNlZCBwcm9wZXJ0aWVzXG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpmb3JpblxuICAgICAgICBmb3IgKGNvbnN0IHByb3AgaW4gdGhpcy5wcmVJbml0T3B0aW9ucykge1xuICAgICAgICAgICAgb3B0aW9uc1twcm9wXSA9IHRoaXMucHJlSW5pdE9wdGlvbnNbcHJvcF07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjbGVhciB0aGUgcHJlSW5pdE9wdGlvbnMgYXMgdGhleSBoYXZlIGFscmVhZHkgYmVlbiBtZXJnZWRcbiAgICAgICAgLy8gd2l0aCB0aGUgYXR0cmlidXRlLWJhc2VkIHByb3BlcnRpZXNcbiAgICAgICAgaWYgKHRoaXMuaXNJbml0ZWQpIHtcbiAgICAgICAgICAgIHRoaXMucHJlSW5pdE9wdGlvbnMgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG9wdGlvbnM7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBBc3NpZ24gZ2F1Z2Ugb3B0aW9ucyBhdCBhbnl0aW1lIGluIHRoZSBsaWZlY3ljbGUuXG4gICAgICogQHBhcmFtIG5ld09wdGlvbnMgLSBhc3NpZ24gdGhlIHN0eWxlIGFuZCBzaXplIHByb3BlcnRpZXNcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBzZXQgb3B0aW9ucyhuZXdPcHRpb25zOiBUMikge1xuXG4gICAgICAgIC8vIGNhY2hlIG5ld09wdGlvbnMgYXMgcHJlSW5pdE9wdGlvbnMgdW50aWwgZ2F1Z2UgaXMgcmVhZHlcbiAgICAgICAgaWYgKCF0aGlzLmlzSW5pdGVkKSB7XG4gICAgICAgICAgICB0aGlzLnByZUluaXRPcHRpb25zID0gbmV3T3B0aW9ucztcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMudXBkYXRlKG5ld09wdGlvbnMpO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogQXNzaWduIHRoZSB2YWx1ZSBvZiB0aGUgZ2F1Z2UgdmlzdWFsIGluZGljYXRvciBzdWNoIGFzIGEgbmVlZGxlIG9yIHBvaW50ZXJcbiAgICAgKiBAcGFyYW0gbmV3VmFsdWUgIHRoZSBndWFnZSBuZXcgdmFsdWVcbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBzZXQgdmFsdWUobmV3VmFsdWU6IG51bWJlcikge1xuXG4gICAgICAgIC8vIGNhc2UgbmV3IGdhdWdlIHZhbHVlIGFzIHByZUluaXRWYWx1ZSB1bnRpbCB0aGUgZ2F1Z2UgaXMgcmVhZHlcbiAgICAgICAgaWYgKCF0aGlzLmlzSW5pdGVkKSB7XG4gICAgICAgICAgICB0aGlzLnByZUluaXRWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZ2F1Z2UudmFsdWUgPSBuZXdWYWx1ZTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIGdhdWdlIG9wdGlvbnMuIERvIG5vdCB1c2UgdW50aWwgYWZ0ZXIgT25WaWV3SW5pdCgpIGJlZm9yZSB1c2luZy5cbiAgICAgKlxuICAgICAqIFNwZWNpYWwgaW1wbGVtZW50YXRpb24gbm90ZSAtIG9wdGlvbnMucHJvcGVydGllcyBhcmUgbWFpbnRhaW5lZCBhc1xuICAgICAqIGF0dHJpYnV0ZSBuYW1lLT52YWx1ZSBvbiB0aGlzIGNvbXBvbmVudCdzIGVsZW1lbnRSZWYuICBUaHVzIHRoaXMgbWV0aG9kXG4gICAgICogbWFwcyBlYWNoIG5ld09wdGlvbnMgcHJvcGVydHkgb250byB0aGUgcHJvcGVydHkncyBjb3JyZXNwb25kaW5nIGF0dHJpYnV0ZS5cbiAgICAgKiBUaGUgYXR0cmlidXRlIHVwZGF0ZSB0cmlnZ2VycyBhIERPTSBtdXRhdGlvbiBldmVudCB3aGljaCAgXCJ0aGlzXCIgbGlzdGVucyBmb3IuXG4gICAgICogU2VlICNsaXN0ZW5Gb3JET01FdmVudHMoKVxuICAgICAqXG4gICAgICogQHBhcmFtIG5ld09wdGlvbnMgIC0gdGhlIG9wdGlvbnMgdG8gdXBkYXRlIHRoZSBnYXVnZVxuICAgICAqL1xuICAgIHB1YmxpYyB1cGRhdGUobmV3T3B0aW9uczogVDIgfCB7fSkge1xuXG4gICAgICAgIC8vIG1hcCBhbGwgb3B0aW9ucyBvbnRvIHRoaXMgZWxlbWVudCdzIGF0dHJpYnV0ZXNcbiAgICAgICAgLy8gVGhlbiBhdHRyaWJ1dGUgY2hhbmdlcyB3aWxsIGJlIGRldGVjdGVkIGFuZCBwdXNoZWQgdG8gdGhlIGdhdWdlLnVwZGF0ZSgpXG4gICAgICAgIGlmICghbmV3T3B0aW9ucykgeyByZXR1cm47IH1cblxuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6Zm9yaW5cbiAgICAgICAgZm9yIChjb25zdCBwcm9wIGluIG5ld09wdGlvbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbCA9IG5ld09wdGlvbnNbcHJvcF0udG9TdHJpbmcoKTtcblxuICAgICAgICAgICAgaWYgKHByb3AgPT09ICd2YWx1ZScpIHtcbiAgICAgICAgICAgICAgICAvLyBzaG9ydCBjaXJjdWl0IHRoZSB2YWx1ZSBwcm9wZXJ0eSB1cGRhdGUgYnkgY2FsbGluZ1xuICAgICAgICAgICAgICAgIC8vIHRoZSBnYXVnZS52YWx1ZSBhcGkgZGlyZWN0bHkgZm9yIGVmZmljaWVudCBhbmltYXRlZCB1cGRhdGVcbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gQ2FudmFzR2F1Z2VzLkRvbU9ic2VydmVyLnBhcnNlKHZhbCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGF0dHJOYW1lID0gdG9LZWJhYkNhc2UocHJvcCk7XG4gICAgICAgICAgICAgICAgdGhpcy5lbC5uYXRpdmVFbGVtZW50LnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgdmFsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogUGVyZm9ybSBnYXVnZSBpbml0aWFsaXphdGlvbi5cbiAgICAgKiBTdWJjbGFzc2VzIHRoYXQgb3ZlcnJpZGUgdGhpcyBtZXRob2QgbXVzdCB0aGlzIHN1cGVyIHZlcnNpb25cbiAgICAgKiBmb3IgcHJvcGVyIG9wZXJhdGlvbi5cbiAgICAgKi9cbiAgICBwdWJsaWMgbmdBZnRlclZpZXdJbml0KCkge1xuXG4gICAgICAgIC8vIGluaXRpYWwgdXBkYXRlIG9mIGdhdWdlIHByb3BlcnRpZXNcbiAgICAgICAgdGhpcy5pbml0R2F1Z2UoKTtcblxuICAgICAgICB0aGlzLmxpc3RlbkZvckRPTUV2ZW50cygpO1xuXG4gICAgICAgIHRoaXMuaXNJbml0ZWQgPSB0cnVlO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogTGlzdGVuIGZvciBhdHRyaWJ1dGUtY2hhbmdlIGV2ZW50cyB0aGF0IGFyZSBjcmVhdGVkIHdoZW4gdXBkYXRpbmdcbiAgICAgKiB0aGUgb3B0aW9ucyBvZiB0aGlzIGdhdWdlLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBsaXN0ZW5Gb3JET01FdmVudHMoKSB7XG4gICAgICAgIC8vIExpc3RlbiB0byBnYXVnZSBlbGVtZW50IGZvciBhdHRyaWJ1dGUgY2hhbmdlc1xuICAgICAgICAvLyBDb252ZXJ0IGFsbCBjaGFuZ2VkIGF0dHJpYnR1ZXMgaW50byBhIEdlbmVyaWNPcHRpb25zIG9yIHN1YmNsYXNzXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgZ2F1Z2Ugd2l0aCB0aGUgbmV3IG9wdGlvbnMuXG4gICAgICAgIHRoaXMuZG9tTGlzdGVuZXIgPVxuICAgICAgICAgICAgUnguRE9NLmZyb21NdXRhdGlvbk9ic2VydmVyKHRoaXMuZWwubmF0aXZlRWxlbWVudCwgeyBhdHRyaWJ1dGVzOiB0cnVlIH0pLlxuICAgICAgICAgICAgICAgIHN1YnNjcmliZShjaGFuZ2VzID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV3T3B0aW9ucyA9IHt9IGFzIFQyO1xuICAgICAgICAgICAgICAgICAgICBjaGFuZ2VzLmZvckVhY2goY2hhbmdlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgnYXR0cmlidXRlcycgPT09IGNoYW5nZS50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJ0RPTSwgY2hhbmdlJywgY2hhbmdlLmF0dHJpYnV0ZU5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld09wdGlvbnNbYXR0cmlidXRlTmFtZTJQcm9wZXJ0eU5hbWUoY2hhbmdlLmF0dHJpYnV0ZU5hbWUpXSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENhbnZhc0dhdWdlcy5Eb21PYnNlcnZlci5wYXJzZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWwubmF0aXZlRWxlbWVudC5nZXRBdHRyaWJ1dGUoY2hhbmdlLmF0dHJpYnV0ZU5hbWUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5iYXNpY1VwZGF0ZShuZXdPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIERpc2NvbnRpbnVlIGxpc3RlbmluZyBmb3IgYXR0cmlidXRlIGNoYW5nZSBldmVudHMuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHN0b3BMaXN0ZW5pbmdGb3JET01FdmVudHMoKSB7XG4gICAgICAgIGlmICh0aGlzLmRvbUxpc3RlbmVyKSB7XG4gICAgICAgICAgICB0aGlzLmRvbUxpc3RlbmVyLmRpc2Nvbm5lY3QoKTtcbiAgICAgICAgICAgIHRoaXMuZG9tTGlzdGVuZXIgPSBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBJbml0YWxpemUgdGhlIGdhdWdlIHdpdGggYWxsIG9wdGlvbnMgZGVmaW5lZCBieSBhdHRyaWJ1dGVzIGFuZFxuICAgICAqIHBhcmVudCBjb21wb25lbnQgb3B0aW9ucy5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgaW5pdEdhdWdlKCkge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgICBpZiAodGhpcy5wcmVJbml0VmFsdWUpIHtcbiAgICAgICAgICAgIG9wdGlvbnMudmFsdWUgPSB0aGlzLnByZUluaXRWYWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGluaXQgb3B0aW9ucy5yZW5kZXJUbyBpZiBuZWVkZWRcbiAgICAgICAgaWYgKCFvcHRpb25zLmhhc093blByb3BlcnR5KCdyZW5kZXJUbycpIHx8ICFvcHRpb25zLnJlbmRlclRvKSB7XG4gICAgICAgICAgICBvcHRpb25zLnJlbmRlclRvID0gdGhpcy5jYW52YXMubmF0aXZlRWxlbWVudDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuYmFzaWNVcGRhdGUob3B0aW9ucyk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtcyB0aGUgZ2F1Z2UgdXBkYXRlIHVzaW5nIHRoZSBjdXJyZW50IG9wdGlvbnNcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAgVGhlIG9wdGlvbnMgZm9yIHRoZSBndWFnZVxuICAgICAqL1xuICAgIHByb3RlY3RlZCBiYXNpY1VwZGF0ZShvcHRpb25zOiBUMikge1xuXG4gICAgICAgIC8vIHRyZWF0IHRoZSB2YWx1ZSBwcm9wZXJ0eSBzcGVjaWFsIGFuZCB1cGRhdGUgaXQgdGhyb3VnaCB0aGVcbiAgICAgICAgLy8gdmFsdWUgZ2V0dGVyLlxuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMudmFsdWUgPT09ICdudW1iZXInKSB7XG5cbiAgICAgICAgICAgIC8vIHVzZSBnYXVnZSBhcGkgZGlyZWN0bHkgZm9yIG1vc3QgZWZmaWNpZW50IHVwZGF0ZSBtZXRob2RcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBvcHRpb25zLnZhbHVlO1xuXG4gICAgICAgICAgICAvLyBmaWx0ZXIgdmFsdWUgcHJvcGVydHkgZnJvbSBvcHRpb25zIHRvIGF2b2lkIHJlZHVuZGFudFxuICAgICAgICAgICAgLy8gcHJvY2Vzc2luZyBieSBnYXVnZVxuICAgICAgICAgICAgZGVsZXRlIG9wdGlvbnMudmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBkbyBub3RoaW5nIGlmIG5vIG9wdGlvbiBwcm9wZXJ0aWVzIHRvIHVwZGF0ZVxuICAgICAgICBpZiAoT2JqZWN0LmtleXMob3B0aW9ucykubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLmdhdWdlLnVwZGF0ZShvcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH1cblxufVxuXG5cblxuIl19