Add xLabels option to specify x-label intervals.

Clean up whitespace (hooray for Whitespace.tmbundle!).
This commit is contained in:
Olly Smith 2012-04-02 21:27:45 +01:00
parent 2d901e04fa
commit e670a6dbee
4 changed files with 133 additions and 83 deletions

View File

@ -61,6 +61,7 @@ class Morris.Line
parseTime: true
units: ''
dateFormat: (x) -> new Date(x).toString()
xLabels: 'auto'
# Do any necessary pre-processing for a new dataset
#
@ -112,7 +113,7 @@ class Morris.Line
@options.ymin = Math.min parseInt(@options.ymin[5..], 10), ymin
else
@options.ymin = ymin
# Some instance variables for later
@pointGrow = Raphael.animation r: @options.pointSize + 3, 25, 'linear'
@pointShrink = Raphael.animation r: @options.pointSize, 25, 'linear'
@ -131,7 +132,7 @@ class Morris.Line
return touch
@el.bind 'touchstart', touchHandler
@el.bind 'touchmove', touchHandler
@el.bind 'touchend', touchHandler
@el.bind 'touchend', touchHandler
# Do any size-related calculations
#
@ -160,8 +161,8 @@ class Morris.Line
scoords.push(x: @columns[i], y: @transY(y))
@seriesCoords.push(scoords)
# calculate hover margins
@hoverMargins = $.map @columns.slice(1), (x, i) => (x + @columns[i]) / 2
@hoverMargins = $.map @columns.slice(1), (x, i) => (x + @columns[i]) / 2
# quick translation helpers
#
transX: (x) =>
@ -181,7 +182,7 @@ class Morris.Line
# the raphael drawing instance
@r = new Raphael(@el[0])
@calc()
@drawGrid()
@drawSeries()
@ -221,13 +222,19 @@ class Morris.Line
else
label.remove()
if @options.parseTime
for l in Morris.labelSeries(@xmin, @xmax, @width, xLabelMargin)
drawLabel(l[0], l[1])
if @columnLabels.length == 1 and @options.xLabels == 'auto'
# 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
# column label
drawLabel(@columnLabels[0], @xvals[0])
else
for l in Morris.labelSeries(@xmin, @xmax, @width, @options.xLabels)
drawLabel(l[0], l[1])
else
for i in [0..@columnLabels.length]
labelText = @columnLabels[@columnLabels.length - i - 1]
drawLabel(labelText, i)
# draw the data series
#
drawSeries: ->
@ -249,7 +256,7 @@ class Morris.Line
.attr('stroke-width', 1)
.attr('stroke', '#ffffff')
@seriesPoints[i].push(circle)
# create a path for a data series
#
createPath: (all_coords, top, left, bottom, right) ->
@ -334,7 +341,7 @@ class Morris.Line
xloc = Math.min @left + @width - maxLabelWidth / 2 - @options.hoverPaddingX, @columns[index]
xloc = Math.max @left + maxLabelWidth / 2 + @options.hoverPaddingX, xloc
@hoverSet.attr 'transform', "t#{xloc},#{yloc}"
hideHover: ->
@hoverSet.hide()
@ -358,7 +365,7 @@ class Morris.Line
if hoverIndex == 0 || @hoverMargins[hoverIndex - 1] > x
@hilight hoverIndex
break
measureText: (text, fontSize = 12) ->
tt = @r.text(100, 100, text).attr('font-size', fontSize)
ret = tt.getBBox()
@ -443,64 +450,73 @@ Morris.pad2 = (number) -> (if number < 10 then '0' else '') + number
# generate a series of label, timestamp pairs for x-axis labels
#
Morris.labelSeries = (dmin, dmax, pxwidth) ->
Morris.labelSeries = (dmin, dmax, pxwidth, specName) ->
ddensity = 200 * (dmax - dmin) / pxwidth # seconds per `margin` pixels
d0 = new Date(dmin)
for s in Morris.LABEL_SPECS
if ddensity >= s.span or s.span == Morris.LABEL_SPECS[Morris.LABEL_SPECS.length - 1].span
d = s.start(d0)
ret = []
while (t = d.getTime()) <= dmax
if t >= dmin
ret.push [s.fmt(d), t]
s.incr(d)
return ret
spec = Morris.LABEL_SPECS[specName]
# if the spec doesn't exist, search for the closest one in the list
if spec is undefined
for name in Morris.AUTO_LABEL_ORDER
s = Morris.LABEL_SPECS[name]
if ddensity >= s.span
spec = s
break
# if we run out of options, use second-intervals
if spec is undefined
spec = Morris.LABEL_SPECS["second"]
# calculate labels
d = spec.start(d0)
ret = []
while (t = d.getTime()) <= dmax
if t >= dmin
ret.push [spec.fmt(d), t]
spec.incr(d)
return ret
minutesSpecHelper = (interval) ->
{
span: interval * 60 * 1000
start: (d) -> new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours())
fmt: (d) -> "#{Morris.pad2(d.getHours())}:#{Morris.pad2(d.getMinutes())}"
incr: (d) -> d.setMinutes(d.getMinutes() + interval)
}
secondsSpecHelper = (interval) ->
{
span: interval * 1000
start: (d) -> new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes())
fmt: (d) -> "#{Morris.pad2(d.getHours())}:#{Morris.pad2(d.getMinutes())}:#{Morris.pad2(d.getSeconds())}"
incr: (d) -> d.setSeconds(d.getSeconds() + interval)
}
span: interval * 60 * 1000
start: (d) -> new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours())
fmt: (d) -> "#{Morris.pad2(d.getHours())}:#{Morris.pad2(d.getMinutes())}"
incr: (d) -> d.setMinutes(d.getMinutes() + interval)
Morris.LABEL_SPECS = [
{
secondsSpecHelper = (interval) ->
span: interval * 1000
start: (d) -> new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes())
fmt: (d) -> "#{Morris.pad2(d.getHours())}:#{Morris.pad2(d.getMinutes())}:#{Morris.pad2(d.getSeconds())}"
incr: (d) -> d.setSeconds(d.getSeconds() + interval)
Morris.LABEL_SPECS =
"year":
span: 17280000000 # 365 * 24 * 60 * 60 * 1000
start: (d) -> new Date(d.getFullYear(), 0, 1)
fmt: (d) -> "#{d.getFullYear()}"
incr: (d) -> d.setFullYear(d.getFullYear() + 1)
}
{
"month":
span: 2419200000 # 28 * 24 * 60 * 60 * 1000
start: (d) -> new Date(d.getFullYear(), d.getMonth(), 1)
fmt: (d) -> "#{d.getFullYear()}-#{Morris.pad2(d.getMonth() + 1)}"
incr: (d) -> d.setMonth(d.getMonth() + 1)
}
{
"day":
span: 86400000 # 24 * 60 * 60 * 1000
start: (d) -> new Date(d.getFullYear(), d.getMonth(), d.getDate())
fmt: (d) -> "#{d.getFullYear()}-#{Morris.pad2(d.getMonth() + 1)}-#{Morris.pad2(d.getDate())}"
incr: (d) -> d.setDate(d.getDate() + 1)
}
minutesSpecHelper(60)
minutesSpecHelper(30)
minutesSpecHelper(15)
minutesSpecHelper(10)
minutesSpecHelper(5)
minutesSpecHelper(1)
secondsSpecHelper(30)
secondsSpecHelper(15)
secondsSpecHelper(10)
secondsSpecHelper(5)
secondsSpecHelper(1)
"hour": minutesSpecHelper(60)
"30min": minutesSpecHelper(30)
"15min": minutesSpecHelper(15)
"10min": minutesSpecHelper(10)
"5min": minutesSpecHelper(5)
"minute": minutesSpecHelper(1)
"30sec": secondsSpecHelper(30)
"15sec": secondsSpecHelper(15)
"10sec": secondsSpecHelper(10)
"5sec": secondsSpecHelper(5)
"second": secondsSpecHelper(1)
Morris.AUTO_LABEL_ORDER = [
"year", "month", "day", "hour",
"30min", "15min", "10min", "5min", "minute",
"30sec", "15sec", "10sec", "5sec", "second"
]
window.Morris = Morris

View File

@ -56,7 +56,8 @@
units: '',
dateFormat: function(x) {
return new Date(x).toString();
}
},
xLabels: 'auto'
};
Line.prototype.precalc = function() {
@ -244,13 +245,17 @@
}
};
if (this.options.parseTime) {
_ref = Morris.labelSeries(this.xmin, this.xmax, this.width, xLabelMargin);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
l = _ref[_i];
_results.push(drawLabel(l[0], l[1]));
if (this.columnLabels.length === 1 && this.options.xLabels === 'auto') {
return drawLabel(this.columnLabels[0], this.xvals[0]);
} else {
_ref = Morris.labelSeries(this.xmin, this.xmax, this.width, this.options.xLabels);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
l = _ref[_i];
_results.push(drawLabel(l[0], l[1]));
}
return _results;
}
return _results;
} else {
_results2 = [];
for (i = 0, _ref2 = this.columnLabels.length; 0 <= _ref2 ? i <= _ref2 : i >= _ref2; 0 <= _ref2 ? i++ : i--) {
@ -493,23 +498,30 @@
return (number < 10 ? '0' : '') + number;
};
Morris.labelSeries = function(dmin, dmax, pxwidth) {
var d, d0, ddensity, ret, s, t, _i, _len, _ref;
Morris.labelSeries = function(dmin, dmax, pxwidth, specName) {
var d, d0, ddensity, name, ret, s, spec, t, _i, _len, _ref;
ddensity = 200 * (dmax - dmin) / pxwidth;
d0 = new Date(dmin);
_ref = Morris.LABEL_SPECS;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
s = _ref[_i];
if (ddensity >= s.span || s.span === Morris.LABEL_SPECS[Morris.LABEL_SPECS.length - 1].span) {
d = s.start(d0);
ret = [];
while ((t = d.getTime()) <= dmax) {
if (t >= dmin) ret.push([s.fmt(d), t]);
s.incr(d);
spec = Morris.LABEL_SPECS[specName];
if (spec === void 0) {
_ref = Morris.AUTO_LABEL_ORDER;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
name = _ref[_i];
s = Morris.LABEL_SPECS[name];
if (ddensity >= s.span) {
spec = s;
break;
}
return ret;
}
}
if (spec === void 0) spec = Morris.LABEL_SPECS["second"];
d = spec.start(d0);
ret = [];
while ((t = d.getTime()) <= dmax) {
if (t >= dmin) ret.push([spec.fmt(d), t]);
spec.incr(d);
}
return ret;
};
minutesSpecHelper = function(interval) {
@ -542,8 +554,8 @@
};
};
Morris.LABEL_SPECS = [
{
Morris.LABEL_SPECS = {
"year": {
span: 17280000000,
start: function(d) {
return new Date(d.getFullYear(), 0, 1);
@ -554,7 +566,8 @@
incr: function(d) {
return d.setFullYear(d.getFullYear() + 1);
}
}, {
},
"month": {
span: 2419200000,
start: function(d) {
return new Date(d.getFullYear(), d.getMonth(), 1);
@ -565,7 +578,8 @@
incr: function(d) {
return d.setMonth(d.getMonth() + 1);
}
}, {
},
"day": {
span: 86400000,
start: function(d) {
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
@ -576,8 +590,21 @@
incr: function(d) {
return d.setDate(d.getDate() + 1);
}
}, minutesSpecHelper(60), minutesSpecHelper(30), minutesSpecHelper(15), minutesSpecHelper(10), minutesSpecHelper(5), minutesSpecHelper(1), secondsSpecHelper(30), secondsSpecHelper(15), secondsSpecHelper(10), secondsSpecHelper(5), secondsSpecHelper(1)
];
},
"hour": minutesSpecHelper(60),
"30min": minutesSpecHelper(30),
"15min": minutesSpecHelper(15),
"10min": minutesSpecHelper(10),
"5min": minutesSpecHelper(5),
"minute": minutesSpecHelper(1),
"30sec": secondsSpecHelper(30),
"15sec": secondsSpecHelper(15),
"10sec": secondsSpecHelper(10),
"5sec": secondsSpecHelper(5),
"second": secondsSpecHelper(1)
};
Morris.AUTO_LABEL_ORDER = ["year", "month", "day", "hour", "30min", "15min", "10min", "5min", "minute", "30sec", "15sec", "10sec", "5sec", "second"];
window.Morris = Morris;

2
morris.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -40,7 +40,7 @@
equal(Morris.commas(-123.456), "-123.456", "commas(-123.456) = -123.456")
equal(Morris.commas(-1234.56), "-1,234.56", "commas(-1234.56) = -1,234.56")
});
test("Morris.pad2", function () {
equal(Morris.pad2(0), "00", "pad2(0) = 0")
equal(Morris.pad2(1), "01", "pad2(1) = 1")
@ -57,10 +57,10 @@
equal(Morris.pad2(34), "34", "pad2(34) = 34")
equal(Morris.pad2(123), "123", "pad2(123) = 123")
});
test("Morris.labelSeries", function () {
var expected = [
[
[
new Date(2007, 0, 1).getTime(),
new Date(2012, 0, 1).getTime(),
[["2007", new Date(2007, 0, 1).getTime()],
@ -156,8 +156,15 @@
ret = expected[i][2];
deepEqual(Morris.labelSeries(dmin, dmax, 1000), ret);
}
// test interval override
deepEqual(
Morris.labelSeries(
new Date(2011, 11, 12).getTime(),
new Date(2012, 0, 12).getTime(),
1000, "year"),
[["2012", new Date(2012, 0, 1).getTime()]]);
});
test("Morris.parseDate", function () {
equal(Morris.parseDate("2012"), new Date(2012, 0, 1).getTime());
equal(Morris.parseDate("2012 Q1"), new Date(2012, 2, 1).getTime());
@ -179,7 +186,7 @@
});
});
</script>
</head>
<body>
<h1 id="qunit-header">Morris.js tests</h1>