tsichart-core 1.0.5 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -22
- package/README.md +80 -0
- package/dist/index.d.ts +1744 -0
- package/dist/index.js +14284 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +14209 -0
- package/dist/index.mjs.map +1 -0
- package/dist/{tsiclient.css → styles/index.css} +9498 -9497
- package/dist/styles/index.css.map +1 -0
- package/package.json +115 -124
- package/README.MD +0 -171
- package/dist/AggregateExpression.d.ts +0 -13
- package/dist/AggregateExpression.js +0 -70
- package/dist/AvailabilityChart-C8ewvn3T.js +0 -488
- package/dist/AvailabilityChart.d.ts +0 -59
- package/dist/AvailabilityChart.js +0 -26
- package/dist/ChartComponent-Dg8P-BTZ.js +0 -302
- package/dist/ChartComponent-ONNW31RL.d.ts +0 -80
- package/dist/ChartComponentData-DBW8_FnY.d.ts +0 -47
- package/dist/ChartDataOptions-CNTSB636.js +0 -49
- package/dist/ChartDataOptions-D0BJuRZy.d.ts +0 -38
- package/dist/ChartVisualizationComponent-CTs5Q_sg.js +0 -23
- package/dist/ChartVisualizationComponent-CpR8xZla.d.ts +0 -8
- package/dist/ColorPicker-0p6vkATj.js +0 -120
- package/dist/ColorPicker.d.ts +0 -28
- package/dist/ColorPicker.js +0 -6
- package/dist/Component-BgifJdKl.js +0 -401
- package/dist/Component-DXwYPoSo.d.ts +0 -226
- package/dist/ContextMenu-wqGGgAzp.js +0 -197
- package/dist/DateTimeButton-D7N8XG0S.js +0 -38
- package/dist/DateTimeButton-DfJL5kvr.d.ts +0 -16
- package/dist/DateTimeButtonRange-BM_J646m.js +0 -71
- package/dist/DateTimeButtonRange.d.ts +0 -19
- package/dist/DateTimeButtonRange.js +0 -15
- package/dist/DateTimeButtonSingle-BxMSitQG.js +0 -48
- package/dist/DateTimeButtonSingle.d.ts +0 -17
- package/dist/DateTimeButtonSingle.js +0 -14
- package/dist/DateTimePicker-BgTi-DY9.js +0 -532
- package/dist/DateTimePicker.d.ts +0 -69
- package/dist/DateTimePicker.js +0 -13
- package/dist/EllipsisMenu-CxJ0LoVm.js +0 -116
- package/dist/EllipsisMenu.d.ts +0 -20
- package/dist/EllipsisMenu.js +0 -6
- package/dist/Enums-DWpaQlXk.d.ts +0 -12
- package/dist/EventsTable-CsnBvvIW.js +0 -553
- package/dist/EventsTable.d.ts +0 -34
- package/dist/EventsTable.js +0 -10
- package/dist/GeoProcessGraphic-CUBMHIHX.js +0 -145
- package/dist/GeoProcessGraphic.d.ts +0 -34
- package/dist/GeoProcessGraphic.js +0 -7
- package/dist/Grid-uoHKTet9.js +0 -874
- package/dist/Grid.d.ts +0 -43
- package/dist/Grid.js +0 -6
- package/dist/GroupedBarChart-Bc3cGhgz.js +0 -579
- package/dist/GroupedBarChart.d.ts +0 -22
- package/dist/GroupedBarChart.js +0 -17
- package/dist/GroupedBarChartData-B7BTM9JH.d.ts +0 -20
- package/dist/GroupedBarChartData-Ml5JJimg.js +0 -121
- package/dist/Heatmap-5gFc_AVW.js +0 -524
- package/dist/Heatmap.d.ts +0 -31
- package/dist/Heatmap.js +0 -14
- package/dist/Hierarchy-C5ueDsus.js +0 -260
- package/dist/Hierarchy.d.ts +0 -39
- package/dist/Hierarchy.js +0 -6
- package/dist/HierarchyNavigation-C3Pwt0D6.js +0 -336
- package/dist/HierarchyNavigation.d.ts +0 -34
- package/dist/HierarchyNavigation.js +0 -6
- package/dist/HistoryPlayback-D09bter3.js +0 -175
- package/dist/HistoryPlayback-DmJ6u7lU.d.ts +0 -68
- package/dist/Interfaces-R_1l9lIT.d.ts +0 -6
- package/dist/Legend-gCIrAytG.js +0 -497
- package/dist/LineChart-CzDp5ULB.js +0 -3181
- package/dist/LineChart.d.ts +0 -163
- package/dist/LineChart.js +0 -18
- package/dist/ModelAutocomplete-lU71Ndju.js +0 -100
- package/dist/ModelAutocomplete.d.ts +0 -12
- package/dist/ModelAutocomplete.js +0 -7
- package/dist/ModelSearch-OF4DygOJ.js +0 -189
- package/dist/ModelSearch.d.ts +0 -23
- package/dist/ModelSearch.js +0 -9
- package/dist/PieChart-XLc9Itne.js +0 -258
- package/dist/PieChart.d.ts +0 -26
- package/dist/PieChart.js +0 -17
- package/dist/PlaybackControls-DbG9gExy.js +0 -195
- package/dist/PlaybackControls.d.ts +0 -39
- package/dist/PlaybackControls.js +0 -13
- package/dist/ProcessGraphic-Cft1b4Mf.js +0 -154
- package/dist/ProcessGraphic.d.ts +0 -31
- package/dist/ProcessGraphic.js +0 -7
- package/dist/ScatterPlot-CdnqSHq2.js +0 -924
- package/dist/ScatterPlot.d.ts +0 -115
- package/dist/ScatterPlot.js +0 -17
- package/dist/SingleDateTimePicker-Ddr-ogTk.js +0 -213
- package/dist/SingleDateTimePicker.d.ts +0 -45
- package/dist/SingleDateTimePicker.js +0 -12
- package/dist/Slider-CX0nvlqx.js +0 -186
- package/dist/Slider.d.ts +0 -31
- package/dist/Slider.js +0 -6
- package/dist/TemporalXAxisComponent-DXmMekYq.js +0 -129
- package/dist/TemporalXAxisComponent-PIeiJYUr.d.ts +0 -23
- package/dist/TimezonePicker-CQpXR5eb.js +0 -58
- package/dist/TimezonePicker.d.ts +0 -16
- package/dist/TimezonePicker.js +0 -10
- package/dist/Tooltip-C13k0eeH.js +0 -104
- package/dist/TsqExpression.d.ts +0 -36
- package/dist/TsqExpression.js +0 -89
- package/dist/UXClient-Bn1afElm.js +0 -230
- package/dist/UXClient.d.ts +0 -74
- package/dist/UXClient.js +0 -47
- package/dist/Utils-BcQeZOM3.d.ts +0 -104
- package/dist/Utils-DDGqSryb.js +0 -1138
- package/dist/Utils.d.ts +0 -7
- package/dist/Utils.js +0 -7
- package/dist/_tslib-BYFmvNeL.js +0 -96
- package/dist/pikaday-jh_aVtJs.js +0 -1252
- package/dist/tsiclient.cjs.js +0 -3
- package/dist/tsiclient.cjs.js.LICENSE.txt +0 -19
- package/dist/tsiclient.cjs.js.map +0 -1
- package/dist/tsiclient.d.ts +0 -46
- package/dist/tsiclient.esm.js +0 -3
- package/dist/tsiclient.esm.js.LICENSE.txt +0 -19
- package/dist/tsiclient.esm.js.map +0 -1
- package/dist/tsiclient.js +0 -58
- package/dist/tsiclient.min.css +0 -6
- package/dist/tsiclient.min.css.map +0 -1
- package/dist/tsiclient.umd.js +0 -3
- package/dist/tsiclient.umd.js.LICENSE.txt +0 -19
- package/dist/tsiclient.umd.js.map +0 -1
- package/dist/tsiclient.umd.min.js +0 -3
- package/dist/tsiclient.umd.min.js.LICENSE.txt +0 -19
- package/dist/tsiclient.umd.min.js.map +0 -1
- package/tsiclient.css +0 -17323
- package/tsiclient.d.ts +0 -46
- package/tsiclient.js +0 -58
- package/tsiclient.min.css +0 -6
|
@@ -1,924 +0,0 @@
|
|
|
1
|
-
import { _ as __extends } from './_tslib-BYFmvNeL.js';
|
|
2
|
-
import * as d3 from 'd3';
|
|
3
|
-
import * as d3Voronoi from 'd3-voronoi';
|
|
4
|
-
import { C as ChartVisualizationComponent } from './ChartVisualizationComponent-CTs5Q_sg.js';
|
|
5
|
-
import { L as Legend } from './Legend-gCIrAytG.js';
|
|
6
|
-
import { C as ChartComponentData } from './Grid-uoHKTet9.js';
|
|
7
|
-
import { G as GroupedBarChartData } from './GroupedBarChartData-Ml5JJimg.js';
|
|
8
|
-
import { U as Utils, T as TooltipMeasureFormat } from './Utils-DDGqSryb.js';
|
|
9
|
-
import { T as Tooltip } from './Tooltip-C13k0eeH.js';
|
|
10
|
-
import { S as Slider } from './Slider-CX0nvlqx.js';
|
|
11
|
-
|
|
12
|
-
var ScatterPlotData = /** @class */ (function (_super) {
|
|
13
|
-
__extends(ScatterPlotData, _super);
|
|
14
|
-
function ScatterPlotData() {
|
|
15
|
-
var _this = _super.call(this) || this;
|
|
16
|
-
_this.extents = {};
|
|
17
|
-
_this.extentsSet = false;
|
|
18
|
-
return _this;
|
|
19
|
-
}
|
|
20
|
-
/******** SETS EXTENT OF EACH DATA MEASURE -- MEASURES UPDATED WHEN RENDER CALLED OUTSIDE OF TEMPORAL ********/
|
|
21
|
-
ScatterPlotData.prototype.setExtents = function (measures, forceReset) {
|
|
22
|
-
var _this = this;
|
|
23
|
-
if (forceReset === void 0) { forceReset = false; }
|
|
24
|
-
if (!this.extentsSet || forceReset) {
|
|
25
|
-
// Reset extents
|
|
26
|
-
this.extents = {};
|
|
27
|
-
// Set axis extents
|
|
28
|
-
measures.forEach(function (measure) {
|
|
29
|
-
_this.extents[measure] = d3.extent(_this.allValues, function (v) {
|
|
30
|
-
if (!v.measures)
|
|
31
|
-
return null;
|
|
32
|
-
return measure in v.measures ? v.measures[measure] : null;
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
this.extentsSet = true;
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
/******** UPDATE EXTENTS BASED ON VISIBLE DATA ********/
|
|
39
|
-
ScatterPlotData.prototype.updateExtents = function (measures) {
|
|
40
|
-
var _this = this;
|
|
41
|
-
var visibleData = [];
|
|
42
|
-
this.data.forEach(function (aggregate) {
|
|
43
|
-
var aggName = Object.keys(aggregate)[0];
|
|
44
|
-
var aggKey = aggregate.aggKey;
|
|
45
|
-
if (_this.displayState[aggKey].visible == true) {
|
|
46
|
-
Object.keys(aggregate[aggName]).forEach(function (splitBy) {
|
|
47
|
-
if (_this.displayState[aggKey].splitBys[splitBy].visible == true) {
|
|
48
|
-
visibleData.push(Object.values(aggregate[aggName][splitBy]));
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
visibleData = [].concat.apply([], visibleData);
|
|
54
|
-
measures.forEach(function (measure) {
|
|
55
|
-
_this.extents[measure] = d3.extent(visibleData, function (v) {
|
|
56
|
-
return measure in v ? v[measure] : null;
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
};
|
|
60
|
-
/******** UPDATES CHART DATA, ALL TIMESTAMPS, AND VALUES AT THE CURRENT TIMESTAMP ********/
|
|
61
|
-
ScatterPlotData.prototype.mergeDataToDisplayStateAndTimeArrays = function (data, timestamp, aggregateExpressionOptions) {
|
|
62
|
-
if (aggregateExpressionOptions === void 0) { aggregateExpressionOptions = null; }
|
|
63
|
-
ChartComponentData.prototype.mergeDataToDisplayStateAndTimeArrays.call(this, data, aggregateExpressionOptions);
|
|
64
|
-
this.timestamp = (timestamp != undefined && this.allTimestampsArray.indexOf(timestamp) !== -1) ? timestamp : this.allTimestampsArray[0];
|
|
65
|
-
this.setValuesAtTimestamp();
|
|
66
|
-
this.setAllTimestampsArray();
|
|
67
|
-
};
|
|
68
|
-
/******** UPDATES DATA TO BE DRAWN -- IF SCATTER IS TEMPORAL, FLATTENS ALL TIMESTAMP DATA ********/
|
|
69
|
-
ScatterPlotData.prototype.updateTemporalDataArray = function (isTemporal) {
|
|
70
|
-
var _this = this;
|
|
71
|
-
this.temporalDataArray = [];
|
|
72
|
-
if (!isTemporal) {
|
|
73
|
-
this.allTimestampsArray.forEach(function (ts) {
|
|
74
|
-
_this.timestamp = ts;
|
|
75
|
-
_this.setValuesAtTimestamp();
|
|
76
|
-
_this.updateTemporal();
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
this.updateTemporal();
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
/******** HELPER TO FETCH DATA AT THE CURRENT TIMESTAMP AND BUILD AN OBJECT FOR THAT TIMESTAMP ********/
|
|
84
|
-
ScatterPlotData.prototype.updateTemporal = function () {
|
|
85
|
-
var _this = this;
|
|
86
|
-
Object.keys(this.valuesAtTimestamp).forEach(function (aggKey) {
|
|
87
|
-
Object.keys(_this.valuesAtTimestamp[aggKey].splitBys).forEach(function (splitBy, splitByI) {
|
|
88
|
-
var measures = null, timestamp = null;
|
|
89
|
-
if (_this.getSplitByVisible(aggKey, splitBy) && _this.valuesAtTimestamp[aggKey].splitBys[splitBy].measurements != undefined) {
|
|
90
|
-
measures = _this.valuesAtTimestamp[aggKey].splitBys[splitBy].measurements;
|
|
91
|
-
timestamp = _this.valuesAtTimestamp[aggKey].splitBys[splitBy].timestamp;
|
|
92
|
-
}
|
|
93
|
-
_this.temporalDataArray.push({
|
|
94
|
-
aggregateKey: aggKey,
|
|
95
|
-
aggregateKeyI: _this.data.findIndex(function (datum) { return datum.aggKey === aggKey; }),
|
|
96
|
-
splitBy: splitBy,
|
|
97
|
-
measures: measures,
|
|
98
|
-
timestamp: timestamp,
|
|
99
|
-
splitByI: splitByI
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
};
|
|
104
|
-
/******** OVERRIDES GROUPEDBARCHARTDATA -- UPDATES VALUES AT TIMESTAMP WITH MEASURES & TIMESTAMP********/
|
|
105
|
-
ScatterPlotData.prototype.setValuesAtTimestamp = function () {
|
|
106
|
-
var _this = this;
|
|
107
|
-
var aggregateCounterMap = {};
|
|
108
|
-
this.valuesAtTimestamp = {};
|
|
109
|
-
this.data.forEach(function (aggregate, aggI) {
|
|
110
|
-
var aggName = Object.keys(aggregate)[0];
|
|
111
|
-
var aggKey;
|
|
112
|
-
if (aggregateCounterMap[aggName]) {
|
|
113
|
-
aggKey = Utils.createEntityKey(aggName, aggregateCounterMap[aggName]);
|
|
114
|
-
aggregateCounterMap[aggName] += 1;
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
aggKey = Utils.createEntityKey(aggName, 0);
|
|
118
|
-
aggregateCounterMap[aggName] = 1;
|
|
119
|
-
}
|
|
120
|
-
_this.valuesAtTimestamp[aggKey] = {};
|
|
121
|
-
_this.valuesAtTimestamp[aggKey].splitBys = Object.keys(aggregate[aggName])
|
|
122
|
-
.reduce(function (aggSplitBys, splitBy, splitByI) {
|
|
123
|
-
aggSplitBys[splitBy] = {};
|
|
124
|
-
aggSplitBys[splitBy].measurements = aggregate[aggName][splitBy][_this.timestamp];
|
|
125
|
-
aggSplitBys[splitBy].timestamp = _this.timestamp;
|
|
126
|
-
return aggSplitBys;
|
|
127
|
-
}, {});
|
|
128
|
-
});
|
|
129
|
-
};
|
|
130
|
-
return ScatterPlotData;
|
|
131
|
-
}(GroupedBarChartData));
|
|
132
|
-
|
|
133
|
-
var ScatterPlot = /** @class */ (function (_super) {
|
|
134
|
-
__extends(ScatterPlot, _super);
|
|
135
|
-
function ScatterPlot(renderTarget) {
|
|
136
|
-
var _this = _super.call(this, renderTarget) || this;
|
|
137
|
-
_this.activeDot = null;
|
|
138
|
-
_this.focusedSite = null;
|
|
139
|
-
_this.lowOpacity = 0.15;
|
|
140
|
-
_this.standardOpacity = 0.6;
|
|
141
|
-
_this.focusOpacity = 0.8;
|
|
142
|
-
_this.standardStroke = 1;
|
|
143
|
-
_this.lowStroke = 0.3;
|
|
144
|
-
_this.chartComponentData = new ScatterPlotData();
|
|
145
|
-
/******** DRAW UPDATE FUNCTION ********/
|
|
146
|
-
_this.draw = function (isFromResize, event) {
|
|
147
|
-
if (isFromResize === void 0) { isFromResize = false; }
|
|
148
|
-
_this.activeDot = null;
|
|
149
|
-
_this.chartComponentData.updateTemporalDataArray(_this.chartOptions.isTemporal);
|
|
150
|
-
// Update extents to fit data if not temporal
|
|
151
|
-
_this.chartComponentData.updateExtents(_this.chartOptions.spMeasures);
|
|
152
|
-
_this.focus.attr("visibility", (_this.chartOptions.focusHidden) ? "hidden" : "visible");
|
|
153
|
-
// If only one data series visible, do not highlight on hover
|
|
154
|
-
var visibleSplitBys = 0;
|
|
155
|
-
Object.keys(_this.chartComponentData.displayState).forEach(function (aggKey) {
|
|
156
|
-
if (_this.chartComponentData.displayState[aggKey].visible)
|
|
157
|
-
Object.keys(_this.chartComponentData.displayState[aggKey].splitBys).forEach(function (splitBy) {
|
|
158
|
-
if (_this.chartComponentData.displayState[aggKey].splitBys[splitBy].visible)
|
|
159
|
-
visibleSplitBys++;
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
if (visibleSplitBys == 1)
|
|
163
|
-
_this.focusOpacity = _this.standardOpacity;
|
|
164
|
-
// Determine the number of timestamps present, add margin for slider
|
|
165
|
-
if (_this.chartComponentData.allTimestampsArray.length > 1 && _this.chartOptions.isTemporal) {
|
|
166
|
-
_this.chartMargins.bottom = 88;
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
_this.chartMargins.bottom = 48;
|
|
170
|
-
}
|
|
171
|
-
_this.setWidthAndHeight(isFromResize);
|
|
172
|
-
_this.svgSelection
|
|
173
|
-
.attr("height", _this.height)
|
|
174
|
-
.style("width", "".concat(_this.getSVGWidth(), "px"));
|
|
175
|
-
_this.g
|
|
176
|
-
.attr("transform", "translate(" + _this.chartMargins.left + "," + _this.chartMargins.top + ")");
|
|
177
|
-
_this.voronoiGroup
|
|
178
|
-
.attr("width", _this.chartWidth)
|
|
179
|
-
.attr("height", _this.chartHeight);
|
|
180
|
-
_super.prototype.themify.call(_this, _this.targetElement, _this.chartOptions.theme);
|
|
181
|
-
// Draw control panel
|
|
182
|
-
if (!_this.chartOptions.hideChartControlPanel && _this.chartControlsPanel === null) {
|
|
183
|
-
_this.chartControlsPanel = Utils.createControlPanel(_this.renderTarget, _this.CONTROLSWIDTH, _this.chartMargins.top, _this.chartOptions);
|
|
184
|
-
}
|
|
185
|
-
else if (_this.chartOptions.hideChartControlPanel && _this.chartControlsPanel !== null) {
|
|
186
|
-
_this.removeControlPanel();
|
|
187
|
-
}
|
|
188
|
-
if (_this.chartControlsPanel !== null && _this.ellipsisItemsExist()) {
|
|
189
|
-
_this.drawEllipsisMenu();
|
|
190
|
-
_this.chartControlsPanel.style("top", Math.max((_this.chartMargins.top - 44), 0) + 'px');
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
_this.removeEllipsisMenu();
|
|
194
|
-
}
|
|
195
|
-
// Resize focus line
|
|
196
|
-
_this.focus.select('.tsi-hLine').attr("x2", _this.chartWidth);
|
|
197
|
-
_this.focus.select('.tsi-vLine').attr("y2", _this.chartHeight);
|
|
198
|
-
_this.measures = _this.chartOptions.spMeasures;
|
|
199
|
-
_this.xMeasure = _this.measures[0];
|
|
200
|
-
_this.yMeasure = _this.measures[1];
|
|
201
|
-
_this.rMeasure = _this.measures[2] !== undefined ? _this.measures[2] : null;
|
|
202
|
-
var xExtentRange = _this.chartComponentData.extents[_this.xMeasure][1] - _this.chartComponentData.extents[_this.xMeasure][0];
|
|
203
|
-
var yExtentRange = _this.chartComponentData.extents[_this.yMeasure][1] - _this.chartComponentData.extents[_this.yMeasure][0];
|
|
204
|
-
// Pad extents
|
|
205
|
-
var xOffset = (20 / _this.chartWidth) * (xExtentRange == 0 ? 1 : xExtentRange);
|
|
206
|
-
var yOffset = (20 / _this.chartHeight) * (yExtentRange == 0 ? 1 : yExtentRange);
|
|
207
|
-
var rOffset = null;
|
|
208
|
-
if (_this.rMeasure) {
|
|
209
|
-
var rExtentRange = _this.chartComponentData.extents[_this.rMeasure][1] - _this.chartComponentData.extents[_this.rMeasure][0];
|
|
210
|
-
rOffset = (20 / _this.chartHeight) * (rExtentRange == 0 ? 1 : rExtentRange);
|
|
211
|
-
}
|
|
212
|
-
// Check measure validity
|
|
213
|
-
if (!_this.checkExtentValidity())
|
|
214
|
-
return;
|
|
215
|
-
// Init scales
|
|
216
|
-
_this.yScale = d3.scaleLinear()
|
|
217
|
-
.range([_this.chartHeight, 0])
|
|
218
|
-
.domain([_this.chartComponentData.extents[_this.yMeasure][0] - yOffset, _this.chartComponentData.extents[_this.yMeasure][1] + yOffset]);
|
|
219
|
-
_this.xScale = d3.scaleLinear()
|
|
220
|
-
.range([0, _this.chartWidth])
|
|
221
|
-
.domain([_this.chartComponentData.extents[_this.xMeasure][0] - xOffset, _this.chartComponentData.extents[_this.xMeasure][1] + xOffset]);
|
|
222
|
-
_this.rScale = d3.scaleLinear()
|
|
223
|
-
.range(_this.chartOptions.scatterPlotRadius.slice(0, 2))
|
|
224
|
-
.domain(_this.rMeasure === null ? [0, 0] : [_this.chartComponentData.extents[_this.rMeasure][0] - rOffset, _this.chartComponentData.extents[_this.rMeasure][1] + rOffset]);
|
|
225
|
-
// Draw axis
|
|
226
|
-
_this.drawAxis();
|
|
227
|
-
// Draw axis labels
|
|
228
|
-
_this.drawAxisLabels();
|
|
229
|
-
// Draw connecting lines (if toggled on)
|
|
230
|
-
_this.drawConnectingLines();
|
|
231
|
-
// Draw data
|
|
232
|
-
var scatter = _this.pointWrapper.selectAll(".tsi-dot")
|
|
233
|
-
.data(_this.cleanData(_this.chartComponentData.temporalDataArray), function (d) {
|
|
234
|
-
if (_this.chartOptions.isTemporal) {
|
|
235
|
-
return d.aggregateKey + d.splitBy + d.splitByI;
|
|
236
|
-
}
|
|
237
|
-
else {
|
|
238
|
-
return d.aggregateKey + d.splitBy + d.timestamp;
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
scatter
|
|
242
|
-
.enter()
|
|
243
|
-
.append("circle")
|
|
244
|
-
.attr("class", "tsi-dot")
|
|
245
|
-
.attr("r", function (d) { return _this.rScale(d.measures[_this.rMeasure]); })
|
|
246
|
-
.attr("cx", function (d) { return _this.xScale(d.measures[_this.xMeasure]); })
|
|
247
|
-
.attr("cy", function (d) { return _this.yScale(d.measures[_this.yMeasure]); })
|
|
248
|
-
.merge(scatter)
|
|
249
|
-
.attr("id", function (d) { return _this.getClassHash(d.aggregateKey, d.splitBy, d.splitByI, d.timestamp); })
|
|
250
|
-
.transition()
|
|
251
|
-
.duration(_this.chartOptions.noAnimate ? 0 : _this.TRANSDURATION)
|
|
252
|
-
.ease(d3.easeExp)
|
|
253
|
-
.attr("r", function (d) { return _this.rScale(d.measures[_this.rMeasure]); })
|
|
254
|
-
.attr("cx", function (d) { return _this.xScale(d.measures[_this.xMeasure]); })
|
|
255
|
-
.attr("cy", function (d) { return _this.yScale(d.measures[_this.yMeasure]); })
|
|
256
|
-
.attr("fill", function (d) { return Utils.colorSplitBy(_this.chartComponentData.displayState, d.splitByI, d.aggregateKey, _this.chartOptions.keepSplitByColor); })
|
|
257
|
-
.attr("stroke", function (d) { return Utils.colorSplitBy(_this.chartComponentData.displayState, d.splitByI, d.aggregateKey, _this.chartOptions.keepSplitByColor); })
|
|
258
|
-
.attr("stroke-opacity", _this.standardStroke)
|
|
259
|
-
.attr("fill-opacity", _this.standardOpacity)
|
|
260
|
-
.attr("stroke-width", "1px");
|
|
261
|
-
scatter.exit().remove();
|
|
262
|
-
// Draw voronoi
|
|
263
|
-
_this.drawVoronoi();
|
|
264
|
-
// Resize controls
|
|
265
|
-
_this.setControlsPanelWidth();
|
|
266
|
-
/******************** Temporal Slider ************************/
|
|
267
|
-
if (_this.chartComponentData.allTimestampsArray.length > 1 && _this.chartOptions.isTemporal) {
|
|
268
|
-
d3.select(_this.renderTarget).select('.tsi-sliderWrapper').classed('tsi-hidden', false);
|
|
269
|
-
_this.slider.render(_this.chartComponentData.allTimestampsArray.map(function (ts) {
|
|
270
|
-
var action = function () {
|
|
271
|
-
_this.chartOptions.timestamp = ts;
|
|
272
|
-
_this.render(_this.chartComponentData.data, _this.chartOptions, _this.aggregateExpressionOptions, true);
|
|
273
|
-
};
|
|
274
|
-
return { label: Utils.timeFormat(_this.chartComponentData.usesSeconds, _this.chartComponentData.usesMillis, _this.chartOptions.offset, _this.chartOptions.is24HourTime, null, null, _this.chartOptions.dateLocale)(new Date(ts)), action: action };
|
|
275
|
-
}), _this.chartOptions, _this.getSliderWidth(), Utils.timeFormat(_this.chartComponentData.usesSeconds, _this.chartComponentData.usesMillis, _this.chartOptions.offset, _this.chartOptions.is24HourTime, null, null, _this.chartOptions.dateLocale)(new Date(_this.chartComponentData.timestamp)));
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
278
|
-
if (_this.slider)
|
|
279
|
-
_this.slider.remove();
|
|
280
|
-
d3.select(_this.renderTarget).select('.tsi-sliderWrapper').classed('tsi-hidden', true);
|
|
281
|
-
}
|
|
282
|
-
// Draw Legend
|
|
283
|
-
_this.legendObject.draw(_this.chartOptions.legend, _this.chartComponentData, _this.labelMouseOver.bind(_this), _this.svgSelection, _this.chartOptions, _this.labelMouseOut.bind(_this), _this.stickySeries, event);
|
|
284
|
-
_this.sliderWrapper
|
|
285
|
-
.style("width", "".concat(_this.svgSelection.node().getBoundingClientRect().width + 10, "px"));
|
|
286
|
-
};
|
|
287
|
-
/******** UPDATE STICKY SPLITBY ********/
|
|
288
|
-
_this.stickySeries = function (aggregateKey, splitBy) {
|
|
289
|
-
if (splitBy === void 0) { splitBy = null; }
|
|
290
|
-
var filteredValues = _this.getVoronoiData(_this.chartComponentData.temporalDataArray);
|
|
291
|
-
if (filteredValues == null || filteredValues.length == 0)
|
|
292
|
-
return;
|
|
293
|
-
_this.chartComponentData.stickiedKey = {
|
|
294
|
-
aggregateKey: aggregateKey,
|
|
295
|
-
splitBy: (splitBy == null ? null : splitBy)
|
|
296
|
-
};
|
|
297
|
-
_this.legendObject.legendElement.selectAll('.tsi-splitByLabel').filter(function (filteredSplitBy) {
|
|
298
|
-
return (d3.select(this.parentNode).datum() == aggregateKey) && (filteredSplitBy == splitBy);
|
|
299
|
-
}).classed("stickied", true);
|
|
300
|
-
_this.voronoiDiagram = _this.voronoi(_this.getVoronoiData(_this.chartComponentData.temporalDataArray));
|
|
301
|
-
};
|
|
302
|
-
_this.chartMargins = {
|
|
303
|
-
top: 40,
|
|
304
|
-
bottom: 48,
|
|
305
|
-
left: 70,
|
|
306
|
-
right: 60
|
|
307
|
-
};
|
|
308
|
-
return _this;
|
|
309
|
-
}
|
|
310
|
-
ScatterPlot.prototype.ScatterPlot = function () { };
|
|
311
|
-
ScatterPlot.prototype.render = function (data, options, aggregateExpressionOptions, fromSlider) {
|
|
312
|
-
var _this = this;
|
|
313
|
-
if (fromSlider === void 0) { fromSlider = false; }
|
|
314
|
-
_super.prototype.render.call(this, data, options, aggregateExpressionOptions);
|
|
315
|
-
// If measure options not set, or less than 2, return
|
|
316
|
-
if (this.chartOptions["spMeasures"] == null || (this.chartOptions["spMeasures"] != null && this.chartOptions["spMeasures"].length < 2)) {
|
|
317
|
-
var invalidMessage = "spMeasures not correctly specified or has length < 2: " + this.chartOptions["spMeasures"] +
|
|
318
|
-
"\n\nPlease add the following chartOption: {spMeasures: ['example_x_axis_measure', 'example_y_axis_measure', 'example_radius_measure']} " +
|
|
319
|
-
"where the measures correspond to the data key names.";
|
|
320
|
-
console.log(invalidMessage);
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
this.chartMargins.top = (this.chartOptions.legend === 'compact') ? 84 : 40;
|
|
324
|
-
if (!this.chartOptions.hideChartControlPanel)
|
|
325
|
-
this.chartMargins.top += 20;
|
|
326
|
-
this.chartMargins.left = (this.chartOptions.spAxisLabels != null && this.chartOptions.spAxisLabels.length >= 2) ? 120 : 70;
|
|
327
|
-
this.chartComponentData.mergeDataToDisplayStateAndTimeArrays(this.data, this.chartOptions.timestamp, this.aggregateExpressionOptions);
|
|
328
|
-
this.chartComponentData.setExtents(this.chartOptions.spMeasures, !fromSlider);
|
|
329
|
-
// Check measure validity
|
|
330
|
-
if (!this.checkExtentValidity())
|
|
331
|
-
return;
|
|
332
|
-
this.controlsOffset = (this.chartOptions.legend == "shown" ? this.CONTROLSWIDTH : 0);
|
|
333
|
-
this.setWidthAndHeight();
|
|
334
|
-
/******** STATIC INITIALIZATION ********/
|
|
335
|
-
if (this.svgSelection == null) {
|
|
336
|
-
// Initialize extents
|
|
337
|
-
//this.chartComponentData.setExtents(this.chartOptions.spMeasures);
|
|
338
|
-
this.targetElement = d3.select(this.renderTarget)
|
|
339
|
-
.classed("tsi-scatterPlot", true);
|
|
340
|
-
this.svgSelection = this.targetElement.append("svg")
|
|
341
|
-
.attr("class", "tsi-scatterPlotSVG tsi-chartSVG")
|
|
342
|
-
.attr('title', this.getString('Scatter plot'))
|
|
343
|
-
.attr("height", this.height);
|
|
344
|
-
this.g = this.svgSelection.append("g")
|
|
345
|
-
.classed("tsi-svgGroup", true);
|
|
346
|
-
this.lineWrapper = this.g.append("g")
|
|
347
|
-
.classed("tsi-lineWrapper", true);
|
|
348
|
-
this.pointWrapper = this.g.append("g")
|
|
349
|
-
.classed("tsi-pointWrapper", true);
|
|
350
|
-
// Create temporal slider div
|
|
351
|
-
this.sliderWrapper = d3.select(this.renderTarget).append('div').classed('tsi-sliderWrapper', true);
|
|
352
|
-
this.tooltip = new Tooltip(d3.select(this.renderTarget));
|
|
353
|
-
// Initialize voronoi
|
|
354
|
-
this.voronoiGroup = this.g.append("rect")
|
|
355
|
-
.attr("class", "tsi-voronoiWrap")
|
|
356
|
-
.attr("fill", "transparent");
|
|
357
|
-
// Initialize focus crosshair lines
|
|
358
|
-
this.focus = this.pointWrapper.append("g")
|
|
359
|
-
.attr("transform", "translate(-100,-100)")
|
|
360
|
-
.attr("class", "tsi-focus")
|
|
361
|
-
.style("display", "none");
|
|
362
|
-
this.focus.append("line")
|
|
363
|
-
.attr("class", "tsi-focusLine tsi-vLine")
|
|
364
|
-
.attr("x1", 0)
|
|
365
|
-
.attr("x2", 0)
|
|
366
|
-
.attr("y1", this.chartOptions.aggTopMargin)
|
|
367
|
-
.attr("y2", this.chartHeight);
|
|
368
|
-
this.focus.append("line")
|
|
369
|
-
.attr("class", "tsi-focusLine tsi-hLine")
|
|
370
|
-
.attr("x1", 0)
|
|
371
|
-
.attr("x2", this.chartWidth)
|
|
372
|
-
.attr("y1", 0)
|
|
373
|
-
.attr("y2", 0);
|
|
374
|
-
// Initialize focus axis data boxes
|
|
375
|
-
var hHoverG = this.focus.append("g")
|
|
376
|
-
.attr("class", 'hHoverG')
|
|
377
|
-
.style("pointer-events", "none")
|
|
378
|
-
.attr("transform", "translate(0," + (this.chartHeight + this.chartOptions.aggTopMargin) + ")");
|
|
379
|
-
hHoverG.append("rect")
|
|
380
|
-
.style("pointer-events", "none")
|
|
381
|
-
.attr("class", 'hHoverBox')
|
|
382
|
-
.attr("x", 0)
|
|
383
|
-
.attr("y", 4)
|
|
384
|
-
.attr("width", 0)
|
|
385
|
-
.attr("height", 0);
|
|
386
|
-
hHoverG.append("text")
|
|
387
|
-
.style("pointer-events", "none")
|
|
388
|
-
.attr("class", "hHoverText")
|
|
389
|
-
.attr("dy", ".71em")
|
|
390
|
-
.attr("transform", "translate(0,9)")
|
|
391
|
-
.text(function (d) { return d; });
|
|
392
|
-
var vHoverG = this.focus.append("g")
|
|
393
|
-
.attr("class", 'vHoverG')
|
|
394
|
-
.attr("transform", "translate(0," + (this.chartHeight + this.chartOptions.aggTopMargin) + ")");
|
|
395
|
-
vHoverG.append("rect")
|
|
396
|
-
.attr("class", 'vHoverBox')
|
|
397
|
-
.attr("x", -5)
|
|
398
|
-
.attr("y", 0)
|
|
399
|
-
.attr("width", 0)
|
|
400
|
-
.attr("height", 0);
|
|
401
|
-
vHoverG.append("text")
|
|
402
|
-
.attr("class", "vHoverText")
|
|
403
|
-
.attr("dy", ".32em")
|
|
404
|
-
.attr("x", -10)
|
|
405
|
-
.text(function (d) { return d; });
|
|
406
|
-
// Add Window Resize Listener
|
|
407
|
-
window.addEventListener("resize", function (event) {
|
|
408
|
-
if (!_this.chartOptions.suppressResizeListener) {
|
|
409
|
-
_this.draw(true, event);
|
|
410
|
-
}
|
|
411
|
-
});
|
|
412
|
-
// Temporal slider
|
|
413
|
-
this.slider = new Slider(d3.select(this.renderTarget).select('.tsi-sliderWrapper').node());
|
|
414
|
-
// Legend
|
|
415
|
-
this.legendObject = new Legend(this.draw.bind(this), this.renderTarget, this.CONTROLSWIDTH);
|
|
416
|
-
}
|
|
417
|
-
// Draw scatter plot
|
|
418
|
-
this.draw();
|
|
419
|
-
this.gatedShowGrid();
|
|
420
|
-
d3.select("html").on("click." + Utils.guid(), function (event) {
|
|
421
|
-
if (_this.ellipsisContainer && event.target != _this.ellipsisContainer.select(".tsi-ellipsisButton").node()) {
|
|
422
|
-
_this.ellipsisMenu.setMenuVisibility(false);
|
|
423
|
-
}
|
|
424
|
-
});
|
|
425
|
-
this.legendPostRenderProcess(this.chartOptions.legend, this.svgSelection, false);
|
|
426
|
-
};
|
|
427
|
-
ScatterPlot.prototype.getSliderWidth = function () {
|
|
428
|
-
return this.chartWidth + this.chartMargins.left + this.chartMargins.right - 16;
|
|
429
|
-
};
|
|
430
|
-
ScatterPlot.prototype.tooltipFormat = function (d, text, measureFormat, xyrMeasures) {
|
|
431
|
-
_super.prototype.tooltipFormat.call(this, d, text, measureFormat, xyrMeasures);
|
|
432
|
-
if (!this.chartOptions.isTemporal) {
|
|
433
|
-
var titleGroup = text.select('.tsi-tooltipTitleGroup');
|
|
434
|
-
if (d.timestamp) {
|
|
435
|
-
titleGroup.append('h4')
|
|
436
|
-
.attr('class', 'tsi-tooltipSubtitle tsi-tooltipTimeStamp')
|
|
437
|
-
.text(this.formatDate(d.timestamp, this.chartComponentData.getTemporalShiftMillis(d.aggregateKey)));
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
};
|
|
441
|
-
/******** DRAW CONNECTING LINES BETWEEN POINTS ********/
|
|
442
|
-
ScatterPlot.prototype.drawConnectingLines = function () {
|
|
443
|
-
var _this = this;
|
|
444
|
-
// Don't render connecting lines on temporal mode
|
|
445
|
-
if (this.chartOptions.isTemporal) {
|
|
446
|
-
this.lineWrapper.selectAll("*").remove();
|
|
447
|
-
return;
|
|
448
|
-
}
|
|
449
|
-
var dataSet = this.cleanData(this.chartComponentData.temporalDataArray);
|
|
450
|
-
var connectedSeriesMap = {};
|
|
451
|
-
// Find measure by which to connect series of points
|
|
452
|
-
var getPointConnectionMeasure = (function (point) {
|
|
453
|
-
var _a;
|
|
454
|
-
var pConMes = (_a = _this.aggregateExpressionOptions[point.aggregateKeyI]) === null || _a === void 0 ? void 0 : _a.pointConnectionMeasure;
|
|
455
|
-
return pConMes && pConMes in point.measures ? pConMes : null;
|
|
456
|
-
});
|
|
457
|
-
// Map data into groups of connected points, if connectedPoints enabled for agg
|
|
458
|
-
dataSet.forEach(function (point) {
|
|
459
|
-
if (point.aggregateKeyI !== null && point.aggregateKeyI < _this.aggregateExpressionOptions.length &&
|
|
460
|
-
_this.aggregateExpressionOptions[point.aggregateKeyI].connectPoints) {
|
|
461
|
-
var series = point.aggregateKey + "_" + point.splitBy;
|
|
462
|
-
if (series in connectedSeriesMap) {
|
|
463
|
-
connectedSeriesMap[series].data.push(point);
|
|
464
|
-
}
|
|
465
|
-
else {
|
|
466
|
-
connectedSeriesMap[series] = {
|
|
467
|
-
data: [point],
|
|
468
|
-
pointConnectionMeasure: getPointConnectionMeasure(point)
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
});
|
|
473
|
-
var _loop_1 = function (key) {
|
|
474
|
-
var sortMeasure = connectedSeriesMap[key].pointConnectionMeasure;
|
|
475
|
-
// If sort measure specified, sort by that measure
|
|
476
|
-
if (sortMeasure) {
|
|
477
|
-
connectedSeriesMap[key].data.sort(function (a, b) {
|
|
478
|
-
if (a.measures[sortMeasure] < b.measures[sortMeasure])
|
|
479
|
-
return -1;
|
|
480
|
-
if (a.measures[sortMeasure] > b.measures[sortMeasure])
|
|
481
|
-
return 1;
|
|
482
|
-
return 0;
|
|
483
|
-
});
|
|
484
|
-
}
|
|
485
|
-
};
|
|
486
|
-
// Sort connected series by pointConnectionMeasure
|
|
487
|
-
for (var _i = 0, _a = Object.keys(connectedSeriesMap); _i < _a.length; _i++) {
|
|
488
|
-
var key = _a[_i];
|
|
489
|
-
_loop_1(key);
|
|
490
|
-
}
|
|
491
|
-
var line = d3.line()
|
|
492
|
-
.x(function (d) { return _this.xScale(d.measures[_this.xMeasure]); })
|
|
493
|
-
.y(function (d) { return _this.yScale(d.measures[_this.yMeasure]); })
|
|
494
|
-
.curve(this.chartOptions.interpolationFunction); // apply smoothing to the line
|
|
495
|
-
// Group lines by aggregate
|
|
496
|
-
var connectedGroups = this.lineWrapper.selectAll(".tsi-lineSeries").data(Object.keys(connectedSeriesMap));
|
|
497
|
-
var self = this;
|
|
498
|
-
connectedGroups.enter()
|
|
499
|
-
.append("g")
|
|
500
|
-
.attr("class", 'tsi-lineSeries')
|
|
501
|
-
.merge(connectedGroups)
|
|
502
|
-
.each(function (seriesName) {
|
|
503
|
-
var series = d3.select(this).selectAll(".tsi-line").data([connectedSeriesMap[seriesName].data], function (d) { return d[0].aggregateKeyI + d[0].splitBy; });
|
|
504
|
-
series.exit().remove();
|
|
505
|
-
series
|
|
506
|
-
.enter()
|
|
507
|
-
.append("path")
|
|
508
|
-
.attr("class", "tsi-line")
|
|
509
|
-
.merge(series)
|
|
510
|
-
.attr("fill", "none")
|
|
511
|
-
.transition()
|
|
512
|
-
.duration(self.chartOptions.noAnimate ? 0 : self.TRANSDURATION)
|
|
513
|
-
.ease(d3.easeExp)
|
|
514
|
-
.attr("stroke", function (d) { return Utils.colorSplitBy(self.chartComponentData.displayState, d[0].splitByI, d[0].aggregateKey, self.chartOptions.keepSplitByColor); })
|
|
515
|
-
.attr("stroke-width", 2.5)
|
|
516
|
-
.attr("stroke-linejoin", "round")
|
|
517
|
-
.attr("stroke-linecap", "round")
|
|
518
|
-
.attr("d", line);
|
|
519
|
-
});
|
|
520
|
-
connectedGroups.exit().remove();
|
|
521
|
-
};
|
|
522
|
-
/******** CHECK VALIDITY OF EXTENTS ********/
|
|
523
|
-
ScatterPlot.prototype.checkExtentValidity = function () {
|
|
524
|
-
var _this = this;
|
|
525
|
-
if (this.chartComponentData.allValues == 0) {
|
|
526
|
-
return true;
|
|
527
|
-
}
|
|
528
|
-
var testExtent = {};
|
|
529
|
-
this.chartOptions.spMeasures.forEach(function (measure) {
|
|
530
|
-
testExtent[measure] = d3.extent(_this.chartComponentData.allValues, function (v) {
|
|
531
|
-
if (!v.measures)
|
|
532
|
-
return null;
|
|
533
|
-
return measure in v.measures ? v.measures[measure] : null;
|
|
534
|
-
});
|
|
535
|
-
});
|
|
536
|
-
Object.keys(testExtent).forEach(function (extent) {
|
|
537
|
-
testExtent[extent].forEach(function (el) {
|
|
538
|
-
if (el == undefined) {
|
|
539
|
-
console.log("Undefined Measure: ", extent);
|
|
540
|
-
return false;
|
|
541
|
-
}
|
|
542
|
-
});
|
|
543
|
-
});
|
|
544
|
-
return true;
|
|
545
|
-
};
|
|
546
|
-
/******** CREATE VORONOI DIAGRAM FOR MOUSE EVENTS ********/
|
|
547
|
-
ScatterPlot.prototype.drawVoronoi = function () {
|
|
548
|
-
var _this = this;
|
|
549
|
-
var voronoiData = this.getVoronoiData(this.chartComponentData.temporalDataArray);
|
|
550
|
-
var self = this;
|
|
551
|
-
// Create random offset to solve colinear data issue
|
|
552
|
-
var getRandomInRange = function (min, max) {
|
|
553
|
-
return Math.random() * (max - min) + min;
|
|
554
|
-
};
|
|
555
|
-
var getOffset = function () { return (Math.random() < 0.5 ? -1 : 1) * getRandomInRange(0, .01); };
|
|
556
|
-
this.voronoi = d3Voronoi.voronoi()
|
|
557
|
-
.x(function (d) { return _this.xScale(d.measures[_this.xMeasure]) + getOffset(); })
|
|
558
|
-
.y(function (d) { return _this.yScale(d.measures[_this.yMeasure]) + getOffset(); })
|
|
559
|
-
.extent([[0, 0], [this.chartWidth, this.chartHeight]]);
|
|
560
|
-
this.voronoiDiagram = this.voronoi(voronoiData);
|
|
561
|
-
this.voronoiGroup
|
|
562
|
-
.on("mousemove", function (event) {
|
|
563
|
-
var mouseEvent = d3.pointer(event);
|
|
564
|
-
self.voronoiMouseMove(mouseEvent);
|
|
565
|
-
})
|
|
566
|
-
.on("mouseover", function (event) {
|
|
567
|
-
var mouseEvent = d3.pointer(event);
|
|
568
|
-
self.voronoiMouseMove(mouseEvent);
|
|
569
|
-
var site = self.voronoiDiagram.find(mouseEvent[0], mouseEvent[1]);
|
|
570
|
-
if (site != null)
|
|
571
|
-
self.labelMouseOver(site.data.aggregateKey, site.data.splitBy);
|
|
572
|
-
})
|
|
573
|
-
.on("mouseout", function () {
|
|
574
|
-
self.voronoiMouseOut();
|
|
575
|
-
})
|
|
576
|
-
.on("click", function (event) {
|
|
577
|
-
var mouseEvent = d3.pointer(event);
|
|
578
|
-
self.voronoiClick(mouseEvent);
|
|
579
|
-
});
|
|
580
|
-
};
|
|
581
|
-
/******** STICKY/UNSTICKY DATA GROUPS ON VORONOI DIAGRAM CLICK ********/
|
|
582
|
-
ScatterPlot.prototype.voronoiClick = function (mouseEvent) {
|
|
583
|
-
var site = this.voronoiDiagram.find(mouseEvent[0], mouseEvent[1]);
|
|
584
|
-
if (site == null)
|
|
585
|
-
return;
|
|
586
|
-
// Unsticky all
|
|
587
|
-
this.legendObject.legendElement.selectAll('.tsi-splitByLabel').classed("stickied", false);
|
|
588
|
-
if (this.chartComponentData.stickiedKey != null) {
|
|
589
|
-
this.chartComponentData.stickiedKey = null;
|
|
590
|
-
// Recompute Voronoi
|
|
591
|
-
this.voronoiDiagram = this.voronoi(this.getVoronoiData(this.chartComponentData.temporalDataArray));
|
|
592
|
-
site = this.voronoiDiagram.find(mouseEvent[0], mouseEvent[1]);
|
|
593
|
-
this.voronoiMouseMove(mouseEvent);
|
|
594
|
-
this.chartOptions.onUnsticky(site.data.aggregateKey, site.data.splitBy);
|
|
595
|
-
return;
|
|
596
|
-
}
|
|
597
|
-
this.stickySeries(site.data.aggregateKey, site.data.splitBy);
|
|
598
|
-
this.chartOptions.onSticky(site.data.aggregateKey, site.data.splitBy);
|
|
599
|
-
};
|
|
600
|
-
/******** HIGHLIGHT DOT TARGETED BY CROSSHAIRS WITH BLACK / WHITE STROKE BORDER ********/
|
|
601
|
-
ScatterPlot.prototype.highlightDot = function (site) {
|
|
602
|
-
//If dot is active, unhighlight
|
|
603
|
-
this.unhighlightDot();
|
|
604
|
-
// Add highlight border to newly focused dot
|
|
605
|
-
var highlightColor = this.chartOptions.theme == "light" ? "black" : "white";
|
|
606
|
-
var idSelector = "#" + this.getClassHash(site.data.aggregateKey, site.data.splitBy, site.data.splitByI, site.data.timestamp);
|
|
607
|
-
this.activeDot = this.svgSelection.select(idSelector);
|
|
608
|
-
this.activeDot
|
|
609
|
-
.attr("stroke", highlightColor)
|
|
610
|
-
.attr("stroke-width", "2px")
|
|
611
|
-
// Raise active dot above crosshair
|
|
612
|
-
.raise().classed("active", true);
|
|
613
|
-
};
|
|
614
|
-
/******** GET UNIQUE STRING HASH ID FOR EACH DOT USING DATA ATTRIBUTES ********/
|
|
615
|
-
ScatterPlot.prototype.getClassHash = function (aggKey, splitBy, splitByI, timestamp) {
|
|
616
|
-
return String("dot" + Utils.hash(aggKey + splitBy + splitByI.toString() + timestamp));
|
|
617
|
-
};
|
|
618
|
-
/******** UNHIGHLIGHT ACTIVE DOT ********/
|
|
619
|
-
ScatterPlot.prototype.unhighlightDot = function () {
|
|
620
|
-
var _this = this;
|
|
621
|
-
if (this.activeDot) {
|
|
622
|
-
this.activeDot
|
|
623
|
-
.attr("stroke", function (d) { return Utils.colorSplitBy(_this.chartComponentData.displayState, d.splitByI, d.aggregateKey, _this.chartOptions.keepSplitByColor); })
|
|
624
|
-
.attr("stroke-width", "1px");
|
|
625
|
-
}
|
|
626
|
-
this.activeDot = null;
|
|
627
|
-
};
|
|
628
|
-
/******** EFFICIENTLY SWAP NEW FOCUSED GROUP WITH OLD FOCUSED GROUP ********/
|
|
629
|
-
ScatterPlot.prototype.labelMouseMove = function (aggKey, splitBy) {
|
|
630
|
-
if (aggKey !== this.focusedAggKey || splitBy !== this.focusedSplitBy) {
|
|
631
|
-
var selectedFilter = Utils.createValueFilter(aggKey, splitBy);
|
|
632
|
-
var oldFilter = Utils.createValueFilter(this.focusedAggKey, this.focusedSplitBy);
|
|
633
|
-
this.svgSelection.selectAll(".tsi-dot")
|
|
634
|
-
.filter(selectedFilter)
|
|
635
|
-
.attr("stroke-opacity", this.standardStroke)
|
|
636
|
-
.attr("fill-opacity", this.focusOpacity);
|
|
637
|
-
this.svgSelection.selectAll(".tsi-dot")
|
|
638
|
-
.filter(oldFilter)
|
|
639
|
-
.attr("stroke-opacity", this.lowStroke)
|
|
640
|
-
.attr("fill-opacity", this.lowOpacity);
|
|
641
|
-
var lineSelectedFilter_1 = function (d) {
|
|
642
|
-
return (d[0].aggregateKey === aggKey && d[0].splitBy === splitBy);
|
|
643
|
-
};
|
|
644
|
-
this.svgSelection.selectAll(".tsi-line")
|
|
645
|
-
.filter(function (d) { return lineSelectedFilter_1(d); })
|
|
646
|
-
.attr("stroke-opacity", this.standardStroke);
|
|
647
|
-
this.svgSelection.selectAll(".tsi-line")
|
|
648
|
-
.filter(function (d) { return !lineSelectedFilter_1(d); })
|
|
649
|
-
.attr("stroke-opacity", this.lowStroke);
|
|
650
|
-
this.focusedAggKey = aggKey;
|
|
651
|
-
this.focusedSplitBy = splitBy;
|
|
652
|
-
}
|
|
653
|
-
// Raise crosshair to top
|
|
654
|
-
this.focus.raise().classed("active", true);
|
|
655
|
-
// Raise highlighted dot above crosshairs
|
|
656
|
-
if (this.activeDot != null)
|
|
657
|
-
this.activeDot.raise().classed("active", true);
|
|
658
|
-
// Highlight legend group
|
|
659
|
-
(this.legendObject.legendElement.selectAll('.tsi-splitByLabel').filter(function (filteredSplitBy) {
|
|
660
|
-
return (d3.select(this.parentNode).datum() == aggKey) && (filteredSplitBy == splitBy);
|
|
661
|
-
})).classed("inFocus", true);
|
|
662
|
-
};
|
|
663
|
-
/******** DRAW CROSSHAIRS, TOOLTIP, AND LEGEND FOCUS ********/
|
|
664
|
-
ScatterPlot.prototype.voronoiMouseMove = function (mouseEvent) {
|
|
665
|
-
var mouse_x = mouseEvent[0];
|
|
666
|
-
var mouse_y = mouseEvent[1];
|
|
667
|
-
var site = this.voronoiDiagram.find(mouse_x, mouse_y);
|
|
668
|
-
if (site == null)
|
|
669
|
-
return;
|
|
670
|
-
// Short circuit mouse move if focused site has not changed
|
|
671
|
-
if (this.focusedSite == null)
|
|
672
|
-
this.focusedSite = site;
|
|
673
|
-
else if (this.focusedSite == site)
|
|
674
|
-
return;
|
|
675
|
-
this.focusedSite = site;
|
|
676
|
-
this.drawTooltip(site.data, [site[0], site[1]]);
|
|
677
|
-
this.labelMouseMove(site.data.aggregateKey, site.data.splitBy);
|
|
678
|
-
this.highlightDot(site);
|
|
679
|
-
// Draw focus cross hair
|
|
680
|
-
this.focus.style("display", "block");
|
|
681
|
-
this.focus.attr("transform", "translate(" + site[0] + "," + site[1] + ")");
|
|
682
|
-
this.focus.select('.tsi-hLine').attr("transform", "translate(" + (-site[0]) + ",0)");
|
|
683
|
-
this.focus.select('.tsi-vLine').attr("transform", "translate(0," + (-site[1]) + ")");
|
|
684
|
-
// Draw horizontal hover box
|
|
685
|
-
this.focus.select('.hHoverG')
|
|
686
|
-
.attr("transform", "translate(0," + (this.chartHeight - site[1]) + ")")
|
|
687
|
-
.select("text")
|
|
688
|
-
.text((Utils.formatYAxisNumber(site.data.measures[this.xMeasure])));
|
|
689
|
-
var textElemDimensions = this.focus.select('.hHoverG').select("text")
|
|
690
|
-
.node().getBoundingClientRect();
|
|
691
|
-
this.focus.select(".hHoverG").select("rect")
|
|
692
|
-
.attr("x", -(textElemDimensions.width / 2) - 3)
|
|
693
|
-
.attr("width", textElemDimensions.width + 6)
|
|
694
|
-
.attr("height", textElemDimensions.height + 5);
|
|
695
|
-
// Draw vertical hover box
|
|
696
|
-
this.focus.select('.vHoverG')
|
|
697
|
-
.attr("transform", "translate(" + (-site[0]) + ",0)")
|
|
698
|
-
.select("text")
|
|
699
|
-
.text(Utils.formatYAxisNumber(site.data.measures[this.yMeasure]));
|
|
700
|
-
textElemDimensions = this.focus.select('.vHoverG').select("text")
|
|
701
|
-
.node().getBoundingClientRect();
|
|
702
|
-
this.focus.select(".vHoverG").select("rect")
|
|
703
|
-
.attr("x", -(textElemDimensions.width) - 13)
|
|
704
|
-
.attr("y", -(textElemDimensions.height / 2) - 3)
|
|
705
|
-
.attr("width", textElemDimensions.width + 6)
|
|
706
|
-
.attr("height", textElemDimensions.height + 4);
|
|
707
|
-
this.legendObject.triggerSplitByFocus(site.data.aggregateKey, site.data.splitBy);
|
|
708
|
-
};
|
|
709
|
-
/******** HIDE TOOLTIP AND CROSSHAIRS ********/
|
|
710
|
-
ScatterPlot.prototype.voronoiMouseOut = function () {
|
|
711
|
-
this.focusedSite = null;
|
|
712
|
-
this.focus.style("display", "none");
|
|
713
|
-
this.tooltip.hide();
|
|
714
|
-
this.labelMouseOut();
|
|
715
|
-
this.unhighlightDot();
|
|
716
|
-
};
|
|
717
|
-
/******** FILTER DATA BY VISIBLE AND STICKIED ********/
|
|
718
|
-
ScatterPlot.prototype.getVoronoiData = function (rawData) {
|
|
719
|
-
var _this = this;
|
|
720
|
-
var cleanData = this.cleanData(rawData);
|
|
721
|
-
var filteredValues = cleanData.filter(function (d) {
|
|
722
|
-
return (_this.chartComponentData.displayState[d.aggregateKey].visible &&
|
|
723
|
-
_this.chartComponentData.displayState[d.aggregateKey].splitBys[d.splitBy].visible);
|
|
724
|
-
});
|
|
725
|
-
if (this.chartComponentData.stickiedKey == null)
|
|
726
|
-
return filteredValues;
|
|
727
|
-
var stickiedValues = filteredValues.filter(function (d) {
|
|
728
|
-
return d.aggregateKey == _this.chartComponentData.stickiedKey.aggregateKey &&
|
|
729
|
-
((_this.chartComponentData.stickiedKey.splitBy == null) ? true :
|
|
730
|
-
d.splitBy == _this.chartComponentData.stickiedKey.splitBy);
|
|
731
|
-
});
|
|
732
|
-
return stickiedValues;
|
|
733
|
-
};
|
|
734
|
-
/******** HIGHLIGHT FOCUSED GROUP ********/
|
|
735
|
-
ScatterPlot.prototype.labelMouseOver = function (aggKey, splitBy) {
|
|
736
|
-
if (splitBy === void 0) { splitBy = null; }
|
|
737
|
-
// Remove highlight on previous legend group
|
|
738
|
-
this.legendObject.legendElement.selectAll('.tsi-splitByLabel').classed("inFocus", false);
|
|
739
|
-
// Filter selected
|
|
740
|
-
var selectedFilter = function (d) {
|
|
741
|
-
var currAggKey = null, currSplitBy = null;
|
|
742
|
-
if (d.aggregateKey != null)
|
|
743
|
-
currAggKey = d.aggregateKey;
|
|
744
|
-
if (d.splitBy != null)
|
|
745
|
-
currSplitBy = d.splitBy;
|
|
746
|
-
if (splitBy == null)
|
|
747
|
-
return currAggKey == aggKey;
|
|
748
|
-
if (currAggKey == aggKey && currSplitBy == splitBy)
|
|
749
|
-
return false;
|
|
750
|
-
return true;
|
|
751
|
-
};
|
|
752
|
-
//Highlight active group
|
|
753
|
-
this.svgSelection.selectAll(".tsi-dot")
|
|
754
|
-
.filter(function (d) { return !selectedFilter(d); })
|
|
755
|
-
.attr("stroke-opacity", this.standardStroke)
|
|
756
|
-
.attr("fill-opacity", this.focusOpacity);
|
|
757
|
-
// Decrease opacity of unselected
|
|
758
|
-
this.svgSelection.selectAll(".tsi-dot")
|
|
759
|
-
.filter(selectedFilter)
|
|
760
|
-
.attr("stroke-opacity", this.lowStroke)
|
|
761
|
-
.attr("fill-opacity", this.lowOpacity);
|
|
762
|
-
// Decrease opacity of unselected line
|
|
763
|
-
this.svgSelection.selectAll(".tsi-line")
|
|
764
|
-
.filter(function (d) { return !(d[0].aggregateKey === aggKey && d[0].splitBy === splitBy); })
|
|
765
|
-
.attr("stroke-opacity", this.lowStroke);
|
|
766
|
-
};
|
|
767
|
-
/******** UNHIGHLIGHT FOCUSED GROUP ********/
|
|
768
|
-
ScatterPlot.prototype.labelMouseOut = function () {
|
|
769
|
-
var _this = this;
|
|
770
|
-
// Remove highlight on legend group
|
|
771
|
-
this.legendObject.legendElement.selectAll('.tsi-splitByLabel').classed("inFocus", false);
|
|
772
|
-
this.g.selectAll(".tsi-dot")
|
|
773
|
-
.attr("stroke-opacity", this.standardStroke)
|
|
774
|
-
.attr("fill-opacity", this.standardOpacity)
|
|
775
|
-
.attr("stroke", function (d) { return Utils.colorSplitBy(_this.chartComponentData.displayState, d.splitByI, d.aggregateKey, _this.chartOptions.keepSplitByColor); })
|
|
776
|
-
.attr("fill", function (d) { return Utils.colorSplitBy(_this.chartComponentData.displayState, d.splitByI, d.aggregateKey, _this.chartOptions.keepSplitByColor); })
|
|
777
|
-
.attr("stroke-width", "1px");
|
|
778
|
-
this.g.selectAll(".tsi-line")
|
|
779
|
-
.attr("stroke-opacity", this.standardStroke);
|
|
780
|
-
};
|
|
781
|
-
/******** FILTER DATA, ONLY KEEPING POINTS WITH ALL REQUIRED MEASURES ********/
|
|
782
|
-
ScatterPlot.prototype.cleanData = function (data) {
|
|
783
|
-
var _this = this;
|
|
784
|
-
// Exclude any data which does not contain the specified
|
|
785
|
-
// chart option measure
|
|
786
|
-
var filtered = data.filter(function (value) {
|
|
787
|
-
var valOk = true;
|
|
788
|
-
_this.chartOptions.spMeasures
|
|
789
|
-
.forEach(function (measure) {
|
|
790
|
-
if (value.measures == null)
|
|
791
|
-
valOk = false;
|
|
792
|
-
else if (!(measure in value.measures)) {
|
|
793
|
-
valOk = false;
|
|
794
|
-
}
|
|
795
|
-
});
|
|
796
|
-
return valOk;
|
|
797
|
-
});
|
|
798
|
-
return filtered;
|
|
799
|
-
};
|
|
800
|
-
/******** UPDATE CHART DIMENSIONS ********/
|
|
801
|
-
ScatterPlot.prototype.setWidthAndHeight = function (isFromResize) {
|
|
802
|
-
if (isFromResize === void 0) { isFromResize = false; }
|
|
803
|
-
this.height = Math.max(d3.select(this.renderTarget).node().clientHeight, this.MINHEIGHT);
|
|
804
|
-
this.chartHeight = this.height - this.chartMargins.top - this.chartMargins.bottom;
|
|
805
|
-
this.width = this.getWidth();
|
|
806
|
-
if (!isFromResize) {
|
|
807
|
-
this.chartWidth = this.getChartWidth();
|
|
808
|
-
}
|
|
809
|
-
};
|
|
810
|
-
/******** SCALE AND DRAW AXIS ********/
|
|
811
|
-
ScatterPlot.prototype.drawAxis = function () {
|
|
812
|
-
// Draw dynamic x axis and label
|
|
813
|
-
this.xAxis = this.pointWrapper.selectAll(".xAxis").data([this.xScale]);
|
|
814
|
-
this.xAxis.enter()
|
|
815
|
-
.append("g")
|
|
816
|
-
.attr("class", "xAxis")
|
|
817
|
-
.merge(this.xAxis)
|
|
818
|
-
.attr("transform", "translate(0," + (this.chartHeight) + ")")
|
|
819
|
-
.call(d3.axisBottom(this.xScale).ticks(Math.max(2, Math.floor(this.chartWidth / 150))));
|
|
820
|
-
this.xAxis.exit().remove();
|
|
821
|
-
// Draw dynamic y axis and label
|
|
822
|
-
this.yAxis = this.pointWrapper.selectAll(".yAxis").data([this.yScale]);
|
|
823
|
-
this.yAxis.enter()
|
|
824
|
-
.append("g")
|
|
825
|
-
.attr("class", "yAxis")
|
|
826
|
-
.merge(this.yAxis)
|
|
827
|
-
.call(d3.axisLeft(this.yScale).ticks(Math.max(2, Math.floor(this.chartHeight / 90))));
|
|
828
|
-
this.yAxis.exit().remove();
|
|
829
|
-
};
|
|
830
|
-
/******** DRAW X AND Y AXIS LABELS ********/
|
|
831
|
-
ScatterPlot.prototype.drawAxisLabels = function () {
|
|
832
|
-
var self = this;
|
|
833
|
-
var xLabelData, yLabelData;
|
|
834
|
-
var truncateTextLength = function (textSelection, maxTextLengthPx) {
|
|
835
|
-
if (textSelection.node() && textSelection.node().getComputedTextLength) {
|
|
836
|
-
var textLength = textSelection.node().getComputedTextLength();
|
|
837
|
-
var text = textSelection.text();
|
|
838
|
-
while (textLength > maxTextLengthPx && text.length > 0) {
|
|
839
|
-
text = text.slice(0, -1);
|
|
840
|
-
textSelection.text(text + '...');
|
|
841
|
-
textLength = textSelection.node().getComputedTextLength();
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
};
|
|
845
|
-
// Associate axis label data
|
|
846
|
-
(this.chartOptions.spAxisLabels != null && this.chartOptions.spAxisLabels.length >= 1) ?
|
|
847
|
-
xLabelData = [this.chartOptions.spAxisLabels[0]] : xLabelData = [];
|
|
848
|
-
(this.chartOptions.spAxisLabels != null && this.chartOptions.spAxisLabels.length >= 2) ?
|
|
849
|
-
yLabelData = [this.chartOptions.spAxisLabels[1]] : yLabelData = [];
|
|
850
|
-
this.xAxisLabel = this.pointWrapper.selectAll('.tsi-xAxisLabel').data(xLabelData);
|
|
851
|
-
var xAxisLabel = this.xAxisLabel
|
|
852
|
-
.enter()
|
|
853
|
-
.append("text")
|
|
854
|
-
.attr("class", "tsi-xAxisLabel tsi-AxisLabel")
|
|
855
|
-
.merge(this.xAxisLabel)
|
|
856
|
-
.style("text-anchor", "middle")
|
|
857
|
-
.attr("transform", "translate(" + (this.chartWidth / 2) + " ," + (this.chartHeight + 42) + ")")
|
|
858
|
-
.text(null);
|
|
859
|
-
xAxisLabel.each(function (d) {
|
|
860
|
-
var label = d3.select(this);
|
|
861
|
-
Utils.appendFormattedElementsFromString(label, d, { inSvg: true });
|
|
862
|
-
});
|
|
863
|
-
//text is either in tspans or just in text. Either truncate text directly or through tspan
|
|
864
|
-
if (xAxisLabel.selectAll("tspan").size() == 0)
|
|
865
|
-
truncateTextLength(xAxisLabel, this.chartWidth);
|
|
866
|
-
else {
|
|
867
|
-
xAxisLabel.selectAll("tspan").each(function () {
|
|
868
|
-
var tspanTextSelection = d3.select(this);
|
|
869
|
-
truncateTextLength(tspanTextSelection, self.chartWidth / xAxisLabel.selectAll("tspan").size());
|
|
870
|
-
});
|
|
871
|
-
}
|
|
872
|
-
this.xAxisLabel.exit().remove();
|
|
873
|
-
this.yAxisLabel = this.pointWrapper.selectAll('.tsi-yAxisLabel').data(yLabelData);
|
|
874
|
-
var yAxisLabel = this.yAxisLabel
|
|
875
|
-
.enter()
|
|
876
|
-
.append("text")
|
|
877
|
-
.attr("class", "tsi-yAxisLabel tsi-AxisLabel")
|
|
878
|
-
.merge(this.yAxisLabel)
|
|
879
|
-
.style("text-anchor", "middle")
|
|
880
|
-
.attr("transform", "translate(" + (-70) + " ," + (this.chartHeight / 2) + ") rotate(-90)")
|
|
881
|
-
.text(null);
|
|
882
|
-
yAxisLabel.each(function (d) {
|
|
883
|
-
var label = d3.select(this);
|
|
884
|
-
Utils.appendFormattedElementsFromString(label, d, { inSvg: true });
|
|
885
|
-
});
|
|
886
|
-
//text is either in tspans or just in text. Either truncate text directly or through tspan
|
|
887
|
-
if (yAxisLabel.selectAll("tspan").size() == 0)
|
|
888
|
-
truncateTextLength(yAxisLabel, this.chartHeight);
|
|
889
|
-
else {
|
|
890
|
-
yAxisLabel.selectAll("tspan").each(function () {
|
|
891
|
-
var tspanTextSelection = d3.select(this);
|
|
892
|
-
truncateTextLength(tspanTextSelection, self.chartHeight / yAxisLabel.selectAll("tspan").size());
|
|
893
|
-
});
|
|
894
|
-
}
|
|
895
|
-
this.yAxisLabel.exit().remove();
|
|
896
|
-
};
|
|
897
|
-
/******** DRAW TOOLTIP IF ENABLED ********/
|
|
898
|
-
ScatterPlot.prototype.drawTooltip = function (d, mousePosition) {
|
|
899
|
-
var _this = this;
|
|
900
|
-
if (this.chartOptions.tooltip) {
|
|
901
|
-
var xPos = mousePosition[0];
|
|
902
|
-
var yPos = mousePosition[1];
|
|
903
|
-
var xyrMeasures_1 = [this.xMeasure, this.yMeasure];
|
|
904
|
-
if (this.rMeasure !== null) {
|
|
905
|
-
xyrMeasures_1.push(this.rMeasure);
|
|
906
|
-
}
|
|
907
|
-
this.tooltip.render(this.chartOptions.theme);
|
|
908
|
-
this.tooltip.draw(d, this.chartComponentData, xPos, yPos, this.chartMargins, function (text) {
|
|
909
|
-
d.aggregateName = _this.chartComponentData.displayState[d.aggregateKey].name;
|
|
910
|
-
_this.tooltipFormat(d, text, TooltipMeasureFormat.Scatter, xyrMeasures_1);
|
|
911
|
-
}, null, 20, 20, Utils.colorSplitBy(this.chartComponentData.displayState, d.splitByI, d.aggregateKey, this.chartOptions.keepSplitByColor));
|
|
912
|
-
}
|
|
913
|
-
};
|
|
914
|
-
/******** HELPERS TO FORMAT TIME DISPLAY ********/
|
|
915
|
-
ScatterPlot.prototype.labelFormatUsesSeconds = function () {
|
|
916
|
-
return !this.chartOptions.minutesForTimeLabels && this.chartComponentData.usesSeconds;
|
|
917
|
-
};
|
|
918
|
-
ScatterPlot.prototype.labelFormatUsesMillis = function () {
|
|
919
|
-
return !this.chartOptions.minutesForTimeLabels && this.chartComponentData.usesMillis;
|
|
920
|
-
};
|
|
921
|
-
return ScatterPlot;
|
|
922
|
-
}(ChartVisualizationComponent));
|
|
923
|
-
|
|
924
|
-
export { ScatterPlot as S };
|