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:
Olly Smith 2012-03-18 19:50:40 +00:00
parent ad8d0b6a8c
commit bde431ac34
5 changed files with 306 additions and 230 deletions

View File

@ -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',

View File

@ -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',

View File

@ -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
View File

@ -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

File diff suppressed because one or more lines are too long