ng-canvas-gauges
Version:
Angular 6+ component wrapper for the canvas-gauges lib written by @Mikhus
465 lines (457 loc) • 16.1 kB
JavaScript
import { DOM } from 'rx-dom-html';
import { __values, __extends } from 'tslib';
import { ViewChild, Input, ElementRef, Component, NgZone, NgModule } from '@angular/core';
import { DomObserver, LinearGauge, RadialGauge } from 'canvas-gauges';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
// String utils
/** @type {?} */
var toCamelCase = (/**
* @param {?} str
* @return {?}
*/
function (str) { return str.replace(/(\-\w)/g, (/**
* @param {?} matches
* @return {?}
*/
function (matches) { return matches[1].toUpperCase(); })); });
/** @type {?} */
var toKebabCase = (/**
* @param {?} str
* @return {?}
*/
function (str) { return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase(); });
/** @type {?} */
var attributeName2PropertyName = (/**
* @param {?} attrName
* @return {?}
*/
function (attrName) { return toCamelCase(attrName); });
/**
* 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
*/
var BaseGauge = /** @class */ (function () {
/**
*
* @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
*/
function BaseGauge(el, zone) {
this.el = el;
this.zone = zone;
/**
* Flag indicating that OnViewInit life-cycle has completed
*/
this.isInited = false;
}
Object.defineProperty(BaseGauge.prototype, "options", {
/**
* Returns gauges properties as an options object.
* Option properties consist of the attribute-based properties and those
* explicitly set.
* @returns <T2>
*/
get: /**
* Returns gauges properties as an options object.
* Option properties consist of the attribute-based properties and those
* explicitly set.
* @return {?} <T2>
*/
function () {
var e_1, _a;
/** @type {?} */
var options = (/** @type {?} */ ({}));
options.renderTo = this.canvas.nativeElement;
try {
// Map attribute-based options onto options.
// Requries converting kebab style attribute names to camelCase property names
for (var _b = __values(this.el.nativeElement.attributes), _c = _b.next(); !_c.done; _c = _b.next()) {
var attr = _c.value;
/** @type {?} */
var prop = attributeName2PropertyName(attr.name);
options[prop] = DomObserver.parse(attr.value);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
// merge preOptons with attribute-based properties
// tslint:disable-next-line:forin
for (var 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
*/
set: /**
* Assign gauge options at anytime in the lifecycle.
* @param {?} newOptions - assign the style and size properties
* @return {?}
*/
function (newOptions) {
// cache newOptions as preInitOptions until gauge is ready
if (!this.isInited) {
this.preInitOptions = newOptions;
return;
}
this.update(newOptions);
},
enumerable: true,
configurable: true
});
Object.defineProperty(BaseGauge.prototype, "value", {
/**
* Assign the value of the gauge visual indicator such as a needle or pointer
* @param newValue the guage new value
*/
set: /**
* Assign the value of the gauge visual indicator such as a needle or pointer
* @param {?} newValue the guage new value
* @return {?}
*/
function (newValue) {
var _this = this;
// case new gauge value as preInitValue until the gauge is ready
if (!this.isInited) {
this.preInitValue = newValue;
return;
}
this.zone.runOutsideAngular((/**
* @return {?}
*/
function () {
_this.gauge.value = newValue;
}));
},
enumerable: true,
configurable: true
});
/**
* 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
*/
/**
* 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 {?}
*/
BaseGauge.prototype.update = /**
* 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 {?}
*/
function (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 (var prop in newOptions) {
/** @type {?} */
var 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 = DomObserver.parse(val);
}
else {
/** @type {?} */
var attrName = toKebabCase(prop);
this.el.nativeElement.setAttribute(attrName, val);
}
}
};
/**
* Perform gauge initialization.
* Subclasses that override this method must this super version
* for proper operation.
*/
/**
* Perform gauge initialization.
* Subclasses that override this method must this super version
* for proper operation.
* @return {?}
*/
BaseGauge.prototype.ngAfterViewInit = /**
* Perform gauge initialization.
* Subclasses that override this method must this super version
* for proper operation.
* @return {?}
*/
function () {
// 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.
*/
/**
* Listen for attribute-change events that are created when updating
* the options of this gauge.
* @protected
* @return {?}
*/
BaseGauge.prototype.listenForDOMEvents = /**
* Listen for attribute-change events that are created when updating
* the options of this gauge.
* @protected
* @return {?}
*/
function () {
var _this = this;
// 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 =
DOM.fromMutationObserver(this.el.nativeElement, { attributes: true }).
subscribe((/**
* @param {?} changes
* @return {?}
*/
function (changes) {
/** @type {?} */
var newOptions = (/** @type {?} */ ({}));
changes.forEach((/**
* @param {?} change
* @return {?}
*/
function (change) {
if ('attributes' === change.type) {
// console.log('DOM, change', change.attributeName);
newOptions[attributeName2PropertyName(change.attributeName)] =
DomObserver.parse(_this.el.nativeElement.getAttribute(change.attributeName));
}
}));
_this.basicUpdate(newOptions);
}));
};
/**
* Discontinue listening for attribute change events.
*/
/**
* Discontinue listening for attribute change events.
* @protected
* @return {?}
*/
BaseGauge.prototype.stopListeningForDOMEvents = /**
* Discontinue listening for attribute change events.
* @protected
* @return {?}
*/
function () {
if (this.domListener) {
this.domListener.disconnect();
this.domListener = null;
}
};
/**
* Initalize the gauge with all options defined by attributes and
* parent component options.
*/
/**
* Initalize the gauge with all options defined by attributes and
* parent component options.
* @protected
* @return {?}
*/
BaseGauge.prototype.initGauge = /**
* Initalize the gauge with all options defined by attributes and
* parent component options.
* @protected
* @return {?}
*/
function () {
/** @type {?} */
var 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
* @param options The options for the guage
*/
/**
* Performs the gauge update using the current options
* @protected
* @param {?} options The options for the guage
* @return {?}
*/
BaseGauge.prototype.basicUpdate = /**
* Performs the gauge update using the current options
* @protected
* @param {?} options The options for the guage
* @return {?}
*/
function (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 }]
};
return BaseGauge;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Implements Linear Gauge from the original library
*/
var LinearGauge$1 = /** @class */ (function (_super) {
__extends(LinearGauge$$1, _super);
function LinearGauge$$1(el, zone) {
return _super.call(this, el, zone) || this;
}
/**
* @return {?}
*/
LinearGauge$$1.prototype.ngOnInit = /**
* @return {?}
*/
function () {
this.gauge = new LinearGauge(this.options).draw();
};
LinearGauge$$1.decorators = [
{ type: Component, args: [{
// tslint:disable-next-line:component-selector
selector: 'linear-gauge',
template: '<canvas #gauge></canvas>'
}] }
];
/** @nocollapse */
LinearGauge$$1.ctorParameters = function () { return [
{ type: ElementRef },
{ type: NgZone }
]; };
return LinearGauge$$1;
}(BaseGauge));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* Implements Radial Gauge from the original library
*/
var RadialGauge$1 = /** @class */ (function (_super) {
__extends(RadialGauge$$1, _super);
function RadialGauge$$1(el, zone) {
return _super.call(this, el, zone) || this;
}
/**
* @return {?}
*/
RadialGauge$$1.prototype.ngOnInit = /**
* @return {?}
*/
function () {
this.gauge = new RadialGauge(this.options).draw();
};
RadialGauge$$1.decorators = [
{ type: Component, args: [{
// tslint:disable-next-line:component-selector
selector: 'radial-gauge',
template: '<canvas #gauge></canvas>'
}] }
];
/** @nocollapse */
RadialGauge$$1.ctorParameters = function () { return [
{ type: ElementRef },
{ type: NgZone }
]; };
return RadialGauge$$1;
}(BaseGauge));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var GaugesModule = /** @class */ (function () {
function GaugesModule() {
}
GaugesModule.decorators = [
{ type: NgModule, args: [{
declarations: [
LinearGauge$1,
RadialGauge$1
],
imports: [],
exports: [
LinearGauge$1,
RadialGauge$1
]
},] }
];
return GaugesModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
export { GaugesModule, LinearGauge$1 as LinearGauge, RadialGauge$1 as RadialGauge, BaseGauge as ɵa };
//# sourceMappingURL=ng-canvas-gauges.js.map