mirror of
https://github.com/morrisjs/morris.js.git
synced 2024-11-10 21:36:34 +01:00
Add xLabels
option to specify x-label intervals.
Clean up whitespace (hooray for Whitespace.tmbundle!).
This commit is contained in:
parent
2d901e04fa
commit
e670a6dbee
120
morris.coffee
120
morris.coffee
@ -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
|
||||
|
77
morris.js
77
morris.js
@ -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
2
morris.min.js
vendored
File diff suppressed because one or more lines are too long
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user