@amcharts/amcharts5
Version:
amCharts 5
361 lines • 11.8 kB
JavaScript
import { __awaiter } from "tslib";
import { Settings } from "../util/Entity";
import { Container } from "./Container";
import { ListData } from "../util/Data";
import * as $array from "../util/Array";
import * as $object from "../util/Object";
/**
* A base element that holds data bit (data item) for any [[Component]].
*/
export class DataItem extends Settings {
constructor(component, dataContext, settings) {
super(settings);
this.dataContext = dataContext;
this.component = component;
this._settings.visible = true;
this._checkDirty();
}
/**
* @ignore
*/
markDirty() {
this.component.markDirtyValues(this);
}
_startAnimation() {
this.component._root._addAnimation(this);
}
_animationTime() {
return this.component._root.animationTime;
}
_dispose() {
if (this.component) {
this.component.disposeDataItem(this);
}
super._dispose();
}
/**
* Shows a data item that's currently hidden.
*/
show(duration) {
this.setRaw("visible", true);
if (this.component) {
this.component.showDataItem(this, duration);
}
}
/**
* Hides a data item that's currently visible.
*/
hide(duration) {
this.setRaw("visible", false);
if (this.component) {
this.component.hideDataItem(this, duration);
}
}
isHidden() {
return !this.get("visible");
}
}
/**
* A base class for elements that make use of data.
*/
export class Component extends Container {
constructor() {
super(...arguments);
this._data = new ListData();
this._dataItems = [];
this._mainDataItems = this._dataItems;
this.valueFields = [];
this.fields = ["id"];
this._valuesDirty = false;
this._dataChanged = false;
this._dataGrouped = false;
/**
* Indicates if the component has already been initialized.
*/
this.inited = false;
}
/**
* Component's data.
*
* @see {@link https://www.amcharts.com/docs/v5/concepts/data/} for more info
*/
set data(data) {
data.incrementRef();
this._data.decrementRef();
this._data = data;
}
/**
* @return Data
*/
get data() {
return this._data;
}
_dispose() {
super._dispose();
this._data.decrementRef();
}
_onDataClear() {
}
_afterNew() {
super._afterNew();
this._data.incrementRef();
this._updateFields();
this._disposers.push(this.data.events.onAll((change) => {
const dataItems = this._mainDataItems;
this.markDirtyValues();
this._markDirtyGroup();
this._dataChanged = true;
if (change.type === "clear") {
$array.each(dataItems, (dataItem) => {
dataItem.dispose();
});
dataItems.length = 0;
this._onDataClear();
}
else if (change.type === "push") {
const dataItem = new DataItem(this, change.newValue, this._makeDataItem(change.newValue));
dataItems.push(dataItem);
this.processDataItem(dataItem);
}
else if (change.type === "setIndex") {
const dataItem = dataItems[change.index];
const properties = this._makeDataItem(change.newValue);
if (dataItem.bullets && dataItem.bullets.length == 0) {
dataItem.bullets = undefined;
}
$object.entries(properties).forEach(([key, value]) => {
if (dataItem.get(key) == value) {
return;
}
dataItem.animate({
key: key,
to: value,
duration: this.get("interpolationDuration", 0),
easing: this.get("interpolationEasing"),
});
});
dataItem.dataContext = change.newValue;
}
else if (change.type === "insertIndex") {
const dataItem = new DataItem(this, change.newValue, this._makeDataItem(change.newValue));
dataItems.splice(change.index, 0, dataItem);
this.processDataItem(dataItem);
}
else if (change.type === "removeIndex") {
const dataItem = dataItems[change.index];
dataItem.dispose();
dataItems.splice(change.index, 1);
}
else if (change.type === "moveIndex") {
const dataItem = dataItems[change.oldIndex];
dataItems.splice(change.oldIndex, 1);
dataItems.splice(change.newIndex, 0, dataItem);
}
else {
throw new Error("Unknown IStreamEvent type");
}
this._afterDataChange();
}));
}
_postUpdateData() {
}
/**
* Updates existing data in the component without disposing old data items. If there are more data items than before, new ones will be created. If there are less, old ones will be removed.
* @param data
*/
updateData(data) {
let ii = 0;
$array.each(data, (dataObject, index) => {
const dataItem = this.dataItems[index];
if (!dataItem) {
this.data.push(dataObject);
}
else {
const dataContext = dataItem.dataContext;
if (dataContext) {
$object.entries(dataObject).forEach(([key, value]) => {
dataContext[key] = value;
});
}
const properties = this._makeDataItem(dataContext);
$object.entries(properties).forEach(([key, value]) => {
var _a;
if (dataItem.get(key) != value) {
dataItem.set(key, value);
const workingKey = (_a = this._valueFieldsF[key]) === null || _a === void 0 ? void 0 : _a.workingKey;
if (workingKey) {
dataItem.set(workingKey, value);
}
}
});
}
ii = index;
});
for (let i = this.dataItems.length - 1; i > ii; i--) {
const dataItem = this.dataItems[i];
$array.remove(this.dataItems, dataItem);
dataItem.dispose();
}
this._postUpdateData();
}
_updateFields() {
if (this.valueFields) {
this._valueFields = [];
this._valueFieldsF = {};
$array.each(this.valueFields, (key) => {
const field = this.get((key + "Field"));
if (field) {
this._valueFields.push(key);
this._valueFieldsF[key] = { fieldKey: key + "Field", workingKey: key + "Working" };
}
});
}
if (this.fields) {
this._fields = [];
this._fieldsF = {};
$array.each(this.fields, (key) => {
const field = this.get((key + "Field"));
if (field) {
this._fields.push(key);
this._fieldsF[key] = key + "Field";
}
});
}
}
/**
* A list of component's data items.
*
* @return Data items
*/
get dataItems() {
return this._dataItems;
}
processDataItem(_dataItem) { }
_makeDataItem(data) {
//const output: this["_dataItemSettings"] = {};
const output = {}; // temporary to solve error
if (this._valueFields) {
$array.each(this._valueFields, (key) => {
const field = this.get((this._valueFieldsF[key].fieldKey));
output[key] = data[field];
output[this._valueFieldsF[key].workingKey] = output[key];
});
}
if (this._fields) {
$array.each(this._fields, (key) => {
const field = this.get((this._fieldsF[key]));
output[key] = data[field];
});
}
return output;
}
/**
* Creates a new data item and processes it.
*
* @param data Data item settings
* @param dataContext Data context
* @return New data item
*/
makeDataItem(data, dataContext) {
let dataItem = new DataItem(this, dataContext, data);
this.processDataItem(dataItem);
return dataItem;
}
/**
* Adds new explicit data item to series.
*
* @param data Data item settings
* @param dataContext Data context
* @return New data item
*/
pushDataItem(data, dataContext) {
const dataItem = this.makeDataItem(data, dataContext);
this._mainDataItems.push(dataItem);
return dataItem;
}
/**
* @ignore
*/
disposeDataItem(_dataItem) {
}
/**
* Shows component's data item.
*
* @param dataItem Data item
* @param _duration Animation duration in milliseconds
* @return Promise
*/
showDataItem(dataItem, _duration) {
return __awaiter(this, void 0, void 0, function* () {
dataItem.set("visible", true);
});
}
/**
* Hides component's data item.
*
* @param dataItem Data item
* @param _duration Animation duration in milliseconds
* @return Promise
*/
hideDataItem(dataItem, _duration) {
return __awaiter(this, void 0, void 0, function* () {
dataItem.set("visible", false);
});
}
_clearDirty() {
super._clearDirty();
this._valuesDirty = false;
}
_afterDataChange() {
}
_afterChanged() {
super._afterChanged();
if (this._dataChanged) {
const type = "datavalidated";
if (this.events.isEnabled(type)) {
this.events.dispatch(type, { type: type, target: this });
}
this._dataChanged = false;
}
if (this._valuesDirty) {
const type = "valueschanged";
if (this.events.isEnabled(type)) {
this.events.dispatch(type, { type: type, target: this });
}
}
this.inited = true;
}
/**
* Forces a repaint of the element which relies on data.
*
* @since 5.0.21
*/
markDirtyValues(_dataItem) {
this.markDirty();
this._valuesDirty = true;
}
_markDirtyGroup() {
this._dataGrouped = false;
}
/**
* @ignore
*/
markDirtySize() {
this._sizeDirty = true;
this.markDirty();
}
/**
* Looks up and returns a data item by its ID.
*
* @param id ID
* @return Data item
*/
getDataItemById(id) {
return $array.find(this.dataItems, (dataItem) => {
return dataItem.get("id") == id;
});
}
}
Component.className = "Component";
Component.classNames = Container.classNames.concat([Component.className]);
//# sourceMappingURL=Component.js.map