UNPKG

166 kBJavaScriptView Raw
1import { a as __extends, _ as __assign } from './tslib.es6-863e3717.js';
2import { U as Utils, Y as YAxisStates, D as DataTypes, L as LINECHARTTOPPADDING, N as NONNUMERICTOPMARGIN, a as EventElementTypes, S as ShiftTypes, K as KeyCodes, M as MARKERVALUENUMERICHEIGHT, b as LINECHARTXOFFSET, V as VALUEBARHEIGHT, s as swimlaneLabelConstants, c as SERIESLABELWIDTH, d as LINECHARTCHARTMARGINS, T as TooltipMeasureFormat } from './Utils-5f9f1f09.js';
3import * as d3 from 'd3';
4import { area, scaleLinear, line, axisLeft, select, easeExp, event, drag, extent, mouse, scaleTime, set, brushX, voronoi, local } from 'd3';
5import { C as Component } from './Component-5b66527b.js';
6import { L as Legend } from './Legend-1be9e8e0.js';
7import { C as ChartComponentData } from './Grid-545284f2.js';
8import { T as TemporalXAxisComponent } from './TemporalXAxisComponent-daca2af1.js';
9import { C as ContextMenu } from './ContextMenu-4ba8fc74.js';
10import { T as Tooltip } from './Tooltip-4daae28d.js';
11import { interpolatePath } from 'd3-interpolate-path';
12
13var LineChartData = /** @class */ (function (_super) {
14 __extends(LineChartData, _super);
15 function LineChartData() {
16 var _this = _super.call(this) || this;
17 _this.timeMap = {};
18 _this._yExtents = [];
19 return _this;
20 }
21 Object.defineProperty(LineChartData.prototype, "yExtents", {
22 get: function () {
23 return this._yExtents;
24 },
25 enumerable: false,
26 configurable: true
27 });
28 LineChartData.prototype.setYExtents = function (idx, value) {
29 this._yExtents[idx] = value;
30 };
31 LineChartData.prototype.resetYExtents = function () {
32 this._yExtents = [];
33 for (var i = 0; i < this.data.length; i++) {
34 this._yExtents.push(null);
35 }
36 };
37 LineChartData.prototype.setTimeMap = function () {
38 this.timeMap = this.allValues.reduce(function (timeMap, currVal) {
39 var millis = currVal.dateTime.valueOf();
40 if (currVal.bucketSize != undefined) {
41 millis += (currVal.bucketSize / 2);
42 }
43 if (currVal.measures != null) {
44 if (timeMap[millis] == undefined) {
45 timeMap[millis] = [currVal];
46 }
47 else {
48 timeMap[millis].push(currVal);
49 }
50 }
51 return timeMap;
52 }, {});
53 };
54 LineChartData.prototype.mergeDataToDisplayStateAndTimeArrays = function (data, aggregateExpressionOptions) {
55 if (aggregateExpressionOptions === void 0) { aggregateExpressionOptions = null; }
56 _super.prototype.mergeDataToDisplayStateAndTimeArrays.call(this, data, aggregateExpressionOptions);
57 };
58 return LineChartData;
59}(ChartComponentData));
60
61var Plot = /** @class */ (function (_super) {
62 __extends(Plot, _super);
63 function Plot(renderTarget) {
64 var _this = _super.call(this, renderTarget) || this;
65 _this.backdropRect = null;
66 return _this;
67 }
68 Plot.prototype.getVisibleSeries = function (aggKey) {
69 var _this = this;
70 return Object.keys(this.chartComponentData.timeArrays[aggKey]).filter(function (s) {
71 return _this.chartComponentData.isSplitByVisible(aggKey, s);
72 });
73 };
74 Plot.prototype.createGradientKey = function (d, splitByIndex, i) {
75 return d.aggregateKey.replace(/^[^a-z]+|[^\w:.-]+/gi, "") + '_' + splitByIndex + '_' + i;
76 };
77 Plot.prototype.addGradientStops = function (d, gradient) {
78 var _this = this;
79 gradient.selectAll('stop').remove();
80 var colorMap = this.chartDataOptions.valueMap;
81 if (!d.measures) {
82 return;
83 }
84 //behavior if numeric measures
85 var allMeasuresNumeric = Object.keys(d.measures).reduce(function (p, currMeasure) {
86 return (typeof d.measures[currMeasure]) === 'number' && p;
87 }, true);
88 var sumOfMeasures;
89 if (allMeasuresNumeric) {
90 sumOfMeasures = Object.keys(d.measures).reduce(function (p, currMeasure) {
91 return p + d.measures[currMeasure];
92 }, 0);
93 if (sumOfMeasures <= 0) {
94 return;
95 }
96 }
97 var numMeasures = Object.keys(d.measures).length;
98 Object.keys(d.measures).reduce(function (p, currMeasure, i) {
99 var currFraction = allMeasuresNumeric ? (d.measures[currMeasure] / sumOfMeasures) : (i / numMeasures);
100 gradient.append('stop')
101 .attr("offset", (p * 100) + "%")
102 .attr("stop-color", _this.getColorForValue(currMeasure))
103 .attr("stop-opacity", 1);
104 var newFraction = allMeasuresNumeric ? (p + currFraction) : ((i + 1) / numMeasures);
105 gradient.append('stop')
106 .attr("offset", (newFraction * 100) + "%")
107 .attr("stop-color", _this.getColorForValue(currMeasure))
108 .attr("stop-opacity", 1);
109 return newFraction;
110 }, 0);
111 };
112 Plot.prototype.createBackdropRect = function (isVisible) {
113 this.backdropRect = this.aggregateGroup.selectAll('.tsi-backdropRect')
114 .data([isVisible]);
115 this.backdropRect.enter().append('rect')
116 .attr('class', 'tsi-backdropRect')
117 .attr('x', 0)
118 .attr('y', 0)
119 .merge(this.backdropRect)
120 .attr('visibility', function (d) { return d ? 'visible' : 'hidden'; })
121 .attr('width', this.x.range()[1])
122 .attr('height', this.height);
123 this.backdropRect.exit().remove();
124 };
125 Plot.prototype.getColorForValue = function (value) {
126 return Utils.getColorForValue(this.chartDataOptions, value);
127 };
128 Plot.prototype.getVisibleMeasures = function (measures) {
129 return Object.keys(measures).filter(function (measure) {
130 return measures[measure] !== 0;
131 });
132 };
133 Plot.prototype.hasData = function (d) {
134 return d.measures && (Object.keys(d.measures).length !== 0);
135 };
136 return Plot;
137}(Component));
138
139var LinePlot = /** @class */ (function (_super) {
140 __extends(LinePlot, _super);
141 function LinePlot(svgSelection) {
142 var _this = _super.call(this, svgSelection) || this;
143 _this.plotDataType = DataTypes.Numeric;
144 return _this;
145 }
146 LinePlot.prototype.getXPosition = function (d, x) {
147 var bucketSize = this.chartComponentData.displayState[d.aggregateKey].bucketSize;
148 if (bucketSize) {
149 return (x(d.dateTime) + x((new Date(d.dateTime.valueOf() + bucketSize)))) / 2;
150 }
151 return x(d.dateTime);
152 };
153 LinePlot.prototype.createAreaPath = function (y) {
154 var _this = this;
155 this.areaPath = area()
156 .curve(this.chartOptions.interpolationFunction)
157 .defined(function (d) {
158 return (d.measures !== null) &&
159 (d.measures[_this.chartComponentData.getVisibleMeasure(d.aggregateKey, d.splitBy)] !== null);
160 })
161 .x(function (d) {
162 return _this.getXPosition(d, _this.x);
163 })
164 .y0(function (d) {
165 return d.measures ? y(d.measures[_this.chartComponentData.getVisibleMeasure(d.aggregateKey, d.splitBy)]) : 0;
166 })
167 .y1(this.chartHeight);
168 };
169 // returns the next visibleAggI
170 LinePlot.prototype.render = function (chartOptions, visibleAggI, agg, aggVisible, aggregateGroup, chartComponentData, yAxisState, chartHeight, visibleAggCount, colorMap, previousAggregateData, x, areaPath, strokeOpacity, y, yMap, defs, chartDataOptions, previousIncludeDots, yTopAndHeight, svgSelection, categoricalMouseover, categoricalMouseout, yAxisOnClick) {
171 var _this = this;
172 this.previousIncludeDots = previousIncludeDots;
173 this.defs = defs;
174 this.chartOptions = chartOptions;
175 this.chartHeight = chartHeight;
176 this.visibleAggCount = visibleAggCount;
177 this.chartComponentData = chartComponentData;
178 this.x = x;
179 this.y = y;
180 var aggKey = agg.aggKey;
181 this.aggregateGroup = aggregateGroup;
182 var yAxisHasOnClick = yAxisOnClick && typeof yAxisOnClick === "function";
183 visibleAggI = yAxisState.positionInGroup;
184 this.yTop = yTopAndHeight[0];
185 this.height = yTopAndHeight[1];
186 var aggY;
187 var aggLine;
188 var aggEnvelope;
189 this.yAxisState = yAxisState;
190 var yExtent = this.yAxisState.yExtent;
191 aggY = scaleLinear();
192 aggY.range([this.height, this.chartOptions.aggTopMargin]);
193 if (this.chartComponentData.aggHasVisibleSplitBys(aggKey)) {
194 var yRange = (yExtent[1] - yExtent[0]) > 0 ? yExtent[1] - yExtent[0] : 1;
195 var yOffsetPercentage = 10 / (this.chartHeight / ((this.yAxisState.axisType === YAxisStates.Overlap) ? 1 : this.visibleAggCount));
196 var yDomainMin = this.chartOptions.isArea ?
197 (Math.max(yExtent[0] - (yRange * yOffsetPercentage), 0)) :
198 (yExtent[0] - (yRange * yOffsetPercentage));
199 aggY.domain([yDomainMin, yExtent[1] + (yRange * (10 / this.chartHeight))]);
200 }
201 else {
202 aggY.domain([0, 1]);
203 yExtent = [0, 1];
204 }
205 aggLine = line()
206 .curve(this.chartComponentData.displayState[aggKey].interpolationFunction ? d3[this.chartComponentData.displayState[aggKey].interpolationFunction] : this.chartOptions.interpolationFunction)
207 .defined(function (d) {
208 return (d.measures !== null) &&
209 (d.measures[_this.chartComponentData.getVisibleMeasure(d.aggregateKey, d.splitBy)] !== null);
210 })
211 .x(function (d) { return _this.getXPosition(d, _this.x); })
212 .y(function (d) {
213 return d.measures ? aggY(d.measures[_this.chartComponentData.getVisibleMeasure(d.aggregateKey, d.splitBy)]) : null;
214 });
215 aggEnvelope = area()
216 .curve(this.chartComponentData.displayState[aggKey].interpolationFunction ? d3[this.chartComponentData.displayState[aggKey].interpolationFunction] : this.chartOptions.interpolationFunction)
217 .defined(function (d) { return (d.measures !== null) && (d.measures['min'] !== null) && (d.measures['max'] !== null); })
218 .x(function (d) { return _this.getXPosition(d, _this.x); })
219 .y0(function (d) { return d.measures ? aggY(d.measures['max']) : 0; })
220 .y1(function (d) { return d.measures ? aggY(d.measures['min']) : 0; });
221 var localY = aggY.copy();
222 localY.range([this.yTop + this.height, this.yTop + this.chartOptions.aggTopMargin]);
223 yMap[aggKey] = localY;
224 var yAxis = this.aggregateGroup.selectAll(".yAxis")
225 .data([aggKey]);
226 var visibleYAxis = (aggVisible && (this.yAxisState.axisType !== YAxisStates.Shared || visibleAggI === 0));
227 yAxis = yAxis.enter()
228 .append("g")
229 .attr("class", "yAxis " + (yAxisHasOnClick ? "tsi-clickableYAxis tsi-swimLaneAxis-" + this.chartComponentData.displayState[aggKey].aggregateExpression.swimLane : ''))
230 .merge(yAxis)
231 .style("visibility", ((visibleYAxis && !this.chartOptions.yAxisHidden) ? "visible" : "hidden"));
232 if (this.yAxisState.axisType === YAxisStates.Overlap) {
233 yAxis.call(axisLeft(aggY).tickFormat(Utils.formatYAxisNumber).tickValues(yExtent))
234 .selectAll("text")
235 .attr("y", function (d, j) { return (j == 0) ? (-visibleAggI * 16) : (visibleAggI * 16); })
236 .style("fill", this.chartComponentData.displayState[aggKey].color);
237 }
238 else {
239 yAxis.call(axisLeft(aggY).tickFormat(Utils.formatYAxisNumber)
240 .ticks(Math.max(2, Math.ceil(this.height / (this.yAxisState.axisType === YAxisStates.Stacked ? this.visibleAggCount : 1) / 90))))
241 .selectAll("text").classed("standardYAxisText", true);
242 }
243 // If yAxisOnClick present, attach to yAxis
244 if (yAxisHasOnClick) {
245 yAxis.on("click", function () {
246 yAxisOnClick();
247 });
248 var label_1 = document.getElementsByClassName("tsi-swimLaneLabel-" + agg.swimLane)[0];
249 if (label_1) {
250 yAxis.on("mouseover", function () {
251 label_1.classList.add("tsi-axisHover");
252 yAxis.selectAll("text").classed("tsi-boldYAxisText", true);
253 });
254 yAxis.on("mouseout", function () {
255 label_1.classList.remove("tsi-axisHover");
256 yAxis.selectAll("text").classed("tsi-boldYAxisText", false);
257 });
258 }
259 }
260 yAxis.exit().remove();
261 var guideLinesData = {
262 x: this.x,
263 y: aggY,
264 visible: visibleYAxis
265 };
266 var splitByColors = Utils.createSplitByColors(this.chartComponentData.displayState, aggKey, this.chartOptions.keepSplitByColor);
267 var includeDots = this.chartOptions.includeDots || this.chartComponentData.displayState[aggKey].includeDots;
268 var self = this;
269 var splitByGroups = this.aggregateGroup.selectAll(".tsi-splitByGroup")
270 .data(Object.keys(this.chartComponentData.timeArrays[aggKey]));
271 splitByGroups.enter()
272 .append("g")
273 .attr("class", "tsi-splitByGroup " + agg.aggKey)
274 .merge(splitByGroups)
275 .each(function (splitBy, j) {
276 var _this = this;
277 colorMap[aggKey + "_" + splitBy] = splitByColors[j];
278 // creation of segments between each gap in the data
279 var segments = [];
280 var lineData = self.chartComponentData.timeArrays[aggKey][splitBy];
281 var visibleMeasure = self.chartComponentData.getVisibleMeasure(aggKey, splitBy);
282 for (var i = 0; i < lineData.length - 1; i++) {
283 if (lineData[i].measures !== null && lineData[i].measures[visibleMeasure] !== null) {
284 var scannerI = i + 1;
285 while (scannerI < lineData.length && ((lineData[scannerI].measures == null) ||
286 lineData[scannerI].measures[visibleMeasure] == null)) {
287 scannerI++;
288 }
289 if (scannerI < lineData.length && scannerI != i + 1) {
290 segments.push([lineData[i], lineData[scannerI]]);
291 }
292 i = scannerI - 1;
293 }
294 }
295 var durationFunction = function (d) {
296 var previousUndefined = previousAggregateData.get(_this) === undefined;
297 return (self.chartOptions.noAnimate || previousUndefined) ? 0 : self.TRANSDURATION;
298 };
299 var gapPath = select(this).selectAll(".tsi-gapLine")
300 .data(segments.map(function (d) {
301 d.inTransition = true;
302 return d;
303 }));
304 gapPath.enter()
305 .append("path")
306 .attr("class", "tsi-valueElement tsi-gapLine")
307 .merge(gapPath)
308 .style("visibility", function (d) {
309 return (self.chartComponentData.isSplitByVisible(aggKey, splitBy)) ? "visible" : "hidden";
310 })
311 .transition()
312 .duration(durationFunction)
313 .ease(easeExp)
314 .attr("stroke-dasharray", "5,5")
315 .attr("stroke", splitByColors[j])
316 .attrTween('d', function (d) {
317 var previous = select(this).attr('d');
318 var current = aggLine(d);
319 return interpolatePath(previous, current);
320 })
321 .on('end', function (d) {
322 d.inTransition = false;
323 });
324 var path = select(this).selectAll(".tsi-valueLine")
325 .data([self.chartComponentData.timeArrays[aggKey][splitBy]].map(function (d) {
326 d.inTransition = true;
327 return d;
328 }));
329 path.enter()
330 .append("path")
331 .attr("class", "tsi-valueElement tsi-valueLine")
332 .merge(path)
333 .style("visibility", function (d) {
334 return (self.chartComponentData.isSplitByVisible(aggKey, splitBy)) ? "visible" : "hidden";
335 })
336 .transition()
337 .duration(durationFunction)
338 .ease(easeExp)
339 .attr("stroke", splitByColors[j])
340 .attr("stroke-opacity", self.strokeOpacity)
341 .attrTween('d', function (d) {
342 var previous = select(this).attr('d');
343 var current = aggLine(d);
344 return interpolatePath(previous, current);
345 })
346 .on('end', function (d) {
347 d.inTransition = false;
348 });
349 if (self.chartOptions.includeDots || self.chartComponentData.displayState[aggKey].includeDots) {
350 var dots = select(this).selectAll(".tsi-valueDot")
351 .data(self.chartComponentData.timeArrays[aggKey][splitBy].filter(function (d) {
352 return d && d.measures && d.measures[self.chartComponentData.getVisibleMeasure(d.aggregateKey, d.splitBy)] !== null;
353 }), function (d, i) {
354 return d.dateTime.toString();
355 });
356 dots.enter()
357 .append('circle')
358 .attr('class', 'tsi-valueElement tsi-valueDot')
359 .attr('r', 3)
360 .merge(dots)
361 .style("visibility", function (d) {
362 return (self.chartComponentData.isSplitByVisible(aggKey, splitBy) && d.measures) ? "visible" : "hidden";
363 })
364 .transition()
365 .duration(function (d, i) {
366 return (self.previousIncludeDots.get(this) === true) ? durationFunction() : 0;
367 })
368 .ease(easeExp)
369 .attr("fill", splitByColors[j])
370 .attr('cx', function (d) { return self.getXPosition(d, self.x); })
371 .attr('cy', function (d) {
372 return d.measures ? aggY(d.measures[self.chartComponentData.getVisibleMeasure(d.aggregateKey, d.splitBy)]) : null;
373 })
374 .each(function () {
375 self.previousIncludeDots.set(this, includeDots);
376 });
377 dots.exit().remove();
378 }
379 else {
380 select(this).selectAll(".tsi-valueDot").remove();
381 }
382 var envelopeData = {};
383 if ((self.chartComponentData.displayState[aggKey].includeEnvelope || self.chartOptions.includeEnvelope) && self.chartComponentData.isPossibleEnvelope(aggKey, splitBy)) {
384 envelopeData = self.chartComponentData.timeArrays[aggKey][splitBy].map(function (d) { return (__assign(__assign({}, d), { isEnvelope: true })); });
385 }
386 var envelope = select(this).selectAll(".tsi-valueEnvelope")
387 .data([envelopeData]);
388 envelope.enter()
389 .append("path")
390 .attr("class", "tsi-valueElement tsi-valueEnvelope")
391 .merge(envelope)
392 .style("visibility", function (d) {
393 return (self.chartComponentData.isSplitByVisible(aggKey, splitBy)) ? "visible" : "hidden";
394 })
395 .transition()
396 .duration(durationFunction)
397 .ease(easeExp)
398 .style("fill", splitByColors[j])
399 .attr("fill-opacity", .2)
400 .attr("d", aggEnvelope);
401 if (self.chartOptions.isArea) {
402 self.createAreaPath(aggY);
403 var area = select(this).selectAll(".tsi-valueArea")
404 .data([self.chartComponentData.timeArrays[aggKey][splitBy]]);
405 // logic for shiny gradient fill via url()
406 var svgId = Utils.guid();
407 var lg = self.defs.selectAll('linearGradient')
408 .data([self.chartComponentData.timeArrays[aggKey][splitBy]]);
409 var gradient = lg.enter()
410 .append('linearGradient');
411 gradient.merge(lg)
412 .attr('id', svgId).attr('x1', '0%').attr('x2', '0%').attr('y1', '0%').attr('y2', '100%');
413 gradient.append('stop').attr('offset', '0%').attr('style', function () { return 'stop-color:' + splitByColors[j] + ';stop-opacity:.2'; });
414 gradient.append('stop').attr('offset', '100%').attr('style', function () { return 'stop-color:' + splitByColors[j] + ';stop-opacity:.03'; });
415 lg.exit().remove();
416 area.enter()
417 .append("path")
418 .attr("class", "tsi-valueArea")
419 .merge(area)
420 .style("fill", 'url(#' + (svgId) + ')')
421 .style("visibility", function (d) {
422 return (self.chartComponentData.isSplitByVisible(aggKey, splitBy)) ? "visible" : "hidden";
423 })
424 .transition()
425 .duration(durationFunction)
426 .ease(easeExp)
427 .attr("d", self.areaPath);
428 area.exit().remove();
429 }
430 gapPath.exit().remove();
431 path.exit().remove();
432 previousAggregateData.set(this, splitBy);
433 });
434 splitByGroups.exit().remove();
435 };
436 return LinePlot;
437}(Plot));
438
439var TOPMARGIN = 4;
440var CategoricalPlot = /** @class */ (function (_super) {
441 __extends(CategoricalPlot, _super);
442 function CategoricalPlot(svgSelection) {
443 var _this = _super.call(this, svgSelection) || this;
444 _this.plotDataType = DataTypes.Categorical;
445 return _this;
446 }
447 CategoricalPlot.prototype.onMouseover = function (d, rectWidth) {
448 var _this = this;
449 var visibleMeasures = this.getVisibleMeasures(d.measures);
450 this.hoverRect.attr('visibility', 'visible')
451 .attr('x', function () {
452 return _this.x(new Date(d.dateTime));
453 })
454 .attr('width', rectWidth)
455 .attr('height', Math.max(0, this.chartHeight + 1 - LINECHARTTOPPADDING))
456 .attr('fill', function () {
457 return visibleMeasures.length === 1 ? _this.getColorForValue(visibleMeasures[0]) : 'none';
458 });
459 };
460 CategoricalPlot.prototype.onMouseout = function () {
461 this.hoverRect.attr('visibility', 'hidden');
462 this.categoricalMouseout();
463 };
464 CategoricalPlot.prototype.createHoverRect = function () {
465 if (!this.hoverRect) {
466 this.hoverRect = this.chartGroup.append('rect')
467 .attr('class', 'tsi-categoricalHoverRect')
468 .attr('y', LINECHARTTOPPADDING)
469 .attr('height', this.chartHeight + 1);
470 }
471 else {
472 this.hoverRect.raise();
473 }
474 };
475 CategoricalPlot.prototype.getSeriesEndDate = function () {
476 if (this.chartDataOptions.searchSpan) {
477 return new Date(this.chartDataOptions.searchSpan.to);
478 }
479 return new Date(this.chartComponentData.toMillis);
480 };
481 CategoricalPlot.prototype.getBucketEndDate = function (d, i) {
482 var _this = this;
483 var data = this.chartComponentData.timeArrays[d.aggregateKey][d.splitBy];
484 if (i + 1 < data.length) {
485 return data[i + 1].dateTime;
486 }
487 else {
488 var shouldRoundEnd = Utils.safeNotNullOrUndefined(function () { return _this.chartDataOptions.searchSpan; }) && Utils.safeNotNullOrUndefined(function () { return _this.chartDataOptions.searchSpan.bucketSize; });
489 return shouldRoundEnd ? Utils.roundToMillis(this.getSeriesEndDate().valueOf(), Utils.parseTimeInput(this.chartDataOptions.searchSpan.bucketSize)) : this.getSeriesEndDate();
490 }
491 };
492 CategoricalPlot.prototype.render = function (chartOptions, visibleAggI, agg, aggVisible, aggregateGroup, chartComponentData, yExtent, chartHeight, visibleAggCount, colorMap, previousAggregateData, x, areaPath, strokeOpacity, y, yMap, defs, chartDataOptions, previousIncludeDots, yTopAndHeight, chartGroup, categoricalMouseover, categoricalMouseout) {
493 var _this = this;
494 this.chartOptions = chartOptions;
495 this.yTop = yTopAndHeight[0];
496 this.height = yTopAndHeight[1];
497 this.x = x;
498 this.chartComponentData = chartComponentData;
499 var aggKey = agg.aggKey;
500 this.chartDataOptions = chartDataOptions;
501 this.chartHeight = chartHeight;
502 this.chartGroup = chartGroup;
503 this.categoricalMouseover = categoricalMouseover;
504 this.aggregateGroup = aggregateGroup;
505 this.categoricalMouseout = categoricalMouseout;
506 this.createBackdropRect(true);
507 if (this.aggregateGroup.selectAll('defs').empty()) {
508 this.defs = this.aggregateGroup.append('defs');
509 }
510 if (this.aggregateGroup.selectAll('.tsi-splitBysGroup').empty()) {
511 this.splitBysGroup = this.aggregateGroup.append('g').classed('tsi-splitBysGroup', true);
512 }
513 var gradientData = [];
514 var durationFunction = function (d) {
515 var previousUndefined = previousAggregateData.get(_this) === undefined;
516 return (self.chartOptions.noAnimate || previousUndefined) ? 0 : self.TRANSDURATION;
517 };
518 var self = this;
519 this.createHoverRect();
520 var series = this.getVisibleSeries(aggKey);
521 var heightPerSeries = Math.max((self.chartDataOptions.height - (series.length * TOPMARGIN)) / series.length, 0);
522 var splitByGroups = this.splitBysGroup.selectAll(".tsi-splitByGroup")
523 .data(series, function (d) {
524 return d.splitBy;
525 });
526 splitByGroups.enter()
527 .append("g")
528 .attr("class", "tsi-splitByGroup " + agg.aggKey)
529 .merge(splitByGroups)
530 .attr('transform', function (d, i) {
531 return 'translate(0,' + (NONNUMERICTOPMARGIN + (i * (_this.chartDataOptions.height / series.length))) + ')';
532 })
533 .each(function (splitBy, j) {
534 var data = self.chartComponentData.timeArrays[aggKey][splitBy];
535 var categoricalBuckets = select(this).selectAll(".tsi-categoricalBucket")
536 .data(data);
537 var getWidth = function (d, i) {
538 var seriesWidth = self.x.range()[1] - self.x.range()[0];
539 var xPos1 = Math.max(self.x(new Date(d.dateTime)), 0);
540 var xPos2 = self.x(self.getBucketEndDate(d, i));
541 return Math.max(xPos2 - xPos1, 1);
542 };
543 categoricalBuckets.enter()
544 .append("rect")
545 .attr("class", "tsi-valueElement tsi-categoricalBucket")
546 .merge(categoricalBuckets)
547 .style("visibility", function (d) {
548 return (self.chartComponentData.isSplitByVisible(aggKey, splitBy) && self.hasData(d)) ? "visible" : "hidden";
549 })
550 .on('mouseover', function (d, i) {
551 var y = self.yTop + (j * (self.chartDataOptions.height / series.length));
552 var x = self.x(new Date(d.dateTime)) + (getWidth(d, i));
553 var shouldMouseover = self.categoricalMouseover(d, x, y + NONNUMERICTOPMARGIN, self.getBucketEndDate(d, i), getWidth(d, i));
554 if (shouldMouseover) {
555 self.onMouseover(d, getWidth(d, i));
556 }
557 })
558 .on('mouseout', function () {
559 self.onMouseout();
560 })
561 .attr('cursor', (self.chartDataOptions.onElementClick ? 'pointer' : 'inherit'))
562 .on('click', function (d) {
563 if (self.chartDataOptions.onElementClick) {
564 self.chartDataOptions.onElementClick(d.aggregateKey, d.splitBy, d.dateTime.toISOString(), d.measures);
565 }
566 })
567 .transition()
568 .duration(durationFunction)
569 .ease(easeExp)
570 .attr('height', heightPerSeries)
571 .attr('width', getWidth)
572 .attr('x', function (d) {
573 return self.x(new Date(d.dateTime));
574 })
575 .each(function (d, i) {
576 var gradientKey = self.createGradientKey(d, j, i);
577 gradientData.push([gradientKey, d]);
578 select(this)
579 .attr('fill', "url(#" + gradientKey + ")");
580 });
581 categoricalBuckets.exit().remove();
582 });
583 splitByGroups.exit().remove();
584 //corresponding linear gradients
585 var gradients = this.defs.selectAll('linearGradient')
586 .data(gradientData, function (d) {
587 return d[1].splitBy;
588 });
589 var enteredGradients = gradients.enter()
590 .append('linearGradient')
591 .attr("x2", "0%")
592 .attr("y2", "100%")
593 .merge(gradients)
594 .attr("id", function (d) { return d[0]; });
595 enteredGradients
596 .each(function (d) {
597 self.addGradientStops(d[1], select(this));
598 });
599 gradients.exit().remove();
600 };
601 return CategoricalPlot;
602}(Plot));
603
604var EventsPlot = /** @class */ (function (_super) {
605 __extends(EventsPlot, _super);
606 function EventsPlot(svgSelection) {
607 var _this = _super.call(this, svgSelection) || this;
608 _this.gradientArray = {};
609 _this.eventOnClick = function (d) {
610 if (_this.chartDataOptions.onElementClick) {
611 _this.chartDataOptions.onElementClick(d.aggregateKey, d.splitBy, d.dateTime.toISOString(), d.measures);
612 }
613 };
614 _this.colorFunction = function (d) {
615 if (d.measures) {
616 if (Object.keys(d.measures).length === 1) {
617 return _this.getColorForValue(Object.keys(d.measures)[0]);
618 }
619 else {
620 return 'grey';
621 }
622 }
623 return 'none';
624 };
625 _this.createDateStringFunction = function (shiftMillis) {
626 return Utils.timeFormat(_this.chartComponentData.usesSeconds, _this.chartComponentData.usesMillis, _this.chartOptions.offset, _this.chartOptions.is24HourTime, shiftMillis, null, _this.chartOptions.dateLocale);
627 };
628 _this.createEventElements = function (splitBy, g, splitByIndex) {
629 var sortEvents = function () {
630 enteredEvents.sort(function (a, b) {
631 if (a.dateTime < b.dateTime) {
632 return -1;
633 }
634 else if (a.dateTime > b.dateTime) {
635 return 1;
636 }
637 return 0;
638 });
639 };
640 var data = _this.chartComponentData.timeArrays[_this.aggKey][splitBy];
641 var discreteEvents = g.selectAll(".tsi-discreteEvent")
642 .data(data, function (d) { return d.dateTime; });
643 var self = _this;
644 var enteredEvents;
645 var shiftMillis = _this.chartComponentData.getTemporalShiftMillis(_this.aggKey);
646 var dateStringFn = _this.createDateStringFunction(shiftMillis);
647 switch (_this.chartDataOptions.eventElementType) {
648 case EventElementTypes.Teardrop:
649 if (discreteEvents.size() && discreteEvents.classed('tsi-discreteEventDiamond')) {
650 g.selectAll('.tsi-discreteEvent').remove();
651 discreteEvents = g.selectAll(".tsi-discreteEvent")
652 .data(data, function (d) { return d.dateTime; });
653 }
654 enteredEvents = discreteEvents.enter()
655 .append('path')
656 .attr('class', 'tsi-discreteEvent tsi-valueElement')
657 .merge(discreteEvents)
658 .classed('tsi-discreteEventDiamond', false)
659 .classed('tsi-discreteEventTeardrop', true)
660 .attr('transform', function (d) {
661 return 'translate(' + (_this.x(new Date(d.dateTime)) + _this.eventHeight / 2) + ',' + (_this.eventHeight * 1.4) + ') rotate(180)';
662 })
663 .attr('d', _this.teardropD(_this.eventHeight, _this.eventHeight))
664 .attr('stroke-width', Math.min(_this.eventHeight / 2.25, 8))
665 .attr('stroke', _this.colorFunction)
666 .attr('fill', 'none');
667 break;
668 case EventElementTypes.Diamond:
669 if (discreteEvents.size() && discreteEvents.classed('tsi-discreteEventTeardrop')) {
670 g.selectAll('.tsi-discreteEvent').remove();
671 discreteEvents = g.selectAll(".tsi-discreteEvent")
672 .data(data, function (d) { return d.dateTime; });
673 }
674 enteredEvents = discreteEvents.enter()
675 .append('rect')
676 .attr('class', 'tsi-discreteEvent tsi-valueElement')
677 .merge(discreteEvents)
678 .classed('tsi-discreteEventTeardrop', false)
679 .classed('tsi-discreteEventDiamond', true)
680 .attr('d', 'none')
681 .attr('transform', function (d) {
682 return 'translate(' + _this.x(new Date(d.dateTime)) + ',0) rotate(45)';
683 })
684 .attr('fill', _this.colorFunction)
685 .attr('stroke', 'none');
686 break;
687 }
688 enteredEvents
689 .attr('y', 0)
690 .attr('x', 0)
691 .attr('width', _this.eventHeight)
692 .attr('height', _this.eventHeight)
693 .on('mouseover', function (d) {
694 select(this).raise();
695 self.onMouseover(d, splitByIndex);
696 })
697 .on('mouseout', function () {
698 _this.onMouseout();
699 })
700 .on('click', function (d) {
701 _this.eventOnClick(d);
702 })
703 .on('touchstart', function (d) {
704 _this.eventOnClick(d);
705 })
706 .on('keydown', function (d) {
707 if (event.keyCode === 9) {
708 sortEvents();
709 select(this).node().focus();
710 }
711 if (event.keyCode === 32 || event.keyCode === 13) {
712 self.eventOnClick(d);
713 }
714 })
715 .attr('role', _this.chartDataOptions.onElementClick ? 'button' : null)
716 .attr('tabindex', _this.chartDataOptions.onElementClick ? '0' : null)
717 .attr('cursor', _this.chartDataOptions.onElementClick ? 'pointer' : 'inherit')
718 .attr('aria-label', function (d) {
719 if (_this.chartDataOptions.onElementClick) {
720 var dateString = dateStringFn(d);
721 var retString_1 = _this.getString('event in series') + " " + d.aggregateName + " " + _this.getString('at time') + " " + dateString + ".";
722 Object.keys(d.measures).forEach(function (mKey) {
723 retString_1 += " " + _this.getString('measure with key') + " " + mKey + " " + _this.getString('and value') + " " + d.measures[mKey] + ".";
724 });
725 return retString_1;
726 }
727 return null;
728 })
729 .style('visibility', function (d) {
730 return (self.chartComponentData.isSplitByVisible(_this.aggKey, splitBy) && self.hasData(d)) ? 'visible' : 'hidden';
731 })
732 .each(function (d, i) {
733 if (Object.keys(d.measures).length > 1) {
734 var gradientKey = self.createGradientKey(d, splitByIndex, i);
735 self.gradientData.push([gradientKey, d]);
736 select(this)
737 .attr(self.chartDataOptions.eventElementType === EventElementTypes.Teardrop ? 'stroke' : 'fill', "url(#" + gradientKey + ")");
738 }
739 });
740 discreteEvents.exit().remove();
741 };
742 _this.shouldDrawBackdrop = function () {
743 //check to see if this is the first aggregate within a collapsed swimlane.
744 var lane = _this.chartComponentData.getSwimlane(_this.aggKey);
745 if (!_this.chartOptions.swimLaneOptions || !_this.chartOptions.swimLaneOptions[lane] ||
746 !_this.chartOptions.swimLaneOptions[lane].collapseEvents) {
747 return true;
748 }
749 var eventSeriesInLane = Object.keys(_this.chartComponentData.displayState).filter(function (aggKey) {
750 return _this.chartComponentData.getSwimlane(aggKey) === lane;
751 });
752 return eventSeriesInLane.indexOf(_this.aggKey) === 0;
753 };
754 _this.plotDataType = DataTypes.Events;
755 return _this;
756 }
757 EventsPlot.prototype.onMouseover = function (d, seriesNumber) {
758 var _this = this;
759 var getX = function () {
760 return _this.x(new Date(d.dateTime));
761 };
762 var seriesWidth = Math.ceil(this.eventHeight * Math.sqrt(2));
763 var seriesTop = this.yTop + NONNUMERICTOPMARGIN + (seriesWidth * seriesNumber) + (seriesWidth / 2);
764 var shouldMouseover = this.discreteEventsMouseover(d, getX() + (seriesWidth / 2), seriesTop, seriesWidth);
765 if (!shouldMouseover) {
766 return;
767 }
768 var visibleMeasures = this.getVisibleMeasures(d.measures);
769 this.hoverLine.attr('visibility', 'visible')
770 .attr('x1', getX)
771 .attr('x2', getX)
772 .attr('y1', LINECHARTTOPPADDING)
773 .attr('y2', this.chartHeight + 1)
774 .attr('stroke', function () {
775 return visibleMeasures.length === 1 ? _this.getColorForValue(visibleMeasures[0]) : 'grey';
776 });
777 };
778 EventsPlot.prototype.onMouseout = function () {
779 this.hoverLine.attr('visibility', 'hidden');
780 this.discreteEventsMouseout();
781 };
782 EventsPlot.prototype.createHoverLine = function () {
783 if (!this.hoverLine) {
784 this.hoverLine = this.chartGroup.append('line')
785 .attr('class', 'tsi-discreteEventHoverLine')
786 .attr('y1', LINECHARTTOPPADDING)
787 .attr('y2', this.chartHeight + 1)
788 .attr('pointer-events', 'none')
789 .attr('visibility', 'hidden');
790 }
791 else {
792 this.hoverLine.raise();
793 }
794 };
795 EventsPlot.prototype.setEventHeight = function (visibleSeriesCount) {
796 var useableHeight = this.height - NONNUMERICTOPMARGIN;
797 this.eventHeight = Math.floor((useableHeight / visibleSeriesCount) / Math.sqrt(2));
798 };
799 EventsPlot.prototype.render = function (chartOptions, visibleAggI, agg, aggVisible, aggregateGroup, chartComponentData, yExtent, chartHeight, visibleAggCount, colorMap, previousAggregateData, x, areaPath, strokeOpacity, y, yMap, defs, chartDataOptions, previousIncludeDots, yTopAndHeight, chartGroup, discreteEventsMouseover, discreteEventsMouseout) {
800 var _this = this;
801 this.chartOptions = chartOptions;
802 this.yTop = yTopAndHeight[0];
803 this.height = yTopAndHeight[1];
804 this.x = x;
805 this.chartComponentData = chartComponentData;
806 this.aggKey = agg.aggKey;
807 this.chartDataOptions = chartDataOptions;
808 this.chartHeight = chartHeight;
809 this.chartGroup = chartGroup;
810 this.aggregateGroup = aggregateGroup;
811 this.discreteEventsMouseover = discreteEventsMouseover;
812 this.discreteEventsMouseout = discreteEventsMouseout;
813 this.createBackdropRect(this.shouldDrawBackdrop());
814 if (this.aggregateGroup.selectAll('defs').empty()) {
815 this.defs = this.aggregateGroup.append('defs');
816 }
817 this.createHoverLine();
818 var series = this.getVisibleSeries(agg.aggKey);
819 this.setEventHeight(series.length);
820 if (this.aggregateGroup.selectAll('.tsi-splitBysGroup').empty()) {
821 this.splitBysGroup = this.aggregateGroup.append('g').classed('tsi-splitBysGroup', true);
822 }
823 var self = this;
824 var splitByGroups = this.splitBysGroup.selectAll(".tsi-splitByGroup")
825 .data(series, function (d) {
826 return d.splitBy;
827 });
828 this.gradientData = [];
829 var enteredSplitByGroups = splitByGroups.enter()
830 .append("g")
831 .attr("class", "tsi-eventsGroup tsi-splitByGroup " + this.aggKey)
832 .merge(splitByGroups)
833 .attr('transform', function (d, i) {
834 return 'translate(0,' + (+(i * (_this.chartDataOptions.height / series.length))) + ')';
835 })
836 .each(function (splitBy, j) {
837 self.createEventElements(splitBy, select(this), j);
838 }).each(function () {
839 self.themify(select(this), self.chartOptions.theme);
840 });
841 splitByGroups.exit().remove();
842 var gradients = this.defs.selectAll('linearGradient')
843 .data(this.gradientData, function (d) {
844 return d[1].splitBy;
845 });
846 var enteredGradients = gradients.enter()
847 .append('linearGradient')
848 .attr("x2", "0%")
849 .attr("y2", "100%")
850 .merge(gradients)
851 .attr("id", function (d) { return d[0]; });
852 enteredGradients
853 .each(function (d) {
854 self.addGradientStops(d[1], select(this));
855 });
856 gradients.exit().remove();
857 };
858 return EventsPlot;
859}(Plot));
860
861var AxisState = /** @class */ (function () {
862 function AxisState(axisType, yExtent, positionInGroup) {
863 this.axisType = axisType;
864 this.yExtent = yExtent;
865 this.positionInGroup = positionInGroup;
866 }
867 return AxisState;
868}());
869
870var MARKERSTRINGMAXLENGTH = 250;
871var MARKERVALUEMAXWIDTH = 80;
872var Marker = /** @class */ (function (_super) {
873 __extends(Marker, _super);
874 function Marker(renderTarget) {
875 var _this = _super.call(this, renderTarget) || this;
876 _this.tooltipMap = {};
877 _this.labelText = '';
878 _this.markerIsDragging = false;
879 _this.isSeriesLabels = false;
880 _this.ADDITIONALRIGHTSIDEOVERHANG = 12;
881 _this.guid = Utils.guid();
882 return _this;
883 }
884 Marker.prototype.getGuid = function () {
885 return this.guid;
886 };
887 Marker.prototype.setMillis = function (millis) {
888 this.timestampMillis = millis;
889 };
890 Marker.prototype.getMillis = function () {
891 return this.timestampMillis;
892 };
893 // returns whether the string was trimmed to the max length
894 Marker.prototype.setLabelText = function (labelText) {
895 if (labelText.length > MARKERSTRINGMAXLENGTH) {
896 this.labelText = labelText.slice(0, MARKERSTRINGMAXLENGTH);
897 return true;
898 }
899 this.labelText = labelText;
900 return false;
901 };
902 Marker.prototype.getLabelText = function () {
903 return this.labelText;
904 };
905 Marker.prototype.setSeriesLabelText = function (d, text, isSeriesLabelInFocus) {
906 text.classed('tsi-isExpanded', false);
907 var title = text.append('h4')
908 .attr('class', 'tsi-seriesLabelGroupName tsi-tooltipTitle');
909 Utils.appendFormattedElementsFromString(title, d.aggregateName);
910 var shiftTuple = this.chartComponentData.getTemporalShiftStringTuple(d.aggregateKey);
911 var shiftString = '';
912 if (shiftTuple !== null) {
913 shiftString = shiftTuple[0] === ShiftTypes.startAt ? this.timeFormat(new Date(shiftTuple[1])) : shiftTuple[1];
914 }
915 var labelDatum = {
916 splitBy: d.splitBy,
917 variableAlias: this.chartComponentData.displayState[d.aggregateKey].aggregateExpression.variableAlias,
918 timeShift: shiftString,
919 };
920 var subtitle = text.selectAll('.tsi-seriesLabelSeriesName').data([labelDatum]);
921 var enteredSubtitle = subtitle.enter()
922 .append('div')
923 .attr('class', 'tsi-seriesLabelSeriesName tsi-tooltipSubtitle');
924 if (labelDatum.splitBy && labelDatum.splitBy !== '') {
925 enteredSubtitle.append('span')
926 .classed('tsi-splitBy', true);
927 }
928 if (labelDatum.timeShift) {
929 enteredSubtitle.append('span')
930 .classed('tsi-timeShift', true);
931 }
932 if (labelDatum.variableAlias) {
933 enteredSubtitle.append('span')
934 .classed('tsi-variableAlias', true);
935 }
936 subtitle.exit().remove();
937 Utils.setSeriesLabelSubtitleText(enteredSubtitle, false);
938 };
939 Marker.prototype.tooltipFormat = function (d, text, measureFormat, xyrMeasures, isSeriesLabelInFocus) {
940 if (isSeriesLabelInFocus === void 0) { isSeriesLabelInFocus = false; }
941 var tooltipHeight = MARKERVALUENUMERICHEIGHT;
942 // revert to default text format if none specified
943 if (!this.isSeriesLabels) {
944 text.text(Utils.formatYAxisNumber(this.getValueOfVisible(d)))
945 .style('height', tooltipHeight + 'px')
946 .style('line-height', ((tooltipHeight - 2) + 'px')); // - 2 to account for border height
947 }
948 else {
949 this.setSeriesLabelText(d, text, isSeriesLabelInFocus);
950 }
951 text.classed('tsi-markerValueTooltipInner', true)
952 .style('border-color', this.colorMap[d.aggregateKey + "_" + d.splitBy]);
953 };
954 Marker.prototype.getLeft = function (d) {
955 return Math.round(this.x(d.timestamp) + this.marginLeft);
956 };
957 // check to see if any marker is being dragged
958 Marker.prototype.isMarkerDragOccuring = function () {
959 return this.markerIsDragging;
960 };
961 Marker.prototype.bumpMarker = function () {
962 var _this = this;
963 select(this.renderTarget).selectAll('.tsi-markerContainer')
964 .style('animation', 'none')
965 .sort(function (a, b) {
966 if (a.timestamp === _this.timestampMillis) {
967 return 1;
968 }
969 if (b.timestamp === _this.timestampMillis) {
970 return -1;
971 }
972 return a.timestamp < b.timestamp ? 1 : -1;
973 });
974 };
975 Marker.prototype.renderMarker = function () {
976 var _this = this;
977 var self = this;
978 var marker = select(this.renderTarget).selectAll(".tsi-markerContainer")
979 .filter(function (d) { return d.guid === _this.guid; })
980 .data([{ guid: this.guid, timestamp: this.timestampMillis }]);
981 this.markerContainer = marker.enter()
982 .append('div')
983 .attr('class', 'tsi-markerContainer')
984 .classed('tsi-isSeriesLabels', this.isSeriesLabels)
985 .merge(marker)
986 .style('top', this.chartMargins.top + this.chartOptions.aggTopMargin + "px")
987 .style('height', this.chartHeight - (this.chartMargins.top + this.chartMargins.bottom + this.chartOptions.aggTopMargin) + "px")
988 .style('left', function (d) {
989 return _this.getLeft(d) + "px";
990 })
991 .classed('tsi-isFlipped', function (d) {
992 if (_this.isSeriesLabels) {
993 return false;
994 }
995 return (_this.chartOptions.labelSeriesWithMarker && _this.x(d.timestamp) > (_this.x.range()[1] - MARKERVALUEMAXWIDTH));
996 })
997 .each(function (markerD) {
998 if (self.isSeriesLabels) {
999 return;
1000 }
1001 if (select(this).selectAll('.tsi-markerLine').empty()) {
1002 select(this).append('div')
1003 .attr('class', 'tsi-markerLine');
1004 self.markerLabel = select(this).append('div')
1005 .attr('class', 'tsi-markerLabel')
1006 .on('mouseleave', function () {
1007 select(this).classed('tsi-markerLabelHovered', false);
1008 });
1009 self.markerLabel.append('div')
1010 .attr('class', 'tsi-markerGrabber')
1011 .on('mouseenter', function () {
1012 self.bumpMarker();
1013 });
1014 self.markerLabel.append('div')
1015 .attr('class', 'tsi-markerLabelText')
1016 .attr('contenteditable', 'true')
1017 .text(self.labelText)
1018 .on('keydown', function () {
1019 if (event.keyCode === KeyCodes.Enter && !event.shiftKey) {
1020 event.preventDefault();
1021 self.closeButton.node().focus();
1022 }
1023 })
1024 .on('input', function () {
1025 var didTrim = self.setLabelText(select(this).text());
1026 if (didTrim) {
1027 select(this).text(self.labelText);
1028 }
1029 })
1030 .on('focus', function () {
1031 select(this.parentNode).classed('tsi-markerLabelTextFocused', true);
1032 })
1033 .on('blur', function () {
1034 select(this.parentNode).classed('tsi-markerLabelTextFocused', false);
1035 self.onChange(false, false, false);
1036 })
1037 .on('mousedown', function () {
1038 event.stopPropagation();
1039 })
1040 .on('mouseover', function () {
1041 if (!self.isMarkerDragOccuring()) {
1042 select(select(this).node().parentNode).classed('tsi-markerLabelHovered', true);
1043 self.bumpMarker();
1044 }
1045 });
1046 self.closeButton = self.markerLabel.append("button")
1047 .attr("aria-label", self.getString('Delete marker'))
1048 .classed("tsi-closeButton", true)
1049 .on("click", function () {
1050 self.onChange(true, false);
1051 select(select(this).node().parentNode.parentNode).remove();
1052 });
1053 self.timeLabel = select(this).append("div")
1054 .attr('class', 'tsi-markerTimeLabel');
1055 }
1056 select(this).selectAll('.tsi-markerTimeLabel,.tsi-markerLine,.tsi-markerLabel')
1057 .call(drag()
1058 .on('start', function (d) {
1059 d.isDragging = true;
1060 self.markerIsDragging = true;
1061 self.bumpMarker();
1062 })
1063 .on('drag', function (d) {
1064 if (select(event.sourceEvent.target).classed('tsi-closeButton')) {
1065 return;
1066 }
1067 var marker = select(select(this).node().parentNode);
1068 var startPosition = self.x(new Date(self.timestampMillis));
1069 var newPosition = startPosition + event.x;
1070 self.timestampMillis = Utils.findClosestTime(self.x.invert(newPosition).valueOf(), self.chartComponentData.timeMap);
1071 self.setPositionsAndLabels(self.timestampMillis);
1072 })
1073 .on('end', function (d) {
1074 if (!select(event.sourceEvent.target).classed('tsi-closeButton')) {
1075 self.onChange(false, false);
1076 }
1077 d.isDragging = false;
1078 self.markerIsDragging = false;
1079 }));
1080 });
1081 marker.exit().remove();
1082 };
1083 Marker.prototype.getValueOfVisible = function (d) {
1084 return Utils.getValueOfVisible(d, this.chartComponentData.getVisibleMeasure(d.aggregateKey, d.splitBy));
1085 };
1086 Marker.prototype.getTooltipKey = function (d) {
1087 return d.aggregateKey + '_' + d.splitBy;
1088 };
1089 Marker.prototype.findYatX = function (x, path) {
1090 var pathParent = path.parentNode;
1091 var length_end = path.getTotalLength();
1092 var length_start = 0;
1093 var point = path.getPointAtLength((length_end + length_start) / 2);
1094 var bisection_iterations_max = 100;
1095 var bisection_iterations = 0;
1096 var error = 0.01;
1097 while (x < point.x - error || x > point.x + error) {
1098 point = path.getPointAtLength((length_end + length_start) / 2);
1099 if (x < point.x) {
1100 length_end = (length_start + length_end) / 2;
1101 }
1102 else {
1103 length_start = (length_start + length_end) / 2;
1104 }
1105 if (bisection_iterations_max < ++bisection_iterations) {
1106 break;
1107 }
1108 }
1109 var offset = path.parentNode.parentNode.transform.baseVal[0].matrix.f; // roundabout way of getting the y transform of the agg group
1110 return point.y + offset;
1111 };
1112 Marker.prototype.positionToValue = function (yPos, aggKey) {
1113 var yScale = this.yMap[aggKey];
1114 return yScale.invert(yPos);
1115 };
1116 Marker.prototype.bisectionInterpolateValue = function (millis, aggKey, splitBy, path) {
1117 if (path === null) {
1118 return null;
1119 }
1120 var yPosition = this.findYatX(this.x(millis), path);
1121 var interpolatedValue = this.positionToValue(yPosition, aggKey);
1122 var newDatum = this.createNewDatum(aggKey, splitBy, interpolatedValue);
1123 newDatum.isInterpolated = true;
1124 return newDatum;
1125 };
1126 Marker.prototype.getPath = function (aggKey, splitBy) {
1127 var selectedPaths = select(this.renderTarget).selectAll('.tsi-valueLine').filter(function (d) {
1128 if (d.length) {
1129 return d[0].aggregateKey === aggKey && d[0].splitBy === splitBy;
1130 }
1131 return false;
1132 });
1133 if (selectedPaths.size() === 0) {
1134 return null;
1135 }
1136 return selectedPaths.nodes()[0];
1137 };
1138 Marker.prototype.createNewDatum = function (aggKey, splitBy, valueOfVisible) {
1139 var newDatum = {};
1140 newDatum.aggregateKey = aggKey;
1141 newDatum.splitBy = splitBy;
1142 newDatum.measures = {};
1143 newDatum.measures[this.chartComponentData.getVisibleMeasure(aggKey, splitBy)] = valueOfVisible;
1144 return newDatum;
1145 };
1146 Marker.prototype.findGapPath = function (aggKey, splitBy, millis) {
1147 var gapPath = select(this.renderTarget).selectAll('.tsi-gapLine')
1148 .filter(function (d) {
1149 if (d.length === 2 && aggKey === d[0].aggregateKey && splitBy === d[0].splitBy) {
1150 return (millis > d[0].dateTime.valueOf() && millis < d[1].dateTime.valueOf());
1151 }
1152 return false;
1153 });
1154 if (gapPath.size() === 0) {
1155 return null;
1156 }
1157 return gapPath.nodes()[0];
1158 };
1159 //check if a value is within the time constrained bounds of a path
1160 Marker.prototype.inBounds = function (path, millis) {
1161 var _this = this;
1162 var filteredData = path.data()[0].filter(function (d) {
1163 return d.measures && _this.getValueOfVisible(d) !== null;
1164 });
1165 if (filteredData.length > 0) {
1166 var lowerBound = filteredData[0].dateTime.valueOf();
1167 var upperBound = filteredData[filteredData.length - 1].dateTime.valueOf();
1168 return millis >= lowerBound && millis <= upperBound;
1169 }
1170 return false;
1171 };
1172 Marker.prototype.getIntersectingPath = function (aggKey, splitBy, millis) {
1173 if (this.chartComponentData.displayState[aggKey].bucketSize) {
1174 millis = millis - (this.chartComponentData.displayState[aggKey].bucketSize / 2);
1175 }
1176 var gapPath = this.findGapPath(aggKey, splitBy, millis);
1177 if (gapPath) {
1178 return gapPath;
1179 }
1180 else {
1181 return this.inBounds(select(this.getPath(aggKey, splitBy)), millis) ? this.getPath(aggKey, splitBy) : null;
1182 }
1183 };
1184 Marker.prototype.interpolateValue = function (millis, aggKey, splitBy) {
1185 var path = this.getIntersectingPath(aggKey, splitBy, millis);
1186 if (path === null) {
1187 return null;
1188 }
1189 return this.bisectionInterpolateValue(millis, aggKey, splitBy, path);
1190 };
1191 Marker.prototype.getValuesAtTime = function (closestTime) {
1192 var _this = this;
1193 var valueArray = [];
1194 var values = this.chartComponentData.timeMap[closestTime] != undefined ? this.chartComponentData.timeMap[closestTime] : [];
1195 Object.keys(this.chartComponentData.visibleTAs).forEach(function (aggKey) {
1196 Object.keys(_this.chartComponentData.visibleTAs[aggKey]).forEach(function (splitBy) {
1197 if (_this.chartComponentData.displayState[aggKey].dataType !== DataTypes.Numeric) {
1198 return;
1199 }
1200 var filteredValues = values.filter(function (v) {
1201 return (v.aggregateKey === aggKey && v.splitBy === splitBy && _this.getValueOfVisible(v) !== null);
1202 });
1203 if (filteredValues.length === 1 && (_this.getValueOfVisible(filteredValues[0]) !== null)) {
1204 valueArray.push(filteredValues[0]);
1205 }
1206 else {
1207 var interpolatedValue = _this.interpolateValue(closestTime, aggKey, splitBy);
1208 if (interpolatedValue !== null || !_this.isSeriesLabels) {
1209 valueArray.push(interpolatedValue);
1210 }
1211 else {
1212 var lastValue = _this.chartComponentData.findLastTimestampWithValue(aggKey, splitBy);
1213 if (lastValue !== null) {
1214 valueArray.push(lastValue);
1215 }
1216 }
1217 }
1218 });
1219 });
1220 return valueArray;
1221 };
1222 Marker.prototype.setValueLabels = function (closestTime) {
1223 var _this = this;
1224 var values = this.getValuesAtTime(closestTime);
1225 values = values.filter(function (d) {
1226 return d && _this.chartComponentData.getDataType(d.aggregateKey) === DataTypes.Numeric;
1227 });
1228 var self = this;
1229 var valueLabels = this.markerContainer.selectAll(".tsi-markerValue").data(values, function (d) {
1230 return d.aggregateKey + "_" + d.splitBy;
1231 });
1232 valueLabels.enter()
1233 .append("div")
1234 .classed("tsi-markerValue", true)
1235 .classed('tsi-seriesLabelValue', this.isSeriesLabels)
1236 .merge(valueLabels)
1237 .classed('tsi-isInterpolated', function (d) {
1238 return d.isInterpolated;
1239 })
1240 .style('top', function (d) { return _this.calcTopOfValueLabel(d) + 'px'; })
1241 .each(function (d) {
1242 var tooltipKey = self.getTooltipKey(d);
1243 var tooltip;
1244 if (self.tooltipMap[tooltipKey]) {
1245 tooltip = self.tooltipMap[tooltipKey];
1246 }
1247 else {
1248 tooltip = new Tooltip(select(this));
1249 self.tooltipMap[tooltipKey] = tooltip;
1250 }
1251 tooltip.render(self.chartOptions.theme);
1252 tooltip.draw(d, self.chartComponentData, 0, MARKERVALUENUMERICHEIGHT / 2, { right: 0, left: 0, top: 0, bottom: 0 }, function (tooltipTextElement) {
1253 self.tooltipFormat(d, tooltipTextElement, null, null);
1254 }, null, 0, 0, self.colorMap[d.aggregateKey + "_" + d.splitBy], true);
1255 var markerValueCaret = select(this).selectAll('.tsi-markerValueCaret')
1256 .data([d]);
1257 markerValueCaret.enter().append('div')
1258 .attr('class', 'tsi-markerValueCaret')
1259 .merge(markerValueCaret)
1260 .style("border-right-color", function () { return self.colorMap[d.aggregateKey + "_" + d.splitBy]; });
1261 markerValueCaret.exit().remove();
1262 });
1263 var valueLabelsExit = valueLabels.exit();
1264 valueLabelsExit.each(function (d) {
1265 delete _this.tooltipMap[_this.getTooltipKey(d)];
1266 });
1267 valueLabelsExit.remove();
1268 };
1269 Marker.prototype.calcTopOfValueLabel = function (d) {
1270 var yScale = this.yMap[d.aggregateKey];
1271 return Math.round(yScale(this.getValueOfVisible(d)) - this.chartOptions.aggTopMargin);
1272 };
1273 Marker.prototype.getTimeFormat = function () {
1274 return Utils.timeFormat(this.chartComponentData.usesSeconds, this.chartComponentData.usesMillis, this.chartOptions.offset, this.chartOptions.is24HourTime, 0, null, this.chartOptions.dateLocale);
1275 };
1276 Marker.prototype.setTimeLabel = function (closestTime) {
1277 if (this.isSeriesLabels) {
1278 return;
1279 }
1280 var values = this.chartComponentData.timeMap[closestTime];
1281 if (values == undefined || values.length == 0) {
1282 return;
1283 }
1284 var firstValue = values[0].dateTime;
1285 var secondValue = new Date(values[0].dateTime.valueOf() + (values[0].bucketSize != null ? values[0].bucketSize : 0));
1286 this.timeLabel.text('');
1287 this.timeLabel.append('div')
1288 .attr('class', 'tsi-markerTimeLine')
1289 .text(this.timeFormat(firstValue));
1290 if (values[0].bucketSize !== null) {
1291 this.timeLabel.append('div')
1292 .attr('class', 'tsi-markerTimeLine')
1293 .text(this.timeFormat(secondValue));
1294 }
1295 var markerLeft = Number(this.markerContainer.style("left").replace("px", ""));
1296 var timeLabelWidth = Math.round(this.timeLabel.node().getBoundingClientRect().width);
1297 var minLeftPosition = this.marginLeft + LINECHARTXOFFSET;
1298 var width = this.x.range()[1] - this.x.range()[0];
1299 var maxRightPosition = width + this.marginLeft + LINECHARTXOFFSET + this.ADDITIONALRIGHTSIDEOVERHANG;
1300 var calculatedLeftPosition = markerLeft - (timeLabelWidth / 2);
1301 var calculatedRightPosition = markerLeft + (timeLabelWidth / 2);
1302 var translate = "translateX(calc(-50% + 1px))";
1303 if (calculatedLeftPosition < minLeftPosition) {
1304 translate = "translateX(-" + Math.max(0, markerLeft - minLeftPosition) + "px)";
1305 }
1306 if (calculatedRightPosition > maxRightPosition) {
1307 translate = "translateX(calc(-50% + " + (maxRightPosition - calculatedRightPosition) + "px))";
1308 }
1309 this.timeLabel
1310 .style("-webkit-tranform", translate)
1311 .style("transform", translate);
1312 };
1313 Marker.prototype.focusCloseButton = function () {
1314 if (this.closeButton) {
1315 this.closeButton.node().focus();
1316 }
1317 };
1318 Marker.prototype.isMarkerInRange = function (millis) {
1319 if (millis === void 0) { millis = this.timestampMillis; }
1320 var domain = this.x.domain();
1321 return !(millis < domain[0].valueOf() || millis > domain[1].valueOf());
1322 };
1323 Marker.prototype.destroyMarker = function () {
1324 if (this.markerContainer) {
1325 this.markerContainer.remove();
1326 }
1327 this.tooltipMap = {};
1328 this.markerContainer = null;
1329 };
1330 Marker.prototype.render = function (timestampMillis, chartOptions, chartComponentData, additionalMarkerFields) {
1331 this.chartMargins = Object.assign({}, additionalMarkerFields.chartMargins);
1332 this.chartHeight = additionalMarkerFields.chartHeight;
1333 this.timestampMillis = timestampMillis;
1334 this.chartOptions = chartOptions;
1335 this.x = additionalMarkerFields.x;
1336 this.chartComponentData = chartComponentData;
1337 this.marginLeft = additionalMarkerFields.marginLeft;
1338 this.colorMap = additionalMarkerFields.colorMap;
1339 this.timeFormat = this.getTimeFormat();
1340 this.isSeriesLabels = additionalMarkerFields.isSeriesLabels;
1341 if (additionalMarkerFields.labelText) {
1342 this.labelText = additionalMarkerFields.labelText;
1343 }
1344 this.yMap = additionalMarkerFields.yMap;
1345 if (additionalMarkerFields.onChange) { // only update onChange if passed in, otherwise maintain previous
1346 this.onChange = additionalMarkerFields.onChange;
1347 }
1348 if (!this.isMarkerInRange(this.timestampMillis)) {
1349 this.destroyMarker();
1350 return;
1351 }
1352 this.renderMarker();
1353 var closestTime = Utils.findClosestTime(this.timestampMillis, this.chartComponentData.timeMap);
1354 this.setPositionsAndLabels(closestTime);
1355 _super.prototype.themify.call(this, this.markerContainer, this.chartOptions.theme);
1356 };
1357 Marker.prototype.setPositionsAndLabels = function (millis) {
1358 if (!this.isMarkerInRange(millis)) {
1359 this.destroyMarker();
1360 return;
1361 }
1362 this.renderMarker();
1363 this.setTimeLabel(millis);
1364 this.setValueLabels(millis);
1365 };
1366 return Marker;
1367}(Component));
1368
1369var LineChart = /** @class */ (function (_super) {
1370 __extends(LineChart, _super);
1371 function LineChart(renderTarget) {
1372 var _this = _super.call(this, renderTarget) || this;
1373 _this.minBrushWidth = 1;
1374 _this.strokeOpacity = 1;
1375 _this.nonFocusStrokeOpactiy = .3;
1376 _this.chartComponentData = new LineChartData();
1377 _this.surpressBrushTimeSet = false;
1378 _this.hasStackedButton = false;
1379 _this.stackedButton = null;
1380 _this.horizontalLabelOffset = LINECHARTCHARTMARGINS.left + swimlaneLabelConstants.leftMarginOffset;
1381 _this.markers = {};
1382 _this.seriesLabelsMarker = null;
1383 _this.markerGuidMap = {};
1384 _this.isDroppingMarker = false;
1385 _this.brushStartPosition = null;
1386 _this.brushEndPosition = null;
1387 _this.hasBrush = false;
1388 _this.isClearingBrush = false;
1389 _this.previousAggregateData = local();
1390 _this.previousIncludeDots = local();
1391 _this.mx = null;
1392 _this.my = null;
1393 _this.focusedAggKey = null;
1394 _this.focusedSplitby = null;
1395 _this.plotComponents = {};
1396 _this.isFirstMarkerDrop = true;
1397 _this.xOffset = 8;
1398 _this.swimlaneYExtents = {}; // mapping of swimlanes to the y extents of that swimlane
1399 _this.swimLaneContents = {};
1400 _this.resetValueElementsFocus = function () {
1401 _this.svgSelection.selectAll(".tsi-valueElement")
1402 .attr("stroke-opacity", _this.strokeOpacity)
1403 .filter(function () {
1404 return !select(this).classed("tsi-valueEnvelope");
1405 })
1406 .attr("fill-opacity", 1);
1407 _this.svgSelection.selectAll(".tsi-valueEnvelope")
1408 .attr("fill-opacity", .2);
1409 Utils.revertAllSubtitleText(select(_this.renderTarget).selectAll('.tsi-markerValue'));
1410 _this.focusedAggKey = null;
1411 _this.focusedSplitby = null;
1412 };
1413 _this.triggerLineFocus = function (aggKey, splitBy) {
1414 _this.focusedAggKey = null;
1415 _this.focusedSplitby = null;
1416 _this.focusOnlyHoveredSeries(aggKey, splitBy, true);
1417 };
1418 _this.focusOnlyHoveredSeries = function (aggKey, splitBy, shouldSetFocusedValues) {
1419 if (aggKey !== _this.focusedAggKey || splitBy !== _this.focusedSplitby) {
1420 var selectedFilter = Utils.createValueFilter(aggKey, splitBy);
1421 _this.focusMarkerLabel(selectedFilter, aggKey, splitBy);
1422 _this.svgSelection.selectAll(".tsi-valueElement")
1423 .attr("stroke-opacity", _this.nonFocusStrokeOpactiy)
1424 .attr("fill-opacity", .3);
1425 _this.svgSelection.selectAll(".tsi-valueEnvelope")
1426 .attr("fill-opacity", .1);
1427 _this.svgSelection.selectAll(".tsi-valueElement")
1428 .filter(selectedFilter)
1429 .attr("stroke-opacity", _this.strokeOpacity)
1430 .attr("fill-opacity", 1);
1431 _this.svgSelection.selectAll(".tsi-valueEnvelope")
1432 .filter(selectedFilter)
1433 .attr("fill-opacity", .3);
1434 if (shouldSetFocusedValues) {
1435 _this.focusedAggKey = aggKey;
1436 _this.focusedSplitby = splitBy;
1437 }
1438 }
1439 };
1440 _this.discreteEventsMouseover = function (d, x, y, width) {
1441 if (_this.isDroppingMarker) {
1442 return false;
1443 }
1444 _this.legendObject.triggerSplitByFocus(d.aggregateKey, d.splitBy);
1445 _this.focusOnlyHoveredSeries(d.aggregateKey, d.splitBy, true);
1446 var xPos = x;
1447 var yPos = y + _this.chartMargins.top;
1448 var yValue = _this.getValueOfVisible(d);
1449 if (_this.chartOptions.tooltip) {
1450 _this.tooltip.render(_this.chartOptions.theme);
1451 _this.tooltip.draw(d, _this.chartComponentData, xPos, y, _this.chartMargins, function (text) {
1452 _this.tooltipFormat(d, text, TooltipMeasureFormat.SingleValue);
1453 }, width, 0, 0);
1454 }
1455 else
1456 _this.tooltip.hide();
1457 return true;
1458 };
1459 _this.discreteEventsMouseout = function () {
1460 _this.legendObject.legendElement.selectAll('.tsi-splitByLabel').classed("inFocus", false);
1461 _this.resetValueElementsFocus();
1462 _this.tooltip.hide();
1463 };
1464 //returns false if supressed via isDroppingMarker, true otherwise
1465 _this.categoricalMouseover = function (d, x, y, endDate, width) {
1466 if (_this.isDroppingMarker) {
1467 return false;
1468 }
1469 _this.legendObject.triggerSplitByFocus(d.aggregateKey, d.splitBy);
1470 _this.focusOnlyHoveredSeries(d.aggregateKey, d.splitBy, true);
1471 var xPos = x;
1472 var yPos = y + _this.chartMargins.top;
1473 var yValue = _this.getValueOfVisible(d);
1474 if (_this.chartOptions.tooltip) {
1475 _this.tooltip.render(_this.chartOptions.theme);
1476 _this.tooltip.draw(d, _this.chartComponentData, xPos, y, _this.chartMargins, function (text) {
1477 d.endDate = endDate;
1478 _this.tooltipFormat(d, text, TooltipMeasureFormat.SingleValue);
1479 }, width, 0, 0);
1480 }
1481 else
1482 _this.tooltip.hide();
1483 return true;
1484 };
1485 _this.categoricalMouseout = function () {
1486 _this.legendObject.legendElement.selectAll('.tsi-splitByLabel').classed("inFocus", false);
1487 _this.resetValueElementsFocus();
1488 _this.tooltip.hide();
1489 };
1490 _this.voronoiMouseover = function (d) {
1491 //supress if the context menu is visible
1492 if (_this.contextMenu && _this.contextMenu.contextMenuVisible)
1493 return;
1494 var shiftMillis = _this.chartComponentData.getTemporalShiftMillis(d.aggregateKey);
1495 var yScale = _this.yMap[d.aggregateKey];
1496 var xValue = d.dateTime;
1497 var xPos = _this.getXPosition(d, _this.x);
1498 var yValue = _this.getValueOfVisible(d);
1499 var yPos = yScale(yValue);
1500 _this.focus.style("display", "block");
1501 _this.focus.attr("transform", "translate(" + xPos + "," + yPos + ")");
1502 _this.focus.select('.tsi-hLine').attr("transform", "translate(" + (-xPos) + ",0)");
1503 _this.focus.select('.tsi-vLine').attr("transform", "translate(0," + (-yPos) + ")");
1504 _this.setHorizontalValuePosAndText(d, xPos + _this.getSVGLeftOffset() + _this.chartMargins.left, xValue, shiftMillis);
1505 _this.setVerticalValueAndPosition(yValue, yPos + _this.chartMargins.top);
1506 var bucketSize = _this.chartComponentData.displayState[d.aggregateKey].bucketSize;
1507 var endValue = bucketSize ? (new Date(xValue.valueOf() + bucketSize)) : null;
1508 if (endValue) {
1509 var barWidth = _this.x(endValue) - _this.x(xValue);
1510 _this.horizontalValueBar
1511 .style('display', 'block')
1512 .attr("x1", (-barWidth / 2))
1513 .attr("x2", (barWidth / 2))
1514 .attr('y1', _this.chartHeight - yPos + 2)
1515 .attr('y2', _this.chartHeight - yPos + 2);
1516 }
1517 else {
1518 _this.horizontalValueBar.style('display', 'none');
1519 }
1520 if (_this.chartOptions.tooltip) {
1521 _this.tooltip.render(_this.chartOptions.theme);
1522 _this.tooltip.draw(d, _this.chartComponentData, xPos, yPos, _this.chartMargins, function (text) {
1523 _this.tooltipFormat(d, text, TooltipMeasureFormat.Enveloped);
1524 }, null, 20, 20, _this.colorMap[d.aggregateKey + "_" + d.splitBy]);
1525 }
1526 else
1527 _this.tooltip.hide();
1528 _this.focus.node().parentNode.appendChild(_this.focus.node());
1529 _this.legendObject.triggerSplitByFocus(d.aggregateKey, d.splitBy);
1530 /** update the y axis for in focus aggregate */
1531 if (_this.chartOptions.yAxisState === YAxisStates.Overlap) {
1532 _this.svgSelection.selectAll(".yAxis")
1533 .selectAll("text")
1534 .style("fill-opacity", .5)
1535 .classed("standardYAxisText", true);
1536 _this.svgSelection.selectAll(".yAxis")
1537 .filter(function (yAxisAggKey) {
1538 return yAxisAggKey == d.aggregateKey;
1539 })
1540 .selectAll("text")
1541 .style("fill-opacity", 1)
1542 .classed("standardYAxisText", false)
1543 .style("font-weight", "bold");
1544 }
1545 if (_this.chartOptions.yAxisHidden) {
1546 _this.svgSelection.selectAll(".yAxis").style("display", "hidden");
1547 }
1548 if (_this.chartOptions.xAxisHidden) {
1549 _this.svgSelection.selectAll(".xAxis").style("display", "none");
1550 }
1551 _this.chartOptions.onMouseover(d.aggregateKey, d.splitBy);
1552 };
1553 _this.stickyOrUnstickySeries = function (aggKey, splitBy) {
1554 if (_this.chartComponentData.stickiedKey && _this.chartComponentData.stickiedKey.aggregateKey === aggKey &&
1555 _this.chartComponentData.stickiedKey.splitBy === splitBy) {
1556 _this.unstickySeries(aggKey, splitBy);
1557 }
1558 else {
1559 _this.stickySeries(aggKey, splitBy);
1560 }
1561 };
1562 _this.unstickySeries = function (aggKey, splitby) {
1563 if (splitby === void 0) { splitby = null; }
1564 if (_this.getDataType(aggKey) !== DataTypes.Numeric || !_this.chartOptions.shouldSticky) {
1565 return;
1566 }
1567 _this.chartComponentData.stickiedKey = null;
1568 _this.legendObject.legendElement.selectAll('.tsi-splitByLabel').classed("stickied", false);
1569 // recompute voronoi with no sticky
1570 _this.voronoiDiagram = _this.voronoi(_this.getFilteredAndSticky(_this.chartComponentData.allValues));
1571 _this.chartOptions.onUnsticky(aggKey, splitby);
1572 };
1573 _this.stickySeries = function (aggregateKey, splitBy) {
1574 if (splitBy === void 0) { splitBy = null; }
1575 if (_this.getDataType(aggregateKey) !== DataTypes.Numeric || !_this.chartOptions.shouldSticky) {
1576 return;
1577 }
1578 var filteredValues = _this.getFilteredAndSticky(_this.chartComponentData.allValues);
1579 if (filteredValues == null || filteredValues.length == 0)
1580 return;
1581 _this.focusedAggKey = null;
1582 _this.focusedSplitby = null;
1583 _this.chartComponentData.stickiedKey = {
1584 aggregateKey: aggregateKey,
1585 splitBy: (splitBy == null ? null : splitBy)
1586 };
1587 _this.legendObject.legendElement.selectAll('.tsi-splitByLabel').filter(function (filteredSplitBy) {
1588 return (select(this.parentNode).datum() == aggregateKey) && (filteredSplitBy == splitBy);
1589 }).classed("stickied", true);
1590 _this.voronoiDiagram = _this.voronoi(_this.getFilteredAndSticky(_this.chartComponentData.allValues));
1591 _this.chartOptions.onSticky(aggregateKey, splitBy);
1592 };
1593 _this.filteredValueExist = function () {
1594 var filteredValues = _this.getFilteredAndSticky(_this.chartComponentData.allValues);
1595 return !(filteredValues == null || filteredValues.length == 0);
1596 };
1597 _this.addMarker = function () {
1598 if (_this.isFirstMarkerDrop) {
1599 _this.isFirstMarkerDrop = false;
1600 _this.createMarkerInstructions();
1601 }
1602 _this.isDroppingMarker = !_this.isDroppingMarker;
1603 if (!_this.isDroppingMarker) {
1604 _this.destroyMarkerInstructions();
1605 return;
1606 }
1607 Utils.focusOnEllipsisButton(_this.renderTarget);
1608 var marker = new Marker(_this.renderTarget);
1609 var markerUID = Utils.guid();
1610 var onChange = _this.createOnMarkerChange(markerUID, marker);
1611 _this.activeMarker = marker;
1612 _this.markerGuidMap[markerUID] = marker;
1613 _this.renderMarker(marker, Infinity, onChange, _this.getString('Marker') + " " + Object.keys(_this.markerGuidMap).length);
1614 };
1615 _this.labelMouseout = function () {
1616 if (_this.svgSelection) {
1617 Utils.revertAllSubtitleText(select(_this.renderTarget).selectAll('.tsi-markerValue'));
1618 _this.svgSelection.selectAll(".tsi-valueElement")
1619 .filter(function () { return !select(this).classed("tsi-valueEnvelope"); })
1620 .attr("stroke-opacity", 1)
1621 .attr("fill-opacity", 1);
1622 _this.svgSelection.selectAll(".tsi-valueEnvelope")
1623 .attr("fill-opacity", .3);
1624 }
1625 };
1626 _this.labelMouseover = function (aggregateKey, splitBy) {
1627 if (splitBy === void 0) { splitBy = null; }
1628 _this.focusOnlyHoveredSeries(aggregateKey, splitBy, false);
1629 };
1630 _this.nextStackedState = function () {
1631 if (_this.chartOptions.yAxisState === YAxisStates.Stacked)
1632 return "shared";
1633 else if (_this.chartOptions.yAxisState === YAxisStates.Shared)
1634 return "overlap";
1635 else
1636 return "stacked";
1637 };
1638 _this.MINHEIGHT = 26;
1639 _this.chartMargins = Object.assign({}, LINECHARTCHARTMARGINS);
1640 return _this;
1641 }
1642 LineChart.prototype.LineChart = function () {
1643 };
1644 //get the left and right positions of the brush
1645 LineChart.prototype.getBrushPositions = function () {
1646 var leftPos = null;
1647 var rightPos = null;
1648 if (this.brushStartTime) {
1649 var rawLeft = this.x(this.brushStartTime);
1650 if (rawLeft >= 0 && rawLeft <= this.chartWidth)
1651 leftPos = Math.round(rawLeft + this.chartMargins.left);
1652 }
1653 if (this.brushEndTime) {
1654 var rawRight = this.x(this.brushEndTime);
1655 if (rawRight >= 0 && rawRight <= this.chartWidth)
1656 rightPos = Math.round(rawRight + this.chartMargins.left);
1657 }
1658 return {
1659 leftPos: leftPos,
1660 rightPos: rightPos
1661 };
1662 };
1663 LineChart.prototype.hideFocusElements = function () {
1664 this.focus.style('display', 'none');
1665 this.verticalValueBox.style('display', 'none');
1666 this.horizontalValueBox.style('display', 'none');
1667 };
1668 LineChart.prototype.voronoiMouseout = function (d) {
1669 //supress if the context menu is visible
1670 if (this.contextMenu && this.contextMenu.contextMenuVisible)
1671 return;
1672 this.hideFocusElements();
1673 this.tooltip.hide();
1674 this.legendObject.legendElement.selectAll('.tsi-splitByLabel').classed("inFocus", false);
1675 if (event && event.type != 'end') {
1676 event.stopPropagation();
1677 }
1678 this.resetValueElementsFocus();
1679 /** Update y Axis */
1680 if (this.chartOptions.yAxisState == YAxisStates.Overlap) {
1681 this.svgSelection.selectAll(".yAxis")
1682 .selectAll("text")
1683 .style("fill-opacity", 1)
1684 .classed("standardYAxisText", false)
1685 .style("font-weight", "normal");
1686 }
1687 };
1688 LineChart.prototype.createMarkerInstructions = function () {
1689 this.targetElement.selectAll(".tsi-markerInstructions").remove();
1690 this.targetElement.append("div")
1691 .classed("tsi-markerInstructions", true)
1692 .text(this.getString("Click to drop marker") + "," + this.getString("drag to reposition") + ".");
1693 };
1694 LineChart.prototype.destroyMarkerInstructions = function () {
1695 this.targetElement.selectAll(".tsi-markerInstructions").remove();
1696 };
1697 LineChart.prototype.getMouseoverFunction = function (chartType) {
1698 if (chartType === void 0) { chartType = DataTypes.Numeric; }
1699 switch (chartType) {
1700 case DataTypes.Categorical:
1701 return this.categoricalMouseover;
1702 case DataTypes.Events:
1703 return this.discreteEventsMouseover;
1704 default:
1705 return function () { };
1706 }
1707 };
1708 LineChart.prototype.getMouseoutFunction = function (chartType) {
1709 if (chartType === void 0) { chartType = DataTypes.Numeric; }
1710 switch (chartType) {
1711 case DataTypes.Categorical:
1712 return this.categoricalMouseout;
1713 case DataTypes.Events:
1714 return this.discreteEventsMouseout;
1715 default:
1716 return function () { };
1717 }
1718 };
1719 LineChart.prototype.mismatchingChartType = function (aggKey) {
1720 if (!this.plotComponents[aggKey]) {
1721 return false;
1722 }
1723 var typeOfPlot = this.plotComponents[aggKey].plotDataType;
1724 return typeOfPlot !== this.getDataType(aggKey);
1725 };
1726 LineChart.prototype.setHorizontalValuePosAndText = function (d, xPos, xValue, shiftMillis) {
1727 var bucketSize = this.chartComponentData.displayState[d.aggregateKey].bucketSize;
1728 var endValue = bucketSize ? (new Date(xValue.valueOf() + bucketSize)) : null;
1729 this.horizontalValueBox.text('')
1730 .style('left', xPos + "px")
1731 .style('top', (this.chartMargins.top + this.chartHeight + VALUEBARHEIGHT) + "px")
1732 .style('display', 'block');
1733 this.horizontalValueBox.append('div')
1734 .attr('class', 'tsi-valueBoxText')
1735 .text(Utils.timeFormat(this.chartComponentData.usesSeconds, this.chartComponentData.usesMillis, this.chartOptions.offset, this.chartOptions.is24HourTime, shiftMillis, null, this.chartOptions.dateLocale)(xValue));
1736 if (endValue !== null) {
1737 this.horizontalValueBox.append('div')
1738 .attr('class', 'tsi-valueBoxText')
1739 .text(Utils.timeFormat(this.chartComponentData.usesSeconds, this.chartComponentData.usesMillis, this.chartOptions.offset, this.chartOptions.is24HourTime, shiftMillis, null, this.chartOptions.dateLocale)(endValue));
1740 }
1741 };
1742 LineChart.prototype.setVerticalValueAndPosition = function (yValue, yPos) {
1743 this.verticalValueBox.style('top', yPos + "px")
1744 .style('right', (this.chartMargins.right + this.chartWidth) + "px")
1745 .style('display', 'block')
1746 .text(Utils.formatYAxisNumber(yValue));
1747 };
1748 //get the extent of an array of timeValues
1749 LineChart.prototype.getYExtent = function (aggValues, isEnvelope, aggKey) {
1750 var _this = this;
1751 if (aggKey === void 0) { aggKey = null; }
1752 var extent$1;
1753 if (aggKey !== null && (this.chartComponentData.displayState[aggKey].yExtent !== null)) {
1754 return this.chartComponentData.displayState[aggKey].yExtent;
1755 }
1756 if (this.chartOptions.yExtent !== null) {
1757 return this.chartOptions.yExtent;
1758 }
1759 if (isEnvelope) {
1760 var filteredValues = this.getFilteredValues(aggValues);
1761 var flatValuesList = [];
1762 filteredValues.forEach(function (d) {
1763 if (_this.chartComponentData.isPossibleEnvelope(d.aggregateKey, d.splitBy)) {
1764 if (d.measures['min'] != undefined && d.measures['min'] != null) {
1765 flatValuesList.push(d.measures['min']);
1766 }
1767 if (d.measures['avg'] != undefined && d.measures['avg'] != null) {
1768 flatValuesList.push(d.measures['avg']);
1769 }
1770 if (d.measures['max'] != undefined && d.measures['max'] != null) {
1771 flatValuesList.push(d.measures['max']);
1772 }
1773 }
1774 else {
1775 var visibleMeasure = _this.chartComponentData.getVisibleMeasure(d.aggregateKey, d.splitBy);
1776 if (d.measures[visibleMeasure] != undefined && d.measures[visibleMeasure] != null) {
1777 flatValuesList.push(d.measures[visibleMeasure]);
1778 }
1779 }
1780 });
1781 extent$1 = extent(flatValuesList);
1782 }
1783 else {
1784 extent$1 = extent(this.getFilteredValues(aggValues), function (d) {
1785 var visibleMeasure = _this.chartComponentData.getVisibleMeasure(d.aggregateKey, d.splitBy);
1786 if (d.measures[visibleMeasure] != undefined && d.measures[visibleMeasure] != null) {
1787 return d.measures[visibleMeasure];
1788 }
1789 return null;
1790 });
1791 }
1792 if (extent$1[0] == undefined || extent$1[1] == undefined)
1793 return [0, 1];
1794 return extent$1;
1795 };
1796 LineChart.prototype.getFilteredValues = function (aggValues) {
1797 var _this = this;
1798 return aggValues.filter(function (d) {
1799 return (d.measures && _this.getValueOfVisible(d) !== null);
1800 });
1801 };
1802 LineChart.prototype.getFilteredAndSticky = function (aggValues) {
1803 var _this = this;
1804 var filteredValues = this.getFilteredValues(aggValues);
1805 var numericFiltered = filteredValues.filter(function (d) {
1806 return (_this.getDataType(d.aggregateKey) === DataTypes.Numeric);
1807 });
1808 if (this.chartComponentData.stickiedKey == null)
1809 return numericFiltered;
1810 return numericFiltered.filter(function (d) {
1811 return d.aggregateKey == _this.chartComponentData.stickiedKey.aggregateKey &&
1812 ((_this.chartComponentData.stickiedKey.splitBy == null) ? true :
1813 d.splitBy == _this.chartComponentData.stickiedKey.splitBy);
1814 });
1815 };
1816 LineChart.prototype.getHandleHeight = function () {
1817 return Math.min(Math.max(this.chartHeight / 2, 24), this.chartHeight + 8);
1818 };
1819 LineChart.prototype.getXPosition = function (d, x) {
1820 var bucketSize = this.chartComponentData.displayState[d.aggregateKey].bucketSize;
1821 if (bucketSize)
1822 return (x(d.dateTime) + x((new Date(d.dateTime.valueOf() + bucketSize)))) / 2;
1823 return x(d.dateTime);
1824 };
1825 LineChart.prototype.setBrushStartTime = function (startTime) {
1826 this.brushStartTime = startTime;
1827 };
1828 LineChart.prototype.setBrushEndTime = function (endTime) {
1829 this.brushEndTime = endTime;
1830 };
1831 LineChart.prototype.setBrush = function () {
1832 if (this.brushStartTime && this.brushEndTime && this.brushElem && this.brush) {
1833 var rawLeftSide = this.x(this.brushStartTime);
1834 var rawRightSide = this.x(this.brushEndTime);
1835 //if selection is out of range of brush. clear brush
1836 this.brushElem.call(this.brush.move, null);
1837 if ((rawRightSide < this.xOffset) || (rawLeftSide > (this.chartWidth - (2 * this.xOffset)))) {
1838 this.isClearingBrush = true;
1839 this.brushElem.call(this.brush.move, null);
1840 return;
1841 }
1842 var leftSide = Math.min(this.chartWidth - (2 * this.xOffset), Math.max(this.xOffset, this.x(this.brushStartTime)));
1843 var rightSide = Math.min(this.chartWidth - (2 * this.xOffset), Math.max(this.xOffset, this.x(this.brushEndTime)));
1844 this.surpressBrushTimeSet = true;
1845 this.brushStartPosition = leftSide;
1846 this.brushEndPosition = rightSide;
1847 //small adjusetment so that width is always at least 1 pixel
1848 if (rightSide - leftSide < 1) {
1849 if (rightSide + 1 > this.chartWidth - (2 * this.xOffset)) {
1850 leftSide += -1;
1851 }
1852 else {
1853 rightSide += 1;
1854 }
1855 }
1856 this.brushElem.call(this.brush.move, [leftSide, rightSide]);
1857 }
1858 };
1859 LineChart.prototype.findClosestValidTime = function (rawMillis) {
1860 var minDiff = Infinity;
1861 return Object.keys(this.chartComponentData.timeMap).reduce(function (closestValue, currValue) {
1862 var diff = Math.abs(Number(currValue) - rawMillis);
1863 if (diff < minDiff) {
1864 minDiff = diff;
1865 return Number(currValue);
1866 }
1867 return closestValue;
1868 }, Infinity);
1869 };
1870 LineChart.prototype.getMarkerMarginLeft = function () {
1871 var legendWidth = this.legendObject.legendElement.node().getBoundingClientRect().width;
1872 return this.chartMargins.left + (this.chartOptions.legend === "shown" || this.chartOptions.legend === "hidden" ? legendWidth : 0) +
1873 (this.chartOptions.legend === "shown" ? this.GUTTERWIDTH : 0);
1874 };
1875 LineChart.prototype.exportMarkers = function () {
1876 var _this = this;
1877 this.chartOptions.markers = Object.keys(this.markerGuidMap)
1878 .filter(function (markerGuid) { return !_this.activeMarker || _this.activeMarker.getGuid() !== markerGuid; })
1879 .map(function (markerGuid) { return [_this.markerGuidMap[markerGuid].getMillis(), _this.markerGuidMap[markerGuid].getLabelText()]; });
1880 this.chartOptions.onMarkersChange(this.chartOptions.markers);
1881 };
1882 LineChart.prototype.createOnMarkerChange = function (markerGuid, marker) {
1883 var _this = this;
1884 return function (isDeleting, droppedMarker, shouldSort) {
1885 if (shouldSort === void 0) { shouldSort = true; }
1886 if (droppedMarker) {
1887 _this.markerGuidMap[markerGuid] = marker;
1888 }
1889 else if (isDeleting) {
1890 delete _this.markerGuidMap[markerGuid];
1891 //set focus to first marker if markers exist on delete
1892 var visibleMarkers = Object.values(_this.markerGuidMap).filter(function (marker) {
1893 return marker.isMarkerInRange();
1894 });
1895 if (visibleMarkers.length !== 0) {
1896 visibleMarkers[0].focusCloseButton();
1897 }
1898 else {
1899 _this.focusOnEllipsis();
1900 }
1901 }
1902 _this.exportMarkers();
1903 if (shouldSort)
1904 _this.sortMarkers();
1905 };
1906 };
1907 LineChart.prototype.renderMarker = function (marker, millis, onChange, labelText, isSeriesLabels) {
1908 if (onChange === void 0) { onChange = null; }
1909 if (labelText === void 0) { labelText = null; }
1910 if (isSeriesLabels === void 0) { isSeriesLabels = false; }
1911 marker.render(millis, this.chartOptions, this.chartComponentData, {
1912 chartMargins: this.chartMargins,
1913 x: this.x,
1914 marginLeft: this.getMarkerMarginLeft() + (isSeriesLabels ? this.getAdditionalOffsetFromHorizontalMargin() : 0),
1915 colorMap: this.colorMap,
1916 yMap: this.yMap,
1917 onChange: onChange,
1918 chartHeight: this.height,
1919 isDropping: false,
1920 labelText: labelText,
1921 isSeriesLabels: isSeriesLabels
1922 });
1923 };
1924 LineChart.prototype.sortMarkers = function () {
1925 select(this.renderTarget).selectAll(".tsi-markerContainer").sort(function (a, b) {
1926 return (a.timestamp < b.timestamp) ? 1 : -1;
1927 });
1928 };
1929 LineChart.prototype.getAllLinesTransitionsComplete = function () {
1930 var _this = this;
1931 return new Promise(function (resolve, reject) {
1932 var checkAllLines = function (numberOfAttempts) {
1933 if (numberOfAttempts === void 0) { numberOfAttempts = 0; }
1934 if (numberOfAttempts < 5) {
1935 setTimeout(function () {
1936 var allOutOfTransition = true;
1937 select(_this.renderTarget).selectAll('.tsi-gapLine').data().forEach(function (d) {
1938 allOutOfTransition = allOutOfTransition && !d.inTransition;
1939 });
1940 select(_this.renderTarget).selectAll('.tsi-valueLine').data().forEach(function (d) {
1941 allOutOfTransition = allOutOfTransition && !d.inTransition;
1942 });
1943 if (allOutOfTransition) {
1944 resolve(null);
1945 }
1946 else {
1947 checkAllLines(numberOfAttempts + 1);
1948 }
1949 }, Math.max(_this.TRANSDURATION, 250));
1950 }
1951 else {
1952 reject();
1953 }
1954 };
1955 checkAllLines(0);
1956 });
1957 };
1958 LineChart.prototype.importMarkers = function () {
1959 var _this = this;
1960 if (this.chartOptions.markers && this.chartOptions.markers.length > 0) {
1961 // delete all the old markers
1962 if (Object.keys(this.markerGuidMap).length) {
1963 Object.keys(this.markerGuidMap).forEach(function (guid) {
1964 _this.markerGuidMap[guid].destroyMarker();
1965 delete _this.markerGuidMap[guid];
1966 });
1967 }
1968 this.markerGuidMap = {};
1969 this.chartOptions.markers.forEach(function (markerValueTuples, markerIndex) {
1970 if (markerValueTuples === null || markerValueTuples === undefined) {
1971 return;
1972 }
1973 var marker = new Marker(_this.renderTarget);
1974 var markerUID = Utils.guid();
1975 var markerMillis;
1976 if (typeof markerValueTuples === 'number') {
1977 markerMillis = markerValueTuples;
1978 marker.setLabelText(_this.getString('Marker') + " " + (markerIndex + 1));
1979 }
1980 else {
1981 marker.setLabelText(markerValueTuples[1]);
1982 markerMillis = markerValueTuples[0];
1983 }
1984 marker.setMillis(markerMillis);
1985 _this.markerGuidMap[markerUID] = marker;
1986 });
1987 this.renderAllMarkers();
1988 this.sortMarkers();
1989 }
1990 };
1991 LineChart.prototype.createSeriesLabelsMarker = function () {
1992 this.seriesLabelsMarker = new Marker(this.renderTarget);
1993 };
1994 LineChart.prototype.renderSeriesLabelsMarker = function () {
1995 if (this.chartOptions.labelSeriesWithMarker) {
1996 this.renderMarker(this.seriesLabelsMarker, this.x.domain()[1], function () { }, null, true);
1997 }
1998 };
1999 LineChart.prototype.renderAllMarkers = function () {
2000 var _this = this;
2001 this.getAllLinesTransitionsComplete().then(function () {
2002 Object.keys(_this.markerGuidMap).forEach(function (guid) {
2003 var marker = _this.markerGuidMap[guid];
2004 var onChange = _this.createOnMarkerChange(guid, marker);
2005 _this.renderMarker(marker, marker.getMillis(), onChange);
2006 });
2007 if (_this.seriesLabelsMarker) {
2008 _this.renderSeriesLabelsMarker();
2009 }
2010 });
2011 };
2012 LineChart.prototype.focusOnEllipsis = function () {
2013 if (this.ellipsisContainer !== null) {
2014 this.ellipsisContainer.select(".tsi-ellipsisButton").node().focus();
2015 }
2016 };
2017 LineChart.prototype.voronoiExists = function () {
2018 return (this.getVisibleNumerics() !== 0);
2019 };
2020 LineChart.prototype.voronoiMousemove = function (mouseEvent) {
2021 if (!this.filteredValueExist() || !this.voronoiExists())
2022 return;
2023 this.mx = mouseEvent[0];
2024 this.my = mouseEvent[1];
2025 var mx = mouseEvent[0], my = mouseEvent[1];
2026 var site = this.voronoiDiagram.find(this.mx, this.my);
2027 if (!this.isDroppingMarker) {
2028 this.voronoiMouseover(site.data);
2029 }
2030 else {
2031 var rawTime = this.x.invert(mx);
2032 var closestTime = Utils.findClosestTime(rawTime.valueOf(), this.chartComponentData.timeMap);
2033 this.renderMarker(this.activeMarker, closestTime);
2034 return;
2035 }
2036 if (site.data.aggregateKey !== this.focusedAggKey || site.data.splitBy !== this.focusedSplitby) {
2037 var selectedFilter = Utils.createValueFilter(site.data.aggregateKey, site.data.splitBy);
2038 this.focusMarkerLabel(selectedFilter, site.data.aggregateKey, site.data.splitBy);
2039 this.focusOnlyHoveredSeries(site.data.aggregateKey, site.data.splitBy, true);
2040 }
2041 };
2042 LineChart.prototype.voronoiContextMenu = function (mouseEvent) {
2043 if (!this.filteredValueExist() || !this.voronoiExists())
2044 return;
2045 var _a = mouse(mouseEvent), mx = _a[0], my = _a[1];
2046 var site = this.voronoiDiagram.find(mx, my);
2047 if (this.chartComponentData.displayState[site.data.aggregateKey].contextMenuActions &&
2048 this.chartComponentData.displayState[site.data.aggregateKey].contextMenuActions.length) {
2049 var mousePosition = mouse(this.targetElement.node());
2050 var sitePageCoords = void 0;
2051 if (this.hasBrush) {
2052 sitePageCoords = this.brushElem.node().getBoundingClientRect();
2053 }
2054 else {
2055 sitePageCoords = this.voronoiRegion.node().getBoundingClientRect();
2056 }
2057 var eventSite = { pageX: sitePageCoords.left + site[0], pageY: sitePageCoords.top + site[1] - 12 };
2058 event.preventDefault();
2059 this.contextMenu.draw(this.chartComponentData, this.renderTarget, this.chartOptions, mousePosition, site.data.aggregateKey, site.data.splitBy, null, site.data.dateTime, null, eventSite);
2060 if (this.brushContextMenu) {
2061 this.brushContextMenu.hide();
2062 }
2063 this.voronoiMouseover(site.data);
2064 }
2065 };
2066 LineChart.prototype.voronoiClick = function (mouseEvent) {
2067 var _this = this;
2068 //supress if the context menu is visible
2069 if (this.contextMenu && this.contextMenu.contextMenuVisible)
2070 return;
2071 if (!this.filteredValueExist() || !this.voronoiExists())
2072 return;
2073 if (this.brushElem && !this.isDroppingMarker)
2074 return;
2075 var _a = mouse(mouseEvent), mx = _a[0], my = _a[1];
2076 var site = this.voronoiDiagram.find(mx, my);
2077 var cDO = this.getCDOFromAggKey(site.data.aggregateKey);
2078 if (!this.isDroppingMarker) {
2079 if (site.data && cDO.onElementClick !== null) {
2080 cDO.onElementClick(site.data.aggregateKey, site.data.splitBy, site.data.dateTime.toISOString(), site.data.measures);
2081 }
2082 else {
2083 if (this.chartComponentData.stickiedKey !== null) {
2084 site = this.voronoiDiagram.find(mx, my);
2085 this.voronoiMousemove(site.data);
2086 this.unstickySeries(site.data.aggregateKey, site.data.splitBy);
2087 return;
2088 }
2089 this.stickySeries(site.data.aggregateKey, site.data.splitBy);
2090 }
2091 }
2092 else {
2093 if (!this.hasBrush) {
2094 this.isDroppingMarker = false;
2095 }
2096 }
2097 this.destroyMarkerInstructions();
2098 if (Utils.safeNotNullOrUndefined(function () { return _this.activeMarker; })) {
2099 this.activeMarker.onChange(false, true);
2100 this.exportMarkers();
2101 this.activeMarker = null;
2102 }
2103 };
2104 LineChart.prototype.getValueOfVisible = function (d) {
2105 return Utils.getValueOfVisible(d, this.chartComponentData.getVisibleMeasure(d.aggregateKey, d.splitBy));
2106 };
2107 LineChart.prototype.brushBrush = function () {
2108 var handleHeight = this.getHandleHeight();
2109 this.brushElem.selectAll('.handle')
2110 .attr('height', handleHeight)
2111 .attr('y', (this.chartHeight - handleHeight) / 2);
2112 if (!event.sourceEvent) {
2113 return;
2114 }
2115 if (event.sourceEvent && event.sourceEvent.type === 'mousemove') {
2116 this.brushElem.select(".selection").attr("visibility", "visible");
2117 //check boundary conditions for width of the brush
2118 if (event.selection[1] - event.selection[0] < this.minBrushWidth) {
2119 return;
2120 }
2121 else {
2122 this.brushElem.selectAll(".handle").attr("visibility", "visible");
2123 }
2124 }
2125 if (this.surpressBrushTimeSet == true) {
2126 this.surpressBrushTimeSet = false;
2127 return;
2128 }
2129 if (!event.selection)
2130 return;
2131 if (this.contextMenu)
2132 this.contextMenu.hide();
2133 if (this.brushContextMenu)
2134 this.brushContextMenu.hide();
2135 var newBrushStartPosition = event.selection[0];
2136 var newBrushEndPosition = event.selection[1];
2137 if (newBrushStartPosition != this.brushStartPosition) {
2138 this.brushStartTime = this.x.invert(event.selection[0]);
2139 this.brushStartPosition = newBrushStartPosition;
2140 }
2141 if (newBrushEndPosition != this.brushEndPosition) {
2142 this.brushEndTime = this.x.invert(event.selection[1]);
2143 this.brushEndPosition = newBrushEndPosition;
2144 }
2145 if (this.chartOptions.brushMoveAction) {
2146 this.chartOptions.brushMoveAction(this.brushStartTime, this.brushEndTime);
2147 }
2148 };
2149 LineChart.prototype.brushEnd = function (mouseEvent) {
2150 var _this = this;
2151 if (this.isClearingBrush) {
2152 this.isClearingBrush = false;
2153 if (this.brushContextMenu) {
2154 this.brushContextMenu.hide();
2155 }
2156 return;
2157 }
2158 if (event && event.selection == null && event.sourceEvent && event.sourceEvent.type == "mouseup" && this.chartOptions.minBrushWidth == 0) {
2159 if (this.brushContextMenu) {
2160 this.brushContextMenu.hide();
2161 }
2162 var _a = mouse(mouseEvent), mx = _a[0], my = _a[1];
2163 var site = this.voronoiDiagram.find(mx, my);
2164 var isClearingBrush = (this.brushStartPosition !== null) && (this.brushEndPosition !== null);
2165 if (this.chartComponentData.stickiedKey !== null && !this.isDroppingMarker && !isClearingBrush) {
2166 this.chartComponentData.stickiedKey = null;
2167 this.legendObject.legendElement.selectAll('.tsi-splitByLabel').classed("stickied", false);
2168 // recompute voronoi with no sticky
2169 this.voronoiDiagram = this.voronoi(this.getFilteredAndSticky(this.chartComponentData.allValues));
2170 site = this.voronoiDiagram.find(mx, my);
2171 this.voronoiMousemove(site.data);
2172 this.chartOptions.onUnsticky(site.data.aggregateKey, site.data.splitBy);
2173 return;
2174 }
2175 this.brushStartTime = null;
2176 this.brushEndTime = null;
2177 this.brushStartPosition = null;
2178 this.brushEndPosition = null;
2179 if (!this.isDroppingMarker && !isClearingBrush && !(this.contextMenu && this.contextMenu.contextMenuVisible)) {
2180 this.stickySeries(site.data.aggregateKey, site.data.splitBy);
2181 }
2182 else {
2183 this.isDroppingMarker = false;
2184 }
2185 return;
2186 }
2187 if (event.selection == null) {
2188 if (!this.chartOptions.brushClearable) {
2189 select(mouseEvent).transition().call(event.target.move, [this.x(this.brushStartTime), this.x(this.brushEndTime)]);
2190 }
2191 return;
2192 }
2193 var transformCall = null; //if the brush needs to be transformed due to snap brush or it being too small, this is envoked
2194 var isZeroWidth = false; //clear the brush context menu if the brush has 0 width
2195 if (this.chartOptions.snapBrush) {
2196 //find the closest possible value and set to that
2197 if (this.possibleTimesArray.length > 0) {
2198 var findClosestTime = function (rawXValue) {
2199 var closestDate = null;
2200 _this.possibleTimesArray.reduce(function (prev, curr) {
2201 var prospectiveDiff = Math.abs(rawXValue - _this.x(curr));
2202 var currBestDiff = Math.abs(rawXValue - prev);
2203 if (prospectiveDiff < currBestDiff) {
2204 closestDate = curr;
2205 return _this.x(curr);
2206 }
2207 return prev;
2208 }, Infinity);
2209 return closestDate;
2210 };
2211 var newBrushStartTime = findClosestTime(event.selection[0]);
2212 var newBrushEndTime = findClosestTime(event.selection[1]);
2213 if (newBrushStartTime != this.brushStartTime || newBrushEndTime != this.brushEndTime) {
2214 this.brushStartTime = newBrushStartTime;
2215 this.brushEndTime = newBrushEndTime;
2216 this.brushStartPosition = this.x(this.brushStartTime);
2217 this.brushEndPosition = this.x(this.brushEndTime);
2218 transformCall = function () { return select(mouseEvent).transition().call(event.target.move, [_this.x(_this.brushStartTime), _this.x(_this.brushEndTime)]); };
2219 isZeroWidth = this.x(this.brushStartTime) == this.x(this.brushEndTime);
2220 }
2221 }
2222 }
2223 if (event.selection[1] - event.selection[0] < this.minBrushWidth) {
2224 var rightSide_1 = Math.min(event.selection[0] + this.minBrushWidth, this.x.range()[1]);
2225 transformCall = function () { return select(mouseEvent).transition().call(event.target.move, [rightSide_1 - _this.minBrushWidth, rightSide_1]); };
2226 isZeroWidth = (rightSide_1 - this.minBrushWidth == rightSide_1);
2227 }
2228 if (this.chartOptions.brushMoveEndAction && (event.sourceEvent && event.sourceEvent.type == 'mouseup')) {
2229 this.chartOptions.brushMoveEndAction(this.brushStartTime, this.brushEndTime);
2230 }
2231 if (this.chartOptions.brushContextMenuActions && this.chartOptions.autoTriggerBrushContextMenu &&
2232 (event.sourceEvent && event.sourceEvent.type == 'mouseup')) {
2233 if (!this.chartOptions.brushContextMenuActions || this.chartOptions.brushContextMenuActions.length == 0)
2234 return;
2235 var mousePosition = mouse(this.targetElement.node());
2236 //constrain the mouse position to the renderTarget
2237 var boundingCRect = this.targetElement.node().getBoundingClientRect();
2238 var correctedMousePositionX = Math.min(boundingCRect.width, Math.max(mousePosition[0], 0));
2239 var correctedMousePositionY = Math.min(boundingCRect.height, Math.max(mousePosition[1], 0));
2240 var correctedMousePosition = [correctedMousePositionX, correctedMousePositionY];
2241 this.brushContextMenu.draw(this.chartComponentData, this.renderTarget, this.chartOptions, correctedMousePosition, null, null, null, this.brushStartTime, this.brushEndTime);
2242 }
2243 if (transformCall) {
2244 transformCall();
2245 if (this.brushContextMenu && isZeroWidth) {
2246 this.brushContextMenu.hide();
2247 }
2248 }
2249 };
2250 LineChart.prototype.focusMarkerLabel = function (filterFunction, aggKey, splitBy) {
2251 Utils.revertAllSubtitleText(select(this.renderTarget).selectAll(".tsi-markerValue"), .2);
2252 select(this.renderTarget).selectAll(".tsi-markerValue")
2253 .filter(filterFunction)
2254 .style("opacity", 1)
2255 .classed('tsi-isExpanded', true)
2256 .each(function () {
2257 Utils.setSeriesLabelSubtitleText(select(this).selectAll('.tsi-tooltipSubtitle'), true);
2258 });
2259 select(this.renderTarget).selectAll(".tsi-markerContainer").each(function () {
2260 select(this).selectAll(".tsi-markerValue").sort(function (a, b) {
2261 return (a.aggregateKey == aggKey && (splitBy == null || splitBy == a.splitBy)) ? 1 : -1;
2262 });
2263 });
2264 };
2265 LineChart.prototype.drawBrushRange = function () {
2266 if (this.chartOptions.brushRangeVisible) {
2267 if (this.targetElement.select('.tsi-rangeTextContainer').empty() && (this.brushStartTime || this.brushEndTime)) {
2268 var rangeTextContainer = this.targetElement.append("div")
2269 .attr("class", "tsi-rangeTextContainer");
2270 }
2271 this.updateBrushRange();
2272 }
2273 };
2274 LineChart.prototype.getSVGLeftOffset = function () {
2275 return this.chartOptions.legend === 'shown' ? (this.width - this.svgSelection.node().getBoundingClientRect().width) : 0;
2276 };
2277 LineChart.prototype.updateBrushRange = function () {
2278 var svgLeftOffset = this.getSVGLeftOffset();
2279 if (!(this.brushStartTime || this.brushEndTime)) {
2280 this.deleteBrushRange();
2281 return;
2282 }
2283 var rangeText = Utils.rangeTimeFormat(this.brushEndTime.valueOf() - this.brushStartTime.valueOf());
2284 var rangeTextContainer = this.targetElement.select('.tsi-rangeTextContainer');
2285 var leftPos = this.chartMargins.left +
2286 Math.min(Math.max(0, this.x(this.brushStartTime)), this.x.range()[1]) + svgLeftOffset;
2287 var rightPos = this.chartMargins.left +
2288 Math.min(Math.max(0, this.x(this.brushEndTime)), this.x.range()[1]) + svgLeftOffset;
2289 rangeTextContainer
2290 .text(rangeText)
2291 .style("left", Math.max(8, Math.round((leftPos + rightPos) / 2)) + "px")
2292 .style("top", (this.chartMargins.top + this.chartOptions.aggTopMargin) + 'px');
2293 if (this.chartOptions.color) {
2294 rangeTextContainer
2295 .style('background-color', this.chartOptions.color)
2296 .style('color', 'white');
2297 }
2298 var calcedWidth = rangeTextContainer.node().getBoundingClientRect().width;
2299 if (this.chartOptions.isCompact && (rightPos - leftPos) < calcedWidth) {
2300 rangeTextContainer.style('visibility', 'hidden');
2301 }
2302 else {
2303 rangeTextContainer.style('visibility', 'visible');
2304 }
2305 };
2306 LineChart.prototype.deleteBrushRange = function () {
2307 this.targetElement.select('.tsi-rangeTextContainer').remove();
2308 };
2309 LineChart.prototype.getYExtents = function () {
2310 return this.chartComponentData.yExtents;
2311 };
2312 LineChart.prototype.clearBrush = function () {
2313 this.svgSelection.select('.svgGroup').select(".brushElem").call(this.brush.move, null);
2314 this.deleteBrushRange();
2315 if (this.brushContextMenu) {
2316 this.brushContextMenu.hide();
2317 }
2318 };
2319 LineChart.prototype.getVisibleNumerics = function () {
2320 var _this = this;
2321 var visibleGroups = this.data.filter(function (agg) { return _this.chartComponentData.displayState[agg.aggKey]["visible"]; });
2322 var visibleCDOs = this.aggregateExpressionOptions.filter(function (cDO) { return _this.chartComponentData.displayState[cDO.aggKey]["visible"]; });
2323 return visibleGroups.filter(function (aggKey, i) {
2324 return visibleCDOs[i].dataType === DataTypes.Numeric;
2325 }).length;
2326 };
2327 LineChart.prototype.getSwimlaneOffsets = function (linechartTopPadding, visibleGroups, visibleCDOs, heightPerNumeric, swimLaneSet) {
2328 var _this = this;
2329 var cumulativeOffset = LINECHARTTOPPADDING;
2330 //initialize to null and set while going through swimLanes
2331 var visibleGroupEndValues = visibleGroups.map(function () { return null; });
2332 Object.keys(swimLaneSet).sort(function (a, b) { return (Number(a) <= Number(b) ? -1 : 1); }).forEach(function (swimLaneStr) {
2333 // find all numerics and set to cumulative offset/height per non numeric
2334 var swimlane = Number(swimLaneStr);
2335 var hasNumeric = false;
2336 visibleCDOs.forEach(function (aggGroup, i) {
2337 if (aggGroup.swimLane === swimlane && aggGroup.dataType === DataTypes.Numeric) {
2338 hasNumeric = true;
2339 visibleGroupEndValues[i] = [cumulativeOffset, heightPerNumeric];
2340 }
2341 });
2342 // find all non-numerics and set their offset/heights
2343 var swimLaneOffset = hasNumeric ? heightPerNumeric : 0;
2344 if (_this.chartOptions.swimLaneOptions && _this.chartOptions.swimLaneOptions[swimlane] && _this.chartOptions.swimLaneOptions[swimlane].collapseEvents) {
2345 swimLaneOffset += _this.getEventsCollapsedSwimlaneHeight(visibleCDOs, swimlane);
2346 visibleCDOs.forEach(function (aggGroup, i) {
2347 if (aggGroup.swimLane === swimlane) {
2348 visibleGroupEndValues[i] = [cumulativeOffset, _this.getEventsCollapsedSwimlaneHeight(visibleCDOs, swimlane)];
2349 }
2350 });
2351 }
2352 else {
2353 visibleCDOs.forEach(function (aggGroup, i) {
2354 if (aggGroup.swimLane === swimlane && aggGroup.dataType !== DataTypes.Numeric) {
2355 var currGroupsHeight_1 = Utils.getNonNumericHeight(aggGroup.height);
2356 visibleGroupEndValues[i] = [swimLaneOffset + cumulativeOffset, currGroupsHeight_1];
2357 swimLaneOffset += currGroupsHeight_1;
2358 }
2359 });
2360 }
2361 cumulativeOffset += swimLaneOffset;
2362 });
2363 return visibleGroupEndValues;
2364 };
2365 LineChart.prototype.setSwimLaneYExtents = function (visibleGroups, visibleCDOs, swimLanes, swimLaneOptions) {
2366 var _this = this;
2367 var extents = {};
2368 swimLanes.forEach(function (lane) {
2369 var extent$1 = [];
2370 // Check if swim lane options sets y-axis extents for this lane. If so use that
2371 // value for yExtents.
2372 if (swimLaneOptions && swimLaneOptions[lane] && swimLaneOptions[lane].yExtent) {
2373 extents[lane] = swimLaneOptions[lane].yExtent;
2374 return;
2375 }
2376 visibleGroups.forEach(function (aggGroup, i) {
2377 var cDO = visibleCDOs[i];
2378 if (cDO.dataType !== DataTypes.Numeric) {
2379 return;
2380 }
2381 var aggValues = [];
2382 if (cDO.swimLane === lane) {
2383 var aggKey_1 = cDO.aggKey;
2384 Object.keys(_this.chartComponentData.visibleTAs[aggKey_1]).forEach(function (splitBy) {
2385 aggValues = aggValues.concat(_this.chartComponentData.visibleTAs[aggKey_1][splitBy]);
2386 });
2387 var yExtent = _this.getYExtent(aggValues, _this.chartComponentData.displayState[aggKey_1].includeEnvelope ?
2388 _this.chartComponentData.displayState[aggKey_1].includeEnvelope :
2389 _this.chartOptions.includeEnvelope, aggKey_1);
2390 extent$1 = extent(yExtent.concat(extent$1));
2391 extents[lane] = extent$1;
2392 }
2393 });
2394 });
2395 this.swimlaneYExtents = extents;
2396 };
2397 LineChart.prototype.getEventsCollapsedSwimlaneHeight = function (visibleCDOs, swimlane) {
2398 // if a swimlane has collapsed events, the events height impact is the largest height of a visible events group in the swimlane
2399 var rawHeight = visibleCDOs.reduce(function (tallest, currGroup) {
2400 if (currGroup.dataType === DataTypes.Events && currGroup.swimLane === swimlane) {
2401 return Math.max(tallest, currGroup.height);
2402 }
2403 return tallest;
2404 }, 0);
2405 return rawHeight !== 0 ? Utils.getNonNumericHeight(rawHeight) : 0;
2406 };
2407 //returns an array of tuples of y offset and height for each visible aggregate group
2408 LineChart.prototype.createYOffsets = function () {
2409 var _this = this;
2410 var visibleGroups = this.data.filter(function (agg) { return _this.chartComponentData.displayState[agg.aggKey]["visible"]; });
2411 var visibleCDOs = this.aggregateExpressionOptions.filter(function (cDO) { return _this.chartComponentData.displayState[cDO.aggKey]["visible"]; });
2412 var visibleNumericCount;
2413 var swimLaneSet = {};
2414 visibleCDOs.forEach(function (aEO, i) {
2415 if (aEO.swimLane === null) {
2416 aEO.swimLane = i + 1;
2417 }
2418 });
2419 visibleCDOs.forEach(function (cDO) {
2420 swimLaneSet[cDO.swimLane] = swimLaneSet[cDO.swimLane] || (cDO.dataType === DataTypes.Numeric);
2421 });
2422 visibleNumericCount = Object.keys(swimLaneSet).reduce(function (visibleCount, swimLane) {
2423 return visibleCount + (swimLaneSet[swimLane] ? 1 : 0);
2424 }, 0);
2425 var countNumericLanes = visibleNumericCount;
2426 var linechartTopPadding = this.chartOptions.isArea ? 0 : LINECHARTTOPPADDING;
2427 var useableHeight = this.chartHeight - linechartTopPadding;
2428 var fixedEventsHeight = 0;
2429 if (this.chartOptions.swimLaneOptions) {
2430 Object.keys(this.chartOptions.swimLaneOptions).forEach(function (swimlaneKey) {
2431 var swimlane = Number(swimlaneKey);
2432 var sLO = _this.chartOptions.swimLaneOptions[swimlane];
2433 if (sLO.collapseEvents) {
2434 var swimlaneHeight = _this.getEventsCollapsedSwimlaneHeight(visibleCDOs, swimlane);
2435 fixedEventsHeight += swimlaneHeight;
2436 }
2437 });
2438 }
2439 var heightNonNumeric = visibleCDOs.reduce(function (sumPrevious, currGroup, i) {
2440 if (currGroup.dataType === DataTypes.Events && _this.chartOptions.swimLaneOptions && _this.chartOptions.swimLaneOptions[currGroup.swimLane] && _this.chartOptions.swimLaneOptions[currGroup.swimLane].collapseEvents) {
2441 return sumPrevious;
2442 }
2443 return sumPrevious + (currGroup.dataType !== DataTypes.Numeric ? Utils.getNonNumericHeight(currGroup.height) : 0);
2444 }, 0);
2445 heightNonNumeric += fixedEventsHeight;
2446 var heightPerNumeric = (useableHeight - heightNonNumeric) / countNumericLanes;
2447 this.setSwimLaneYExtents(visibleGroups, visibleCDOs, Object.keys(swimLaneSet)
2448 .filter(function (lane) { return swimLaneSet[lane]; })
2449 .map(function (stringLane) { return Number(stringLane); }), this.chartOptions.swimLaneOptions);
2450 return this.getSwimlaneOffsets(linechartTopPadding, visibleGroups, visibleCDOs, heightPerNumeric, swimLaneSet);
2451 };
2452 LineChart.prototype.heightNonNumeric = function () {
2453 var _this = this;
2454 var visibleCDOs = this.aggregateExpressionOptions.filter(function (agg) { return _this.chartComponentData.displayState[agg.aggKey]["visible"]; });
2455 return visibleCDOs.reduce(function (sumPrevious, currGroup) {
2456 return sumPrevious + (currGroup.dataType !== DataTypes.Numeric ? Utils.getNonNumericHeight(currGroup.height) : 0);
2457 }, 0);
2458 };
2459 LineChart.prototype.getGroupYExtent = function (aggKey, aggVisible, aggValues, yExtent) {
2460 if ((this.chartOptions.yAxisState === YAxisStates.Shared) || (Object.keys(this.chartComponentData.timeArrays)).length < 2 || !aggVisible) {
2461 yExtent = this.getYExtent(this.chartComponentData.allNumericValues, this.chartComponentData.displayState[aggKey].includeEnvelope ?
2462 this.chartComponentData.displayState[aggKey].includeEnvelope :
2463 this.chartOptions.includeEnvelope, null);
2464 }
2465 else if (this.chartComponentData.aggHasVisibleSplitBys(aggKey)) {
2466 yExtent = this.getYExtent(aggValues, this.chartComponentData.displayState[aggKey].includeEnvelope ?
2467 this.chartComponentData.displayState[aggKey].includeEnvelope :
2468 this.chartOptions.includeEnvelope, aggKey);
2469 }
2470 else {
2471 yExtent = [0, 1];
2472 }
2473 return yExtent;
2474 };
2475 LineChart.prototype.getAggAxisType = function (agg) {
2476 if (this.chartOptions.yAxisState === YAxisStates.Stacked) {
2477 if (this.chartOptions.swimLaneOptions && this.chartOptions.swimLaneOptions[agg.swimLane] && this.chartOptions.swimLaneOptions[agg.swimLane].yAxisType) {
2478 return this.chartOptions.swimLaneOptions[agg.swimLane].yAxisType;
2479 }
2480 else {
2481 return YAxisStates.Shared;
2482 }
2483 }
2484 return this.chartOptions.yAxisState;
2485 };
2486 LineChart.prototype.adjustSwimLanes = function () {
2487 if (this.chartOptions.yAxisState === YAxisStates.Shared || this.chartOptions.yAxisState === YAxisStates.Overlap) {
2488 this.aggregateExpressionOptions.forEach(function (aEO) {
2489 aEO.swimLane = 0;
2490 });
2491 // consolidate horizontal markers
2492 var horizontalMarkers_1 = [];
2493 Object.values(this.chartOptions.swimLaneOptions).forEach(function (lane) {
2494 horizontalMarkers_1.push.apply(horizontalMarkers_1, lane.horizontalMarkers);
2495 });
2496 this.chartOptions.swimLaneOptions = { 0: { yAxisType: this.chartOptions.yAxisState, horizontalMarkers: horizontalMarkers_1 } };
2497 }
2498 else {
2499 var minimumPresentSwimLane_1 = this.aggregateExpressionOptions.reduce(function (currMin, aEO) {
2500 return Math.max(aEO.swimLane, currMin);
2501 }, 0);
2502 this.aggregateExpressionOptions.forEach(function (aEO) {
2503 if (aEO.swimLane === null) {
2504 aEO.swimLane = ++minimumPresentSwimLane_1;
2505 }
2506 });
2507 }
2508 };
2509 LineChart.prototype.overwriteSwimLanes = function () {
2510 var _this = this;
2511 this.aggregateExpressionOptions.forEach(function (aEO, i) {
2512 _this.aggregateExpressionOptions[i].swimLane = _this.originalSwimLanes[i];
2513 });
2514 this.chartOptions.swimLaneOptions = this.originalSwimLaneOptions;
2515 };
2516 LineChart.prototype.getHorizontalMarkersWithYScales = function () {
2517 var _this = this;
2518 var visibleCDOs = this.aggregateExpressionOptions.filter(function (cDO) { return _this.chartComponentData.displayState[cDO.aggKey]["visible"]; });
2519 var markerList = [];
2520 var pushMarker = function (cDO, marker, markerList) {
2521 var _a, _b;
2522 if (_this.chartOptions.yAxisState === YAxisStates.Overlap) {
2523 return;
2524 }
2525 var domain = _this.chartOptions.yAxisState === YAxisStates.Stacked ?
2526 _this.swimlaneYExtents[cDO.swimLane] :
2527 _this.swimlaneYExtents[0];
2528 // filter out markers not in the y range of that lane and in lanes that have overlap axis
2529 if (domain &&
2530 ((_b = (_a = _this.chartOptions.swimLaneOptions) === null || _a === void 0 ? void 0 : _a[cDO.swimLane]) === null || _b === void 0 ? void 0 : _b.yAxisType) !== YAxisStates.Overlap &&
2531 marker.value >= domain[0] &&
2532 marker.value <= domain[1]) {
2533 markerList.push(__assign({ yScale: _this.yMap[cDO.aggKey] }, marker));
2534 }
2535 };
2536 visibleCDOs.forEach(function (cDO) {
2537 cDO.horizontalMarkers.forEach(function (horizontalMarkerParams) {
2538 pushMarker(cDO, horizontalMarkerParams, markerList);
2539 });
2540 });
2541 // find a visible CDO for a swimlane
2542 var findFirstVisibleCDO = function (swimlaneNumber) {
2543 return visibleCDOs.find(function (cDO) {
2544 return (cDO.swimLane === swimlaneNumber);
2545 });
2546 };
2547 if (this.chartOptions.yAxisState !== YAxisStates.Overlap && this.chartOptions.swimLaneOptions) {
2548 Object.keys(this.chartOptions.swimLaneOptions).forEach(function (swimlaneNumber) {
2549 var _a;
2550 var swimlaneOptions = _this.chartOptions.swimLaneOptions[swimlaneNumber];
2551 (_a = swimlaneOptions.horizontalMarkers) === null || _a === void 0 ? void 0 : _a.forEach(function (horizontalMarkerParams) {
2552 var firstVisibleCDO = findFirstVisibleCDO(Number(swimlaneNumber));
2553 if (firstVisibleCDO) {
2554 pushMarker(firstVisibleCDO, horizontalMarkerParams, markerList);
2555 }
2556 });
2557 });
2558 }
2559 return markerList;
2560 };
2561 // having horizontal markers present should add additional right hand margin to allow space for series labels
2562 LineChart.prototype.getAdditionalOffsetFromHorizontalMargin = function () {
2563 return this.getHorizontalMarkersWithYScales().length ? 16 : 0;
2564 };
2565 LineChart.prototype.drawHorizontalMarkers = function () {
2566 var markerList = this.getHorizontalMarkersWithYScales();
2567 var self = this;
2568 var markerContainers = this.svgSelection.select('.svgGroup').selectAll('.tsi-horizontalMarker')
2569 .data(markerList);
2570 markerContainers
2571 .enter()
2572 .append('g')
2573 .merge(markerContainers)
2574 .attr('class', 'tsi-horizontalMarker')
2575 .attr("transform", function (marker) {
2576 return "translate(" + 0 + "," + marker.yScale(marker.value) + ")";
2577 })
2578 .each(function (marker) {
2579 var valueText = select(this)
2580 .selectAll('.tsi-horizontalMarkerText')
2581 .data([marker.value]);
2582 valueText
2583 .enter()
2584 .append('text')
2585 .merge(valueText)
2586 .attr('class', 'tsi-horizontalMarkerText')
2587 .attr('x', self.chartWidth)
2588 .attr('y', -4)
2589 .text(function (value) { return value; });
2590 valueText.exit().remove();
2591 var valueLine = select(this)
2592 .selectAll('.tsi-horizontalMarkerLine')
2593 .data([marker]);
2594 valueLine
2595 .enter()
2596 .append('line')
2597 .merge(valueLine)
2598 .attr('class', 'tsi-horizontalMarkerLine')
2599 .attr('stroke', function (marker) { return marker.color; })
2600 .attr('x1', 0)
2601 .attr('y1', 0)
2602 .attr('x2', self.chartWidth)
2603 .attr('y2', 0);
2604 valueLine.exit().remove();
2605 });
2606 markerContainers.exit().remove();
2607 };
2608 LineChart.prototype.createSwimlaneLabels = function (offsetsAndHeights, visibleCDOs) {
2609 var _this = this;
2610 // swimLaneLabels object contains data needed to render each lane label
2611 var swimLaneLabels = {};
2612 /*
2613 The logic below constructs swimlane labels. The first aggregate found in each
2614 lane is used to position that lanes label. Numeric aggs are prioritized first,
2615 as they share a y-Axis, meaning only the first numeric in each lane needs to be
2616 considered. Next, non-numerics are checked, if they are the first agg found in
2617 their lane, their position data is used, otherwise, their height is added to the
2618 current height of the lane.
2619 */
2620 var useAggForLaneLabel = function (aggGroup) {
2621 var _a, _b, _c, _d, _e, _f;
2622 var swimLane = aggGroup.swimLane;
2623 var aggIndex = visibleCDOs.findIndex(function (el) { return el.aggKey === aggGroup.aggKey; });
2624 var onClick = null;
2625 if (typeof ((_c = (_b = (_a = _this.chartOptions) === null || _a === void 0 ? void 0 : _a.swimLaneOptions) === null || _b === void 0 ? void 0 : _b[swimLane]) === null || _c === void 0 ? void 0 : _c.onClick) === 'function') {
2626 onClick = function () { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = _this.chartOptions) === null || _a === void 0 ? void 0 : _a.swimLaneOptions) === null || _b === void 0 ? void 0 : _b[swimLane]) === null || _c === void 0 ? void 0 : _c.onClick) === null || _d === void 0 ? void 0 : _d.call(_c, swimLane); };
2627 }
2628 swimLaneLabels[swimLane] = {
2629 offset: offsetsAndHeights[aggIndex][0],
2630 height: offsetsAndHeights[aggIndex][1],
2631 label: (_f = (_e = (_d = _this.chartOptions) === null || _d === void 0 ? void 0 : _d.swimLaneOptions) === null || _e === void 0 ? void 0 : _e[swimLane]) === null || _f === void 0 ? void 0 : _f.label,
2632 onClick: onClick
2633 };
2634 };
2635 // First add numeric dataTypes (share Y-Axis) to label map
2636 visibleCDOs.filter(function (aggGroup) { return aggGroup.dataType === DataTypes.Numeric; }).forEach(function (aggGroup) {
2637 if (!(aggGroup.swimLane in swimLaneLabels)) { // Only add swimlanes once to swimLaneLabels map
2638 useAggForLaneLabel(aggGroup);
2639 }
2640 });
2641 // Then, map over any non-numeric dataType and increment heights if they're sharing a lane
2642 visibleCDOs.filter(function (aggGroup) { return aggGroup.dataType !== DataTypes.Numeric; }).forEach(function (aggGroup) {
2643 var _a, _b, _c;
2644 var aggIndex = visibleCDOs.findIndex(function (el) { return el.aggKey === aggGroup.aggKey; });
2645 if (!(aggGroup.swimLane in swimLaneLabels)) { // Only add swimlanes once to swimLaneLabels map
2646 useAggForLaneLabel(aggGroup);
2647 }
2648 else { // if lane contains non-numeric data and is being added to another lane
2649 if (!((_c = (_b = (_a = _this.chartOptions) === null || _a === void 0 ? void 0 : _a.swimLaneOptions) === null || _b === void 0 ? void 0 : _b[aggGroup.swimLane]) === null || _c === void 0 ? void 0 : _c.collapseEvents)) { // Only increment event heights if collapseEvents === false
2650 swimLaneLabels[aggGroup.swimLane].height += offsetsAndHeights[aggIndex][1]; // add heights (non-numerics don't share Y axis)
2651 }
2652 }
2653 });
2654 // Clear prior labels
2655 this.swimLaneLabelGroup.selectAll('*').remove();
2656 // Function to trim labels to max height
2657 var truncateLabel = function (labelRef, data) {
2658 var maxHeight = data.height - swimlaneLabelConstants.swimLaneLabelHeightPadding; // padding on actual lane height
2659 if (data.label) {
2660 var labelClientRect = labelRef.getBoundingClientRect();
2661 var labelText = labelRef.textContent;
2662 while (labelClientRect.height > maxHeight && labelText.length > 0) {
2663 labelText = labelText.slice(0, -1);
2664 labelRef.textContent = labelText + '...';
2665 labelClientRect = labelRef.getBoundingClientRect();
2666 }
2667 }
2668 };
2669 var boldYAxisText = function (enabled, lane) {
2670 _this.svgSelection.select('.svgGroup')
2671 .selectAll(".tsi-swimLaneAxis-" + lane)
2672 .selectAll('text')
2673 .classed('tsi-boldYAxisText', enabled);
2674 };
2675 var onClickPresentAndValid = function (dp) { return dp.onClick && typeof dp.onClick === 'function'; };
2676 // Map over swimLanes and create labels
2677 Object.keys(swimLaneLabels).forEach(function (lane) {
2678 var labelData = [swimLaneLabels[lane]];
2679 var label = _this.swimLaneLabelGroup.selectAll("tsi-swimLaneLabel-" + lane).data(labelData);
2680 label.enter()
2681 .append("text")
2682 .attr("class", function (d) { return "tsi-swimLaneLabel-" + lane + " tsi-swimLaneLabel " + (onClickPresentAndValid(d) ? 'tsi-boldOnHover' : ''); })
2683 .merge(label)
2684 .style("text-anchor", "middle")
2685 .attr("transform", function (d) { return "translate(" + (-_this.horizontalLabelOffset + swimlaneLabelConstants.labelLeftPadding) + "," + (d.offset + d.height / 2) + ") rotate(-90)"; })
2686 .text(function (d) { return d.label; })
2687 .each(function (d) { truncateLabel(this, d); })
2688 .on("click", function (d) {
2689 if (onClickPresentAndValid(d)) {
2690 d.onClick();
2691 }
2692 })
2693 .on("mouseover", function (d) {
2694 if (onClickPresentAndValid(d)) {
2695 boldYAxisText(true, lane);
2696 }
2697 })
2698 .on("mouseout", function () {
2699 boldYAxisText(false, lane);
2700 })
2701 .append("svg:title")
2702 .text(function (d) { return d.label; });
2703 label.exit().remove();
2704 });
2705 };
2706 LineChart.prototype.render = function (data, options, aggregateExpressionOptions) {
2707 var _this = this;
2708 _super.prototype.render.call(this, data, options, aggregateExpressionOptions);
2709 this.originalSwimLanes = this.aggregateExpressionOptions.map(function (aEO) {
2710 return aEO.swimLane;
2711 });
2712 this.originalSwimLaneOptions = options.swimLaneOptions;
2713 this.hasBrush = options && (options.brushMoveAction || options.brushMoveEndAction || options.brushContextMenuActions);
2714 this.chartOptions.setOptions(options);
2715 this.chartMargins.right = this.chartOptions.labelSeriesWithMarker ? (SERIESLABELWIDTH + 8) : LINECHARTCHARTMARGINS.right;
2716 this.width = this.getWidth();
2717 this.height = Math.max(select(this.renderTarget).node().clientHeight, this.MINHEIGHT);
2718 if (this.chartOptions.legend == "compact")
2719 this.chartMargins.top = 72;
2720 else
2721 this.chartMargins.top = 40;
2722 if (this.chartOptions.hideChartControlPanel) {
2723 this.chartMargins.top += -28;
2724 }
2725 if (!this.chartOptions.brushRangeVisible && this.targetElement) {
2726 this.deleteBrushRange();
2727 }
2728 if (this.seriesLabelsMarker && !this.chartOptions.labelSeriesWithMarker) {
2729 this.seriesLabelsMarker.destroyMarker();
2730 this.seriesLabelsMarker = null;
2731 }
2732 this.strokeOpacity = this.chartOptions.isArea ? .55 : 1;
2733 this.nonFocusStrokeOpactiy = this.chartOptions.isArea ? .55 : .3;
2734 this.chartComponentData.mergeDataToDisplayStateAndTimeArrays(this.data, this.aggregateExpressionOptions);
2735 this.chartComponentData.data.forEach(function (d, i) {
2736 _this.aggregateExpressionOptions[i].aggKey = d.aggKey;
2737 });
2738 if (this.chartOptions.xAxisHidden && this.chartOptions.focusHidden) {
2739 this.chartMargins.bottom = 5;
2740 }
2741 this.chartHeight = Math.max(1, this.height - this.chartMargins.bottom - this.chartMargins.top);
2742 this.chartWidth = this.getChartWidth();
2743 if (this.brush && this.svgSelection.select('.svgGroup').select(".brushElem") && !this.chartOptions.keepBrush) {
2744 this.brushStartTime = null;
2745 this.brushEndTime = null;
2746 this.brushStartPosition = null;
2747 this.brushEndPosition = null;
2748 this.clearBrush();
2749 }
2750 if (!this.chartOptions.hideChartControlPanel && this.chartControlsPanel === null) {
2751 this.chartControlsPanel = Utils.createControlPanel(this.renderTarget, this.legendWidth + (this.GUTTERWIDTH / 2), Math.max((this.chartMargins.top + 12), 0), this.chartOptions);
2752 var self = this;
2753 this.hasStackedButton = true;
2754 this.stackedButton = this.chartControlsPanel.append("button")
2755 .style("left", "60px")
2756 .attr("class", "tsi-stackedButton")
2757 .attr("aria-label", function () { return _this.getString("set axis state to") + ' ' + _this.nextStackedState(); })
2758 .attr("title", function () { return _this.getString("Change y-axis type"); })
2759 .attr("type", "button")
2760 .on("click", function () {
2761 var _this = this;
2762 self.overwriteSwimLanes();
2763 self.render(self.data, __assign(__assign({}, self.chartOptions), { yAxisState: self.nextStackedState() }), self.aggregateExpressionOptions);
2764 select(this).attr("aria-label", function () { return self.getString("set axis state to") + ' ' + self.nextStackedState(); });
2765 setTimeout(function () { return select(_this).node().focus(); }, 200);
2766 });
2767 }
2768 else if (this.chartOptions.hideChartControlPanel && this.chartControlsPanel !== null) {
2769 this.hasStackedButton = false;
2770 this.removeControlPanel();
2771 }
2772 if (this.chartControlsPanel !== null) {
2773 this.drawEllipsisMenu([{
2774 iconClass: "flag",
2775 label: this.getString("Drop a Marker"),
2776 action: this.addMarker,
2777 description: ""
2778 }]);
2779 this.chartControlsPanel.style("top", Math.max((this.chartMargins.top - 24), 0) + 'px');
2780 }
2781 this.adjustSwimLanes();
2782 if (this.svgSelection == null) {
2783 /******************** Static Elements *********************************/
2784 this.targetElement = select(this.renderTarget)
2785 .classed("tsi-lineChart", true);
2786 this.svgSelection = this.targetElement.append("svg")
2787 .attr("class", "tsi-lineChartSVG tsi-chartSVG")
2788 .attr('title', this.getString('Line chart'))
2789 .attr("height", this.height);
2790 var g = this.svgSelection.append("g")
2791 .classed("svgGroup", true)
2792 .attr("transform", "translate(" + this.chartMargins.left + "," + this.chartMargins.top + ")");
2793 var defs = this.svgSelection.append('defs');
2794 this.brushElem = null;
2795 if (this.hasBrush) {
2796 this.brushElem = g.append("g")
2797 .attr("class", "brushElem");
2798 this.brushElem.classed("hideBrushHandles", !this.chartOptions.brushHandlesVisible);
2799 }
2800 else {
2801 //if there is no brushElem, the voronoi lives here
2802 this.voronoiRegion = g.append("rect").classed("voronoiRect", true);
2803 }
2804 this.focus = g.append("g")
2805 .attr("transform", "translate(-200,-100)")
2806 .attr("class", "tsi-focus");
2807 this.focus.append("line")
2808 .attr("class", "tsi-focusLine tsi-vLine")
2809 .attr("x1", 0)
2810 .attr("x2", 0)
2811 .attr("y1", this.chartOptions.aggTopMargin)
2812 .attr("y2", this.chartHeight);
2813 this.focus.append("line")
2814 .attr("class", "tsi-focusLine tsi-hLine")
2815 .attr("x1", 0)
2816 .attr("x2", this.chartWidth)
2817 .attr("y1", 0)
2818 .attr("y2", 0);
2819 this.focus.append("circle")
2820 .attr("r", 4);
2821 this.horizontalValueBox = select(this.renderTarget)
2822 .append('div')
2823 .attr('class', 'tsi-horizontalValueBox tsi-chartValueTextBox')
2824 .style('display', 'none')
2825 .attr('pointer-events', 'none');
2826 this.verticalValueBox = select(this.renderTarget)
2827 .append('div')
2828 .attr('class', 'tsi-verticalValueBox')
2829 .style('display', 'none');
2830 this.horizontalValueBar = this.focus.append('line')
2831 .attr('y1', 0)
2832 .attr('y2', 0)
2833 .attr('class', 'tsi-horizontalValueBar')
2834 .style('display', 'none');
2835 this.swimLaneLabelGroup = g.append("g").
2836 attr("class", "tsi-swimLaneLabels");
2837 if (!this.tooltip) {
2838 this.tooltip = new Tooltip(select(this.renderTarget));
2839 }
2840 this.draw = function (isFromResize) {
2841 if (isFromResize === void 0) { isFromResize = false; }
2842 _this.minBrushWidth = (_this.chartOptions.minBrushWidth) ? _this.chartOptions.minBrushWidth : _this.minBrushWidth;
2843 _this.focus.attr("visibility", (_this.chartOptions.focusHidden) ? "hidden" : "visible");
2844 _this.verticalValueBox.style("visibility", (_this.chartOptions.focusHidden) ? "hidden" : "visible");
2845 _this.horizontalValueBox.style("visibility", (_this.chartOptions.focusHidden) ? "hidden" : "visible");
2846 if (_this.chartOptions.xAxisHidden && _this.chartOptions.focusHidden) {
2847 _this.chartMargins.bottom = 5;
2848 }
2849 // Check if any swimlane labels present & modify left margin if so
2850 var isLabelVisible = false;
2851 _this.aggregateExpressionOptions.filter(function (aggExpOpt) {
2852 return _this.chartComponentData.displayState[aggExpOpt.aggKey]["visible"];
2853 }).forEach(function (visibleAgg) {
2854 var _a, _b;
2855 if ((_b = (_a = _this.originalSwimLaneOptions) === null || _a === void 0 ? void 0 : _a[visibleAgg.swimLane]) === null || _b === void 0 ? void 0 : _b.label) {
2856 isLabelVisible = true;
2857 }
2858 });
2859 if (isLabelVisible) {
2860 _this.chartMargins.left = _this.horizontalLabelOffset;
2861 }
2862 else if (_this.chartMargins.left === _this.horizontalLabelOffset) {
2863 _this.chartMargins.left = LINECHARTCHARTMARGINS.left;
2864 }
2865 _this.width = Math.max(select(_this.renderTarget).node().clientWidth, _this.MINWIDTH);
2866 if (!isFromResize) {
2867 _this.chartWidth = _this.getChartWidth();
2868 }
2869 _this.height = Math.max(select(_this.renderTarget).node().clientHeight, _this.MINHEIGHT);
2870 _this.chartHeight = Math.max(1, _this.height - _this.chartMargins.bottom - _this.chartMargins.top);
2871 g.attr("transform", "translate(" + _this.chartMargins.left + "," + _this.chartMargins.top + ")");
2872 if (_this.brushElem) {
2873 _this.brushElem.classed("hideBrushHandles", !_this.chartOptions.brushHandlesVisible);
2874 }
2875 _this.focus.select('.tsi-hLine').attr("x2", _this.chartWidth);
2876 _this.focus.select('.tsi-vLine').attr("y2", _this.chartHeight);
2877 _this.svgSelection
2878 .style("width", _this.getSVGWidth() + "px")
2879 .style("height", _this.height + "px");
2880 _super.prototype.themify.call(_this, _this.targetElement, _this.chartOptions.theme);
2881 if (!isFromResize) {
2882 _this.legendObject.draw(_this.chartOptions.legend, _this.chartComponentData, function (aggKey, splitBy) { _this.labelMouseover(aggKey, splitBy); }, _this.svgSelection, _this.chartOptions, function () {
2883 Utils.revertAllSubtitleText(select(_this.renderTarget).selectAll('.tsi-markerValue'));
2884 }, _this.stickySeries);
2885 }
2886 _this.svgSelection.selectAll(".yAxis").style("visibility", "hidden");
2887 _this.x = scaleTime()
2888 .rangeRound([_this.xOffset, Math.max(_this.xOffset, _this.chartWidth - (2 * _this.xOffset))]);
2889 _this.y = scaleLinear()
2890 .range([Math.max(_this.chartHeight - _this.heightNonNumeric(), _this.chartOptions.aggTopMargin) - LINECHARTTOPPADDING, _this.chartOptions.aggTopMargin]);
2891 var fromAndTo = _this.chartComponentData.setAllValuesAndVisibleTAs();
2892 var xExtent = (_this.chartComponentData.allValues.length != 0) ? extent(_this.chartComponentData.allValues, function (d) { return d.dateTime; }) : [0, 1];
2893 var timeSet = set(_this.chartComponentData.allValues, function (d) { return d.dateTime; });
2894 var xRange = (_this.chartComponentData.allValues.length != 0) ? Math.max(2, (xExtent[1].valueOf() - xExtent[0].valueOf())) : 2;
2895 var xOffsetPercentage = _this.xOffset / _this.chartWidth;
2896 if (_this.chartOptions.timeFrame) {
2897 fromAndTo = [new Date(_this.chartOptions.timeFrame[0]), new Date(_this.chartOptions.timeFrame[1])];
2898 }
2899 _this.x.domain(fromAndTo);
2900 _this.xLowerBound = _this.x(fromAndTo[0]);
2901 _this.xUpperBound = _this.x(fromAndTo[1]);
2902 //allPossibleTimes -> a combination of the beginning and end of buckets
2903 _this.chartComponentData.setTimeMap();
2904 var startOfBuckets = _this.chartComponentData.allValues.map(function (d) { return d.dateTime; });
2905 var endOfBuckets = _this.chartComponentData.allValues.filter(function (d) { return d.bucketSize != null; })
2906 .map(function (d) { return new Date(d.dateTime.valueOf() + d.bucketSize); });
2907 var allPossibleTimes = startOfBuckets.concat(endOfBuckets);
2908 var timeSet = set(allPossibleTimes);
2909 _this.possibleTimesArray = timeSet.values().sort().map(function (ts) {
2910 return new Date(ts);
2911 });
2912 if (_this.voronoiRegion) {
2913 _this.voronoiRegion.attr("x", xOffsetPercentage * _this.chartWidth)
2914 .attr("y", _this.chartOptions.aggTopMargin)
2915 .attr("width", _this.chartWidth - (xOffsetPercentage * _this.chartWidth * 2))
2916 .attr("height", _this.chartHeight);
2917 }
2918 if (_this.brushElem) {
2919 var self = _this;
2920 _this.brush = brushX()
2921 .extent([[_this.xLowerBound, Math.min(_this.chartHeight, _this.chartOptions.aggTopMargin)],
2922 [_this.xUpperBound, _this.chartHeight]])
2923 .on("start", function () {
2924 if (self.activeMarker !== null && self.isDroppingMarker) {
2925 self.voronoiClick(this);
2926 }
2927 var handleHeight = self.getHandleHeight();
2928 self.brushElem.selectAll('.handle')
2929 .attr('height', handleHeight)
2930 .attr('y', (self.chartHeight - handleHeight) / 2)
2931 .attr('rx', '4px')
2932 .attr('ry', '4px');
2933 })
2934 .on("brush", function () {
2935 self.brushBrush();
2936 self.drawBrushRange();
2937 })
2938 .on("end", function () {
2939 self.brushEnd(this);
2940 self.drawBrushRange();
2941 });
2942 _this.brushElem.call(_this.brush);
2943 _this.setBrush();
2944 }
2945 var yExtent = _this.getYExtent(_this.chartComponentData.allValues, false, null);
2946 var yRange = (yExtent[1] - yExtent[0]) > 0 ? yExtent[1] - yExtent[0] : 1;
2947 var yOffsetPercentage = _this.chartOptions.isArea ? (1.5 / _this.chartHeight) : (10 / _this.chartHeight);
2948 _this.y.domain([yExtent[0] - (yRange * yOffsetPercentage), yExtent[1] + (yRange * (10 / _this.chartHeight))]);
2949 if (_this.chartOptions.isArea) {
2950 _this.areaPath = area()
2951 .curve(_this.chartOptions.interpolationFunction)
2952 .defined(function (d) {
2953 return (d.measures !== null) &&
2954 (d.measures[_this.chartComponentData.getVisibleMeasure(d.aggregateKey, d.splitBy)] !== null);
2955 })
2956 .x(function (d) {
2957 return _this.getXPosition(d, _this.x);
2958 })
2959 .y0(function (d) {
2960 return d.measures ? _this.y(d.measures[_this.chartComponentData.getVisibleMeasure(d.aggregateKey, d.splitBy)]) : 0;
2961 })
2962 .y1(_this.chartHeight);
2963 }
2964 if (!_this.chartOptions.xAxisHidden) {
2965 _this.xAxis = g.selectAll(".xAxis").data([_this.x]);
2966 _this.drawXAxis(_this.chartHeight);
2967 _this.xAxis.exit().remove();
2968 var xAxisBaseline = g.selectAll(".xAxisBaseline").data([_this.x]);
2969 var xAxisBaselineEntered = xAxisBaseline.enter().append("line")
2970 .attr("class", "xAxisBaseline")
2971 .attr("x1", .5)
2972 .merge(xAxisBaseline)
2973 .attr("y2", _this.chartHeight + .5)
2974 .attr("y1", _this.chartHeight + .5)
2975 .attr("x2", _this.chartWidth - _this.xOffset);
2976 xAxisBaseline.exit().remove();
2977 }
2978 if (g.selectAll(".xAxis").size() !== 0) {
2979 g.selectAll(".xAxis").style("visibility", ((!_this.chartOptions.xAxisHidden) ? "visible" : "hidden"));
2980 }
2981 /******************** Draw Line and Points ************************/
2982 _this.visibleAggCount = Object.keys(_this.chartComponentData.timeArrays).reduce(function (count, aggKey) {
2983 return count + (_this.chartComponentData.displayState[aggKey]['visible'] ? 1 : 0);
2984 }, 0);
2985 _this.yMap = {};
2986 _this.colorMap = {};
2987 _this.svgSelection.selectAll(".yAxis").remove();
2988 var visibleGroupData = _this.chartComponentData.data.filter(function (agg) { return _this.chartComponentData.displayState[agg.aggKey]["visible"]; });
2989 var visibleCDOs = _this.aggregateExpressionOptions.filter(function (cDO) {
2990 return _this.chartComponentData.displayState[cDO.aggKey]["visible"];
2991 });
2992 var offsetsAndHeights = _this.createYOffsets();
2993 // Add swimlane labels to SVG
2994 _this.createSwimlaneLabels(offsetsAndHeights, visibleCDOs);
2995 var swimLaneCounts = {};
2996 // Reset public facing yExtents
2997 _this.chartComponentData.resetYExtents();
2998 var aggregateGroups = _this.svgSelection.select('.svgGroup').selectAll('.tsi-aggGroup')
2999 .data(visibleCDOs, function (agg) { return agg.aggKey; });
3000 var self = _this;
3001 var visibleNumericI = 0;
3002 aggregateGroups.enter()
3003 .append('g')
3004 .classed('tsi-aggGroup', true)
3005 .merge(aggregateGroups)
3006 .transition()
3007 .duration((_this.chartOptions.noAnimate) ? 0 : self.TRANSDURATION)
3008 .ease(easeExp)
3009 .attr('transform', function (agg, i) {
3010 return self.chartOptions.isArea ? null : 'translate(0,' + offsetsAndHeights[i][0] + ')';
3011 })
3012 .each(function (agg, i) {
3013 var _a, _b, _c;
3014 var yExtent;
3015 var aggVisible = true;
3016 var aggValues = [];
3017 var aggKey = agg.aggKey;
3018 Object.keys(self.chartComponentData.visibleTAs[aggKey]).forEach(function (splitBy) {
3019 aggValues = aggValues.concat(self.chartComponentData.visibleTAs[aggKey][splitBy]);
3020 });
3021 yExtent = self.getGroupYExtent(aggKey, aggVisible, aggValues, yExtent);
3022 if (self.plotComponents[aggKey] === undefined || self.mismatchingChartType(aggKey)) {
3023 var g_1 = select(this);
3024 delete self.plotComponents[aggKey];
3025 g_1.selectAll('*').remove();
3026 self.plotComponents[aggKey] = self.createPlot(g_1, i, visibleCDOs);
3027 }
3028 var mouseoverFunction = self.getMouseoverFunction(visibleCDOs[i].dataType);
3029 var mouseoutFunction = self.getMouseoutFunction(visibleCDOs[i].dataType);
3030 var positionInGroup = visibleNumericI;
3031 if (self.getAggAxisType(agg) === YAxisStates.Shared) {
3032 yExtent = self.swimlaneYExtents[agg.swimLane];
3033 }
3034 // Update yExtent index in LineChartData after all local yExtent updates (this is public facing yExtent)
3035 // Only update if dataType is numeric
3036 if (agg.dataType === 'numeric') {
3037 var idx = self.aggregateExpressionOptions.findIndex(function (el) { return el.aggKey === aggKey; });
3038 self.chartComponentData.setYExtents(idx, yExtent);
3039 }
3040 //should count all as same swim lane when not in stacked.
3041 var swimLane = agg.swimLane;
3042 var offsetImpact = (agg.dataType === DataTypes.Numeric) ? 1 : 0;
3043 if (swimLaneCounts[swimLane]) {
3044 positionInGroup = swimLaneCounts[swimLane];
3045 swimLaneCounts[swimLane] += offsetImpact;
3046 }
3047 else {
3048 positionInGroup = 0;
3049 swimLaneCounts[swimLane] = offsetImpact;
3050 }
3051 var axisState = new AxisState(self.getAggAxisType(agg), yExtent, positionInGroup);
3052 var yAxisOnClick = null;
3053 if (typeof ((_c = (_b = (_a = self.chartOptions) === null || _a === void 0 ? void 0 : _a.swimLaneOptions) === null || _b === void 0 ? void 0 : _b[swimLane]) === null || _c === void 0 ? void 0 : _c.onClick) === 'function') {
3054 yAxisOnClick = function () { var _a, _b; return (_b = (_a = self.chartOptions.swimLaneOptions[swimLane]).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, swimLane); };
3055 }
3056 self.plotComponents[aggKey].render(self.chartOptions, visibleNumericI, agg, true, select(this), self.chartComponentData, axisState, self.chartHeight, self.visibleAggCount, self.colorMap, self.previousAggregateData, self.x, self.areaPath, self.strokeOpacity, self.y, self.yMap, defs, visibleCDOs[i], self.previousIncludeDots, offsetsAndHeights[i], g, mouseoverFunction, mouseoutFunction, yAxisOnClick);
3057 //increment index of visible numerics if appropriate
3058 visibleNumericI += (visibleCDOs[i].dataType === DataTypes.Numeric ? 1 : 0);
3059 });
3060 aggregateGroups.exit().remove();
3061 /******************** Voronoi diagram for hover action ************************/
3062 _this.voronoi = voronoi()
3063 .x(function (d) {
3064 return (d.bucketSize != undefined ? self.x(new Date(d.dateTime.valueOf() + (d.bucketSize / 2))) : self.x(d.dateTime));
3065 })
3066 .y(function (d) {
3067 if (d.measures) {
3068 return self.yMap[d.aggregateKey] ? self.yMap[d.aggregateKey](self.getValueOfVisible(d)) : null;
3069 }
3070 return null;
3071 })
3072 .extent([[0, 0], [_this.chartWidth, _this.chartHeight]]);
3073 //if brushElem present then use the overlay, otherwise create a rect to put the voronoi on
3074 var voronoiSelection = (_this.brushElem ? _this.brushElem.select(".overlay") : _this.voronoiRegion);
3075 voronoiSelection.on("mousemove", function () {
3076 var mouseEvent = mouse(this);
3077 self.voronoiMousemove(mouseEvent);
3078 })
3079 .on("mouseout", function (d) {
3080 if (!self.filteredValueExist() || !self.voronoiExists())
3081 return;
3082 var _a = mouse(this), mx = _a[0], my = _a[1];
3083 var site = self.voronoiDiagram.find(mx, my);
3084 self.voronoiMouseout(site.data);
3085 self.chartOptions.onMouseout();
3086 if (self.tooltip)
3087 self.tooltip.hide();
3088 })
3089 .on("contextmenu", function (d) {
3090 self.voronoiContextMenu(this);
3091 })
3092 .on("click", function (d) {
3093 self.voronoiClick(this);
3094 });
3095 if (_this.brushElem) {
3096 _this.brushElem.selectAll(".selection, .handle").on("contextmenu", function (d) {
3097 if (!self.chartOptions.brushContextMenuActions || self.chartOptions.brushContextMenuActions.length == 0 || self.chartOptions.autoTriggerBrushContextMenu)
3098 return;
3099 var mousePosition = mouse(self.targetElement.node());
3100 event.preventDefault();
3101 self.brushContextMenu.draw(self.chartComponentData, self.renderTarget, self.chartOptions, mousePosition, null, null, null, self.brushStartTime, self.brushEndTime);
3102 });
3103 _this.brushElem.selectAll('.selection')
3104 .attr('stroke', _this.chartOptions.color ? _this.chartOptions.color : 'none')
3105 .attr('fill', _this.chartOptions.color ? _this.chartOptions.color : 'grey');
3106 var handleHeight = self.getHandleHeight();
3107 _this.brushElem.selectAll('.handle')
3108 .attr('fill', _this.chartOptions.color ? _this.chartOptions.color : 'grey')
3109 .attr('height', handleHeight)
3110 .attr('y', (_this.chartHeight - handleHeight) / 2);
3111 }
3112 /******************** Stack/Unstack button ************************/
3113 if (_this.hasStackedButton) {
3114 _this.stackedButton.style("opacity", function () {
3115 if (_this.chartOptions.yAxisState === YAxisStates.Stacked)
3116 return 1;
3117 if (_this.chartOptions.yAxisState === YAxisStates.Shared)
3118 return .6;
3119 return .3;
3120 })
3121 .style("display", _this.visibleAggCount < 2 ? "none" : "block")
3122 .classed('tsi-lightTheme', _this.chartOptions.theme == 'light')
3123 .classed('tsi-darkTheme', _this.chartOptions.theme == 'dark');
3124 }
3125 var timeFrame = (_this.chartOptions.timeFrame) ? _this.chartOptions.timeFrame : _this.x.domain();
3126 if (!_this.chartOptions.hideChartControlPanel && _this.chartControlsPanel !== null) {
3127 _this.chartControlsPanel.style("width", _this.calcSVGWidth() + "px");
3128 }
3129 _this.renderAllMarkers();
3130 _this.drawHorizontalMarkers();
3131 _this.voronoiDiagram = _this.voronoi(_this.getFilteredAndSticky(_this.chartComponentData.allValues));
3132 };
3133 this.legendObject = new Legend(this.draw, this.renderTarget, this.legendWidth);
3134 this.contextMenu = new ContextMenu(this.draw, this.renderTarget);
3135 this.brushContextMenu = new ContextMenu(this.draw, this.renderTarget);
3136 window.addEventListener("resize", function () {
3137 if (!_this.chartOptions.suppressResizeListener) {
3138 _this.draw();
3139 _this.renderAllMarkers();
3140 }
3141 });
3142 }
3143 this.chartComponentData.mergeDataToDisplayStateAndTimeArrays(this.data, this.aggregateExpressionOptions);
3144 this.draw();
3145 this.gatedShowGrid();
3146 this.chartOptions.noAnimate = false; // ensure internal renders are always animated, overriding the users noAnimate option
3147 if (this.chartOptions.labelSeriesWithMarker && this.seriesLabelsMarker === null) {
3148 this.createSeriesLabelsMarker();
3149 }
3150 this.renderSeriesLabelsMarker();
3151 if (this.chartOptions.markers && this.chartOptions.markers.length > 0) {
3152 this.importMarkers();
3153 }
3154 select("html").on("click." + Utils.guid(), function () {
3155 if (_this.ellipsisContainer && event.target != _this.ellipsisContainer.select(".tsi-ellipsisButton").node()) {
3156 _this.ellipsisMenu.setMenuVisibility(false);
3157 }
3158 });
3159 this.legendPostRenderProcess(this.chartOptions.legend, this.svgSelection, true, function () {
3160 _this.updateBrushRange();
3161 });
3162 };
3163 LineChart.prototype.createPlot = function (svgGroup, i, cDO) {
3164 var chartType = cDO[i].dataType;
3165 if (chartType === DataTypes.Numeric) {
3166 return new LinePlot(svgGroup);
3167 }
3168 else if (chartType === DataTypes.Categorical) {
3169 return new CategoricalPlot(svgGroup);
3170 }
3171 else if (chartType === DataTypes.Events) {
3172 return new EventsPlot(svgGroup);
3173 }
3174 return null;
3175 };
3176 return LineChart;
3177}(TemporalXAxisComponent));
3178
3179export { LineChart as L };