kloudbuster/kb_server/public/ui/scripts/line-chart.js

1182 lines
70 KiB
JavaScript

var directive, m, mod, old_m, __indexOf = [].indexOf || function(item) {
for (var i = 0, l = this.length; l > i; i++) if (i in this && this[i] === item) return i;
return -1;
};
old_m = angular.module("n3-charts.linechart", [ "n3charts.utils" ]), m = angular.module("n3-line-chart", [ "n3charts.utils" ]),
directive = function(name, conf) {
return old_m.directive(name, conf), m.directive(name, conf);
}, directive("linechart", [ "n3utils", "$window", "$timeout", function(n3utils, $window, $timeout) {
var link;
return link = function(scope, element, attrs, ctrl) {
var dispatch, id, initialHandlers, isUpdatingOptions, promise, updateEvents, window_resize, _u;
_u = n3utils, dispatch = _u.getEventDispatcher(), id = _u.uuid(), element[0].style["font-size"] = 0,
scope.redraw = function() {
scope.update();
}, isUpdatingOptions = !1, initialHandlers = {
onSeriesVisibilityChange: function(_arg) {
var index, newVisibility, series;
return series = _arg.series, index = _arg.index, newVisibility = _arg.newVisibility,
scope.options.series[index].visible = newVisibility, scope.$apply();
}
}, scope.update = function() {
var axes, columnWidth, dataPerSeries, dimensions, fn, handlers, isThumbnail, options, svg;
return options = _u.sanitizeOptions(scope.options, attrs.mode), handlers = angular.extend(initialHandlers, _u.getTooltipHandlers(options)),
dataPerSeries = _u.getDataPerSeries(scope.data, options), dimensions = _u.getDimensions(options, element, attrs),
isThumbnail = "thumbnail" === attrs.mode, _u.clean(element[0]), svg = _u.bootstrap(element[0], id, dimensions),
fn = function(key) {
return options.series.filter(function(s) {
return s.axis === key && s.visible !== !1;
}).length > 0;
}, axes = _u.createAxes(svg, dimensions, options.axes).andAddThemIf({
all: !isThumbnail,
x: !0,
y: fn("y"),
y2: fn("y2")
}), dataPerSeries.length && _u.setScalesDomain(axes, scope.data, options.series, svg, options),
_u.createContent(svg, id, options, handlers), dataPerSeries.length && (columnWidth = _u.getBestColumnWidth(axes, dimensions, dataPerSeries, options),
_u.drawData(svg, dimensions, axes, dataPerSeries, columnWidth, options, handlers, dispatch)),
options.drawLegend && _u.drawLegend(svg, options.series, dimensions, handlers, dispatch),
"scrubber" === options.tooltip.mode ? _u.createGlass(svg, dimensions, handlers, axes, dataPerSeries, options, dispatch, columnWidth) : "none" !== options.tooltip.mode && _u.addTooltips(svg, dimensions, options.axes),
_u.createFocus(svg, dimensions, options), _u.setZoom(svg, dimensions, axes, dataPerSeries, columnWidth, options, handlers, dispatch);
}, updateEvents = function() {
return scope.oldclick ? dispatch.on("click", scope.oldclick) : scope.click ? dispatch.on("click", scope.click) : dispatch.on("click", null),
scope.oldhover ? dispatch.on("hover", scope.oldhover) : scope.hover ? dispatch.on("hover", scope.hover) : dispatch.on("hover", null),
scope.mouseenter ? dispatch.on("mouseenter", scope.mouseenter) : dispatch.on("mouseenter", null),
scope.mouseover ? dispatch.on("mouseover", scope.mouseover) : dispatch.on("mouseover", null),
scope.mouseout ? dispatch.on("mouseout", scope.mouseout) : dispatch.on("mouseout", null),
scope.oldfocus ? dispatch.on("focus", scope.oldfocus) : scope.focus ? dispatch.on("focus", scope.focus) : dispatch.on("focus", null),
scope.toggle ? dispatch.on("toggle", scope.toggle) : dispatch.on("toggle", null);
}, promise = void 0, window_resize = function() {
return null != promise && $timeout.cancel(promise), promise = $timeout(scope.redraw, 1);
}, $window.addEventListener("resize", window_resize), scope.$watch("data", scope.redraw, !0),
scope.$watch("options", scope.redraw, !0), scope.$watchCollection("[click, hover, focus, toggle]", updateEvents),
scope.$watchCollection("[mouseenter, mouseover, mouseout]", updateEvents), scope.$watchCollection("[oldclick, oldhover, oldfocus]", updateEvents),
scope.$on("$destroy", function() {
return $window.removeEventListener("resize", window_resize);
});
}, {
replace: !0,
restrict: "E",
scope: {
data: "=",
options: "=",
oldclick: "=click",
oldhover: "=hover",
oldfocus: "=focus",
click: "=onClick",
hover: "=onHover",
focus: "=onFocus",
toggle: "=onToggle",
mouseenter: "=onMouseenter",
mouseover: "=onMouseover",
mouseout: "=onMouseout"
},
template: "<div></div>",
link: link
};
} ]), mod = angular.module("n3charts.utils", []), mod.factory("n3utils", [ "$window", "$log", "$rootScope", function($window, $log, $rootScope) {
return {
addPatterns: function(svg, series) {
var pattern;
return pattern = svg.select("defs").selectAll("pattern").data(series.filter(function(s) {
return s.striped;
})).enter().append("pattern").attr({
id: function(s) {
return s.type + "Pattern_" + s.index;
},
patternUnits: "userSpaceOnUse",
x: 0,
y: 0,
width: 60,
height: 60
}).append("g").style({
fill: function(s) {
return s.color;
},
"fill-opacity": .9
}), pattern.append("rect").style("fill-opacity", .9).attr("width", 60).attr("height", 60),
pattern.append("path").attr("d", "M 10 0 l10 0 l -20 20 l 0 -10 z"), pattern.append("path").attr("d", "M40 0 l10 0 l-50 50 l0 -10 z"),
pattern.append("path").attr("d", "M60 10 l0 10 l-40 40 l-10 0 z"), pattern.append("path").attr("d", "M60 40 l0 10 l-10 10 l -10 0 z");
},
drawArea: function(svg, scales, data, options) {
var areaGroup, areaJoin, areaSeries, drawers;
return areaSeries = data.filter(function(series) {
return "area" === series.type;
}), this.addPatterns(svg, areaSeries), drawers = {
y: this.createLeftAreaDrawer(scales, options.lineMode, options.tension),
y2: this.createRightAreaDrawer(scales, options.lineMode, options.tension)
}, areaJoin = svg.select(".content").selectAll(".areaGroup").data(areaSeries), areaGroup = areaJoin.enter().append("g").attr("class", function(s) {
return "areaGroup series_" + s.index;
}), areaJoin.each(function(series) {
var dataJoin;
return dataJoin = d3.select(this).selectAll("path").data([ series ]), dataJoin.enter().append("path").attr("class", "area"),
dataJoin.style("fill", function(s) {
return s.striped !== !0 ? s.color : "url(#areaPattern_" + s.index + ")";
}).style("opacity", function(s) {
return s.striped ? "1" : "0.8";
}).attr("d", function(d) {
return drawers[d.axis](d.values);
});
}), this;
},
createLeftAreaDrawer: function(scales, mode, tension) {
return d3.svg.area().x(function(d) {
return scales.xScale(d.x);
}).y0(function(d) {
return scales.yScale(d.y0);
}).y1(function(d) {
return scales.yScale(d.y0 + d.y);
}).interpolate(mode).tension(tension);
},
createRightAreaDrawer: function(scales, mode, tension) {
return d3.svg.area().x(function(d) {
return scales.xScale(d.x);
}).y0(function(d) {
return scales.y2Scale(d.y0);
}).y1(function(d) {
return scales.y2Scale(d.y0 + d.y);
}).interpolate(mode).tension(tension);
},
getPseudoColumns: function(data, options) {
var keys, pseudoColumns;
return data = data.filter(function(s) {
return "column" === s.type;
}), pseudoColumns = {}, keys = [], data.forEach(function(series) {
var i, inAStack, index, visible, _ref;
return i = options.series.map(function(d) {
return d.id;
}).indexOf(series.id), visible = null != (_ref = options.series) ? _ref[i].visible : void 0,
void 0 !== visible && visible !== !0 || (inAStack = !1, options.stacks.forEach(function(stack, index) {
var _ref1;
return null != series.id && (_ref1 = series.id, __indexOf.call(stack.series, _ref1) >= 0) ? (pseudoColumns[series.id] = index,
__indexOf.call(keys, index) < 0 && keys.push(index), inAStack = !0) : void 0;
}), inAStack !== !1) ? void 0 : (i = pseudoColumns[series.id] = index = keys.length,
keys.push(i));
}), {
pseudoColumns: pseudoColumns,
keys: keys
};
},
getMinDelta: function(seriesData, key, scale, range) {
return d3.min(seriesData.map(function(series) {
return series.values.map(function(d) {
return scale(d[key]);
}).filter(function(e) {
return range ? e >= range[0] && e <= range[1] : !0;
}).reduce(function(prev, cur, i, arr) {
var diff;
return diff = i > 0 ? Math.max(cur - arr[i - 1], 0) : Number.MAX_VALUE, prev > diff ? diff : prev;
}, Number.MAX_VALUE);
}));
},
getBestColumnWidth: function(axes, dimensions, seriesData, options) {
var colData, delta, innerWidth, keys, nSeries, pseudoColumns, _ref;
return seriesData && 0 !== seriesData.length ? 0 === seriesData.filter(function(s) {
return "column" === s.type;
}).length ? 10 : (_ref = this.getPseudoColumns(seriesData, options), pseudoColumns = _ref.pseudoColumns,
keys = _ref.keys, innerWidth = dimensions.width - dimensions.left - dimensions.right,
colData = seriesData.filter(function(d) {
return pseudoColumns.hasOwnProperty(d.id);
}), delta = this.getMinDelta(colData, "x", axes.xScale, [ 0, innerWidth ]), delta > innerWidth && (delta = .25 * innerWidth),
nSeries = keys.length, options.columnsHGap < delta ? Math.max(1, (delta - options.columnsHGap) / nSeries) : Math.max(1, .8 * delta / nSeries)) : 10;
},
getColumnAxis: function(data, columnWidth, options) {
var keys, pseudoColumns, x1, _ref;
return _ref = this.getPseudoColumns(data, options), pseudoColumns = _ref.pseudoColumns,
keys = _ref.keys, x1 = d3.scale.ordinal().domain(keys).rangeBands([ 0, keys.length * columnWidth ], 0),
function(s) {
var index;
return null == pseudoColumns[s.id] ? 0 : (index = pseudoColumns[s.id], x1(index) - keys.length * columnWidth / 2);
};
},
drawColumns: function(svg, axes, data, columnWidth, options, handlers, dispatch) {
var colGroup, colJoin, x1;
return data = data.filter(function(s) {
return "column" === s.type;
}), x1 = this.getColumnAxis(data, columnWidth, options), data.forEach(function(s) {
return s.xOffset = x1(s) + .5 * columnWidth;
}), colJoin = svg.select(".content").selectAll(".columnGroup").data(data), colGroup = colJoin.enter().append("g").attr("class", function(s) {
return "columnGroup series_" + s.index;
}), colJoin.attr("transform", function(s) {
return "translate(" + x1(s) + ",0)";
}), colJoin.each(function(series) {
var dataJoin, i, visible, _ref;
return i = options.series.map(function(d) {
return d.id;
}).indexOf(series.id), visible = null != (_ref = options.series) ? _ref[i].visible : void 0,
void 0 === visible || visible === !0 ? (dataJoin = d3.select(this).selectAll("rect").data(series.values),
dataJoin.enter().append("rect").on({
click: function(d, i) {
return dispatch.click(d, i, series);
}
}).on("mouseenter", function(d, i) {
return dispatch.mouseenter(d, i, series);
}).on("mouseover", function(d, i) {
return "function" == typeof handlers.onMouseOver && handlers.onMouseOver(svg, {
series: series,
x: axes.xScale(d.x),
y: axes[d.axis + "Scale"](d.y0 + d.y),
datum: d
}, options.axes), dispatch.hover(d, i, series), dispatch.mouseover(d, i, series);
}).on("mouseout", function(d, i) {
return "function" == typeof handlers.onMouseOut && handlers.onMouseOut(svg), dispatch.mouseout(d, i, series);
}), dataJoin.style({
stroke: series.color,
fill: series.color,
"stroke-opacity": function(d) {
return 0 === d.y ? "0" : "1";
},
"stroke-width": "1px",
"fill-opacity": function(d) {
return 0 === d.y ? 0 : .7;
}
}).attr({
width: columnWidth,
x: function(d) {
return axes.xScale(d.x);
},
height: function(d) {
return 0 === d.y ? axes[d.axis + "Scale"].range()[0] : Math.abs(axes[d.axis + "Scale"](d.y0 + d.y) - axes[d.axis + "Scale"](d.y0));
},
y: function(d) {
return 0 === d.y ? 0 : axes[d.axis + "Scale"](Math.max(0, d.y0 + d.y));
}
})) : void 0;
}), this;
},
drawDots: function(svg, axes, data, options, handlers, dispatch) {
var dotGroup, dotJoin;
return dotJoin = svg.select(".content").selectAll(".dotGroup").data(data.filter(function(s) {
var _ref;
return ("line" === (_ref = s.type) || "area" === _ref) && s.drawDots;
})), dotGroup = dotJoin.enter().append("g").attr("class", function(s) {
return "dotGroup series_" + s.index;
}), dotJoin.attr("fill", function(s) {
return s.color;
}), dotJoin.each(function(series) {
var dataJoin;
return dataJoin = d3.select(this).selectAll(".dot").data(series.values), dataJoin.enter().append("circle").attr("class", "dot").on({
click: function(d, i) {
return dispatch.click(d, i, series);
}
}).on({
mouseenter: function(d, i) {
return dispatch.mouseenter(d, i, series);
}
}).on({
mouseover: function(d, i) {
return dispatch.hover(d, i, series), dispatch.mouseover(d, i, series);
}
}).on({
mouseout: function(d, i) {
return dispatch.mouseout(d, i, series);
}
}), dataJoin.attr({
r: function(d) {
return d.dotSize;
},
cx: function(d) {
return axes.xScale(d.x);
},
cy: function(d) {
return axes[d.axis + "Scale"](d.y + d.y0);
}
}).style({
stroke: "white",
"stroke-width": "2px"
});
}), "none" !== options.tooltip.mode && dotGroup.on("mouseover", function(series) {
var d, target;
return target = d3.select(d3.event.target), d = target.datum(), target.attr("r", function(s) {
return s.dotSize + 2;
}), "function" == typeof handlers.onMouseOver ? handlers.onMouseOver(svg, {
series: series,
x: target.attr("cx"),
y: target.attr("cy"),
datum: d
}, options.axes) : void 0;
}).on("mouseout", function(d) {
return d3.select(d3.event.target).attr("r", function(s) {
return s.dotSize;
}), "function" == typeof handlers.onMouseOut ? handlers.onMouseOut(svg) : void 0;
}), this;
},
getEventDispatcher: function() {
var events;
return events = [ "focus", "hover", "mouseenter", "mouseover", "mouseout", "click", "toggle" ],
d3.dispatch.apply(this, events);
},
resetZoom: function(svg, dimensions, axes, data, columnWidth, options, handlers, dispatch, zoom) {
return zoom.scale(1), zoom.translate([ 0, 0 ]), this.getZoomHandler(svg, dimensions, axes, data, columnWidth, options, handlers, dispatch, !1)();
},
getZoomHandler: function(svg, dimensions, axes, data, columnWidth, options, handlers, dispatch, zoom) {
var self;
return self = this, function() {
var zoomed;
return zoomed = !1, [ "x", "y", "y2" ].forEach(function(axis) {
var _ref;
return null != (null != (_ref = options.axes[axis]) ? _ref.zoomable : void 0) ? (svg.selectAll("." + axis + ".axis").call(axes["" + axis + "Axis"]),
zoomed = !0) : void 0;
}), data.length && (columnWidth = self.getBestColumnWidth(axes, dimensions, data, options),
self.drawData(svg, dimensions, axes, data, columnWidth, options, handlers, dispatch)),
zoom && zoomed ? self.createZoomResetIcon(svg, dimensions, axes, data, columnWidth, options, handlers, dispatch, zoom) : void 0;
};
},
setZoom: function(svg, dimensions, axes, data, columnWidth, options, handlers, dispatch) {
var zoom;
return zoom = this.getZoomListener(axes, options), zoom ? (zoom.on("zoom", this.getZoomHandler(svg, dimensions, axes, data, columnWidth, options, handlers, dispatch, zoom)),
svg.call(zoom)) : void 0;
},
getZoomListener: function(axes, options) {
var zoom, zoomable;
return zoomable = !1, zoom = d3.behavior.zoom(), [ "x", "y", "y2" ].forEach(function(axis) {
var _ref;
return (null != (_ref = options.axes[axis]) ? _ref.zoomable : void 0) ? (zoom[axis](axes["" + axis + "Scale"]),
zoomable = !0) : void 0;
}), zoomable ? zoom : !1;
},
computeLegendLayout: function(svg, series, dimensions) {
var cumul, i, j, leftLayout, leftWidths, padding, rightLayout, rightWidths, that, w;
for (padding = 10, that = this, leftWidths = this.getLegendItemsWidths(svg, "y"),
leftLayout = [ 0 ], i = 1; i < leftWidths.length; ) leftLayout.push(leftWidths[i - 1] + leftLayout[i - 1] + padding),
i++;
if (rightWidths = this.getLegendItemsWidths(svg, "y2"), !(rightWidths.length > 0)) return [ leftLayout ];
for (w = dimensions.width - dimensions.right - dimensions.left, cumul = 0, rightLayout = [],
j = rightWidths.length - 1; j >= 0; ) rightLayout.push(w - cumul - rightWidths[j]),
cumul += rightWidths[j] + padding, j--;
return rightLayout.reverse(), [ leftLayout, rightLayout ];
},
getLegendItemsWidths: function(svg, axis) {
var bbox, i, items, that, widths;
if (that = this, bbox = function(t) {
return that.getTextBBox(t).width;
}, items = svg.selectAll(".legendItem." + axis), !(items.length > 0)) return [];
for (widths = [], i = 0; i < items[0].length; ) widths.push(bbox(items[0][i])),
i++;
return widths;
},
drawLegend: function(svg, series, dimensions, handlers, dispatch) {
var d, groups, legend, that, translateLegends;
return that = this, legend = svg.append("g").attr("class", "legend"), d = 16, svg.select("defs").append("svg:clipPath").attr("id", "legend-clip").append("circle").attr("r", d / 2),
groups = legend.selectAll(".legendItem").data(series), groups.enter().append("g").on("click", function(s, i) {
var visibility;
return visibility = !(s.visible !== !1), dispatch.toggle(s, i, visibility), "function" == typeof handlers.onSeriesVisibilityChange ? handlers.onSeriesVisibilityChange({
series: s,
index: i,
newVisibility: visibility
}) : void 0;
}), groups.attr({
"class": function(s, i) {
return "legendItem series_" + i + " " + s.axis;
},
opacity: function(s, i) {
return s.visible === !1 ? (that.toggleSeries(svg, i), "0.2") : "1";
}
}).each(function(s) {
var item, _ref;
return item = d3.select(this), item.append("circle").attr({
fill: s.color,
stroke: s.color,
"stroke-width": "2px",
r: d / 2
}), item.append("path").attr({
"clip-path": "url(#legend-clip)",
"fill-opacity": "area" === (_ref = s.type) || "column" === _ref ? "1" : "0",
fill: "white",
stroke: "white",
"stroke-width": "2px",
d: that.getLegendItemPath(s, d, d)
}), item.append("circle").attr({
"fill-opacity": 0,
stroke: s.color,
"stroke-width": "2px",
r: d / 2
}), item.append("text").attr({
"class": function(d, i) {
return "legendText series_" + i;
},
"font-family": "Courier",
"font-size": 10,
transform: "translate(13, 4)",
"text-rendering": "geometric-precision"
}).text(s.label || s.y);
}), translateLegends = function() {
var left, right, _ref;
return _ref = that.computeLegendLayout(svg, series, dimensions), left = _ref[0],
right = _ref[1], groups.attr({
transform: function(s, i) {
return "y" === s.axis ? "translate(" + left.shift() + "," + (dimensions.height - 40) + ")" : "translate(" + right.shift() + "," + (dimensions.height - 40) + ")";
}
});
}, translateLegends(), setTimeout(translateLegends, 0), this;
},
getLegendItemPath: function(series, w, h) {
var base_path, path;
return "column" === series.type ? (path = "M" + -w / 3 + " " + -h / 8 + " l0 " + h + " ",
path += "M0 " + -h / 3 + " l0 " + h + " ", path += "M" + w / 3 + " " + -h / 10 + " l0 " + h + " ") : (base_path = "M-" + w / 2 + " 0" + h / 3 + " l" + w / 3 + " -" + h / 3 + " l" + w / 3 + " " + h / 3 + " l" + w / 3 + " -" + 2 * h / 3,
"area" === series.type, base_path);
},
toggleSeries: function(svg, index) {
var isVisible;
return isVisible = !1, svg.select(".content").selectAll(".series_" + index).style("display", function(s) {
return "none" === d3.select(this).style("display") ? (isVisible = !0, "initial") : (isVisible = !1,
"none");
}), isVisible;
},
drawLines: function(svg, scales, data, options, handlers) {
var drawers, interpolateData, lineGroup, lineJoin;
return drawers = {
y: this.createLeftLineDrawer(scales, options.lineMode, options.tension),
y2: this.createRightLineDrawer(scales, options.lineMode, options.tension)
}, lineJoin = svg.select(".content").selectAll(".lineGroup").data(data.filter(function(s) {
var _ref;
return "line" === (_ref = s.type) || "area" === _ref;
})), lineGroup = lineJoin.enter().append("g").attr("class", function(s) {
return "lineGroup series_" + s.index;
}), lineJoin.style("stroke", function(s) {
return s.color;
}), lineJoin.each(function(series) {
var dataJoin;
return dataJoin = d3.select(this).selectAll("path").data([ series ]), dataJoin.enter().append("path").attr("class", "line"),
dataJoin.attr("d", function(d) {
return drawers[d.axis](d.values);
}).style({
fill: "none",
"stroke-width": function(s) {
return s.thickness;
},
"stroke-dasharray": function(s) {
return "dashed" === s.lineMode ? "10,3" : void 0;
}
});
}), options.tooltip.interpolate && (interpolateData = function(series) {
var datum, error, i, interpDatum, maxXPos, maxXValue, maxYPos, maxYValue, minXPos, minXValue, minYPos, minYValue, mousePos, target, valuesData, x, xPercentage, xVal, y, yPercentage, yVal, _i, _len;
target = d3.select(d3.event.target);
try {
mousePos = d3.mouse(this);
} catch (_error) {
error = _error, mousePos = [ 0, 0 ];
}
for (valuesData = target.datum().values, i = _i = 0, _len = valuesData.length; _len > _i; i = ++_i) datum = valuesData[i],
x = scales.xScale(datum.x), y = scales.yScale(datum.y), ("undefined" == typeof minXPos || null === minXPos || minXPos > x) && (minXPos = x,
minXValue = datum.x), ("undefined" == typeof maxXPos || null === maxXPos || x > maxXPos) && (maxXPos = x,
maxXValue = datum.x), ("undefined" == typeof minYPos || null === minYPos || minYPos > y) && (minYPos = y),
("undefined" == typeof maxYPos || null === maxYPos || y > maxYPos) && (maxYPos = y),
("undefined" == typeof minYValue || null === minYValue || datum.y < minYValue) && (minYValue = datum.y),
("undefined" == typeof maxYValue || null === maxYValue || datum.y > maxYValue) && (maxYValue = datum.y);
return xPercentage = (mousePos[0] - minXPos) / (maxXPos - minXPos), yPercentage = (mousePos[1] - minYPos) / (maxYPos - minYPos),
xVal = Math.round(xPercentage * (maxXValue - minXValue) + minXValue), yVal = Math.round((1 - yPercentage) * (maxYValue - minYValue) + minYValue),
interpDatum = {
x: xVal,
y: yVal
}, "function" == typeof handlers.onMouseOver ? handlers.onMouseOver(svg, {
series: series,
x: mousePos[0],
y: mousePos[1],
datum: interpDatum
}, options.axes) : void 0;
}, lineGroup.on("mousemove", interpolateData).on("mouseout", function(d) {
return "function" == typeof handlers.onMouseOut ? handlers.onMouseOut(svg) : void 0;
})), this;
},
createLeftLineDrawer: function(scales, mode, tension) {
return d3.svg.line().x(function(d) {
return scales.xScale(d.x);
}).y(function(d) {
return scales.yScale(d.y + d.y0);
}).interpolate(mode).tension(tension);
},
createRightLineDrawer: function(scales, mode, tension) {
return d3.svg.line().x(function(d) {
return scales.xScale(d.x);
}).y(function(d) {
return scales.y2Scale(d.y + d.y0);
}).interpolate(mode).tension(tension);
},
getPixelCssProp: function(element, propertyName) {
var string;
return string = $window.getComputedStyle(element, null).getPropertyValue(propertyName),
+string.replace(/px$/, "");
},
getDefaultMargins: function() {
return {
top: 20,
right: 50,
bottom: 60,
left: 50
};
},
getDefaultThumbnailMargins: function() {
return {
top: 1,
right: 1,
bottom: 2,
left: 0
};
},
getElementDimensions: function(element, width, height) {
var bottom, dim, left, parent, right, top;
return dim = {}, parent = element, top = this.getPixelCssProp(parent, "padding-top"),
bottom = this.getPixelCssProp(parent, "padding-bottom"), left = this.getPixelCssProp(parent, "padding-left"),
right = this.getPixelCssProp(parent, "padding-right"), dim.width = +(width || parent.offsetWidth || 900) - left - right,
dim.height = +(height || parent.offsetHeight || 500) - top - bottom, dim;
},
getDimensions: function(options, element, attrs) {
var dim;
return dim = this.getElementDimensions(element[0].parentElement, attrs.width, attrs.height),
dim = angular.extend(options.margin, dim);
},
clean: function(element) {
return d3.select(element).on("keydown", null).on("keyup", null).select("svg").remove();
},
uuid: function() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
var r, v;
return r = 16 * Math.random() | 0, v = "x" === c ? r : 3 & r | 8, v.toString(16);
});
},
bootstrap: function(element, id, dimensions) {
var defs, height, svg, width;
return d3.select(element).classed("chart", !0), width = dimensions.width, height = dimensions.height,
svg = d3.select(element).append("svg").attr({
width: width,
height: height
}).append("g").attr("transform", "translate(" + dimensions.left + "," + dimensions.top + ")"),
defs = svg.append("defs").attr("class", "patterns"), defs.append("clipPath").attr("class", "content-clip").attr("id", "content-clip-" + id).append("rect").attr({
x: 0,
y: 0,
width: width - dimensions.left - dimensions.right,
height: height - dimensions.top - dimensions.bottom
}), svg;
},
createContent: function(svg, id, options) {
var content;
return content = svg.append("g").attr("class", "content"), options.hideOverflow ? content.attr("clip-path", "url(#content-clip-" + id + ")") : void 0;
},
createZoomResetIcon: function(svg, dimensions, axes, data, columnWidth, options, handlers, dispatch, zoom) {
var icon, iconJoin, left, path, scale, self, top;
return self = this, path = "M22.646,19.307c0.96-1.583,1.523-3.435,1.524-5.421C24.169,8.093,19.478,3.401,13.688,3.399C7.897,3.401,3.204,8.093,3.204,13.885c0,5.789,4.693,10.481,10.484,10.481c1.987,0,3.839-0.563,5.422-1.523l7.128,7.127l3.535-3.537L22.646,19.307zM13.688,20.369c-3.582-0.008-6.478-2.904-6.484-6.484c0.006-3.582,2.903-6.478,6.484-6.486c3.579,0.008,6.478,2.904,6.484,6.486C20.165,17.465,17.267,20.361,13.688,20.369zM8.854,11.884v4.001l9.665-0.001v-3.999L8.854,11.884z",
iconJoin = svg.select(".focus-container").selectAll(".icon.zoom-reset").data([ 1 ]),
icon = iconJoin.enter().append("g").attr("class", "icon zoom-reset").on("click", function() {
return self.resetZoom(svg, dimensions, axes, data, columnWidth, options, handlers, dispatch, zoom),
d3.select(this).remove();
}).on("mouseenter", function() {
return d3.select(this).style("fill", "steelblue");
}).on("mouseout", function() {
return d3.select(this).style("fill", "black");
}), icon.append("path").attr("d", path), left = dimensions.width - dimensions.left - dimensions.right - 24,
top = 2, scale = .7, iconJoin.style({
fill: "black",
stroke: "white",
"stroke-width": 1.5
}).attr({
opacity: 1,
transform: "translate(" + left + ", " + top + ") scale(" + scale + ")"
});
},
createFocus: function(svg, dimensions, options) {
var glass;
return glass = svg.append("g").attr({
"class": "focus-container"
});
},
createGlass: function(svg, dimensions, handlers, axes, data, options, dispatch, columnWidth) {
var glass, scrubberGroup, that;
return that = this, glass = svg.append("g").attr({
"class": "glass-container",
opacity: 0
}), scrubberGroup = glass.selectAll(".scrubberItem").data(data).enter().append("g").attr("class", function(s, i) {
return "scrubberItem series_" + i;
}), scrubberGroup.each(function(s, i) {
var g, g2, item;
return item = d3.select(this), g = item.append("g").attr({
"class": "rightTT"
}), g.append("path").attr({
"class": "scrubberPath series_" + i,
y: "-7px",
fill: s.color
}), that.styleTooltip(g.append("text").style("text-anchor", "start").attr({
"class": function(d, i) {
return "scrubberText series_" + i;
},
height: "14px",
transform: "translate(7, 3)",
"text-rendering": "geometric-precision"
})).text(s.label || s.y), g2 = item.append("g").attr({
"class": "leftTT"
}), g2.append("path").attr({
"class": "scrubberPath series_" + i,
y: "-7px",
fill: s.color
}), that.styleTooltip(g2.append("text").style("text-anchor", "end").attr({
"class": "scrubberText series_" + i,
height: "14px",
transform: "translate(-13, 3)",
"text-rendering": "geometric-precision"
})).text(s.label || s.y), item.append("circle").attr({
"class": "scrubberDot series_" + i,
fill: "white",
stroke: s.color,
"stroke-width": "2px",
r: 4
});
}), glass.append("rect").attr({
"class": "glass",
width: dimensions.width - dimensions.left - dimensions.right,
height: dimensions.height - dimensions.top - dimensions.bottom
}).style("fill", "white").style("fill-opacity", 1e-6).on("mouseover", function() {
return handlers.onChartHover(svg, d3.select(this), axes, data, options, dispatch, columnWidth);
});
},
drawData: function(svg, dimensions, axes, data, columnWidth, options, handlers, dispatch) {
return this.drawArea(svg, axes, data, options, handlers).drawColumns(svg, axes, data, columnWidth, options, handlers, dispatch).drawLines(svg, axes, data, options, handlers),
options.drawDots ? this.drawDots(svg, axes, data, options, handlers, dispatch) : void 0;
},
getDataPerSeries: function(data, options) {
var axes, layout, series, straightened;
return series = options.series, axes = options.axes, series && series.length && data && data.length ? (straightened = series.map(function(s, i) {
var seriesData;
return seriesData = {
index: i,
name: s.y,
values: [],
color: s.color,
axis: s.axis || "y",
xOffset: 0,
type: s.type,
thickness: s.thickness,
drawDots: s.drawDots !== !1
}, null != s.dotSize && (seriesData.dotSize = s.dotSize), s.striped === !0 && (seriesData.striped = !0),
null != s.lineMode && (seriesData.lineMode = s.lineMode), s.id && (seriesData.id = s.id),
data.filter(function(row) {
return null != row[s.y];
}).forEach(function(row) {
var d;
return d = {
x: row[options.axes.x.key],
y: row[s.y],
y0: 0,
axis: s.axis || "y"
}, null != s.dotSize && (d.dotSize = s.dotSize), seriesData.values.push(d);
}), seriesData;
}), null == options.stacks || 0 === options.stacks.length ? straightened : (layout = d3.layout.stack().values(function(s) {
return s.values;
}), options.stacks.forEach(function(stack) {
var layers;
if (stack.series.length > 0) return layers = straightened.filter(function(s, i) {
return void 0 === series[i].visible || series[i].visible;
}).filter(function(s, i) {
var _ref;
return null != s.id && (_ref = s.id, __indexOf.call(stack.series, _ref) >= 0);
}), layout(layers);
}), straightened)) : [];
},
estimateSideTooltipWidth: function(svg, text) {
var bbox, t;
return t = svg.append("text"), t.text("" + text), this.styleTooltip(t), bbox = this.getTextBBox(t[0][0]),
t.remove(), bbox;
},
getTextBBox: function(svgTextElement) {
var error;
if (null !== svgTextElement) try {
return svgTextElement.getBBox();
} catch (_error) {
return error = _error, {
height: 0,
width: 0,
y: 0,
x: 0
};
}
return {};
},
getWidestTickWidth: function(svg, axisKey) {
var bbox, max, ticks, _ref;
return max = 0, bbox = this.getTextBBox, ticks = svg.select("." + axisKey + ".axis").selectAll(".tick"),
null != (_ref = ticks[0]) && _ref.forEach(function(t) {
return max = Math.max(max, bbox(t).width);
}), max;
},
getWidestOrdinate: function(data, series, options) {
var widest;
return widest = "", data.forEach(function(row) {
return series.forEach(function(series) {
var v, _ref;
return v = row[series.y], null != series.axis && (null != (_ref = options.axes[series.axis]) ? _ref.ticksFormatter : void 0) && (v = options.axes[series.axis].ticksFormatter(v)),
null != v && ("" + v).length > ("" + widest).length ? widest = v : void 0;
});
}), widest;
},
getDefaultOptions: function() {
return {
tooltip: {
mode: "scrubber"
},
lineMode: "linear",
tension: .7,
margin: this.getDefaultMargins(),
axes: {
x: {
type: "linear",
key: "x"
},
y: {
type: "linear"
}
},
series: [],
drawLegend: !0,
drawDots: !0,
stacks: [],
columnsHGap: 5,
hideOverflow: !1
};
},
sanitizeOptions: function(options, mode) {
var defaultMargin;
return null == options && (options = {}), "thumbnail" === mode && (options.drawLegend = !1,
options.drawDots = !1, options.tooltip = {
mode: "none",
interpolate: !1
}), options.series = this.sanitizeSeriesOptions(options.series), options.stacks = this.sanitizeSeriesStacks(options.stacks, options.series),
options.axes = this.sanitizeAxes(options.axes, this.haveSecondYAxis(options.series)),
options.tooltip = this.sanitizeTooltip(options.tooltip), options.margin = this.sanitizeMargins(options.margin),
options.lineMode || (options.lineMode = this.getDefaultOptions().lineMode), options.tension = /^\d+(\.\d+)?$/.test(options.tension) ? options.tension : this.getDefaultOptions().tension,
options.drawLegend = options.drawLegend !== !1, options.drawDots = options.drawDots !== !1,
angular.isNumber(options.columnsHGap) || (options.columnsHGap = 5), options.hideOverflow = options.hideOverflow || !1,
defaultMargin = "thumbnail" === mode ? this.getDefaultThumbnailMargins() : this.getDefaultMargins(),
options.series = angular.extend(this.getDefaultOptions().series, options.series),
options.axes = angular.extend(this.getDefaultOptions().axes, options.axes), options.tooltip = angular.extend(this.getDefaultOptions().tooltip, options.tooltip),
options.margin = angular.extend(defaultMargin, options.margin), options;
},
sanitizeMargins: function(options) {
var attrs, margin, opt, value;
attrs = [ "top", "right", "bottom", "left" ], margin = {};
for (opt in options) value = options[opt], __indexOf.call(attrs, opt) >= 0 && (margin[opt] = parseFloat(value));
return margin;
},
sanitizeSeriesStacks: function(stacks, series) {
var seriesKeys;
return null == stacks ? [] : (seriesKeys = {}, series.forEach(function(s) {
return seriesKeys[s.id] = s;
}), stacks.forEach(function(stack) {
return stack.series.forEach(function(id) {
var s;
if (s = seriesKeys[id], null != s) {
if (s.axis !== stack.axis) return $log.warn("Series " + id + " is not on the same axis as its stack");
} else if (!s) return $log.warn("Unknown series found in stack : " + id);
});
}), stacks);
},
sanitizeTooltip: function(options) {
var _ref;
if (!options) return {
mode: "scrubber"
};
if ("none" !== (_ref = options.mode) && "axes" !== _ref && "scrubber" !== _ref && (options.mode = "scrubber"),
"scrubber" === options.mode ? delete options.interpolate : options.interpolate = !!options.interpolate,
"scrubber" === options.mode && options.interpolate) throw new Error("Interpolation is not supported for scrubber tooltip mode.");
return options;
},
sanitizeSeriesOptions: function(options) {
var colors, knownIds;
return null == options ? [] : (colors = d3.scale.category10(), knownIds = {}, options.forEach(function(s, i) {
if (null != knownIds[s.id]) throw new Error("Twice the same ID (" + s.id + ") ? Really ?");
return null != s.id ? knownIds[s.id] = s : void 0;
}), options.forEach(function(s, i) {
var cnt, _ref, _ref1, _ref2, _ref3;
if (s.axis = "y2" !== (null != (_ref = s.axis) ? _ref.toLowerCase() : void 0) ? "y" : "y2",
s.color || (s.color = colors(i)), s.type = "line" === (_ref1 = s.type) || "area" === _ref1 || "column" === _ref1 ? s.type : "line",
"column" === s.type ? (delete s.thickness, delete s.lineMode, delete s.drawDots,
delete s.dotSize) : /^\d+px$/.test(s.thickness) || (s.thickness = "1px"), "line" !== (_ref2 = s.type) && "area" !== _ref2 || ("dashed" !== (_ref3 = s.lineMode) && delete s.lineMode,
s.drawDots !== !1 && null == s.dotSize && (s.dotSize = 2)), null == s.id) {
for (cnt = 0; null != knownIds["series_" + cnt]; ) cnt++;
s.id = "series_" + cnt, knownIds[s.id] = s;
}
return s.drawDots === !1 ? delete s.dotSize : void 0;
}), options);
},
sanitizeAxes: function(axesOptions, secondAxis) {
var _base;
return null == axesOptions && (axesOptions = {}), axesOptions.x = this.sanitizeAxisOptions(axesOptions.x),
(_base = axesOptions.x).key || (_base.key = "x"), axesOptions.y = this.sanitizeAxisOptions(axesOptions.y),
secondAxis && (axesOptions.y2 = this.sanitizeAxisOptions(axesOptions.y2)), axesOptions;
},
sanitizeExtrema: function(axisOptions) {
var extremum, originalValue, _i, _len, _ref, _results;
for (_ref = [ "min", "max" ], _results = [], _i = 0, _len = _ref.length; _len > _i; _i++) extremum = _ref[_i],
originalValue = axisOptions[extremum], null != originalValue ? (axisOptions[extremum] = this.sanitizeExtremum(extremum, axisOptions),
null == axisOptions[extremum] ? _results.push($log.warn("Invalid " + extremum + " value '" + originalValue + "' (parsed as " + axisOptions[extremum] + "), ignoring it.")) : _results.push(void 0)) : _results.push(void 0);
return _results;
},
sanitizeExtremum: function(name, axisOptions) {
var sanitizer;
return sanitizer = this.sanitizeNumber, "date" === axisOptions.type && (sanitizer = this.sanitizeDate),
sanitizer(axisOptions[name]);
},
sanitizeDate: function(value) {
return null != value && value instanceof Date && !isNaN(value.valueOf()) ? value : void 0;
},
sanitizeNumber: function(value) {
var number;
if (null != value && (number = parseFloat(value), !isNaN(number))) return number;
},
sanitizeAxisOptions: function(options) {
return null == options ? {
type: "linear"
} : (options.type || (options.type = "linear"), null != options.ticksRotate && (options.ticksRotate = this.sanitizeNumber(options.ticksRotate)),
null != options.zoomable && (options.zoomable = options.zoomable || !1), null != options.innerTicks && (options.innerTicks = options.innerTicks || !1),
null != options.labelFunction && (options.ticksFormatter = options.labelFunction),
null != options.ticksFormat && ("date" === options.type ? options.ticksFormatter = d3.time.format(options.ticksFormat) : options.ticksFormatter = d3.format(options.ticksFormat),
null == options.tooltipFormatter && (options.tooltipFormatter = options.ticksFormatter)),
null != options.tooltipFormat && ("date" === options.type ? options.tooltipFormatter = d3.time.format(options.tooltipFormat) : options.tooltipFormatter = d3.format(options.tooltipFormat)),
null != options.ticksInterval && (options.ticksInterval = this.sanitizeNumber(options.ticksInterval)),
this.sanitizeExtrema(options), options);
},
createAxes: function(svg, dimensions, axesOptions) {
var createY2Axis, height, style, width, x, xAxis, y, y2, y2Axis, yAxis;
return createY2Axis = null != axesOptions.y2, width = dimensions.width, height = dimensions.height,
width = width - dimensions.left - dimensions.right, height = height - dimensions.top - dimensions.bottom,
x = void 0, x = "date" === axesOptions.x.type ? d3.time.scale().rangeRound([ 0, width ]) : d3.scale.linear().rangeRound([ 0, width ]),
xAxis = this.createAxis(x, "x", axesOptions), y = void 0, y = "log" === axesOptions.y.type ? d3.scale.log().clamp(!0).rangeRound([ height, 0 ]) : d3.scale.linear().rangeRound([ height, 0 ]),
y.clamp(!0), yAxis = this.createAxis(y, "y", axesOptions), y2 = void 0, y2 = createY2Axis && "log" === axesOptions.y2.type ? d3.scale.log().clamp(!0).rangeRound([ height, 0 ]) : d3.scale.linear().rangeRound([ height, 0 ]),
y2.clamp(!0), y2Axis = this.createAxis(y2, "y2", axesOptions), style = function(group) {
return group.style({
font: "10px Courier",
"shape-rendering": "crispEdges"
}), group.selectAll("path").style({
fill: "none",
stroke: "#000"
});
}, {
xScale: x,
yScale: y,
y2Scale: y2,
xAxis: xAxis,
yAxis: yAxis,
y2Axis: y2Axis,
andAddThemIf: function(conditions) {
return conditions.all && (conditions.y && (svg.append("g").attr("class", "y grid"),
svg.append("g").attr("class", "y axis").call(yAxis).call(style)), createY2Axis && conditions.y2 && (svg.append("g").attr("class", "y2 grid").attr("transform", "translate(" + width + ", 0)"),
svg.append("g").attr("class", "y2 axis").attr("transform", "translate(" + width + ", 0)").call(y2Axis).call(style)),
conditions.x && (svg.append("g").attr("class", "x grid").attr("transform", "translate(0," + height + ")"),
svg.append("g").attr("class", "x axis").attr("transform", "translate(0," + height + ")").call(xAxis).call(style))),
{
xScale: x,
yScale: y,
y2Scale: y2,
xAxis: xAxis,
yAxis: yAxis,
y2Axis: y2Axis
};
}
};
},
createAxis: function(scale, key, options) {
var axis, o, sides;
return sides = {
x: "bottom",
y: "left",
y2: "right"
}, o = options[key], axis = d3.svg.axis().scale(scale).orient(sides[key]).innerTickSize(4).tickFormat(null != o ? o.ticksFormatter : void 0),
null == o ? axis : (angular.isArray(o.ticks) ? axis.tickValues(o.ticks) : angular.isNumber(o.ticks) ? axis.ticks(o.ticks) : angular.isFunction(o.ticks) && axis.ticks(o.ticks, o.ticksInterval),
axis);
},
setDefaultStroke: function(selection) {
return selection.attr("stroke", "#000").attr("stroke-width", 1).style("shape-rendering", "crispEdges");
},
setDefaultGrid: function(selection) {
return selection.attr("stroke", "#eee").attr("stroke-width", 1).style("shape-rendering", "crispEdges");
},
setScalesDomain: function(scales, data, series, svg, options) {
var axis, grid, height, width, xGrid, y2Domain, y2Grid, yDomain, yGrid;
return this.setXScale(scales.xScale, data, series, options.axes), axis = svg.selectAll(".x.axis").call(scales.xAxis),
null != options.axes.x.innerTicks && axis.selectAll(".tick>line").call(this.setDefaultStroke),
null != options.axes.x.grid && (height = options.margin.height - options.margin.top - options.margin.bottom,
xGrid = scales.xAxis.tickSize(-height, 0, 0), grid = svg.selectAll(".x.grid").call(xGrid),
grid.selectAll(".tick>line").call(this.setDefaultGrid)), null != options.axes.x.ticksRotate && axis.selectAll(".tick>text").attr("dy", null).attr("transform", "translate(0,5) rotate(" + options.axes.x.ticksRotate + " 0,6)").style("text-anchor", options.axes.x.ticksRotate >= 0 ? "start" : "end"),
series.filter(function(s) {
return "y" === s.axis && s.visible !== !1;
}).length > 0 && (yDomain = this.getVerticalDomain(options, data, series, "y"),
scales.yScale.domain(yDomain).nice(), axis = svg.selectAll(".y.axis").call(scales.yAxis),
null != options.axes.y.innerTicks && axis.selectAll(".tick>line").call(this.setDefaultStroke),
null != options.axes.y.ticksRotate && axis.selectAll(".tick>text").attr("transform", "rotate(" + options.axes.y.ticksRotate + " -6,0)").style("text-anchor", "end"),
null != options.axes.y.grid && (width = options.margin.width - options.margin.left - options.margin.right,
yGrid = scales.yAxis.tickSize(-width, 0, 0), grid = svg.selectAll(".y.grid").call(yGrid),
grid.selectAll(".tick>line").call(this.setDefaultGrid))), series.filter(function(s) {
return "y2" === s.axis && s.visible !== !1;
}).length > 0 && (y2Domain = this.getVerticalDomain(options, data, series, "y2"),
scales.y2Scale.domain(y2Domain).nice(), axis = svg.selectAll(".y2.axis").call(scales.y2Axis),
null != options.axes.y2.innerTicks && axis.selectAll(".tick>line").call(this.setDefaultStroke),
null != options.axes.y2.ticksRotate && axis.selectAll(".tick>text").attr("transform", "rotate(" + options.axes.y2.ticksRotate + " 6,0)").style("text-anchor", "start"),
null != options.axes.y2.grid) ? (width = options.margin.width - options.margin.left - options.margin.right,
y2Grid = scales.y2Axis.tickSize(-width, 0, 0), grid = svg.selectAll(".y2.grid").call(y2Grid),
grid.selectAll(".tick>line").call(this.setDefaultGrid)) : void 0;
},
getVerticalDomain: function(options, data, series, key) {
var domain, mySeries, o;
return (o = options.axes[key]) ? null != o.ticks && angular.isArray(o.ticks) ? [ o.ticks[0], o.ticks[o.ticks.length - 1] ] : (mySeries = series.filter(function(s) {
return s.axis === key && s.visible !== !1;
}), domain = this.yExtent(series.filter(function(s) {
return s.axis === key && s.visible !== !1;
}), data, options.stacks.filter(function(stack) {
return stack.axis === key;
})), "log" === o.type && (domain[0] = 0 === domain[0] ? .001 : domain[0]), null != o.min && (domain[0] = o.min),
null != o.max && (domain[1] = o.max), domain) : [];
},
yExtent: function(series, data, stacks) {
var groups, maxY, minY;
return minY = Number.POSITIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY, groups = [],
stacks.forEach(function(stack) {
return groups.push(stack.series.map(function(id) {
return series.filter(function(s) {
return s.id === id;
})[0];
}));
}), series.forEach(function(series, i) {
var isInStack;
return isInStack = !1, stacks.forEach(function(stack) {
var _ref;
return _ref = series.id, __indexOf.call(stack.series, _ref) >= 0 ? isInStack = !0 : void 0;
}), isInStack ? void 0 : groups.push([ series ]);
}), groups.forEach(function(group) {
return group = group.filter(Boolean), minY = Math.min(minY, d3.min(data, function(d) {
return group.reduce(function(a, s) {
return Math.min(a, d[s.y]);
}, Number.POSITIVE_INFINITY);
})), maxY = Math.max(maxY, d3.max(data, function(d) {
return group.reduce(function(a, s) {
return a + d[s.y];
}, 0);
}));
}), minY === maxY ? minY > 0 ? [ 0, 2 * minY ] : [ 2 * minY, 0 ] : [ minY, maxY ];
},
setXScale: function(xScale, data, series, axesOptions) {
var domain, o;
return domain = this.xExtent(data, axesOptions.x.key, axesOptions.x.type), series.filter(function(s) {
return "column" === s.type;
}).length && this.adjustXDomainForColumns(domain, data, axesOptions.x.key), o = axesOptions.x,
null != o.min && (domain[0] = o.min), null != o.max && (domain[1] = o.max), xScale.domain(domain);
},
xExtent: function(data, key, type) {
var delta, from, to, _ref;
return _ref = d3.extent(data, function(d) {
return d[key];
}), from = _ref[0], to = _ref[1], from === to ? "date" === type ? (delta = 864e5,
[ new Date(+from - delta), new Date(+to + delta) ]) : from > 0 ? [ 0, 2 * from ] : [ 2 * from, 0 ] : [ from, to ];
},
adjustXDomainForColumns: function(domain, data, field) {
var step;
return step = this.getAverageStep(data, field), angular.isDate(domain[0]) ? (domain[0] = new Date(+domain[0] - step),
domain[1] = new Date(+domain[1] + step)) : (domain[0] = domain[0] - step, domain[1] = domain[1] + step);
},
getAverageStep: function(data, field) {
var i, n, sum;
if (!(data.length > 1)) return 0;
for (sum = 0, n = data.length - 1, i = 0; n > i; ) sum += data[i + 1][field] - data[i][field],
i++;
return sum / n;
},
haveSecondYAxis: function(series) {
return !series.every(function(s) {
return "y2" !== s.axis;
});
},
showScrubber: function(svg, glass, axes, data, options, dispatch, columnWidth) {
var that;
return that = this, glass.on("mousemove", function() {
return svg.selectAll(".glass-container").attr("opacity", 1), that.updateScrubber(svg, d3.mouse(this), axes, data, options, dispatch, columnWidth);
}), glass.on("mouseout", function() {
return glass.on("mousemove", null), svg.selectAll(".glass-container").attr("opacity", 0);
});
},
getClosestPoint: function(values, xValue) {
var d, d0, d1, i, xBisector;
return xBisector = d3.bisector(function(d) {
return d.x;
}).left, i = xBisector(values, xValue), 0 === i ? values[0] : i > values.length - 1 ? values[values.length - 1] : (d0 = values[i - 1],
d1 = values[i], d = xValue - d0.x > d1.x - xValue ? d1 : d0);
},
updateScrubber: function(svg, _arg, axes, data, options, dispatch, columnWidth) {
var ease, positions, that, tickLength, x, y;
return x = _arg[0], y = _arg[1], ease = function(element) {
return element.transition().duration(50);
}, that = this, positions = [], data.forEach(function(series, index) {
var color, item, lText, left, rText, right, side, sizes, text, v, xInvert, xPos, yInvert;
return item = svg.select(".scrubberItem.series_" + index), options.series[index].visible === !1 ? void item.attr("opacity", 0) : (item.attr("opacity", 1),
xInvert = axes.xScale.invert(x), yInvert = axes.yScale.invert(y), v = that.getClosestPoint(series.values, xInvert),
dispatch.focus(v, series.values.indexOf(v), [ xInvert, yInvert ]), text = v.x + " : " + v.y,
options.tooltip.formatter && (text = options.tooltip.formatter(v.x, v.y, options.series[index])),
right = item.select(".rightTT"), rText = right.select("text"), rText.text(text),
left = item.select(".leftTT"), lText = left.select("text"), lText.text(text), sizes = {
right: that.getTextBBox(rText[0][0]).width + 5,
left: that.getTextBBox(lText[0][0]).width + 5
}, side = "y2" === series.axis ? "right" : "left", xPos = axes.xScale(v.x), "left" === side ? xPos + that.getTextBBox(lText[0][0]).x - 10 < 0 && (side = "right") : "right" === side && xPos + sizes.right > that.getTextBBox(svg.select(".glass")[0][0]).width && (side = "left"),
"left" === side ? (ease(right).attr("opacity", 0), ease(left).attr("opacity", 1)) : (ease(right).attr("opacity", 1),
ease(left).attr("opacity", 0)), positions[index] = {
index: index,
x: xPos,
y: axes[v.axis + "Scale"](v.y + v.y0),
side: side,
sizes: sizes
}, color = angular.isFunction(series.color) ? series.color(v, series.values.indexOf(v)) : series.color,
item.selectAll("circle").attr("stroke", color), item.selectAll("path").attr("fill", color));
}), positions = this.preventOverlapping(positions), tickLength = Math.max(15, 100 / columnWidth),
data.forEach(function(series, index) {
var item, p, tt, xOffset;
if (options.series[index].visible !== !1) return p = positions[index], item = svg.select(".scrubberItem.series_" + index),
tt = item.select("." + p.side + "TT"), xOffset = "left" === p.side ? series.xOffset : -series.xOffset,
tt.select("text").attr("transform", function() {
return "left" === p.side ? "translate(" + (-3 - tickLength - xOffset) + ", " + (p.labelOffset + 3) + ")" : "translate(" + (4 + tickLength + xOffset) + ", " + (p.labelOffset + 3) + ")";
}), tt.select("path").attr("d", that.getScrubberPath(p.sizes[p.side] + 1, p.labelOffset, p.side, tickLength + xOffset)),
ease(item).attr({
transform: "translate(" + (positions[index].x + series.xOffset) + ", " + positions[index].y + ")"
});
});
},
getScrubberPath: function(w, yOffset, side, padding) {
var h, p, xdir, ydir;
return h = 18, p = padding, w = w, xdir = "left" === side ? 1 : -1, ydir = 1, 0 !== yOffset && (ydir = Math.abs(yOffset) / yOffset),
yOffset || (yOffset = 0), [ "m0 0", "l" + xdir + " 0", "l0 " + (yOffset + ydir), "l" + -xdir * (p + 1) + " 0", "l0 " + (-h / 2 - ydir), "l" + -xdir * w + " 0", "l0 " + h, "l" + xdir * w + " 0", "l0 " + (-h / 2 - ydir), "l" + xdir * (p - 1) + " 0", "l0 " + (-yOffset + ydir), "l1 0", "z" ].join("");
},
preventOverlapping: function(positions) {
var abscissas, getNeighbours, h, offset;
return h = 18, abscissas = {}, positions.forEach(function(p) {
var _name;
return abscissas[_name = p.x] || (abscissas[_name] = {
left: [],
right: []
}), abscissas[p.x][p.side].push(p);
}), getNeighbours = function(side) {
var foundNeighbour, neighbourhood, neighbours, neighboursForX, p, sides, x, y, _ref;
neighbours = [];
for (x in abscissas) if (sides = abscissas[x], 0 !== sides[side].length) {
for (neighboursForX = {}; sides[side].length > 0; ) {
p = sides[side].pop(), foundNeighbour = !1;
for (y in neighboursForX) neighbourhood = neighboursForX[y], +y - h <= (_ref = p.y) && +y + h >= _ref && (neighbourhood.push(p),
foundNeighbour = !0);
foundNeighbour || (neighboursForX[p.y] = [ p ]);
}
neighbours.push(neighboursForX);
}
return neighbours;
}, offset = function(neighboursForAbscissas) {
var abs, n, neighbours, start, step, xNeighbours, y;
step = 20;
for (abs in neighboursForAbscissas) {
xNeighbours = neighboursForAbscissas[abs];
for (y in xNeighbours) neighbours = xNeighbours[y], n = neighbours.length, 1 !== n ? (neighbours = neighbours.sort(function(a, b) {
return a.y - b.y;
}), start = n % 2 === 0 ? -(step / 2) * (n / 2) : -(n - 1) / 2 * step, neighbours.forEach(function(neighbour, i) {
return neighbour.labelOffset = start + step * i;
})) : neighbours[0].labelOffset = 0;
}
}, offset(getNeighbours("left")), offset(getNeighbours("right")), positions;
},
getTooltipHandlers: function(options) {
return "scrubber" === options.tooltip.mode ? {
onChartHover: angular.bind(this, this.showScrubber)
} : {
onMouseOver: angular.bind(this, this.onMouseOver),
onMouseOut: angular.bind(this, this.onMouseOut)
};
},
styleTooltip: function(d3TextElement) {
return d3TextElement.attr({
"font-family": "monospace",
"font-size": 10,
fill: "white",
"text-rendering": "geometric-precision"
});
},
addTooltips: function(svg, dimensions, axesOptions) {
var h, height, p, w, width, xTooltip, y2Tooltip, yTooltip;
return width = dimensions.width, height = dimensions.height, width = width - dimensions.left - dimensions.right,
height = height - dimensions.top - dimensions.bottom, w = 24, h = 18, p = 5, xTooltip = svg.append("g").attr({
id: "xTooltip",
"class": "xTooltip",
opacity: 0
}), xTooltip.append("path").attr("transform", "translate(0," + (height + 1) + ")"),
this.styleTooltip(xTooltip.append("text").style("text-anchor", "middle").attr({
width: w,
height: h,
transform: "translate(0," + (height + 19) + ")"
})), yTooltip = svg.append("g").attr({
id: "yTooltip",
"class": "yTooltip",
opacity: 0
}), yTooltip.append("path"), this.styleTooltip(yTooltip.append("text").attr({
width: h,
height: w
})), null != axesOptions.y2 ? (y2Tooltip = svg.append("g").attr({
id: "y2Tooltip",
"class": "y2Tooltip",
opacity: 0,
transform: "translate(" + width + ",0)"
}), y2Tooltip.append("path"), this.styleTooltip(y2Tooltip.append("text").attr({
width: h,
height: w
}))) : void 0;
},
onMouseOver: function(svg, event, axesOptions) {
return this.updateXTooltip(svg, event, axesOptions.x), "y2" === event.series.axis ? this.updateY2Tooltip(svg, event, axesOptions.y2) : this.updateYTooltip(svg, event, axesOptions.y);
},
onMouseOut: function(svg) {
return this.hideTooltips(svg);
},
updateXTooltip: function(svg, _arg, xAxisOptions) {
var color, datum, label, series, textX, x, xTooltip, _f;
return x = _arg.x, datum = _arg.datum, series = _arg.series, xTooltip = svg.select("#xTooltip"),
xTooltip.transition().attr({
opacity: 1,
transform: "translate(" + x + ",0)"
}), _f = xAxisOptions.tooltipFormatter, textX = _f ? _f(datum.x) : datum.x, label = xTooltip.select("text"),
label.text(textX), color = angular.isFunction(series.color) ? series.color(datum, series.values.indexOf(datum)) : series.color,
xTooltip.select("path").style("fill", color).attr("d", this.getXTooltipPath(label[0][0]));
},
getXTooltipPath: function(textElement) {
var h, p, w;
return w = Math.max(this.getTextBBox(textElement).width, 15), h = 18, p = 5, "m-" + w / 2 + " " + p + " l0 " + h + " l" + w + " 0 l0 " + -h + "l" + (-w / 2 + p) + " 0 l" + -p + " -" + h / 4 + " l" + -p + " " + h / 4 + " l" + (-w / 2 + p) + " 0z";
},
updateYTooltip: function(svg, _arg, yAxisOptions) {
var color, datum, label, series, textY, w, y, yTooltip, _f;
return y = _arg.y, datum = _arg.datum, series = _arg.series, yTooltip = svg.select("#yTooltip"),
yTooltip.transition().attr({
opacity: 1,
transform: "translate(0, " + y + ")"
}), _f = yAxisOptions.tooltipFormatter, textY = _f ? _f(datum.y) : datum.y, label = yTooltip.select("text"),
label.text(textY), w = this.getTextBBox(label[0][0]).width + 5, label.attr({
transform: "translate(" + (-w - 2) + ",3)",
width: w
}), color = angular.isFunction(series.color) ? series.color(datum, series.values.indexOf(datum)) : series.color,
yTooltip.select("path").style("fill", color).attr("d", this.getYTooltipPath(w));
},
updateY2Tooltip: function(svg, _arg, yAxisOptions) {
var color, datum, label, series, textY, w, y, y2Tooltip, _f;
return y = _arg.y, datum = _arg.datum, series = _arg.series, y2Tooltip = svg.select("#y2Tooltip"),
y2Tooltip.transition().attr("opacity", 1), _f = yAxisOptions.tooltipFormatter, textY = _f ? _f(datum.y) : datum.y,
label = y2Tooltip.select("text"), label.text(textY), w = this.getTextBBox(label[0][0]).width + 5,
label.attr({
transform: "translate(7, " + (parseFloat(y) + 3) + ")",
w: w
}), color = angular.isFunction(series.color) ? series.color(datum, series.values.indexOf(datum)) : series.color,
y2Tooltip.select("path").style("fill", color).attr({
d: this.getY2TooltipPath(w),
transform: "translate(0, " + y + ")"
});
},
getYTooltipPath: function(w) {
var h, p;
return h = 18, p = 5, "m0 0l" + -p + " " + -p + " l0 " + (-h / 2 + p) + " l" + -w + " 0 l0 " + h + " l" + w + " 0 l0 " + (-h / 2 + p) + "l" + -p + " " + p + "z";
},
getY2TooltipPath: function(w) {
var h, p;
return h = 18, p = 5, "m0 0l" + p + " " + p + " l0 " + (h / 2 - p) + " l" + w + " 0 l0 " + -h + " l" + -w + " 0 l0 " + (h / 2 - p) + " l" + -p + " " + p + "z";
},
hideTooltips: function(svg) {
return svg.select("#xTooltip").transition().attr("opacity", 0), svg.select("#yTooltip").transition().attr("opacity", 0),
svg.select("#y2Tooltip").transition().attr("opacity", 0);
}
};
} ]);