mirror of
https://github.com/morrisjs/morris.js.git
synced 2024-11-10 21:36:34 +01:00
Merge prettifylabels() into commas().
Stop parsing times for labels when @options.parseTime is false. Tweak examples to show partial data series support.
This commit is contained in:
parent
ad8d0b6a8c
commit
bde431ac34
@ -28,19 +28,19 @@ var quarter_data = [
|
|||||||
{"period": "2008 Q4", "licensed": 3155, "sorned": 681},
|
{"period": "2008 Q4", "licensed": 3155, "sorned": 681},
|
||||||
{"period": "2008 Q3", "licensed": 3190, "sorned": 667},
|
{"period": "2008 Q3", "licensed": 3190, "sorned": 667},
|
||||||
{"period": "2007 Q4", "licensed": 3226, "sorned": 620},
|
{"period": "2007 Q4", "licensed": 3226, "sorned": 620},
|
||||||
{"period": "2006 Q4", "licensed": 3245, "sorned": 0},
|
{"period": "2006 Q4", "licensed": 3245, "sorned": null},
|
||||||
{"period": "2005 Q4", "licensed": 3289, "sorned": 0},
|
{"period": "2005 Q4", "licensed": 3289, "sorned": null},
|
||||||
{"period": "2004 Q4", "licensed": 3263, "sorned": 0},
|
{"period": "2004 Q4", "licensed": 3263, "sorned": null},
|
||||||
{"period": "2003 Q4", "licensed": 3189, "sorned": 0},
|
{"period": "2003 Q4", "licensed": 3189, "sorned": null},
|
||||||
{"period": "2002 Q4", "licensed": 3079, "sorned": 0},
|
{"period": "2002 Q4", "licensed": 3079, "sorned": null},
|
||||||
{"period": "2001 Q4", "licensed": 3085, "sorned": 0},
|
{"period": "2001 Q4", "licensed": 3085, "sorned": null},
|
||||||
{"period": "2000 Q4", "licensed": 3055, "sorned": 0},
|
{"period": "2000 Q4", "licensed": 3055, "sorned": null},
|
||||||
{"period": "1999 Q4", "licensed": 3063, "sorned": 0},
|
{"period": "1999 Q4", "licensed": 3063, "sorned": null},
|
||||||
{"period": "1998 Q4", "licensed": 2943, "sorned": 0},
|
{"period": "1998 Q4", "licensed": 2943, "sorned": null},
|
||||||
{"period": "1997 Q4", "licensed": 2806, "sorned": 0},
|
{"period": "1997 Q4", "licensed": 2806, "sorned": null},
|
||||||
{"period": "1996 Q4", "licensed": 2674, "sorned": 0},
|
{"period": "1996 Q4", "licensed": 2674, "sorned": null},
|
||||||
{"period": "1995 Q4", "licensed": 1702, "sorned": 0},
|
{"period": "1995 Q4", "licensed": 1702, "sorned": null},
|
||||||
{"period": "1994 Q4", "licensed": 1732, "sorned": 0}
|
{"period": "1994 Q4", "licensed": 1732, "sorned": null}
|
||||||
];
|
];
|
||||||
Morris.Line({
|
Morris.Line({
|
||||||
element: 'graph',
|
element: 'graph',
|
||||||
|
@ -27,19 +27,19 @@ var week_data = [
|
|||||||
{"period": "2011 W16", "licensed": 3155, "sorned": 681},
|
{"period": "2011 W16", "licensed": 3155, "sorned": 681},
|
||||||
{"period": "2011 W15", "licensed": 3190, "sorned": 667},
|
{"period": "2011 W15", "licensed": 3190, "sorned": 667},
|
||||||
{"period": "2011 W14", "licensed": 3226, "sorned": 620},
|
{"period": "2011 W14", "licensed": 3226, "sorned": 620},
|
||||||
{"period": "2011 W13", "licensed": 3245, "sorned": 0},
|
{"period": "2011 W13", "licensed": 3245, "sorned": null},
|
||||||
{"period": "2011 W12", "licensed": 3289, "sorned": 0},
|
{"period": "2011 W12", "licensed": 3289, "sorned": null},
|
||||||
{"period": "2011 W11", "licensed": 3263, "sorned": 0},
|
{"period": "2011 W11", "licensed": 3263, "sorned": null},
|
||||||
{"period": "2011 W10", "licensed": 3189, "sorned": 0},
|
{"period": "2011 W10", "licensed": 3189, "sorned": null},
|
||||||
{"period": "2011 W09", "licensed": 3079, "sorned": 0},
|
{"period": "2011 W09", "licensed": 3079, "sorned": null},
|
||||||
{"period": "2011 W08", "licensed": 3085, "sorned": 0},
|
{"period": "2011 W08", "licensed": 3085, "sorned": null},
|
||||||
{"period": "2011 W07", "licensed": 3055, "sorned": 0},
|
{"period": "2011 W07", "licensed": 3055, "sorned": null},
|
||||||
{"period": "2011 W06", "licensed": 3063, "sorned": 0},
|
{"period": "2011 W06", "licensed": 3063, "sorned": null},
|
||||||
{"period": "2011 W05", "licensed": 2943, "sorned": 0},
|
{"period": "2011 W05", "licensed": 2943, "sorned": null},
|
||||||
{"period": "2011 W04", "licensed": 2806, "sorned": 0},
|
{"period": "2011 W04", "licensed": 2806, "sorned": null},
|
||||||
{"period": "2011 W03", "licensed": 2674, "sorned": 0},
|
{"period": "2011 W03", "licensed": 2674, "sorned": null},
|
||||||
{"period": "2011 W02", "licensed": 1702, "sorned": 0},
|
{"period": "2011 W02", "licensed": 1702, "sorned": null},
|
||||||
{"period": "2011 W01", "licensed": 1732, "sorned": 0}
|
{"period": "2011 W01", "licensed": 1732, "sorned": null}
|
||||||
];
|
];
|
||||||
Morris.Line({
|
Morris.Line({
|
||||||
element: 'graph',
|
element: 'graph',
|
||||||
|
@ -86,6 +86,7 @@ class Morris.Line
|
|||||||
else
|
else
|
||||||
@xvals = [(@columnLabels.length-1)..0]
|
@xvals = [(@columnLabels.length-1)..0]
|
||||||
# translate column labels, if they're timestamps
|
# translate column labels, if they're timestamps
|
||||||
|
if @options.parseTime
|
||||||
@columnLabels = $.map @columnLabels, (d) =>
|
@columnLabels = $.map @columnLabels, (d) =>
|
||||||
if typeof d is 'number'
|
if typeof d is 'number'
|
||||||
@options.dateFormat(d)
|
@options.dateFormat(d)
|
||||||
@ -197,7 +198,7 @@ class Morris.Line
|
|||||||
for lineY in [firstY..lastY] by yInterval
|
for lineY in [firstY..lastY] by yInterval
|
||||||
v = Math.floor(lineY)
|
v = Math.floor(lineY)
|
||||||
y = @transY(v)
|
y = @transY(v)
|
||||||
@r.text(@left - @options.marginLeft/2, y, v + @options.units)
|
@r.text(@left - @options.marginLeft/2, y, @commas(v) + @options.units)
|
||||||
.attr('font-size', @options.gridTextSize)
|
.attr('font-size', @options.gridTextSize)
|
||||||
.attr('fill', @options.gridTextColor)
|
.attr('fill', @options.gridTextColor)
|
||||||
.attr('text-anchor', 'end')
|
.attr('text-anchor', 'end')
|
||||||
@ -319,7 +320,7 @@ class Morris.Line
|
|||||||
@hoverSet.show()
|
@hoverSet.show()
|
||||||
@xLabel.attr('text', @columnLabels[index])
|
@xLabel.attr('text', @columnLabels[index])
|
||||||
for i in [0..@series.length-1]
|
for i in [0..@series.length-1]
|
||||||
@yLabels[i].attr('text', "#{@seriesLabels[i]}: #{@prettifylabel(@series[i][index])}#{@options.units}")
|
@yLabels[i].attr('text', "#{@seriesLabels[i]}: #{@commas(@series[i][index])}#{@options.units}")
|
||||||
# recalculate hover box width
|
# recalculate hover box width
|
||||||
maxLabelWidth = Math.max.apply null, $.map @yLabels, (l) ->
|
maxLabelWidth = Math.max.apply null, $.map @yLabels, (l) ->
|
||||||
l.getBBox().width
|
l.getBBox().width
|
||||||
@ -423,15 +424,13 @@ class Morris.Line
|
|||||||
else
|
else
|
||||||
new Date(parseInt(date, 10), 0, 1)
|
new Date(parseInt(date, 10), 0, 1)
|
||||||
|
|
||||||
prettifylabel: (num) ->
|
|
||||||
if num == null
|
|
||||||
return "n/a"
|
|
||||||
return @commas(num)
|
|
||||||
|
|
||||||
# make long numbers prettier by inserting commas
|
# make long numbers prettier by inserting commas
|
||||||
# eg: commas(1234567) -> '1,234,567'
|
# eg: commas(1234567) -> '1,234,567'
|
||||||
#
|
#
|
||||||
commas: (num) ->
|
commas: (num) ->
|
||||||
|
if num is null
|
||||||
|
"n/a"
|
||||||
|
else
|
||||||
ret = if num < 0 then "-" else ""
|
ret = if num < 0 then "-" else ""
|
||||||
absnum = Math.abs(num)
|
absnum = Math.abs(num)
|
||||||
intnum = Math.floor(absnum).toFixed(0)
|
intnum = Math.floor(absnum).toFixed(0)
|
||||||
|
405
morris.js
405
morris.js
@ -1,5 +1,6 @@
|
|||||||
(function() {
|
(function() {
|
||||||
var $, Morris;
|
var $, Morris,
|
||||||
|
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||||
|
|
||||||
$ = jQuery;
|
$ = jQuery;
|
||||||
|
|
||||||
@ -8,7 +9,11 @@
|
|||||||
Morris.Line = (function() {
|
Morris.Line = (function() {
|
||||||
|
|
||||||
function Line(options) {
|
function Line(options) {
|
||||||
if (!(this instanceof Morris.Line)) return new Morris.Line(options);
|
this.updateHilight = __bind(this.updateHilight, this);
|
||||||
|
this.hilight = __bind(this.hilight, this);
|
||||||
|
this.updateHover = __bind(this.updateHover, this);
|
||||||
|
this.transY = __bind(this.transY, this);
|
||||||
|
this.transX = __bind(this.transX, this); if (!(this instanceof Morris.Line)) return new Morris.Line(options);
|
||||||
if (typeof options.element === 'string') {
|
if (typeof options.element === 'string') {
|
||||||
this.el = $(document.getElementById(options.element));
|
this.el = $(document.getElementById(options.element));
|
||||||
} else {
|
} else {
|
||||||
@ -55,7 +60,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
Line.prototype.precalc = function() {
|
Line.prototype.precalc = function() {
|
||||||
var ykey, ymax, ymin, _i, _j, _len, _ref, _ref2, _results,
|
var d, series_data, touchHandler, ykey, ymax, ymin, _i, _j, _k, _len, _len2, _ref, _ref2, _ref3, _results,
|
||||||
_this = this;
|
_this = this;
|
||||||
this.options.data.sort(function(a, b) {
|
this.options.data.sort(function(a, b) {
|
||||||
return (a[_this.options.xkey] < b[_this.options.xkey]) - (b[_this.options.xkey] < a[_this.options.xkey]);
|
return (a[_this.options.xkey] < b[_this.options.xkey]) - (b[_this.options.xkey] < a[_this.options.xkey]);
|
||||||
@ -68,9 +73,13 @@
|
|||||||
_ref = this.options.ykeys;
|
_ref = this.options.ykeys;
|
||||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
ykey = _ref[_i];
|
ykey = _ref[_i];
|
||||||
this.series.push($.map(this.options.data, function(d) {
|
series_data = [];
|
||||||
return d[ykey];
|
_ref2 = this.options.data;
|
||||||
}));
|
for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
|
||||||
|
d = _ref2[_j];
|
||||||
|
series_data.push(d[ykey]);
|
||||||
|
}
|
||||||
|
this.series.push(series_data);
|
||||||
}
|
}
|
||||||
if (this.options.parseTime) {
|
if (this.options.parseTime) {
|
||||||
this.xvals = $.map(this.columnLabels, function(x) {
|
this.xvals = $.map(this.columnLabels, function(x) {
|
||||||
@ -79,10 +88,11 @@
|
|||||||
} else {
|
} else {
|
||||||
this.xvals = (function() {
|
this.xvals = (function() {
|
||||||
_results = [];
|
_results = [];
|
||||||
for (var _j = _ref2 = this.columnLabels.length - 1; _ref2 <= 0 ? _j <= 0 : _j >= 0; _ref2 <= 0 ? _j++ : _j--){ _results.push(_j); }
|
for (var _k = _ref3 = this.columnLabels.length - 1; _ref3 <= 0 ? _k <= 0 : _k >= 0; _ref3 <= 0 ? _k++ : _k--){ _results.push(_k); }
|
||||||
return _results;
|
return _results;
|
||||||
}).apply(this);
|
}).apply(this);
|
||||||
}
|
}
|
||||||
|
if (this.options.parseTime) {
|
||||||
this.columnLabels = $.map(this.columnLabels, function(d) {
|
this.columnLabels = $.map(this.columnLabels, function(d) {
|
||||||
if (typeof d === 'number') {
|
if (typeof d === 'number') {
|
||||||
return _this.options.dateFormat(d);
|
return _this.options.dateFormat(d);
|
||||||
@ -90,6 +100,7 @@
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
this.xmin = Math.min.apply(null, this.xvals);
|
this.xmin = Math.min.apply(null, this.xvals);
|
||||||
this.xmax = Math.max.apply(null, this.xvals);
|
this.xmax = Math.max.apply(null, this.xvals);
|
||||||
if (this.xmin === this.xmax) {
|
if (this.xmin === this.xmax) {
|
||||||
@ -107,42 +118,116 @@
|
|||||||
if (typeof this.options.ymin === 'string' && this.options.ymin.slice(0, 4) === 'auto') {
|
if (typeof this.options.ymin === 'string' && this.options.ymin.slice(0, 4) === 'auto') {
|
||||||
ymin = Math.min.apply(null, Array.prototype.concat.apply([], this.series));
|
ymin = Math.min.apply(null, Array.prototype.concat.apply([], this.series));
|
||||||
if (this.options.ymin.length > 5) {
|
if (this.options.ymin.length > 5) {
|
||||||
return this.options.ymin = Math.min(parseInt(this.options.ymin.slice(5), 10), ymin);
|
this.options.ymin = Math.min(parseInt(this.options.ymin.slice(5), 10), ymin);
|
||||||
} else {
|
} else {
|
||||||
return this.options.ymin = ymin;
|
this.options.ymin = ymin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.pointGrow = Raphael.animation({
|
||||||
|
r: this.options.pointSize + 3
|
||||||
|
}, 25, 'linear');
|
||||||
|
this.pointShrink = Raphael.animation({
|
||||||
|
r: this.options.pointSize
|
||||||
|
}, 25, 'linear');
|
||||||
|
this.elementWidth = null;
|
||||||
|
this.elementHeight = null;
|
||||||
|
this.prevHilight = null;
|
||||||
|
this.el.mousemove(function(evt) {
|
||||||
|
return _this.updateHilight(evt.pageX);
|
||||||
|
});
|
||||||
|
if (this.options.hideHover) {
|
||||||
|
this.el.mouseout(function(evt) {
|
||||||
|
return _this.hilight(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
touchHandler = function(evt) {
|
||||||
|
var touch;
|
||||||
|
touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];
|
||||||
|
_this.updateHilight(touch.pageX);
|
||||||
|
return touch;
|
||||||
|
};
|
||||||
|
this.el.bind('touchstart', touchHandler);
|
||||||
|
this.el.bind('touchmove', touchHandler);
|
||||||
|
return this.el.bind('touchend', touchHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
Line.prototype.calc = function() {
|
||||||
|
var h, s, scoords, w, x, _i, _len, _ref,
|
||||||
|
_this = this;
|
||||||
|
w = this.el.width();
|
||||||
|
h = this.el.height();
|
||||||
|
if (this.elementWidth !== w || this.elementHeight !== h) {
|
||||||
|
this.maxYLabelWidth = Math.max(this.measureText(this.options.ymin + this.options.units, this.options.gridTextSize).width, this.measureText(this.options.ymax + this.options.units, this.options.gridTextSize).width);
|
||||||
|
this.left = this.maxYLabelWidth + this.options.marginLeft;
|
||||||
|
this.width = this.el.width() - this.left - this.options.marginRight;
|
||||||
|
this.height = this.el.height() - this.options.marginTop - this.options.marginBottom;
|
||||||
|
this.dx = this.width / (this.xmax - this.xmin);
|
||||||
|
this.dy = this.height / (this.options.ymax - this.options.ymin);
|
||||||
|
this.columns = (function() {
|
||||||
|
var _i, _len, _ref, _results;
|
||||||
|
_ref = this.xvals;
|
||||||
|
_results = [];
|
||||||
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
x = _ref[_i];
|
||||||
|
_results.push(this.transX(x));
|
||||||
|
}
|
||||||
|
return _results;
|
||||||
|
}).call(this);
|
||||||
|
this.seriesCoords = [];
|
||||||
|
_ref = this.series;
|
||||||
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||||
|
s = _ref[_i];
|
||||||
|
scoords = [];
|
||||||
|
$.each(s, function(i, y) {
|
||||||
|
if (y === null) {
|
||||||
|
return scoords.push(null);
|
||||||
|
} else {
|
||||||
|
return scoords.push({
|
||||||
|
x: _this.columns[i],
|
||||||
|
y: _this.transY(y)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.seriesCoords.push(scoords);
|
||||||
|
}
|
||||||
|
return this.hoverMargins = $.map(this.columns.slice(1), function(x, i) {
|
||||||
|
return (x + _this.columns[i]) / 2;
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Line.prototype.redraw = function() {
|
Line.prototype.transX = function(x) {
|
||||||
var c, circle, columns, coords, dx, dy, firstY, height, hideHover, hilight, hover, hoverHeight, hoverMargins, hoverSet, i, label, labelBox, labelText, lastY, left, lineY, maxYLabelWidth, path, pointGrow, pointShrink, prevHilight, prevLabelMargin, s, seriesCoords, seriesPoints, touchHandler, transX, transY, updateHilight, updateHover, v, width, x, x1, x2, xLabel, xLabelMargin, xpos, y, yInterval, yLabel, yLabels, _i, _j, _len, _len2, _ref, _ref2, _ref3, _ref4, _ref5,
|
if (this.xvals.length === 1) {
|
||||||
_this = this;
|
return this.left + this.width / 2;
|
||||||
this.el.empty();
|
|
||||||
this.r = new Raphael(this.el[0]);
|
|
||||||
maxYLabelWidth = Math.max(this.measureText(this.options.ymin + this.options.units, this.options.gridTextSize).width, this.measureText(this.options.ymax + this.options.units, this.options.gridTextSize).width);
|
|
||||||
left = maxYLabelWidth + this.options.marginLeft;
|
|
||||||
width = this.el.width() - left - this.options.marginRight;
|
|
||||||
height = this.el.height() - this.options.marginTop - this.options.marginBottom;
|
|
||||||
dx = width / (this.xmax - this.xmin);
|
|
||||||
dy = height / (this.options.ymax - this.options.ymin);
|
|
||||||
transX = function(x) {
|
|
||||||
if (_this.xvals.length === 1) {
|
|
||||||
return left + width / 2;
|
|
||||||
} else {
|
} else {
|
||||||
return left + (x - _this.xmin) * dx;
|
return this.left + (x - this.xmin) * this.dx;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
transY = function(y) {
|
|
||||||
return _this.options.marginTop + height - (y - _this.options.ymin) * dy;
|
Line.prototype.transY = function(y) {
|
||||||
|
return this.options.marginTop + this.height - (y - this.options.ymin) * this.dy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Line.prototype.redraw = function() {
|
||||||
|
this.el.empty();
|
||||||
|
this.r = new Raphael(this.el[0]);
|
||||||
|
this.calc();
|
||||||
|
this.drawGrid();
|
||||||
|
this.drawSeries();
|
||||||
|
this.drawHover();
|
||||||
|
return this.hilight(this.options.hideHover ? null : 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
Line.prototype.drawGrid = function() {
|
||||||
|
var firstY, i, label, labelBox, labelText, lastY, lineY, prevLabelMargin, v, x1, x2, xLabelMargin, xpos, y, yInterval, _results;
|
||||||
yInterval = (this.options.ymax - this.options.ymin) / (this.options.numLines - 1);
|
yInterval = (this.options.ymax - this.options.ymin) / (this.options.numLines - 1);
|
||||||
firstY = Math.ceil(this.options.ymin / yInterval) * yInterval;
|
firstY = Math.ceil(this.options.ymin / yInterval) * yInterval;
|
||||||
lastY = Math.floor(this.options.ymax / yInterval) * yInterval;
|
lastY = Math.floor(this.options.ymax / yInterval) * yInterval;
|
||||||
for (lineY = firstY; firstY <= lastY ? lineY <= lastY : lineY >= lastY; lineY += yInterval) {
|
for (lineY = firstY; firstY <= lastY ? lineY <= lastY : lineY >= lastY; lineY += yInterval) {
|
||||||
v = Math.floor(lineY);
|
v = Math.floor(lineY);
|
||||||
y = transY(v);
|
y = this.transY(v);
|
||||||
this.r.text(left - this.options.marginLeft / 2, y, v + this.options.units).attr('font-size', this.options.gridTextSize).attr('fill', this.options.gridTextColor).attr('text-anchor', 'end');
|
this.r.text(this.left - this.options.marginLeft / 2, y, this.commas(v) + this.options.units).attr('font-size', this.options.gridTextSize).attr('fill', this.options.gridTextColor).attr('text-anchor', 'end');
|
||||||
this.r.path("M" + left + "," + y + 'H' + (left + width)).attr('stroke', this.options.gridLineColor).attr('stroke-width', this.options.gridStrokeWidth);
|
this.r.path("M" + this.left + "," + y + "H" + (this.left + this.width)).attr('stroke', this.options.gridLineColor).attr('stroke-width', this.options.gridStrokeWidth);
|
||||||
}
|
}
|
||||||
prevLabelMargin = null;
|
prevLabelMargin = null;
|
||||||
xLabelMargin = 50;
|
xLabelMargin = 50;
|
||||||
@ -153,6 +238,7 @@
|
|||||||
x1 = this.xmin;
|
x1 = this.xmin;
|
||||||
x2 = this.xmax;
|
x2 = this.xmax;
|
||||||
}
|
}
|
||||||
|
_results = [];
|
||||||
for (i = x1; x1 <= x2 ? i <= x2 : i >= x2; x1 <= x2 ? i++ : i--) {
|
for (i = x1; x1 <= x2 ? i <= x2 : i >= x2; x1 <= x2 ? i++ : i--) {
|
||||||
if (this.options.parseTime) {
|
if (this.options.parseTime) {
|
||||||
xpos = new Date(i, 0, 1).getTime();
|
xpos = new Date(i, 0, 1).getTime();
|
||||||
@ -161,163 +247,61 @@
|
|||||||
xpos = i;
|
xpos = i;
|
||||||
}
|
}
|
||||||
labelText = this.options.parseTime ? i : this.columnLabels[this.columnLabels.length - i - 1];
|
labelText = this.options.parseTime ? i : this.columnLabels[this.columnLabels.length - i - 1];
|
||||||
label = this.r.text(transX(xpos), this.options.marginTop + height + this.options.marginBottom / 2, labelText).attr('font-size', this.options.gridTextSize).attr('fill', this.options.gridTextColor);
|
label = this.r.text(this.transX(xpos), this.options.marginTop + this.height + this.options.marginBottom / 2, labelText).attr('font-size', this.options.gridTextSize).attr('fill', this.options.gridTextColor);
|
||||||
labelBox = label.getBBox();
|
labelBox = label.getBBox();
|
||||||
if (prevLabelMargin === null || prevLabelMargin <= labelBox.x) {
|
if (prevLabelMargin === null || prevLabelMargin <= labelBox.x) {
|
||||||
prevLabelMargin = labelBox.x + labelBox.width + xLabelMargin;
|
_results.push(prevLabelMargin = labelBox.x + labelBox.width + xLabelMargin);
|
||||||
} else {
|
} else {
|
||||||
label.remove();
|
_results.push(label.remove());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
columns = (function() {
|
|
||||||
var _i, _len, _ref, _results;
|
|
||||||
_ref = this.xvals;
|
|
||||||
_results = [];
|
|
||||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
||||||
x = _ref[_i];
|
|
||||||
_results.push(transX(x));
|
|
||||||
}
|
|
||||||
return _results;
|
return _results;
|
||||||
}).call(this);
|
|
||||||
seriesCoords = [];
|
|
||||||
_ref = this.series;
|
|
||||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
|
||||||
s = _ref[_i];
|
|
||||||
seriesCoords.push($.map(s, function(y, i) {
|
|
||||||
return {
|
|
||||||
x: columns[i],
|
|
||||||
y: transY(y)
|
|
||||||
};
|
};
|
||||||
}));
|
|
||||||
}
|
Line.prototype.drawSeries = function() {
|
||||||
for (i = _ref2 = seriesCoords.length - 1; _ref2 <= 0 ? i <= 0 : i >= 0; _ref2 <= 0 ? i++ : i--) {
|
var c, circle, coords, i, path, _ref, _ref2, _results;
|
||||||
coords = seriesCoords[i];
|
for (i = _ref = this.seriesCoords.length - 1; _ref <= 0 ? i <= 0 : i >= 0; _ref <= 0 ? i++ : i--) {
|
||||||
|
coords = this.seriesCoords[i];
|
||||||
if (coords.length > 1) {
|
if (coords.length > 1) {
|
||||||
path = this.createPath(coords, this.options.marginTop, left, this.options.marginTop + height, left + width);
|
path = this.createPath(coords, this.options.marginTop, this.left, this.options.marginTop + this.height, this.left + this.width);
|
||||||
this.r.path(path).attr('stroke', this.options.lineColors[i]).attr('stroke-width', this.options.lineWidth);
|
this.r.path(path).attr('stroke', this.options.lineColors[i]).attr('stroke-width', this.options.lineWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
seriesPoints = (function() {
|
this.seriesPoints = (function() {
|
||||||
var _ref3, _results;
|
var _ref2, _results;
|
||||||
_results = [];
|
_results = [];
|
||||||
for (i = 0, _ref3 = seriesCoords.length - 1; 0 <= _ref3 ? i <= _ref3 : i >= _ref3; 0 <= _ref3 ? i++ : i--) {
|
for (i = 0, _ref2 = this.seriesCoords.length - 1; 0 <= _ref2 ? i <= _ref2 : i >= _ref2; 0 <= _ref2 ? i++ : i--) {
|
||||||
_results.push([]);
|
_results.push([]);
|
||||||
}
|
}
|
||||||
return _results;
|
return _results;
|
||||||
})();
|
}).call(this);
|
||||||
for (i = _ref3 = seriesCoords.length - 1; _ref3 <= 0 ? i <= 0 : i >= 0; _ref3 <= 0 ? i++ : i--) {
|
|
||||||
_ref4 = seriesCoords[i];
|
|
||||||
for (_j = 0, _len2 = _ref4.length; _j < _len2; _j++) {
|
|
||||||
c = _ref4[_j];
|
|
||||||
circle = this.r.circle(c.x, c.y, this.options.pointSize).attr('fill', this.options.lineColors[i]).attr('stroke-width', 1).attr('stroke', '#ffffff');
|
|
||||||
seriesPoints[i].push(circle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hoverHeight = this.options.hoverFontSize * 1.5 * (this.series.length + 1);
|
|
||||||
hover = this.r.rect(-10, -hoverHeight / 2 - this.options.hoverPaddingY, 20, hoverHeight + this.options.hoverPaddingY * 2, 10).attr('fill', this.options.hoverFillColor).attr('stroke', this.options.hoverBorderColor).attr('stroke-width', this.options.hoverBorderWidth).attr('opacity', this.options.hoverOpacity);
|
|
||||||
xLabel = this.r.text(0, (this.options.hoverFontSize * 0.75) - hoverHeight / 2, '').attr('fill', this.options.hoverLabelColor).attr('font-weight', 'bold').attr('font-size', this.options.hoverFontSize);
|
|
||||||
hoverSet = this.r.set();
|
|
||||||
hoverSet.push(hover);
|
|
||||||
hoverSet.push(xLabel);
|
|
||||||
yLabels = [];
|
|
||||||
for (i = 0, _ref5 = this.series.length - 1; 0 <= _ref5 ? i <= _ref5 : i >= _ref5; 0 <= _ref5 ? i++ : i--) {
|
|
||||||
yLabel = this.r.text(0, this.options.hoverFontSize * 1.5 * (i + 1.5) - hoverHeight / 2, '').attr('fill', this.options.lineColors[i]).attr('font-size', this.options.hoverFontSize);
|
|
||||||
yLabels.push(yLabel);
|
|
||||||
hoverSet.push(yLabel);
|
|
||||||
}
|
|
||||||
updateHover = function(index) {
|
|
||||||
var i, maxLabelWidth, xloc, yloc, _ref6;
|
|
||||||
hoverSet.show();
|
|
||||||
xLabel.attr('text', _this.columnLabels[index]);
|
|
||||||
for (i = 0, _ref6 = _this.series.length - 1; 0 <= _ref6 ? i <= _ref6 : i >= _ref6; 0 <= _ref6 ? i++ : i--) {
|
|
||||||
yLabels[i].attr('text', "" + _this.seriesLabels[i] + ": " + (_this.commas(_this.series[i][index])) + _this.options.units);
|
|
||||||
}
|
|
||||||
maxLabelWidth = Math.max.apply(null, $.map(yLabels, function(l) {
|
|
||||||
return l.getBBox().width;
|
|
||||||
}));
|
|
||||||
maxLabelWidth = Math.max(maxLabelWidth, xLabel.getBBox().width);
|
|
||||||
hover.attr('width', maxLabelWidth + _this.options.hoverPaddingX * 2);
|
|
||||||
hover.attr('x', -_this.options.hoverPaddingX - maxLabelWidth / 2);
|
|
||||||
yloc = Math.min.apply(null, $.map(_this.series, function(s) {
|
|
||||||
return transY(s[index]);
|
|
||||||
}));
|
|
||||||
if (yloc > hoverHeight + _this.options.hoverPaddingY * 2 + _this.options.hoverMargin + _this.options.marginTop) {
|
|
||||||
yloc = yloc - hoverHeight / 2 - _this.options.hoverPaddingY - _this.options.hoverMargin;
|
|
||||||
} else {
|
|
||||||
yloc = yloc + hoverHeight / 2 + _this.options.hoverPaddingY + _this.options.hoverMargin;
|
|
||||||
}
|
|
||||||
yloc = Math.max(_this.options.marginTop + hoverHeight / 2 + _this.options.hoverPaddingY, yloc);
|
|
||||||
yloc = Math.min(_this.options.marginTop + height - hoverHeight / 2 - _this.options.hoverPaddingY, yloc);
|
|
||||||
xloc = Math.min(left + width - maxLabelWidth / 2 - _this.options.hoverPaddingX, columns[index]);
|
|
||||||
xloc = Math.max(left + maxLabelWidth / 2 + _this.options.hoverPaddingX, xloc);
|
|
||||||
return hoverSet.attr('transform', "t" + xloc + "," + yloc);
|
|
||||||
};
|
|
||||||
hideHover = function() {
|
|
||||||
return hoverSet.hide();
|
|
||||||
};
|
|
||||||
hoverMargins = $.map(columns.slice(1), function(x, i) {
|
|
||||||
return (x + columns[i]) / 2;
|
|
||||||
});
|
|
||||||
prevHilight = null;
|
|
||||||
pointGrow = Raphael.animation({
|
|
||||||
r: this.options.pointSize + 3
|
|
||||||
}, 25, 'linear');
|
|
||||||
pointShrink = Raphael.animation({
|
|
||||||
r: this.options.pointSize
|
|
||||||
}, 25, 'linear');
|
|
||||||
hilight = function(index) {
|
|
||||||
var i, _ref6, _ref7;
|
|
||||||
if (prevHilight !== null && prevHilight !== index) {
|
|
||||||
for (i = 0, _ref6 = seriesPoints.length - 1; 0 <= _ref6 ? i <= _ref6 : i >= _ref6; 0 <= _ref6 ? i++ : i--) {
|
|
||||||
seriesPoints[i][prevHilight].animate(pointShrink);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (index !== null && prevHilight !== index) {
|
|
||||||
for (i = 0, _ref7 = seriesPoints.length - 1; 0 <= _ref7 ? i <= _ref7 : i >= _ref7; 0 <= _ref7 ? i++ : i--) {
|
|
||||||
seriesPoints[i][index].animate(pointGrow);
|
|
||||||
}
|
|
||||||
updateHover(index);
|
|
||||||
}
|
|
||||||
prevHilight = index;
|
|
||||||
if (index === null) return hideHover();
|
|
||||||
};
|
|
||||||
updateHilight = function(x) {
|
|
||||||
var hoverIndex, _ref6, _results;
|
|
||||||
x -= _this.el.offset().left;
|
|
||||||
_results = [];
|
_results = [];
|
||||||
for (hoverIndex = _ref6 = hoverMargins.length; _ref6 <= 0 ? hoverIndex <= 0 : hoverIndex >= 0; _ref6 <= 0 ? hoverIndex++ : hoverIndex--) {
|
for (i = _ref2 = this.seriesCoords.length - 1; _ref2 <= 0 ? i <= 0 : i >= 0; _ref2 <= 0 ? i++ : i--) {
|
||||||
if (hoverIndex === 0 || hoverMargins[hoverIndex - 1] > x) {
|
_results.push((function() {
|
||||||
hilight(hoverIndex);
|
var _i, _len, _ref3, _results2;
|
||||||
break;
|
_ref3 = this.seriesCoords[i];
|
||||||
|
_results2 = [];
|
||||||
|
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
|
||||||
|
c = _ref3[_i];
|
||||||
|
if (c === null) {
|
||||||
|
circle = null;
|
||||||
} else {
|
} else {
|
||||||
_results.push(void 0);
|
circle = this.r.circle(c.x, c.y, this.options.pointSize).attr('fill', this.options.lineColors[i]).attr('stroke-width', 1).attr('stroke', '#ffffff');
|
||||||
}
|
}
|
||||||
|
_results2.push(this.seriesPoints[i].push(circle));
|
||||||
|
}
|
||||||
|
return _results2;
|
||||||
|
}).call(this));
|
||||||
}
|
}
|
||||||
return _results;
|
return _results;
|
||||||
};
|
};
|
||||||
this.el.mousemove(function(evt) {
|
|
||||||
return updateHilight(evt.pageX);
|
|
||||||
});
|
|
||||||
if (this.options.hideHover) {
|
|
||||||
this.el.mouseout(function(evt) {
|
|
||||||
return hilight(null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
touchHandler = function(evt) {
|
|
||||||
var touch;
|
|
||||||
touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];
|
|
||||||
updateHilight(touch.pageX);
|
|
||||||
return touch;
|
|
||||||
};
|
|
||||||
this.el.bind('touchstart', touchHandler);
|
|
||||||
this.el.bind('touchmove', touchHandler);
|
|
||||||
this.el.bind('touchend', touchHandler);
|
|
||||||
return hilight(this.options.hideHover ? null : 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
Line.prototype.createPath = function(coords, top, left, bottom, right) {
|
Line.prototype.createPath = function(all_coords, top, left, bottom, right) {
|
||||||
var c, g, grads, i, ix, lc, lg, path, x1, x2, y1, y2, _ref;
|
var c, coords, g, grads, i, ix, lc, lg, path, x1, x2, y1, y2, _ref;
|
||||||
path = "";
|
path = "";
|
||||||
|
coords = $.map(all_coords, function(c) {
|
||||||
|
return c;
|
||||||
|
});
|
||||||
if (this.options.smooth) {
|
if (this.options.smooth) {
|
||||||
grads = this.gradients(coords);
|
grads = this.gradients(coords);
|
||||||
for (i = 0, _ref = coords.length - 1; 0 <= _ref ? i <= _ref : i >= _ref; 0 <= _ref ? i++ : i--) {
|
for (i = 0, _ref = coords.length - 1; 0 <= _ref ? i <= _ref : i >= _ref; 0 <= _ref ? i++ : i--) {
|
||||||
@ -356,6 +340,93 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Line.prototype.drawHover = function() {
|
||||||
|
var i, yLabel, _ref, _results;
|
||||||
|
this.hoverHeight = this.options.hoverFontSize * 1.5 * (this.series.length + 1);
|
||||||
|
this.hover = this.r.rect(-10, -this.hoverHeight / 2 - this.options.hoverPaddingY, 20, this.hoverHeight + this.options.hoverPaddingY * 2, 10).attr('fill', this.options.hoverFillColor).attr('stroke', this.options.hoverBorderColor).attr('stroke-width', this.options.hoverBorderWidth).attr('opacity', this.options.hoverOpacity);
|
||||||
|
this.xLabel = this.r.text(0, (this.options.hoverFontSize * 0.75) - this.hoverHeight / 2, '').attr('fill', this.options.hoverLabelColor).attr('font-weight', 'bold').attr('font-size', this.options.hoverFontSize);
|
||||||
|
this.hoverSet = this.r.set();
|
||||||
|
this.hoverSet.push(this.hover);
|
||||||
|
this.hoverSet.push(this.xLabel);
|
||||||
|
this.yLabels = [];
|
||||||
|
_results = [];
|
||||||
|
for (i = 0, _ref = this.series.length - 1; 0 <= _ref ? i <= _ref : i >= _ref; 0 <= _ref ? i++ : i--) {
|
||||||
|
yLabel = this.r.text(0, this.options.hoverFontSize * 1.5 * (i + 1.5) - this.hoverHeight / 2, '').attr('fill', this.options.lineColors[i]).attr('font-size', this.options.hoverFontSize);
|
||||||
|
this.yLabels.push(yLabel);
|
||||||
|
_results.push(this.hoverSet.push(yLabel));
|
||||||
|
}
|
||||||
|
return _results;
|
||||||
|
};
|
||||||
|
|
||||||
|
Line.prototype.updateHover = function(index) {
|
||||||
|
var i, maxLabelWidth, xloc, yloc, _ref,
|
||||||
|
_this = this;
|
||||||
|
this.hoverSet.show();
|
||||||
|
this.xLabel.attr('text', this.columnLabels[index]);
|
||||||
|
for (i = 0, _ref = this.series.length - 1; 0 <= _ref ? i <= _ref : i >= _ref; 0 <= _ref ? i++ : i--) {
|
||||||
|
this.yLabels[i].attr('text', "" + this.seriesLabels[i] + ": " + (this.commas(this.series[i][index])) + this.options.units);
|
||||||
|
}
|
||||||
|
maxLabelWidth = Math.max.apply(null, $.map(this.yLabels, function(l) {
|
||||||
|
return l.getBBox().width;
|
||||||
|
}));
|
||||||
|
maxLabelWidth = Math.max(maxLabelWidth, this.xLabel.getBBox().width);
|
||||||
|
this.hover.attr('width', maxLabelWidth + this.options.hoverPaddingX * 2);
|
||||||
|
this.hover.attr('x', -this.options.hoverPaddingX - maxLabelWidth / 2);
|
||||||
|
yloc = Math.min.apply(null, $.map(this.series, function(s) {
|
||||||
|
return _this.transY(s[index]);
|
||||||
|
}));
|
||||||
|
if (yloc > this.hoverHeight + this.options.hoverPaddingY * 2 + this.options.hoverMargin + this.options.marginTop) {
|
||||||
|
yloc = yloc - this.hoverHeight / 2 - this.options.hoverPaddingY - this.options.hoverMargin;
|
||||||
|
} else {
|
||||||
|
yloc = yloc + this.hoverHeight / 2 + this.options.hoverPaddingY + this.options.hoverMargin;
|
||||||
|
}
|
||||||
|
yloc = Math.max(this.options.marginTop + this.hoverHeight / 2 + this.options.hoverPaddingY, yloc);
|
||||||
|
yloc = Math.min(this.options.marginTop + this.height - this.hoverHeight / 2 - this.options.hoverPaddingY, yloc);
|
||||||
|
xloc = Math.min(this.left + this.width - maxLabelWidth / 2 - this.options.hoverPaddingX, this.columns[index]);
|
||||||
|
xloc = Math.max(this.left + maxLabelWidth / 2 + this.options.hoverPaddingX, xloc);
|
||||||
|
return this.hoverSet.attr('transform', "t" + xloc + "," + yloc);
|
||||||
|
};
|
||||||
|
|
||||||
|
Line.prototype.hideHover = function() {
|
||||||
|
return this.hoverSet.hide();
|
||||||
|
};
|
||||||
|
|
||||||
|
Line.prototype.hilight = function(index) {
|
||||||
|
var i, _ref, _ref2;
|
||||||
|
if (this.prevHilight !== null && this.prevHilight !== index) {
|
||||||
|
for (i = 0, _ref = this.seriesPoints.length - 1; 0 <= _ref ? i <= _ref : i >= _ref; 0 <= _ref ? i++ : i--) {
|
||||||
|
if (this.seriesPoints[i][this.prevHilight]) {
|
||||||
|
this.seriesPoints[i][this.prevHilight].animate(this.pointShrink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index !== null && this.prevHilight !== index) {
|
||||||
|
for (i = 0, _ref2 = this.seriesPoints.length - 1; 0 <= _ref2 ? i <= _ref2 : i >= _ref2; 0 <= _ref2 ? i++ : i--) {
|
||||||
|
if (this.seriesPoints[i][index]) {
|
||||||
|
this.seriesPoints[i][index].animate(this.pointGrow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.updateHover(index);
|
||||||
|
}
|
||||||
|
this.prevHilight = index;
|
||||||
|
if (index === null) return this.hideHover();
|
||||||
|
};
|
||||||
|
|
||||||
|
Line.prototype.updateHilight = function(x) {
|
||||||
|
var hoverIndex, _ref, _results;
|
||||||
|
x -= this.el.offset().left;
|
||||||
|
_results = [];
|
||||||
|
for (hoverIndex = _ref = this.hoverMargins.length; _ref <= 0 ? hoverIndex <= 0 : hoverIndex >= 0; _ref <= 0 ? hoverIndex++ : hoverIndex--) {
|
||||||
|
if (hoverIndex === 0 || this.hoverMargins[hoverIndex - 1] > x) {
|
||||||
|
this.hilight(hoverIndex);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
_results.push(void 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _results;
|
||||||
|
};
|
||||||
|
|
||||||
Line.prototype.measureText = function(text, fontSize) {
|
Line.prototype.measureText = function(text, fontSize) {
|
||||||
var ret, tt;
|
var ret, tt;
|
||||||
if (fontSize == null) fontSize = 12;
|
if (fontSize == null) fontSize = 12;
|
||||||
@ -398,13 +469,19 @@
|
|||||||
|
|
||||||
Line.prototype.commas = function(num) {
|
Line.prototype.commas = function(num) {
|
||||||
var absnum, intnum, ret, strabsnum;
|
var absnum, intnum, ret, strabsnum;
|
||||||
|
if (num === null) {
|
||||||
|
return "n/a";
|
||||||
|
} else {
|
||||||
ret = num < 0 ? "-" : "";
|
ret = num < 0 ? "-" : "";
|
||||||
absnum = Math.abs(num);
|
absnum = Math.abs(num);
|
||||||
intnum = Math.floor(absnum).toFixed(0);
|
intnum = Math.floor(absnum).toFixed(0);
|
||||||
ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ',');
|
ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ',');
|
||||||
strabsnum = absnum.toString();
|
strabsnum = absnum.toString();
|
||||||
if (strabsnum.length > intnum.length) ret += strabsnum.slice(intnum.length);
|
if (strabsnum.length > intnum.length) {
|
||||||
|
ret += strabsnum.slice(intnum.length);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return Line;
|
return Line;
|
||||||
|
2
morris.min.js
vendored
2
morris.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user