MUCH simpler internal code.

This commit is contained in:
Olly Smith 2012-10-23 09:15:21 +01:00
parent f6b1cfe7a0
commit 1aca098694
5 changed files with 195 additions and 206 deletions

View File

@ -34,7 +34,7 @@ class Morris.Grid extends Morris.EventEmitter
@init() if @init @init() if @init
# load data # load data
@setData(@options.data) @setData @options.data
# Default options # Default options
# #
@ -55,62 +55,55 @@ class Morris.Grid extends Morris.EventEmitter
# Update the data series and redraw the chart. # Update the data series and redraw the chart.
# #
setData: (data, redraw = true) -> setData: (data, redraw = true) ->
# shallow copy data ymax = null
@options.data = $.map data, (row) => ymin = null
@data = $.map data, (row, index) =>
ret = {}
ret.label = row[@options.xkey]
if @options.parseTime if @options.parseTime
$.extend {'__T': Morris.parseDate(row[@options.xkey])}, row ret.x = Morris.parseDate(ret.label)
if @options.dateFormat
ret.label = @options.dateFormat ret.x
else if typeof ret.label is 'number'
ret.label = new Date(ret.label).toString()
else else
$.extend {}, row ret.x = index
if @options.parseTime ret.y = for ykey in @options.ykeys
@options.data = @options.data.sort (a, b) => yval = row[ykey]
(a['__T'] > b['__T']) - (b['__T'] > a['__T']) yval = parseFloat(yval) if typeof yval is 'string'
yval = null unless typeof yval is 'number'
unless yval is null
if ymax is null
ymax = ymin = yval
else
ymax = Math.max(yval, ymax)
ymin = Math.min(yval, ymin)
yval
ret
# extract series data
@series = []
for ykey in @options.ykeys
seriesData = []
for d in @options.data
y = d[ykey]
seriesData.push switch typeof y
when 'number' then y
when 'string' then parseFloat y
else null
@series.push seriesData
# extract labels / x values
@columnLabels = $.map @options.data, (row) => row[@options.xkey]
if @options.parseTime if @options.parseTime
@xvals = $.map @options.data, (row) -> row['__T'] @data = @data.sort (a, b) -> (a.x > b.x) - (b.x > a.x)
if @options.dateFormat
@columnLabels = $.map @xvals, (d) => @options.dateFormat d
else
@columnLabels = $.map @columnLabels, (d) =>
# default formatter for numeric timestamp labels
if typeof d is 'number' then new Date(d).toString() else d
else
@xvals = [0...@columnLabels.length]
# calculate horizontal range of the graph # calculate horizontal range of the graph
@xmin = Math.min.apply null, @xvals @xmin = @data[0].x
@xmax = Math.max.apply null, @xvals @xmax = @data[@data.length - 1].x
if @xmin is @xmax if @xmin is @xmax
@xmin -= 1 @xmin -= 1
@xmax += 1 @xmax += 1
# Compute the vertical range of the graph if desired # Compute the vertical range of the graph if desired
if typeof @options.ymax is 'string' and @options.ymax[0..3] is 'auto' if typeof @options.ymax is 'string'
# use Array.concat to flatten arrays and find the max y value if @options.ymax[0..3] is 'auto'
ymax = Math.max.apply null, Array.prototype.concat.apply([], @series) # use Array.concat to flatten arrays and find the max y value
if @options.ymax.length > 5 if @options.ymax.length > 5
@ymax = Math.max parseInt(@options.ymax[5..], 10), ymax @ymax = Math.max parseInt(@options.ymax[5..], 10), ymax
else
@ymax = ymax
else else
@ymax = ymax @ymax = parseInt(@options.ymax, 10)
else if typeof @options.ymax is 'string'
@ymax = parseInt(@options.ymax, 10)
else else
@ymax = @options.ymax @ymax = @options.ymax
if typeof @options.ymin is 'string' and @options.ymin[0..3] is 'auto' if typeof @options.ymin is 'string' and @options.ymin[0..3] is 'auto'
ymin = Math.min.apply null, Array.prototype.concat.apply([], @series)
if @options.ymin.length > 5 if @options.ymin.length > 5
@ymin = Math.min parseInt(@options.ymin[5..], 10), ymin @ymin = Math.min parseInt(@options.ymin[5..], 10), ymin
else else
@ -120,7 +113,7 @@ class Morris.Grid extends Morris.EventEmitter
else else
@ymin = @options.ymin @ymin = @options.ymin
if @ymin is @ymax if @ymin is @ymax
if @ymin is not 0 then @ymin -= 1 if @ymin isnt 0 then @ymin -= 1
@ymax += 1 @ymax += 1
@yInterval = (@ymax - @ymin) / (@options.numLines - 1) @yInterval = (@ymax - @ymin) / (@options.numLines - 1)
@ -158,7 +151,7 @@ class Morris.Grid extends Morris.EventEmitter
# #
transY: (y) -> @bottom - (y - @ymin) * @dy transY: (y) -> @bottom - (y - @ymin) * @dy
transX: (x) -> transX: (x) ->
if @xvals.length == 1 if @data.length == 1
(@left + @right) / 2 (@left + @right) / 2
else else
@left + (x - @xmin) * @dx @left + (x - @xmin) * @dx

View File

@ -60,18 +60,15 @@ class Morris.Line extends Morris.Grid
# @private # @private
calc: -> calc: ->
# calculate series data point coordinates # calculate series data point coordinates
@columns = (@transX(x) for x in @xvals) for row in @data
@seriesCoords = [] row._x = @transX(row.x)
for s in @series row._y = for y in row.y
scoords = [] if y is null
$.each s, (i, y) => null
if y == null else
scoords.push(null) @transY(y)
else
scoords.push(x: @columns[i], y: @transY(y))
@seriesCoords.push(scoords)
# calculate hover margins # calculate hover margins
@hoverMargins = $.map @columns.slice(1), (x, i) => (x + @columns[i]) / 2 @hoverMargins = $.map @data.slice(1), (r, i) => (r._x + @data[i]._x) / 2
# Draws the line chart. # Draws the line chart.
# #
@ -79,7 +76,7 @@ class Morris.Line extends Morris.Grid
@drawXAxis() @drawXAxis()
@drawSeries() @drawSeries()
@drawHover() @drawHover()
@hilight(if @options.hideHover then null else @options.data.length - 1) @hilight(if @options.hideHover then null else @data.length - 1)
# draw the x-axis labels # draw the x-axis labels
# #
@ -102,25 +99,24 @@ class Morris.Line extends Morris.Grid
else else
label.remove() label.remove()
if @options.parseTime if @options.parseTime
if @columnLabels.length == 1 and @options.xLabels == 'auto' if @data.length == 1 and @options.xLabels == 'auto'
# where there's only one value in the series, we can't make a # where there's only one value in the series, we can't make a
# sensible guess for an x labelling scheme, so just use the original # sensible guess for an x labelling scheme, so just use the original
# column label # column label
drawLabel(@columnLabels[0], @xvals[0]) drawLabel(@data[0].label, @data[0].x)
else else
for l in Morris.labelSeries(@xmin, @xmax, @width, @options.xLabels, @options.xLabelFormat) for l in Morris.labelSeries(@xmin, @xmax, @width, @options.xLabels, @options.xLabelFormat)
drawLabel(l[0], l[1]) drawLabel(l[0], l[1])
else else
for i in [0...@columnLabels.length] for row in @data
labelText = @columnLabels[i] drawLabel(row.label, row.x)
drawLabel(labelText, i)
# draw the data series # draw the data series
# #
# @private # @private
drawSeries: -> drawSeries: ->
for i in [@seriesCoords.length-1..0] for i in [@options.ykeys.length-1..0]
coords = $.map @seriesCoords[i], (c) -> c coords = ({x: r._x, y: r._y[i]} for r in @data when r._y[i] isnt null)
smooth = @options.smooth is true or smooth = @options.smooth is true or
$.inArray(@options.ykeys[i], @options.smooth) > -1 $.inArray(@options.ykeys[i], @options.smooth) > -1
if coords.length > 1 if coords.length > 1
@ -128,13 +124,13 @@ class Morris.Line extends Morris.Grid
@r.path(path) @r.path(path)
.attr('stroke', @colorForSeries(i)) .attr('stroke', @colorForSeries(i))
.attr('stroke-width', @options.lineWidth) .attr('stroke-width', @options.lineWidth)
@seriesPoints = ([] for i in [0..@seriesCoords.length-1]) @seriesPoints = ([] for i in [0...@options.ykeys.length])
for i in [@seriesCoords.length-1..0] for i in [@options.ykeys.length-1..0]
for c in @seriesCoords[i] for row in @data
if c == null if row._y[i] == null
circle = null circle = null
else else
circle = @r.circle(c.x, c.y, @options.pointSize) circle = @r.circle(row._x, row._y[i], @options.pointSize)
.attr('fill', @pointFillColorForSeries(i) || @colorForSeries(i)) .attr('fill', @pointFillColorForSeries(i) || @colorForSeries(i))
.attr('stroke-width', @strokeWidthForSeries(i)) .attr('stroke-width', @strokeWidthForSeries(i))
.attr('stroke', @strokeForSeries(i)) .attr('stroke', @strokeForSeries(i))
@ -182,7 +178,7 @@ class Morris.Line extends Morris.Grid
# @private # @private
drawHover: -> drawHover: ->
# hover labels # hover labels
@hoverHeight = @options.hoverFontSize * 1.5 * (@series.length + 1) @hoverHeight = @options.hoverFontSize * 1.5 * (@options.ykeys.length + 1)
@hover = @r.rect(-10, -@hoverHeight / 2 - @options.hoverPaddingY, 20, @hoverHeight + @options.hoverPaddingY * 2, 10) @hover = @r.rect(-10, -@hoverHeight / 2 - @options.hoverPaddingY, 20, @hoverHeight + @options.hoverPaddingY * 2, 10)
.attr('fill', @options.hoverFillColor) .attr('fill', @options.hoverFillColor)
.attr('stroke', @options.hoverBorderColor) .attr('stroke', @options.hoverBorderColor)
@ -196,7 +192,7 @@ class Morris.Line extends Morris.Grid
@hoverSet.push(@hover) @hoverSet.push(@hover)
@hoverSet.push(@xLabel) @hoverSet.push(@xLabel)
@yLabels = [] @yLabels = []
for i in [0..@series.length-1] for i in [0...@data.length]
yLabel = @r.text(0, @options.hoverFontSize * 1.5 * (i + 1.5) - @hoverHeight / 2, '') yLabel = @r.text(0, @options.hoverFontSize * 1.5 * (i + 1.5) - @hoverHeight / 2, '')
.attr('fill', @colorForSeries(i)) .attr('fill', @colorForSeries(i))
.attr('font-size', @options.hoverFontSize) .attr('font-size', @options.hoverFontSize)
@ -206,9 +202,10 @@ class Morris.Line extends Morris.Grid
# @private # @private
updateHover: (index) => updateHover: (index) =>
@hoverSet.show() @hoverSet.show()
@xLabel.attr('text', @columnLabels[index]) row = @data[index]
for i in [0..@series.length-1] @xLabel.attr('text', row.label)
@yLabels[i].attr('text', "#{@options.labels[i]}: #{@yLabelFormat(@series[i][index])}") for y, i in row.y
@yLabels[i].attr('text', "#{@options.labels[i]}: #{@yLabelFormat(y)}")
# 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
@ -216,15 +213,14 @@ class Morris.Line extends Morris.Grid
@hover.attr 'width', maxLabelWidth + @options.hoverPaddingX * 2 @hover.attr 'width', maxLabelWidth + @options.hoverPaddingX * 2
@hover.attr 'x', -@options.hoverPaddingX - maxLabelWidth / 2 @hover.attr 'x', -@options.hoverPaddingX - maxLabelWidth / 2
# move to y pos # move to y pos
yloc = Math.min.apply null, $.map @series, (s) => yloc = Math.min.apply null, row.y
@transY s[index]
if yloc > @hoverHeight + @options.hoverPaddingY * 2 + @options.hoverMargin + @top if yloc > @hoverHeight + @options.hoverPaddingY * 2 + @options.hoverMargin + @top
yloc = yloc - @hoverHeight / 2 - @options.hoverPaddingY - @options.hoverMargin yloc = yloc - @hoverHeight / 2 - @options.hoverPaddingY - @options.hoverMargin
else else
yloc = yloc + @hoverHeight / 2 + @options.hoverPaddingY + @options.hoverMargin yloc = yloc + @hoverHeight / 2 + @options.hoverPaddingY + @options.hoverMargin
yloc = Math.max @top + @hoverHeight / 2 + @options.hoverPaddingY, yloc yloc = Math.max @top + @hoverHeight / 2 + @options.hoverPaddingY, yloc
yloc = Math.min @bottom - @hoverHeight / 2 - @options.hoverPaddingY, yloc yloc = Math.min @bottom - @hoverHeight / 2 - @options.hoverPaddingY, yloc
xloc = Math.min @right - maxLabelWidth / 2 - @options.hoverPaddingX, @columns[index] xloc = Math.min @right - maxLabelWidth / 2 - @options.hoverPaddingX, @data[index]._x
xloc = Math.max @left + maxLabelWidth / 2 + @options.hoverPaddingX, xloc xloc = Math.max @left + maxLabelWidth / 2 + @options.hoverPaddingX, xloc
@hoverSet.attr 'transform', "t#{xloc},#{yloc}" @hoverSet.attr 'transform', "t#{xloc},#{yloc}"

252
morris.js
View File

@ -62,6 +62,16 @@
return (number < 10 ? '0' : '') + number; return (number < 10 ? '0' : '') + number;
}; };
Morris.Data = (function() {
function Data() {}
Data.prototype.initialize = function(options) {};
return Data;
})();
Morris.Donut = (function() { Morris.Donut = (function() {
Donut.prototype.defaults = { Donut.prototype.defaults = {
@ -329,94 +339,79 @@
}; };
Grid.prototype.setData = function(data, redraw) { Grid.prototype.setData = function(data, redraw) {
var d, seriesData, y, ykey, ymax, ymin, _i, _j, _k, _len, _len1, _ref, _ref1, _ref2, _results, var ymax, ymin,
_this = this; _this = this;
if (redraw == null) { if (redraw == null) {
redraw = true; redraw = true;
} }
this.options.data = $.map(data, function(row) { ymax = null;
ymin = null;
this.data = $.map(data, function(row, index) {
var ret, ykey, yval;
ret = {};
ret.label = row[_this.options.xkey];
if (_this.options.parseTime) { if (_this.options.parseTime) {
return $.extend({ ret.x = Morris.parseDate(ret.label);
'__T': Morris.parseDate(row[_this.options.xkey]) if (_this.options.dateFormat) {
}, row); ret.label = _this.options.dateFormat(ret.x);
} else if (typeof ret.label === 'number') {
ret.label = new Date(ret.label).toString();
}
} else { } else {
return $.extend({}, row); ret.x = index;
} }
}); ret.y = (function() {
if (this.options.parseTime) { var _i, _len, _ref, _results;
this.options.data = this.options.data.sort(function(a, b) { _ref = this.options.ykeys;
return (a['__T'] > b['__T']) - (b['__T'] > a['__T']);
});
}
this.series = [];
_ref = this.options.ykeys;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
ykey = _ref[_i];
seriesData = [];
_ref1 = this.options.data;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
d = _ref1[_j];
y = d[ykey];
seriesData.push((function() {
switch (typeof y) {
case 'number':
return y;
case 'string':
return parseFloat(y);
default:
return null;
}
})());
}
this.series.push(seriesData);
}
this.columnLabels = $.map(this.options.data, function(row) {
return row[_this.options.xkey];
});
if (this.options.parseTime) {
this.xvals = $.map(this.options.data, function(row) {
return row['__T'];
});
if (this.options.dateFormat) {
this.columnLabels = $.map(this.xvals, function(d) {
return _this.options.dateFormat(d);
});
} else {
this.columnLabels = $.map(this.columnLabels, function(d) {
if (typeof d === 'number') {
return new Date(d).toString();
} else {
return d;
}
});
}
} else {
this.xvals = (function() {
_results = []; _results = [];
for (var _k = 0, _ref2 = this.columnLabels.length; 0 <= _ref2 ? _k < _ref2 : _k > _ref2; 0 <= _ref2 ? _k++ : _k--){ _results.push(_k); } for (_i = 0, _len = _ref.length; _i < _len; _i++) {
ykey = _ref[_i];
yval = row[ykey];
if (typeof yval === 'string') {
yval = parseFloat(yval);
}
if (typeof yval !== 'number') {
yval = null;
}
if (yval !== null) {
if (ymax === null) {
ymax = ymin = yval;
} else {
ymax = Math.max(yval, ymax);
ymin = Math.min(yval, ymin);
}
}
_results.push(yval);
}
return _results; return _results;
}).apply(this); }).call(_this);
return ret;
});
if (this.options.parseTime) {
this.data = this.data.sort(function(a, b) {
return (a.x > b.x) - (b.x > a.x);
});
} }
this.xmin = Math.min.apply(null, this.xvals); this.xmin = this.data[0].x;
this.xmax = Math.max.apply(null, this.xvals); this.xmax = this.data[this.data.length - 1].x;
if (this.xmin === this.xmax) { if (this.xmin === this.xmax) {
this.xmin -= 1; this.xmin -= 1;
this.xmax += 1; this.xmax += 1;
} }
if (typeof this.options.ymax === 'string' && this.options.ymax.slice(0, 4) === 'auto') { if (typeof this.options.ymax === 'string') {
ymax = Math.max.apply(null, Array.prototype.concat.apply([], this.series)); if (this.options.ymax.slice(0, 4) === 'auto') {
if (this.options.ymax.length > 5) { if (this.options.ymax.length > 5) {
this.ymax = Math.max(parseInt(this.options.ymax.slice(5), 10), ymax); this.ymax = Math.max(parseInt(this.options.ymax.slice(5), 10), ymax);
} else {
this.ymax = ymax;
}
} else { } else {
this.ymax = ymax; this.ymax = parseInt(this.options.ymax, 10);
} }
} else if (typeof this.options.ymax === 'string') {
this.ymax = parseInt(this.options.ymax, 10);
} else { } else {
this.ymax = this.options.ymax; this.ymax = this.options.ymax;
} }
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));
if (this.options.ymin.length > 5) { if (this.options.ymin.length > 5) {
this.ymin = Math.min(parseInt(this.options.ymin.slice(5), 10), ymin); this.ymin = Math.min(parseInt(this.options.ymin.slice(5), 10), ymin);
} else { } else {
@ -428,7 +423,7 @@
this.ymin = this.options.ymin; this.ymin = this.options.ymin;
} }
if (this.ymin === this.ymax) { if (this.ymin === this.ymax) {
if (this.ymin === !0) { if (this.ymin !== 0) {
this.ymin -= 1; this.ymin -= 1;
} }
this.ymax += 1; this.ymax += 1;
@ -473,7 +468,7 @@
}; };
Grid.prototype.transX = function(x) { Grid.prototype.transX = function(x) {
if (this.xvals.length === 1) { if (this.data.length === 1) {
return (this.left + this.right) / 2; return (this.left + this.right) / 2;
} else { } else {
return this.left + (x - this.xmin) * this.dx; return this.left + (x - this.xmin) * this.dx;
@ -651,37 +646,29 @@
}; };
Line.prototype.calc = function() { Line.prototype.calc = function() {
var s, scoords, x, _i, _len, _ref, var row, y, _i, _len, _ref,
_this = this; _this = this;
this.columns = (function() { _ref = this.data;
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++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
s = _ref[_i]; row = _ref[_i];
scoords = []; row._x = this.transX(row.x);
$.each(s, function(i, y) { row._y = (function() {
if (y === null) { var _j, _len1, _ref1, _results;
return scoords.push(null); _ref1 = row.y;
} else { _results = [];
return scoords.push({ for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
x: _this.columns[i], y = _ref1[_j];
y: _this.transY(y) if (y === null) {
}); _results.push(null);
} else {
_results.push(this.transY(y));
}
} }
}); return _results;
this.seriesCoords.push(scoords); }).call(this);
} }
return this.hoverMargins = $.map(this.columns.slice(1), function(x, i) { return this.hoverMargins = $.map(this.data.slice(1), function(r, i) {
return (x + _this.columns[i]) / 2; return (r._x + _this.data[i]._x) / 2;
}); });
}; };
@ -689,11 +676,11 @@
this.drawXAxis(); this.drawXAxis();
this.drawSeries(); this.drawSeries();
this.drawHover(); this.drawHover();
return this.hilight(this.options.hideHover ? null : this.options.data.length - 1); return this.hilight(this.options.hideHover ? null : this.data.length - 1);
}; };
Line.prototype.drawXAxis = function() { Line.prototype.drawXAxis = function() {
var drawLabel, i, l, labelText, prevLabelMargin, xLabelMargin, ypos, _i, _j, _len, _ref, _ref1, _results, _results1, var drawLabel, l, prevLabelMargin, row, xLabelMargin, ypos, _i, _j, _len, _len1, _ref, _ref1, _results, _results1,
_this = this; _this = this;
ypos = this.bottom + this.options.gridTextSize * 1.25; ypos = this.bottom + this.options.gridTextSize * 1.25;
xLabelMargin = 50; xLabelMargin = 50;
@ -709,8 +696,8 @@
} }
}; };
if (this.options.parseTime) { if (this.options.parseTime) {
if (this.columnLabels.length === 1 && this.options.xLabels === 'auto') { if (this.data.length === 1 && this.options.xLabels === 'auto') {
return drawLabel(this.columnLabels[0], this.xvals[0]); return drawLabel(this.data[0].label, this.data[0].x);
} else { } else {
_ref = Morris.labelSeries(this.xmin, this.xmax, this.width, this.options.xLabels, this.options.xLabelFormat); _ref = Morris.labelSeries(this.xmin, this.xmax, this.width, this.options.xLabels, this.options.xLabelFormat);
_results = []; _results = [];
@ -721,21 +708,34 @@
return _results; return _results;
} }
} else { } else {
_ref1 = this.data;
_results1 = []; _results1 = [];
for (i = _j = 0, _ref1 = this.columnLabels.length; 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) { for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
labelText = this.columnLabels[i]; row = _ref1[_j];
_results1.push(drawLabel(labelText, i)); _results1.push(drawLabel(row.label, row.x));
} }
return _results1; return _results1;
} }
}; };
Line.prototype.drawSeries = function() { Line.prototype.drawSeries = function() {
var c, circle, coords, i, path, smooth, _i, _j, _ref, _ref1, _results; var circle, coords, i, path, r, row, smooth, _i, _j, _ref, _ref1, _results;
for (i = _i = _ref = this.seriesCoords.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) { for (i = _i = _ref = this.options.ykeys.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {
coords = $.map(this.seriesCoords[i], function(c) { coords = (function() {
return c; var _j, _len, _ref1, _results;
}); _ref1 = this.data;
_results = [];
for (_j = 0, _len = _ref1.length; _j < _len; _j++) {
r = _ref1[_j];
if (r._y[i] !== null) {
_results.push({
x: r._x,
y: r._y[i]
});
}
}
return _results;
}).call(this);
smooth = this.options.smooth === true || $.inArray(this.options.ykeys[i], this.options.smooth) > -1; smooth = this.options.smooth === true || $.inArray(this.options.ykeys[i], this.options.smooth) > -1;
if (coords.length > 1) { if (coords.length > 1) {
path = this.createPath(coords, this.bottom, smooth); path = this.createPath(coords, this.bottom, smooth);
@ -745,23 +745,23 @@
this.seriesPoints = (function() { this.seriesPoints = (function() {
var _j, _ref1, _results; var _j, _ref1, _results;
_results = []; _results = [];
for (i = _j = 0, _ref1 = this.seriesCoords.length - 1; 0 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 0 <= _ref1 ? ++_j : --_j) { for (i = _j = 0, _ref1 = this.options.ykeys.length; 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
_results.push([]); _results.push([]);
} }
return _results; return _results;
}).call(this); }).call(this);
_results = []; _results = [];
for (i = _j = _ref1 = this.seriesCoords.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; i = _ref1 <= 0 ? ++_j : --_j) { for (i = _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; i = _ref1 <= 0 ? ++_j : --_j) {
_results.push((function() { _results.push((function() {
var _k, _len, _ref2, _results1; var _k, _len, _ref2, _results1;
_ref2 = this.seriesCoords[i]; _ref2 = this.data;
_results1 = []; _results1 = [];
for (_k = 0, _len = _ref2.length; _k < _len; _k++) { for (_k = 0, _len = _ref2.length; _k < _len; _k++) {
c = _ref2[_k]; row = _ref2[_k];
if (c === null) { if (row._y[i] === null) {
circle = null; circle = null;
} else { } else {
circle = this.r.circle(c.x, c.y, this.options.pointSize).attr('fill', this.pointFillColorForSeries(i) || this.colorForSeries(i)).attr('stroke-width', this.strokeWidthForSeries(i)).attr('stroke', this.strokeForSeries(i)); circle = this.r.circle(row._x, row._y[i], this.options.pointSize).attr('fill', this.pointFillColorForSeries(i) || this.colorForSeries(i)).attr('stroke-width', this.strokeWidthForSeries(i)).attr('stroke', this.strokeForSeries(i));
} }
_results1.push(this.seriesPoints[i].push(circle)); _results1.push(this.seriesPoints[i].push(circle));
} }
@ -814,7 +814,7 @@
Line.prototype.drawHover = function() { Line.prototype.drawHover = function() {
var i, yLabel, _i, _ref, _results; var i, yLabel, _i, _ref, _results;
this.hoverHeight = this.options.hoverFontSize * 1.5 * (this.series.length + 1); this.hoverHeight = this.options.hoverFontSize * 1.5 * (this.options.ykeys.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.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.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 = this.r.set();
@ -822,7 +822,7 @@
this.hoverSet.push(this.xLabel); this.hoverSet.push(this.xLabel);
this.yLabels = []; this.yLabels = [];
_results = []; _results = [];
for (i = _i = 0, _ref = this.series.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) { for (i = _i = 0, _ref = this.data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
yLabel = this.r.text(0, this.options.hoverFontSize * 1.5 * (i + 1.5) - this.hoverHeight / 2, '').attr('fill', this.colorForSeries(i)).attr('font-size', this.options.hoverFontSize); yLabel = this.r.text(0, this.options.hoverFontSize * 1.5 * (i + 1.5) - this.hoverHeight / 2, '').attr('fill', this.colorForSeries(i)).attr('font-size', this.options.hoverFontSize);
this.yLabels.push(yLabel); this.yLabels.push(yLabel);
_results.push(this.hoverSet.push(yLabel)); _results.push(this.hoverSet.push(yLabel));
@ -831,12 +831,14 @@
}; };
Line.prototype.updateHover = function(index) { Line.prototype.updateHover = function(index) {
var i, maxLabelWidth, xloc, yloc, _i, _ref, var i, maxLabelWidth, row, xloc, y, yloc, _i, _len, _ref;
_this = this;
this.hoverSet.show(); this.hoverSet.show();
this.xLabel.attr('text', this.columnLabels[index]); row = this.data[index];
for (i = _i = 0, _ref = this.series.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) { this.xLabel.attr('text', row.label);
this.yLabels[i].attr('text', "" + this.options.labels[i] + ": " + (this.yLabelFormat(this.series[i][index]))); _ref = row.y;
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
y = _ref[i];
this.yLabels[i].attr('text', "" + this.options.labels[i] + ": " + (this.yLabelFormat(y)));
} }
maxLabelWidth = Math.max.apply(null, $.map(this.yLabels, function(l) { maxLabelWidth = Math.max.apply(null, $.map(this.yLabels, function(l) {
return l.getBBox().width; return l.getBBox().width;
@ -844,9 +846,7 @@
maxLabelWidth = Math.max(maxLabelWidth, this.xLabel.getBBox().width); maxLabelWidth = Math.max(maxLabelWidth, this.xLabel.getBBox().width);
this.hover.attr('width', maxLabelWidth + this.options.hoverPaddingX * 2); this.hover.attr('width', maxLabelWidth + this.options.hoverPaddingX * 2);
this.hover.attr('x', -this.options.hoverPaddingX - maxLabelWidth / 2); this.hover.attr('x', -this.options.hoverPaddingX - maxLabelWidth / 2);
yloc = Math.min.apply(null, $.map(this.series, function(s) { yloc = Math.min.apply(null, row.y);
return _this.transY(s[index]);
}));
if (yloc > this.hoverHeight + this.options.hoverPaddingY * 2 + this.options.hoverMargin + this.top) { if (yloc > this.hoverHeight + this.options.hoverPaddingY * 2 + this.options.hoverMargin + this.top) {
yloc = yloc - this.hoverHeight / 2 - this.options.hoverPaddingY - this.options.hoverMargin; yloc = yloc - this.hoverHeight / 2 - this.options.hoverPaddingY - this.options.hoverMargin;
} else { } else {
@ -854,7 +854,7 @@
} }
yloc = Math.max(this.top + this.hoverHeight / 2 + this.options.hoverPaddingY, yloc); yloc = Math.max(this.top + this.hoverHeight / 2 + this.options.hoverPaddingY, yloc);
yloc = Math.min(this.bottom - this.hoverHeight / 2 - this.options.hoverPaddingY, yloc); yloc = Math.min(this.bottom - this.hoverHeight / 2 - this.options.hoverPaddingY, yloc);
xloc = Math.min(this.right - maxLabelWidth / 2 - this.options.hoverPaddingX, this.columns[index]); xloc = Math.min(this.right - maxLabelWidth / 2 - this.options.hoverPaddingX, this.data[index]._x);
xloc = Math.max(this.left + maxLabelWidth / 2 + this.options.hoverPaddingX, xloc); xloc = Math.max(this.left + maxLabelWidth / 2 + this.options.hoverPaddingX, xloc);
return this.hoverSet.attr('transform', "t" + xloc + "," + yloc); return this.hoverSet.attr('transform', "t" + xloc + "," + yloc);
}; };

2
morris.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -60,7 +60,7 @@ describe 'Morris.Line', ->
xkey: 'x' xkey: 'x'
ykeys: ['y'] ykeys: ['y']
labels: ['dontcare'] labels: ['dontcare']
chart.columnLabels.should == ['2012 Q1', '2012 Q2'] chart.data.map((x) -> x.label).should == ['2012 Q1', '2012 Q2']
it 'should use a default format for timestamp x-values', -> it 'should use a default format for timestamp x-values', ->
d1 = new Date(2012, 0, 1) d1 = new Date(2012, 0, 1)
@ -71,7 +71,7 @@ describe 'Morris.Line', ->
xkey: 'x' xkey: 'x'
ykeys: ['y'] ykeys: ['y']
labels: ['dontcare'] labels: ['dontcare']
chart.columnLabels.should == [d2.toString(), d1.toString()] chart.data.map((x) -> x.label).should == [d2.toString(), d1.toString()]
it 'should use user-defined formatters', -> it 'should use user-defined formatters', ->
d = new Date(2012, 0, 1) d = new Date(2012, 0, 1)
@ -84,4 +84,4 @@ describe 'Morris.Line', ->
dateFormat: (d) -> dateFormat: (d) ->
x = new Date(d) x = new Date(d)
"#{x.getYear()}/#{x.getMonth()+1}/#{x.getDay()}" "#{x.getYear()}/#{x.getMonth()+1}/#{x.getDay()}"
chart.columnLabels.should == ['2012/1/1', '2012/1/2'] chart.data.map((x) -> x.label).should == ['2012/1/1', '2012/1/2']