pm-controls
Version:
ProModel Controls
854 lines (853 loc) • 40.7 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Output, EventEmitter, Component, Input, ElementRef, ViewChild, ChangeDetectionStrategy } from '@angular/core';
import * as d3 from '../../../../bundles/d3-bundle';
import * as Immutable from 'immutable';
import * as _ from 'lodash';
import { Margin } from '../../../objects/margin';
var GraphComponent = /** @class */ (function () {
function GraphComponent(el) {
this.el = el;
this.height = 500;
this.width = 960;
this.includeLineDataPoints = true;
this.includeHoverLine = true;
this.transitionDuration = 300; // in milliseconds
this.hideBorder = false;
this.interpolationMethod = d3.curveLinear;
this.margin = { top: 0, right: 70, bottom: 100, left: 70 };
this.xAxisTextRotation = "-45";
this.AllowZoomX = true;
this.AllowZoomY = true;
// includes an area that displays the difference between the first 2 TimeSeries in the linedData.
this.IncludeDifference = false;
this.disableWheelZoom = false;
this.UseContinuousHoverLine = false;
this.xDomain = null;
this.yDomain = null;
this.lineSizePx = "1px";
this.pointSizeR = 3;
this.UniqueId = "0"; // unique ID to identify this graph. Necessary for the clip-path URL used for the differences.
this.TooltipItemChange = new EventEmitter();
this.isZoomButtonUpdate = false;
}
GraphComponent.prototype.ngOnChanges = function (changeDetection) {
if (changeDetection.lineData !== undefined || changeDetection.pointData !== undefined)
this.handleDataChange(changeDetection.lineData, changeDetection.pointData);
};
GraphComponent.prototype.handleDataChange = function (dataChange, pointChange) {
var _this = this;
if ((!dataChange || !dataChange.currentValue) && (!pointChange || !pointChange.currentValue))
return;
if (!this.lineData)
this.lineData = Immutable.List();
this.mutableData = this.lineData.toArray();
if (!this.pointData)
this.pointData = Immutable.List();
this.mutablePointData = this.pointData.toArray();
this.mutableDataAxis1 = this.yAxisMutableData();
this.mutableDataAxis2 = this.yAxis2MutableData();
if (this.IncludeDifference && this.mutableData.length > 1) {
var index0 = 0;
var index1 = 0;
var list0Done = function () { return index0 == _this.mutableData[0].Data.length; };
var list1Done = function () { return index1 == _this.mutableData[1].Data.length; };
this.differenceData = [];
while (!list0Done() || !list1Done()) {
if (this.mutableData[0].Data[index0].Date.getTime() < this.mutableData[1].Data[index1].Date.getTime() || list1Done()) {
this.differenceData.push({
Date: this.mutableData[0].Data[index0].Date,
Value0: this.mutableData[0].Data[index0].Value,
Value1: index1 == 0 ? 0 : this.mutableData[1].Data[list1Done() ? this.mutableData[1].Data.length - 1 : index1 - 1].Value
});
index0++;
}
else if (this.mutableData[0].Data[index0].Date.getTime() > this.mutableData[1].Data[index1].Date.getTime()) {
this.differenceData.push({
Date: this.mutableData[1].Data[index1].Date,
Value0: index0 == 0 ? 0 : this.mutableData[0].Data[list0Done() ? this.mutableData[0].Data.length - 1 : index0 - 1].Value,
Value1: this.mutableData[1].Data[index1].Value
});
index1++;
}
else {
this.differenceData.push({
Date: this.mutableData[0].Data[index0].Date,
Value0: this.mutableData[0].Data[index0].Value,
Value1: this.mutableData[1].Data[index1].Value
});
index1++;
index0++;
}
}
}
this.flattenedItems = [].concat.apply([], this.mutableDataAxis1.map(function (d, idx) { return d.Data.map(function (dd) { return [dd, d.name]; }); }));
this.flattenedPointItems = [].concat.apply([], this.mutablePointData.map(function (d, idx) { return d.Data.map(function (dd) { return [dd, d.name]; }); }));
if (this.mutableDataAxis2) {
this.flattenedItemsAxis2 = [].concat.apply([], this.mutableDataAxis2.map(function (d) { return d.Data.map(function (dd, idx) { return [dd, d.name]; }); }));
}
this.drawGraph();
setTimeout(function () { return _this.zoomPane.call(_this.zoom.transform, d3.zoomIdentity); }, 1);
};
GraphComponent.prototype.drawGraph = function () {
var _this = this;
if (this.svg) {
if (this.xDomain) {
this.x = this.x.domain(this.xDomain);
}
else {
this.x = this.x.domain(d3.extent(_.concat(this.flattenedItems, this.flattenedPointItems), function (d) {
return d[0].Date;
}));
}
if (this.yDomain) {
this.y = this.y.domain(this.yDomain).nice();
}
else {
this.y = this.y.domain([
d3.min(_.concat(this.mutableDataAxis1, this.mutablePointData), function (c) { return d3.min(c.Data, function (v) { return v.Value; }); }),
d3.max(_.concat(this.mutableDataAxis1, this.mutablePointData), function (c) { return d3.max(c.Data, function (v) { return v.Value; }); })
]).nice();
}
if (this.mutableDataAxis2) {
this.y2.domain([
d3.min(this.mutableDataAxis2, function (c) { return d3.min(c.Data, function (v) { return v.Value; }); }),
d3.max(this.mutableDataAxis2, function (c) { return d3.max(c.Data, function (v) { return v.Value; }); })
]).nice();
}
d3.zoomIdentity.translate(0, 0).scale(1);
this.zoomedX = this.x;
if (this.AllowZoomY) {
this.zoomedY = this.y;
this.zoomedY2 = this.y2;
}
this.updateAxis(true);
this.updateGraph();
// this.svg.selectAll("*").remove();
return this.svg;
}
this.width = this.width - this.margin.left - this.margin.right;
this.height = this.height - this.margin.top - this.margin.bottom;
this.x = d3.scaleTime()
.range([0, this.width]);
this.y = d3.scaleLinear()
.range([this.height, 0]);
if (this.yAxisSecondAxisDataFilter) {
this.y2 = d3.scaleLinear()
.range([this.height, 0]);
this.y2Axis = d3.axisRight(this.y2);
this.area = d3.area()
.x(function (d) { return _this.zoomedX(d.Date); })
.y1(function (d) { return _this.zoomedY2(d.Value); })
.y0(function (d) { return _this.zoomedY2(0); })
.curve(this.interpolationMethod);
}
if (this.IncludeDifference) {
this.differenceArea = d3.area()
.curve(this.interpolationMethod)
.x(function (d) {
return _this.zoomedX(d.Date);
})
.y1(function (d) {
return _this.zoomedY(d.Value0);
});
}
if (this.userColors)
this.color = d3.scaleOrdinal(this.userColors);
else
this.color = d3.scaleOrdinal(["#1f77b4", "#d62728", "#ffba00"]);
this.xAxis = d3.axisBottom(this.x)
.tickFormat(function (d) { return _this.multiTimeFormat(d); });
this.yAxis = d3.axisLeft(this.y);
this.line = d3.line()
.x(function (d) { return _this.zoomedX(d.Date); })
.y(function (d) { return _this.zoomedY(d.Value); })
.curve(this.interpolationMethod);
this.svg = d3.select(this.el.nativeElement).append("svg")
.attr("width", this.width + this.margin.left + this.margin.right)
.attr("height", this.height + this.margin.top + this.margin.bottom)
.append("g")
.attr("transform", "translate(" + this.margin.left + "," + this.margin.top + ")");
this.svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + this.height + ")");
this.svg.append("clipPath")
.attr("id", "clip-" + this.UniqueId)
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", this.width)
.attr("height", this.height);
this.graphContainer = this.svg.append("g")
.attr("clip-path", "url(#clip-" + this.UniqueId + ")")
.append("g");
if (this.includeHoverLine) {
this.setupHoverLine();
}
this.mutableData = this.lineData.toArray();
this.mutableDataAxis1 = this.yAxisMutableData();
this.mutableDataAxis2 = this.yAxis2MutableData();
this.color.domain(this.mutableData.concat(this.mutablePointData).map(function (d) { return d.name; }));
this.flattenedItems = [].concat.apply([], this.mutableDataAxis1.map(function (d) { return d.Data.map(function (dd, idx) { return [dd, d.name]; }); }));
if (this.mutableDataAxis2) {
this.flattenedItemsAxis2 = [].concat.apply([], this.mutableDataAxis2.map(function (d) { return d.Data.map(function (dd, idx) { return [dd, d.name]; }); }));
this.y2.domain([
d3.min(this.mutableDataAxis2, function (c) { return d3.min(c.Data, function (v) { return v.Value; }); }),
d3.max(this.mutableDataAxis2, function (c) { return d3.max(c.Data, function (v) { return v.Value; }); })
]).nice();
}
if (this.xDomain) {
this.x = this.x.domain(this.xDomain);
}
else {
this.x = this.x.domain(d3.extent(_.concat(this.flattenedPointItems, this.flattenedItems), function (d) {
return d[0].Date;
}));
}
if (this.yDomain) {
this.y.domain(this.yDomain).nice();
}
else {
this.y.domain([
d3.min(_.concat(this.mutableDataAxis1, this.mutablePointData), function (c) { return d3.min(c.Data, function (v) { return v.Value; }); }),
d3.max(_.concat(this.mutableDataAxis1, this.mutablePointData), function (c) { return d3.max(c.Data, function (v) { return v.Value; }); })
]).nice();
}
this.setupZoomBehavior();
this.drawBorder();
this.setupLegend(this.mutableData, this.mutablePointData);
this.setupZoomButtons();
this.tooltip = d3.select(this.tooltipElementRef.nativeElement)
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden");
this.updateGraph();
var yAx = this.svg.append("g")
.attr("class", "y axis");
var yAx2;
if (this.yAxisSecondAxisDataFilter) {
yAx2 = this.svg.append("g")
.attr("class", "y2 axis")
.attr("transform", "translate( " + this.width + ", 0 )");
}
if (this.yAxisTitle) {
yAx.append("text")
.attr("transform", "translate(0," + this.height / 2 + ")rotate(-90)")
.attr("dx", "4em")
.attr("dy", "1.31em")
.style("text-anchor", "end")
.style("fill", "#000")
.text(this.yAxisTitle);
}
if (this.ySecondAxisTitle) {
yAx2.append("text")
.attr("transform", "translate(0," + this.height / 2 + ")rotate(-90)")
.attr("dx", "4em")
.attr("dy", "-.31em")
.style("text-anchor", "end")
.style("fill", "#000")
.text(this.ySecondAxisTitle);
}
};
GraphComponent.prototype.multiTimeFormat = function (date) {
var formatMillisecond = d3.timeFormat("%I:%M:%S.%L"), formatSecond = d3.timeFormat("%I:%M:%S"), formatMinute = d3.timeFormat("%d-%b-%Y %I:%M"), formatHour = d3.timeFormat("%d-%b-%Y %I %p"), formatDay = d3.timeFormat("%d-%b-%Y"), formatWeek = d3.timeFormat("%d-%b-%Y"), formatMonth = d3.timeFormat("%B %Y"), formatYear = d3.timeFormat("%Y");
return (d3.timeSecond(date) < date ? formatMillisecond
: d3.timeMinute(date) < date ? formatSecond
: d3.timeHour(date) < date ? formatMinute
: d3.timeDay(date) < date ? formatHour
: d3.timeMonth(date) < date ? (d3.timeWeek(date) < date ? formatDay : formatWeek)
: d3.timeYear(date) < date ? formatMonth
: formatYear)(date);
};
GraphComponent.prototype.setupZoomBehavior = function () {
var _this = this;
this.zoom = d3.zoom()
.on("zoom", function () { return _this.zoomUpdate(_this.isZoomButtonUpdate); }); // .scaleExtent([.5,7]);
if (this.xExtent) {
this.zoom.
translateExtent([[this.x(this.xExtent[0]), 0], [Math.max(this.width, this.x(this.xExtent[1])), Infinity]]);
}
if (this.disableWheelZoom)
this.zoom.filter(function () {
return !d3.event || (!d3.event.button && !d3.event.wheelDelta);
});
this.zoomPane = this.svg.append("rect")
.attr("class", "zoomPane")
.attr("width", this.width)
.attr("height", this.height)
.call(this.zoom);
};
GraphComponent.prototype.setupHoverLine = function () {
var _this = this;
var that = this;
this.hoverLine = this.svg
.on("mousemove", function (d) { that.updateHoverLine(this); })
.on("mouseout", function (d) { return _this.removeHoverLine(); })
.append("g")
.attr("class", "hoverLine")
.append("line");
};
// filter for the "first" y-axis. Just an inverse of the 2nd filter
GraphComponent.prototype.yAxisFilter = function (d) {
return this.yAxisSecondAxisDataFilter ? !this.yAxisSecondAxisDataFilter(d) : true;
};
GraphComponent.prototype.yAxisMutableData = function () {
var _this = this;
return this.mutableData.filter(function (d) { return _this.yAxisFilter(d); });
};
GraphComponent.prototype.yAxis2MutableData = function () {
var _this = this;
if (!this.yAxisSecondAxisDataFilter)
return null;
return this.mutableData.filter(function (d) { return _this.yAxisSecondAxisDataFilter(d); });
};
GraphComponent.prototype.updateHoverLine = function (el) {
var _this = this;
var xCoord = d3.mouse(el)[0];
var vals = this.getValuesAtX(xCoord);
this.svg.selectAll(".inflated.data-point")
.attr("r", this.pointSizeR)
.attr("stroke", undefined)
.style("stroke-width", undefined)
.classed("inflated", false);
var points = this.svg.selectAll(".data-point")
.filter(function (d) { return vals.values.find(function (v) { return v.value.Date == d[0].Date; }); })
.attr("r", this.pointSizeR + 2)
.attr("stroke", "black")
.style("stroke-width", "1px")
.classed("inflated", true);
var selectedDate = vals.values.first().value.Date;
var hoverX = this.UseContinuousHoverLine ? this.zoomedX(selectedDate) : this.zoomedX(vals.datePos);
this.hoverLine.attr("y1", 0)
.attr("y2", this.height)
.attr("x1", hoverX)
.attr("x2", hoverX)
.attr("opacity", 1)
.style("stroke", "black")
.style("stroke-width", "1px");
// this.tooltip.html(this.hoverLineDisplay(vals));
var tooltipBounds = this.tooltip.node().getBoundingClientRect();
// currently, we position the tooltip above the "highest" datapoint, and to the left of the hoverline.
this.tooltip.style("visibility", "visible")
.style("top", (_(points.nodes()).map(function (p) { return p.cy.baseVal.value; }).min() - 40) + "px")
.style("left", function () {
if (+hoverX > (_this.width / 2))
return (+hoverX + _this.margin.left - tooltipBounds.width - 15) + "px";
return (+hoverX + _this.margin.left + 15) + "px";
});
this.TooltipItemChange.emit(vals);
};
GraphComponent.prototype.removeHoverLine = function () {
this.tooltip.style("visibility", "hidden");
this.hoverLine.attr("opacity", 0);
this.svg.selectAll(".inflated.data-point")
.attr("r", this.pointSizeR)
.attr("stroke", undefined)
.style("stroke-width", undefined)
.classed("inflated", false);
};
GraphComponent.prototype.getValuesAtX = function (xCoord) {
var curDate = this.zoomedX.invert(xCoord);
var bisectDate = d3.bisector(function (d) { return d.Date; }).left;
// line values range from the date of the TimeSeriesItem to the next item in the series.
var lineValues = this.lineData.map(function (t, i) {
var curIdx = bisectDate(t.Data, curDate, 1);
var leftVal = t.Data[curIdx - 1];
var rightVal = t.Data[curIdx];
var val;
if (!leftVal)
val = rightVal;
else if (!rightVal)
val = leftVal;
else
val = curDate.getTime() - leftVal.Date.getTime() > rightVal.Date.getTime() - curDate.getTime() ? leftVal : rightVal;
return { "seriesName": t.name, "value": leftVal };
});
var beginningOfDayDate = new Date(curDate.getFullYear(), curDate.getMonth(), curDate.getDate());
// point values are single point in time.
var pointValues = this.pointData.map(function (t, i) {
var item = _(t.Data).filter(function (d) { return d.Date.getTime() == beginningOfDayDate.getTime(); }).first();
if (!item)
return undefined;
return { "seriesName": t.name, "value": item };
}).filter(function (d) { return d !== undefined; });
return { "datePos": curDate, "values": lineValues.concat(pointValues) };
};
GraphComponent.prototype.drawBorder = function () {
var strokeOpacity = this.hideBorder ? 0 : 0.9;
this.svg.append("g")
.attr("class", "d3 border")
.append("rect")
.attr("x", this.margin.left * -1)
.attr("y", this.margin.top * -1)
.style("fill", "none")
.style("stroke", "black")
.style("stroke-width", "2px")
.style("stroke-opacity", strokeOpacity)
.attr("height", this.height + this.margin.top + this.margin.bottom)
.attr("width", this.width + this.margin.left + this.margin.right);
};
GraphComponent.prototype.updateGraph = function () {
this.updateAxis();
if (this.IncludeDifference) {
this.updateDifferenceLines(this.differenceData);
}
if (this.yAxisSecondAxisDataFilter)
this.updateLines(this.mutableDataAxis2, true);
this.updateLines(this.mutableDataAxis1, false);
if (this.includeLineDataPoints) {
if (this.yAxisSecondAxisDataFilter)
this.updateLinePoints(this.flattenedItemsAxis2, true);
this.updateLinePoints(this.flattenedItems, false);
}
if (this.flattenedPointItems && this.flattenedPointItems.length > 0) {
this.updateLinePoints(this.flattenedPointItems, false);
}
};
GraphComponent.prototype.zoomUpdate = function (includeTransitions) {
// if(this.xDomain) {
// var tx = d3.zoomIdentity.x,
// ty = d3.zoomIdentity.y;
if (includeTransitions === void 0) { includeTransitions = false; }
// tx = Math.min(tx, 0);
// tx = Math.max(tx, this.width - this.zoomedX(this.xDomain[1]));
// d3.zoomIdentity.translate(tx, ty);
// }
this.updateAxis(includeTransitions);
if (this.IncludeDifference) {
this.updateExistingDifferenceLines(this.graphContainer.select(".diff-line.diff0"), true, includeTransitions);
this.updateExistingDifferenceLines(this.graphContainer.select(".diff-line.diff1"), false, includeTransitions);
this.updateExistingDifference(this.graphContainer.select("clipPath#clip-below-" + this.UniqueId).select("path"), false, includeTransitions);
this.updateExistingDifference(this.graphContainer.select("clipPath#clip-above-" + this.UniqueId).select("path"), true, includeTransitions);
}
if (this.yAxisSecondAxisDataFilter) {
lines = this.graphContainer.selectAll(".gc-line.ax2");
this.updateExistingLines(lines, includeTransitions, true);
}
var lines = this.graphContainer.selectAll(".gc-line.ax1");
this.updateExistingLines(lines, includeTransitions, false);
this.updateExistingLinePoints(this.svg.selectAll(".data-point.ax1"), includeTransitions, false);
if (this.yAxisSecondAxisDataFilter)
this.updateExistingLinePoints(this.svg.selectAll(".data-point.ax2"), includeTransitions, true);
// this.graphContainer.attr("transform","translate("+ (<any>d3.event).translate +")scale(" + d3.event.scale + ")");
};
GraphComponent.prototype.setupZoomButtons = function () {
var _this = this;
var zoomInButton = d3.select("pm-icon-search-plus")
.on("click", function () { _this.zoomClick(true); });
var zoomOutButton = d3.select("pm-icon-search-minus")
.on("click", function () { _this.zoomClick(false); });
var resetButton = d3.select("pm-icon-arrows")
.on("click", function () { _this.zoomClick(false, true); });
};
GraphComponent.prototype.zoomClick = function (isZoomIn, isZoomReset) {
if (isZoomReset === void 0) { isZoomReset = false; }
var currentDuration = this.transitionDuration;
this.transitionDuration = currentDuration == 0 ? 500 : currentDuration;
this.isZoomButtonUpdate = true;
if (isZoomReset)
this.zoomPane.call(this.zoom.transform, d3.zoomIdentity);
else
this.zoomPane.call(this.zoom.scaleBy, isZoomIn ? 2 : 0.5);
this.isZoomButtonUpdate = false;
this.transitionDuration = currentDuration;
};
GraphComponent.prototype.setupLegend = function (mutableData, mutablePointData) {
var _this = this;
var numberOfLines = mutableData.length;
var legendContainer = this.svg.append("g");
var legend = legendContainer
.attr("font-size", 12)
.attr("text-anchor", "end")
.selectAll("g")
.data(mutableData.concat(mutablePointData))
.enter().append("g")
.attr("transform", function (d, i) { return "translate(0," + i * 20 + ")"; });
legend.filter(function (d, i) { return i < numberOfLines; })
.append("line")
.attr("x1", this.width - 19)
.attr("x2", this.width)
.attr("y1", 19 / 2)
.attr("y2", 19 / 2)
.style('stroke-dasharray', function (d, i) { return i == 0 ? undefined : i * 8 + "," + i * 8; })
.style("stroke-width", 3)
.style("stroke", function (d) {
if (_this.yAxisSecondAxisDataFilter && _this.yAxisSecondAxisDataFilter(d))
return "lightgray";
return _this.color(d.name);
});
legend.filter(function (d, i) { return i >= numberOfLines; })
.append("circle")
.attr("r", 4)
.attr("cx", this.width - 15)
.attr("cy", 19 / 2)
.style("fill", function (d) {
return _this.color(d.name);
});
legend.append("text")
.attr("x", this.width - 24)
.attr("y", 9.5)
.attr("dy", "0.32em")
.text(function (d) { return d.name; });
var legendPadding = 5;
legendContainer.insert("rect", "g")
.attr("x", legendContainer.node().getBBox().x - legendPadding)
.attr("y", legendContainer.node().getBBox().y)
.style("stroke-width", "1")
.style("stroke", "black")
.style("fill", "white")
.style("fill-opacity", 0.8)
.attr("width", legendContainer.node().getBBox().width + (legendPadding * 2))
.attr("height", legendContainer.node().getBBox().height + legendPadding);
};
GraphComponent.prototype.updateAxis = function (includeTransitions) {
if (includeTransitions === void 0) { includeTransitions = true; }
var xAx = this.svg.select(".x.axis");
if (includeTransitions && this.transitionDuration > 0)
xAx = xAx.transition()
.duration(this.transitionDuration);
if (d3.event != null && d3.event.transform && this.AllowZoomX) {
this.zoomedX = d3.event.transform.rescaleX(this.x);
}
else {
this.zoomedX = this.zoomedX ? this.zoomedX : this.x;
}
var rescaledXAxis = this.xAxis.scale(this.zoomedX);
xAx.call(rescaledXAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.3em")
.attr("dy", ".5em")
.attr("transform", "rotate(" + this.xAxisTextRotation + ")");
var yAx = this.svg.select(".y.axis");
if (includeTransitions && this.transitionDuration > 0)
yAx = yAx.transition()
.duration(this.transitionDuration);
if (d3.event != null && d3.event.transform && this.AllowZoomY) {
this.zoomedY = d3.event.transform.rescaleY(this.y);
}
else {
this.zoomedY = this.zoomedY ? this.zoomedY : this.y;
}
var rescaledYAxis = this.yAxis.scale(this.zoomedY);
yAx.call(rescaledYAxis);
if (this.yAxisSecondAxisDataFilter) {
var yAx2 = this.svg.select(".y2.axis");
if (includeTransitions && this.transitionDuration > 0)
yAx2 = yAx2.transition()
.duration(this.transitionDuration);
if (d3.event != null && d3.event.transform && this.AllowZoomY) {
this.zoomedY2 = d3.event.transform.rescaleY(this.y2);
}
else {
this.zoomedY2 = this.zoomedY2 ? this.zoomedY2 : this.y2;
}
var rescaledY2Axis = this.y2Axis.scale(this.zoomedY2);
yAx2.call(rescaledY2Axis);
}
};
GraphComponent.prototype.updateDifferenceLines = function (differenceData) {
var y = this.zoomedY;
var axClass = "ax1";
var enteredClipsBelow = this.graphContainer.selectAll(".clip-below-" + this.UniqueId).data([differenceData])
.enter()
.append("clipPath")
.attr("id", "clip-below-" + this.UniqueId);
enteredClipsBelow.append("path")
.call(this.zoom);
// enteredClipsBelow.merge(enteredClipsBelow)
// .attr("d", d=>this.differenceArea.y0(this.height)(d.Data));
var enteredClipsAbove = this.graphContainer.selectAll(".clip-above-" + this.UniqueId).data([differenceData])
.enter()
.append("clipPath")
.attr("id", "clip-above-" + this.UniqueId);
enteredClipsAbove.append("path")
.call(this.zoom);
// enteredClipsAbove.merge(enteredClipsAbove)
this.updateExistingDifference(enteredClipsBelow.merge(enteredClipsBelow).select("path"), false, true);
this.updateExistingDifference(enteredClipsAbove.merge(enteredClipsAbove).select("path"), true, true);
// var enteredDiffAbove = this.graphContainer.selectAll(".area.above")
// .data([mutableData[0]])
// .enter()
// .append("path")
// .attr("class", "area above")
// .attr("clip-path", "url(#clip-above)");
// enteredDiffAbove.merge(enteredDiffAbove)
// .attr("d", d=>this.differenceArea.y0(function (d) { return y(d.Value); })(d.Data));
// var enteredDiffBelow = this.graphContainer.selectAll(".area.below")
// .data([mutableData[1]])
// .enter()
// .append("path")
// .attr("class", "area below")
// .attr("clip-path", "url(#clip-below)");
// enteredDiffBelow.merge(enteredDiffBelow)
// .attr("d", d=> this.differenceArea(d.Data));
var line0 = this.graphContainer.selectAll(".diff-line.diff0." + axClass)
.data([differenceData])
.enter()
.append("path")
.style('opacity', 0)
.attr("class", "diff-line " + axClass + " diff0")
.call(this.zoom);
var line1 = this.graphContainer.selectAll(".diff-line.diff1." + axClass)
.data([differenceData])
.enter()
.append("path")
.style('opacity', 0)
.attr("class", "diff-line " + axClass + " diff1")
.call(this.zoom);
this.updateExistingDifferenceLines(line0.merge(line0), false, true);
this.updateExistingDifferenceLines(line1.merge(line1), true, true);
line0.exit()
.remove();
line1.exit()
.remove();
};
GraphComponent.prototype.updateExistingDifferenceLines = function (lines, isAbove, includeTransitions) {
var _this = this;
var that = this;
if (includeTransitions && this.transitionDuration > 0)
lines = lines.transition().duration(this.transitionDuration);
lines = lines
.attr("d", isAbove ? this.differenceArea.y0(function (d) { return _this.zoomedY(d.Value1); }) : this.differenceArea)
.style('opacity', 1)
.style("fill", isAbove ? "lightsalmon" : "lightgreen")
.attr("clip-path", isAbove ? "url(#clip-above-" + this.UniqueId + ")" : "url(#clip-below-" + this.UniqueId + ")");
};
GraphComponent.prototype.updateExistingLines = function (lines, includeTransitions, isYAxis2) {
var _this = this;
var that = this;
var shape = isYAxis2 ? this.area : this.line;
if (includeTransitions && this.transitionDuration > 0) {
lines = lines.transition().duration(this.transitionDuration);
if (this.useTweenTransition)
lines.attrTween("d", function (d) { return that.pathTween(shape(d.Data), 4, this)(); });
else {
lines.attr("d", function (d) { return shape(d.Data); });
}
}
else {
lines.attr("d", function (d) { return shape(d.Data); });
}
lines = lines
.style('opacity', 1)
.style('stroke-width', this.lineSizePx)
.style("stroke", function (d) { return _this.color(d.name); });
};
GraphComponent.prototype.updateLines = function (mutableData, isYAxis2) {
var y = isYAxis2 ? this.zoomedY2 : this.zoomedY;
var axClass = isYAxis2 ? "ax2" : "ax1";
var gLines = this.graphContainer.selectAll(".chart-line." + axClass)
.data(mutableData);
var enteredGLines = gLines.enter()
.append("g")
.attr("class", "chart-line " + axClass)
.call(this.zoom);
var enteredLines = enteredGLines
.append("path")
.style('opacity', 0)
.style('stroke-dasharray', function (d, i) { return i == 0 ? undefined : i * 8 + "," + i * 8; })
.attr("class", "gc-line " + axClass);
this.updateExistingLines(enteredGLines.merge(gLines).select(".gc-line"), true, isYAxis2);
gLines.exit()
.remove();
};
GraphComponent.prototype.updateExistingDifference = function (clip, isAbove, includeTransitions) {
if (includeTransitions && this.transitionDuration > 0)
clip = clip.transition().duration(this.transitionDuration);
if (isAbove) {
clip.attr("d", this.differenceArea.y0(0));
}
else {
clip.attr("d", this.differenceArea.y0(this.height));
}
};
GraphComponent.prototype.updateExistingLinePoints = function (circles, includeTransitions, isYAxis2) {
var _this = this;
var y = isYAxis2 ? this.zoomedY2 : this.zoomedY;
if (includeTransitions && this.transitionDuration > 0)
circles = circles.style('opacity', 1)
.transition().duration(this.transitionDuration);
circles.style('opacity', 1)
.style('fill-opacity', .8)
.attr("cx", function (d) { return _this.zoomedX(d[0].Date); })
.attr("cy", function (d) { return y(d[0].Value); });
};
GraphComponent.prototype.updateLinePoints = function (dataPoints, isYAxis2) {
var _this = this;
var y = isYAxis2 ? this.zoomedY2 : this.zoomedY;
var axClass = isYAxis2 ? "ax2" : "ax1";
var circles = this.graphContainer.selectAll(".data-point." + axClass)
.data(dataPoints, function (d) { return d[0].Date; });
var enteredCircles = circles.enter().append("circle")
.attr("r", this.pointSizeR)
.style("fill", function (d) { return isYAxis2 ? "lightgray" : _this.color(d[1]); })
.style('opacity', 0)
.attr("class", "data-point " + axClass)
.attr("cx", function (d) { return _this.zoomedX(d[0].Date); })
.attr("cy", function (d) { return y(d[0].Value); })
.call(this.zoom);
circles.exit()
.remove();
this.updateExistingLinePoints(enteredCircles.merge(circles), true, isYAxis2);
};
GraphComponent.prototype.pathTween = function (d1, precision, element) {
return function () {
if (!d1)
return "";
var path0 = element, path1 = path0.cloneNode(), n0 = path0.getTotalLength(), n1 = (path1.setAttribute("d", d1), path1).getTotalLength();
// Uniform sampling of distance based on specified precision.
var distances = [0], i = 0, dt = precision / Math.max(n0, n1);
while ((i += dt) < 1)
distances.push(i);
distances.push(1);
// Compute point-interpolators at each distance.
var points = distances.map(function (t) {
var p0 = path0.getPointAtLength(t * n0), p1 = path1.getPointAtLength(t * n1);
return d3.interpolate([p0.x, p0.y], [p1.x, p1.y]);
});
return function (t) {
return t < 1 ? "M" + points.map(function (p) { return p(t); }).join("L") : d1;
};
};
};
__decorate([
Input(),
__metadata("design:type", Object)
], GraphComponent.prototype, "lineData", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], GraphComponent.prototype, "pointData", void 0);
__decorate([
Input(),
__metadata("design:type", Number)
], GraphComponent.prototype, "height", void 0);
__decorate([
Input(),
__metadata("design:type", Number)
], GraphComponent.prototype, "width", void 0);
__decorate([
Input(),
__metadata("design:type", Boolean)
], GraphComponent.prototype, "includeLineDataPoints", void 0);
__decorate([
Input(),
__metadata("design:type", Boolean)
], GraphComponent.prototype, "includeHoverLine", void 0);
__decorate([
Input(),
__metadata("design:type", Function)
], GraphComponent.prototype, "hoverLineDisplay", void 0);
__decorate([
Input(),
__metadata("design:type", Number)
], GraphComponent.prototype, "transitionDuration", void 0);
__decorate([
Input(),
__metadata("design:type", Boolean)
], GraphComponent.prototype, "hideBorder", void 0);
__decorate([
Input(),
__metadata("design:type", String)
], GraphComponent.prototype, "yAxisTitle", void 0);
__decorate([
Input(),
__metadata("design:type", String)
], GraphComponent.prototype, "ySecondAxisTitle", void 0);
__decorate([
Input(),
__metadata("design:type", Function)
], GraphComponent.prototype, "interpolationMethod", void 0);
__decorate([
Input(),
__metadata("design:type", Margin)
], GraphComponent.prototype, "margin", void 0);
__decorate([
Input(),
__metadata("design:type", String)
], GraphComponent.prototype, "xAxisTextRotation", void 0);
__decorate([
Input(),
__metadata("design:type", Object)
], GraphComponent.prototype, "yAxisSecondAxisDataFilter", void 0);
__decorate([
Input(),
__metadata("design:type", Boolean)
], GraphComponent.prototype, "AllowZoomX", void 0);
__decorate([
Input(),
__metadata("design:type", Boolean)
], GraphComponent.prototype, "AllowZoomY", void 0);
__decorate([
Input(),
__metadata("design:type", Array)
], GraphComponent.prototype, "xExtent", void 0);
__decorate([
Input(),
__metadata("design:type", Boolean)
], GraphComponent.prototype, "IncludeDifference", void 0);
__decorate([
Input(),
__metadata("design:type", Boolean)
], GraphComponent.prototype, "disableWheelZoom", void 0);
__decorate([
Input(),
__metadata("design:type", Boolean)
], GraphComponent.prototype, "UseContinuousHoverLine", void 0);
__decorate([
Input(),
__metadata("design:type", Array)
], GraphComponent.prototype, "xDomain", void 0);
__decorate([
Input(),
__metadata("design:type", Array)
], GraphComponent.prototype, "yDomain", void 0);
__decorate([
Input(),
__metadata("design:type", Boolean)
], GraphComponent.prototype, "useTweenTransition", void 0);
__decorate([
Input(),
__metadata("design:type", String)
], GraphComponent.prototype, "lineSizePx", void 0);
__decorate([
Input(),
__metadata("design:type", Number)
], GraphComponent.prototype, "pointSizeR", void 0);
__decorate([
Input(),
__metadata("design:type", Array)
], GraphComponent.prototype, "userColors", void 0);
__decorate([
Input(),
__metadata("design:type", String)
], GraphComponent.prototype, "UniqueId", void 0);
__decorate([
Output(),
__metadata("design:type", EventEmitter)
], GraphComponent.prototype, "TooltipItemChange", void 0);
__decorate([
ViewChild('tooltip'),
__metadata("design:type", ElementRef)
], GraphComponent.prototype, "tooltipElementRef", void 0);
GraphComponent = __decorate([
Component({
selector: 'pm-graph',
//templateUrl: './app/controls/components/graph/graph-component.html',
templateUrl: './graph-component.html',
styles: ["\n :host { \n position: relative;\n display: block;\n }"],
changeDetection: ChangeDetectionStrategy.OnPush
}),
__metadata("design:paramtypes", [ElementRef])
], GraphComponent);
return GraphComponent;
}());
export { GraphComponent };