diff --git a/morris.coffee b/morris.coffee
index 79b9eba..6f452ec 100644
--- a/morris.coffee
+++ b/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
diff --git a/morris.js b/morris.js
index e9220aa..0362eb0 100644
--- a/morris.js
+++ b/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;
diff --git a/morris.min.js b/morris.min.js
index de1122b..0030759 100644
--- a/morris.min.js
+++ b/morris.min.js
@@ -1 +1 @@
-(function(){var a,b,c,d,e=function(a,b){return function(){return a.apply(b,arguments)}};a=jQuery,b={},b.Line=function(){function c(c){this.updateHilight=e(this.updateHilight,this),this.hilight=e(this.hilight,this),this.updateHover=e(this.updateHover,this),this.transY=e(this.transY,this),this.transX=e(this.transX,this);if(!(this instanceof b.Line))return new b.Line(c);typeof c.element=="string"?this.el=a(document.getElementById(c.element)):this.el=a(c.element),this.options=a.extend({},this.defaults,c);if(this.options.data===void 0||this.options.data.length===0)return;this.el.addClass("graph-initialised"),this.precalc(),this.redraw()}return c.prototype.defaults={lineWidth:3,pointSize:4,lineColors:["#0b62a4","#7A92A3","#4da74d","#afd8f8","#edc240","#cb4b4b","#9440ed"],ymax:"auto",ymin:"auto 0",marginTop:25,marginRight:25,marginBottom:30,marginLeft:25,numLines:5,gridLineColor:"#aaa",gridTextColor:"#888",gridTextSize:12,gridStrokeWidth:.5,hoverPaddingX:10,hoverPaddingY:5,hoverMargin:10,hoverFillColor:"#fff",hoverBorderColor:"#ccc",hoverBorderWidth:2,hoverOpacity:.95,hoverLabelColor:"#444",hoverFontSize:12,smooth:!0,hideHover:!1,parseTime:!0,units:"",dateFormat:function(a){return(new Date(a)).toString()}},c.prototype.precalc=function(){var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r=this;this.options.data.sort(function(a,b){return(a[r.options.xkey]=0;p<=0?a++:a--)q.push(a);return q}.apply(this),this.options.parseTime&&(this.columnLabels=a.map(this.columnLabels,function(a){return typeof a=="number"?r.options.dateFormat(a):a})),this.xmin=Math.min.apply(null,this.xvals),this.xmax=Math.max.apply(null,this.xvals),this.xmin===this.xmax&&(this.xmin-=1,this.xmax+=1),typeof this.options.ymax=="string"&&this.options.ymax.slice(0,4)==="auto"&&(g=Math.max.apply(null,Array.prototype.concat.apply([],this.series)),this.options.ymax.length>5?this.options.ymax=Math.max(parseInt(this.options.ymax.slice(5),10),g):this.options.ymax=g),typeof this.options.ymin=="string"&&this.options.ymin.slice(0,4)==="auto"&&(h=Math.min.apply(null,Array.prototype.concat.apply([],this.series)),this.options.ymin.length>5?this.options.ymin=Math.min(parseInt(this.options.ymin.slice(5),10),h):this.options.ymin=h),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(a){return r.updateHilight(a.pageX)}),this.options.hideHover&&this.el.mouseout(function(a){return r.hilight(null)}),e=function(a){var b;return b=a.originalEvent.touches[0]||a.originalEvent.changedTouches[0],r.updateHilight(b.pageX),b},this.el.bind("touchstart",e),this.el.bind("touchmove",e),this.el.bind("touchend",e)},c.prototype.calc=function(){var b,c,d,e,f,g,h,i,j=this;e=this.el.width(),b=this.el.height();if(this.elementWidth!==e||this.elementHeight!==b){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 a,b,c,d;c=this.xvals,d=[];for(a=0,b=c.length;a=g;h+=m)j=Math.floor(h),l=this.transY(j),this.r.text(this.left-this.options.marginLeft/2,l,b.commas(j)+this.options.units).attr("font-size",this.options.gridTextSize).attr("fill",this.options.gridTextColor).attr("text-anchor","end"),this.r.path("M"+this.left+","+l+"H"+(this.left+this.width)).attr("stroke",this.options.gridLineColor).attr("stroke-width",this.options.gridStrokeWidth);n=this.options.marginTop+this.height+this.options.marginBottom/2,k=50,i=null,a=function(a,b){var c,d;return c=u.r.text(u.transX(b),n,a).attr("font-size",u.options.gridTextSize).attr("fill",u.options.gridTextColor),d=c.getBBox(),i===null||i<=d.x?i=d.x+d.width+k:c.remove()};if(this.options.parseTime){q=b.labelSeries(this.xmin,this.xmax,this.width,k),s=[];for(o=0,p=q.length;o
=r;0<=r?d++:d--)f=this.columnLabels[this.columnLabels.length-d-1],t.push(a(f,d));return t},c.prototype.drawSeries=function(){var a,b,c,d,e,f,g,h;for(d=f=this.seriesCoords.length-1;f<=0?d<=0:d>=0;f<=0?d++:d--)c=this.seriesCoords[d],c.length>1&&(e=this.createPath(c,this.options.marginTop,this.left,this.options.marginTop+this.height,this.left+this.width),this.r.path(e).attr("stroke",this.options.lineColors[d]).attr("stroke-width",this.options.lineWidth));this.seriesPoints=function(){var a,b;b=[];for(d=0,a=this.seriesCoords.length-1;0<=a?d<=a:d>=a;0<=a?d++:d--)b.push([]);return b}.call(this),h=[];for(d=g=this.seriesCoords.length-1;g<=0?d<=0:d>=0;g<=0?d++:d--)h.push(function(){var c,e,f,g;f=this.seriesCoords[d],g=[];for(c=0,e=f.length;c=t;0<=t?k++:k--)g=h[k],k===0?o+="M"+g.x+","+g.y:(i=j[k],m=h[k-1],n=j[k-1],l=(g.x-m.x)/4,p=m.x+l,r=Math.min(e,m.y+l*n),q=g.x-l,s=Math.min(e,g.y-l*i),o+="C"+p+","+r+","+q+","+s+","+g.x+","+g.y)}else o="M"+a.map(h,function(a){return""+a.x+","+a.y}).join("L");return o},c.prototype.gradients=function(b){return a.map(b,function(a,c){return c===0?(b[1].y-a.y)/(b[1].x-a.x):c===b.length-1?(a.y-b[c-1].y)/(a.x-b[c-1].x):(b[c+1].y-b[c-1].y)/(b[c+1].x-b[c-1].x)})},c.prototype.drawHover=function(){var a,b,c,d;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*.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=[],d=[];for(a=0,c=this.series.length-1;0<=c?a<=c:a>=c;0<=c?a++:a--)b=this.r.text(0,this.options.hoverFontSize*1.5*(a+1.5)-this.hoverHeight/2,"").attr("fill",this.options.lineColors[a]).attr("font-size",this.options.hoverFontSize),this.yLabels.push(b),d.push(this.hoverSet.push(b));return d},c.prototype.updateHover=function(c){var d,e,f,g,h,i=this;this.hoverSet.show(),this.xLabel.attr("text",this.columnLabels[c]);for(d=0,h=this.series.length-1;0<=h?d<=h:d>=h;0<=h?d++:d--)this.yLabels[d].attr("text",""+this.seriesLabels[d]+": "+b.commas(this.series[d][c])+this.options.units);return e=Math.max.apply(null,a.map(this.yLabels,function(a){return a.getBBox().width})),e=Math.max(e,this.xLabel.getBBox().width),this.hover.attr("width",e+this.options.hoverPaddingX*2),this.hover.attr("x",-this.options.hoverPaddingX-e/2),g=Math.min.apply(null,a.map(this.series,function(a){return i.transY(a[c])})),g>this.hoverHeight+this.options.hoverPaddingY*2+this.options.hoverMargin+this.options.marginTop?g=g-this.hoverHeight/2-this.options.hoverPaddingY-this.options.hoverMargin:g=g+this.hoverHeight/2+this.options.hoverPaddingY+this.options.hoverMargin,g=Math.max(this.options.marginTop+this.hoverHeight/2+this.options.hoverPaddingY,g),g=Math.min(this.options.marginTop+this.height-this.hoverHeight/2-this.options.hoverPaddingY,g),f=Math.min(this.left+this.width-e/2-this.options.hoverPaddingX,this.columns[c]),f=Math.max(this.left+e/2+this.options.hoverPaddingX,f),this.hoverSet.attr("transform","t"+f+","+g)},c.prototype.hideHover=function(){return this.hoverSet.hide()},c.prototype.hilight=function(a){var b,c,d;if(this.prevHilight!==null&&this.prevHilight!==a)for(b=0,c=this.seriesPoints.length-1;0<=c?b<=c:b>=c;0<=c?b++:b--)this.seriesPoints[b][this.prevHilight]&&this.seriesPoints[b][this.prevHilight].animate(this.pointShrink);if(a!==null&&this.prevHilight!==a){for(b=0,d=this.seriesPoints.length-1;0<=d?b<=d:b>=d;0<=d?b++:b--)this.seriesPoints[b][a]&&this.seriesPoints[b][a].animate(this.pointGrow);this.updateHover(a)}this.prevHilight=a;if(a===null)return this.hideHover()},c.prototype.updateHilight=function(a){var b,c,d;a-=this.el.offset().left,d=[];for(b=c=this.hoverMargins.length;c<=0?b<=0:b>=0;c<=0?b++:b--){if(b===0||this.hoverMargins[b-1]>a){this.hilight(b);break}d.push(void 0)}return d},c.prototype.measureText=function(a,b){var c,d;return b==null&&(b=12),d=this.r.text(100,100,a).attr("font-size",b),c=d.getBBox(),d.remove(),c},c}(),b.parseDate=function(a){var b,c,d,e,f,g,h,i,j,k;return typeof a=="number"?a:(c=a.match(/^(\d+) Q(\d)$/),e=a.match(/^(\d+)-(\d+)$/),f=a.match(/^(\d+)-(\d+)-(\d+)$/),g=a.match(/^(\d+) W(\d+)$/),h=a.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)Z?$/),i=a.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)Z?$/),c?(new Date(parseInt(c[1],10),parseInt(c[2],10)*3-1,1)).getTime():e?(new Date(parseInt(e[1],10),parseInt(e[2],10)-1,1)).getTime():f?(new Date(parseInt(f[1],10),parseInt(f[2],10)-1,parseInt(f[3],10))).getTime():g?(j=new Date(parseInt(g[1],10),0,1),j.getDay()!==4&&j.setMonth(0,1+(4-j.getDay()+7)%7),j.getTime()+parseInt(g[2],10)*6048e5):h?(new Date(parseInt(h[1],10),parseInt(h[2],10)-1,parseInt(h[3],10),parseInt(h[4],10),parseInt(h[5],10))).getTime():i?(k=parseFloat(i[6]),b=Math.floor(k),d=Math.round((k-b)*1e3),(new Date(parseInt(i[1],10),parseInt(i[2],10)-1,parseInt(i[3],10),parseInt(i[4],10),parseInt(i[5],10),b,d)).getTime()):(new Date(parseInt(a,10),0,1)).getTime())},b.commas=function(a){var b,c,d,e;return a===null?"n/a":(d=a<0?"-":"",b=Math.abs(a),c=Math.floor(b).toFixed(0),d+=c.replace(/(?=(?:\d{3})+$)(?!^)/g,","),e=b.toString(),e.length>c.length&&(d+=e.slice(c.length)),d)},b.pad2=function(a){return(a<10?"0":"")+a},b.labelSeries=function(a,c,d){var e,f,g,h,i,j,k,l,m;g=200*(c-a)/d,f=new Date(a),m=b.LABEL_SPECS;for(k=0,l=m.length;k=i.span||i.span===b.LABEL_SPECS[b.LABEL_SPECS.length-1].span){e=i.start(f),h=[];while((j=e.getTime())<=c)j>=a&&h.push([i.fmt(e),j]),i.incr(e);return h}}},c=function(a){return{span:a*60*1e3,start:function(a){return new Date(a.getFullYear(),a.getMonth(),a.getDate(),a.getHours())},fmt:function(a){return""+b.pad2(a.getHours())+":"+b.pad2(a.getMinutes())},incr:function(b){return b.setMinutes(b.getMinutes()+a)}}},d=function(a){return{span:a*1e3,start:function(a){return new Date(a.getFullYear(),a.getMonth(),a.getDate(),a.getHours(),a.getMinutes())},fmt:function(a){return""+b.pad2(a.getHours())+":"+b.pad2(a.getMinutes())+":"+b.pad2(a.getSeconds())},incr:function(b){return b.setSeconds(b.getSeconds()+a)}}},b.LABEL_SPECS=[{span:1728e7,start:function(a){return new Date(a.getFullYear(),0,1)},fmt:function(a){return""+a.getFullYear()},incr:function(a){return a.setFullYear(a.getFullYear()+1)}},{span:24192e5,start:function(a){return new Date(a.getFullYear(),a.getMonth(),1)},fmt:function(a){return""+a.getFullYear()+"-"+b.pad2(a.getMonth()+1)},incr:function(a){return a.setMonth(a.getMonth()+1)}},{span:864e5,start:function(a){return new Date(a.getFullYear(),a.getMonth(),a.getDate())},fmt:function(a){return""+a.getFullYear()+"-"+b.pad2(a.getMonth()+1)+"-"+b.pad2(a.getDate())},incr:function(a){return a.setDate(a.getDate()+1)}},c(60),c(30),c(15),c(10),c(5),c(1),d(30),d(15),d(10),d(5),d(1)],window.Morris=b}).call(this);
\ No newline at end of file
+(function(){var a,b,c,d,e=function(a,b){return function(){return a.apply(b,arguments)}};a=jQuery,b={},b.Line=function(){function c(c){this.updateHilight=e(this.updateHilight,this),this.hilight=e(this.hilight,this),this.updateHover=e(this.updateHover,this),this.transY=e(this.transY,this),this.transX=e(this.transX,this);if(!(this instanceof b.Line))return new b.Line(c);typeof c.element=="string"?this.el=a(document.getElementById(c.element)):this.el=a(c.element),this.options=a.extend({},this.defaults,c);if(this.options.data===void 0||this.options.data.length===0)return;this.el.addClass("graph-initialised"),this.precalc(),this.redraw()}return c.prototype.defaults={lineWidth:3,pointSize:4,lineColors:["#0b62a4","#7A92A3","#4da74d","#afd8f8","#edc240","#cb4b4b","#9440ed"],ymax:"auto",ymin:"auto 0",marginTop:25,marginRight:25,marginBottom:30,marginLeft:25,numLines:5,gridLineColor:"#aaa",gridTextColor:"#888",gridTextSize:12,gridStrokeWidth:.5,hoverPaddingX:10,hoverPaddingY:5,hoverMargin:10,hoverFillColor:"#fff",hoverBorderColor:"#ccc",hoverBorderWidth:2,hoverOpacity:.95,hoverLabelColor:"#444",hoverFontSize:12,smooth:!0,hideHover:!1,parseTime:!0,units:"",dateFormat:function(a){return(new Date(a)).toString()},xLabels:"auto"},c.prototype.precalc=function(){var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r=this;this.options.data.sort(function(a,b){return(a[r.options.xkey]=0;p<=0?a++:a--)q.push(a);return q}.apply(this),this.options.parseTime&&(this.columnLabels=a.map(this.columnLabels,function(a){return typeof a=="number"?r.options.dateFormat(a):a})),this.xmin=Math.min.apply(null,this.xvals),this.xmax=Math.max.apply(null,this.xvals),this.xmin===this.xmax&&(this.xmin-=1,this.xmax+=1),typeof this.options.ymax=="string"&&this.options.ymax.slice(0,4)==="auto"&&(g=Math.max.apply(null,Array.prototype.concat.apply([],this.series)),this.options.ymax.length>5?this.options.ymax=Math.max(parseInt(this.options.ymax.slice(5),10),g):this.options.ymax=g),typeof this.options.ymin=="string"&&this.options.ymin.slice(0,4)==="auto"&&(h=Math.min.apply(null,Array.prototype.concat.apply([],this.series)),this.options.ymin.length>5?this.options.ymin=Math.min(parseInt(this.options.ymin.slice(5),10),h):this.options.ymin=h),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(a){return r.updateHilight(a.pageX)}),this.options.hideHover&&this.el.mouseout(function(a){return r.hilight(null)}),e=function(a){var b;return b=a.originalEvent.touches[0]||a.originalEvent.changedTouches[0],r.updateHilight(b.pageX),b},this.el.bind("touchstart",e),this.el.bind("touchmove",e),this.el.bind("touchend",e)},c.prototype.calc=function(){var b,c,d,e,f,g,h,i,j=this;e=this.el.width(),b=this.el.height();if(this.elementWidth!==e||this.elementHeight!==b){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 a,b,c,d;c=this.xvals,d=[];for(a=0,b=c.length;a=g;h+=m)j=Math.floor(h),l=this.transY(j),this.r.text(this.left-this.options.marginLeft/2,l,b.commas(j)+this.options.units).attr("font-size",this.options.gridTextSize).attr("fill",this.options.gridTextColor).attr("text-anchor","end"),this.r.path("M"+this.left+","+l+"H"+(this.left+this.width)).attr("stroke",this.options.gridLineColor).attr("stroke-width",this.options.gridStrokeWidth);n=this.options.marginTop+this.height+this.options.marginBottom/2,k=50,i=null,a=function(a,b){var c,d;return c=u.r.text(u.transX(b),n,a).attr("font-size",u.options.gridTextSize).attr("fill",u.options.gridTextColor),d=c.getBBox(),i===null||i<=d.x?i=d.x+d.width+k:c.remove()};if(this.options.parseTime){if(this.columnLabels.length===1&&this.options.xLabels==="auto")return a(this.columnLabels[0],this.xvals[0]);q=b.labelSeries(this.xmin,this.xmax,this.width,this.options.xLabels),s=[];for(o=0,p=q.length;o=r;0<=r?d++:d--)f=this.columnLabels[this.columnLabels.length-d-1],t.push(a(f,d));return t},c.prototype.drawSeries=function(){var a,b,c,d,e,f,g,h;for(d=f=this.seriesCoords.length-1;f<=0?d<=0:d>=0;f<=0?d++:d--)c=this.seriesCoords[d],c.length>1&&(e=this.createPath(c,this.options.marginTop,this.left,this.options.marginTop+this.height,this.left+this.width),this.r.path(e).attr("stroke",this.options.lineColors[d]).attr("stroke-width",this.options.lineWidth));this.seriesPoints=function(){var a,b;b=[];for(d=0,a=this.seriesCoords.length-1;0<=a?d<=a:d>=a;0<=a?d++:d--)b.push([]);return b}.call(this),h=[];for(d=g=this.seriesCoords.length-1;g<=0?d<=0:d>=0;g<=0?d++:d--)h.push(function(){var c,e,f,g;f=this.seriesCoords[d],g=[];for(c=0,e=f.length;c=t;0<=t?k++:k--)g=h[k],k===0?o+="M"+g.x+","+g.y:(i=j[k],m=h[k-1],n=j[k-1],l=(g.x-m.x)/4,p=m.x+l,r=Math.min(e,m.y+l*n),q=g.x-l,s=Math.min(e,g.y-l*i),o+="C"+p+","+r+","+q+","+s+","+g.x+","+g.y)}else o="M"+a.map(h,function(a){return""+a.x+","+a.y}).join("L");return o},c.prototype.gradients=function(b){return a.map(b,function(a,c){return c===0?(b[1].y-a.y)/(b[1].x-a.x):c===b.length-1?(a.y-b[c-1].y)/(a.x-b[c-1].x):(b[c+1].y-b[c-1].y)/(b[c+1].x-b[c-1].x)})},c.prototype.drawHover=function(){var a,b,c,d;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*.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=[],d=[];for(a=0,c=this.series.length-1;0<=c?a<=c:a>=c;0<=c?a++:a--)b=this.r.text(0,this.options.hoverFontSize*1.5*(a+1.5)-this.hoverHeight/2,"").attr("fill",this.options.lineColors[a]).attr("font-size",this.options.hoverFontSize),this.yLabels.push(b),d.push(this.hoverSet.push(b));return d},c.prototype.updateHover=function(c){var d,e,f,g,h,i=this;this.hoverSet.show(),this.xLabel.attr("text",this.columnLabels[c]);for(d=0,h=this.series.length-1;0<=h?d<=h:d>=h;0<=h?d++:d--)this.yLabels[d].attr("text",""+this.seriesLabels[d]+": "+b.commas(this.series[d][c])+this.options.units);return e=Math.max.apply(null,a.map(this.yLabels,function(a){return a.getBBox().width})),e=Math.max(e,this.xLabel.getBBox().width),this.hover.attr("width",e+this.options.hoverPaddingX*2),this.hover.attr("x",-this.options.hoverPaddingX-e/2),g=Math.min.apply(null,a.map(this.series,function(a){return i.transY(a[c])})),g>this.hoverHeight+this.options.hoverPaddingY*2+this.options.hoverMargin+this.options.marginTop?g=g-this.hoverHeight/2-this.options.hoverPaddingY-this.options.hoverMargin:g=g+this.hoverHeight/2+this.options.hoverPaddingY+this.options.hoverMargin,g=Math.max(this.options.marginTop+this.hoverHeight/2+this.options.hoverPaddingY,g),g=Math.min(this.options.marginTop+this.height-this.hoverHeight/2-this.options.hoverPaddingY,g),f=Math.min(this.left+this.width-e/2-this.options.hoverPaddingX,this.columns[c]),f=Math.max(this.left+e/2+this.options.hoverPaddingX,f),this.hoverSet.attr("transform","t"+f+","+g)},c.prototype.hideHover=function(){return this.hoverSet.hide()},c.prototype.hilight=function(a){var b,c,d;if(this.prevHilight!==null&&this.prevHilight!==a)for(b=0,c=this.seriesPoints.length-1;0<=c?b<=c:b>=c;0<=c?b++:b--)this.seriesPoints[b][this.prevHilight]&&this.seriesPoints[b][this.prevHilight].animate(this.pointShrink);if(a!==null&&this.prevHilight!==a){for(b=0,d=this.seriesPoints.length-1;0<=d?b<=d:b>=d;0<=d?b++:b--)this.seriesPoints[b][a]&&this.seriesPoints[b][a].animate(this.pointGrow);this.updateHover(a)}this.prevHilight=a;if(a===null)return this.hideHover()},c.prototype.updateHilight=function(a){var b,c,d;a-=this.el.offset().left,d=[];for(b=c=this.hoverMargins.length;c<=0?b<=0:b>=0;c<=0?b++:b--){if(b===0||this.hoverMargins[b-1]>a){this.hilight(b);break}d.push(void 0)}return d},c.prototype.measureText=function(a,b){var c,d;return b==null&&(b=12),d=this.r.text(100,100,a).attr("font-size",b),c=d.getBBox(),d.remove(),c},c}(),b.parseDate=function(a){var b,c,d,e,f,g,h,i,j,k;return typeof a=="number"?a:(c=a.match(/^(\d+) Q(\d)$/),e=a.match(/^(\d+)-(\d+)$/),f=a.match(/^(\d+)-(\d+)-(\d+)$/),g=a.match(/^(\d+) W(\d+)$/),h=a.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)Z?$/),i=a.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)Z?$/),c?(new Date(parseInt(c[1],10),parseInt(c[2],10)*3-1,1)).getTime():e?(new Date(parseInt(e[1],10),parseInt(e[2],10)-1,1)).getTime():f?(new Date(parseInt(f[1],10),parseInt(f[2],10)-1,parseInt(f[3],10))).getTime():g?(j=new Date(parseInt(g[1],10),0,1),j.getDay()!==4&&j.setMonth(0,1+(4-j.getDay()+7)%7),j.getTime()+parseInt(g[2],10)*6048e5):h?(new Date(parseInt(h[1],10),parseInt(h[2],10)-1,parseInt(h[3],10),parseInt(h[4],10),parseInt(h[5],10))).getTime():i?(k=parseFloat(i[6]),b=Math.floor(k),d=Math.round((k-b)*1e3),(new Date(parseInt(i[1],10),parseInt(i[2],10)-1,parseInt(i[3],10),parseInt(i[4],10),parseInt(i[5],10),b,d)).getTime()):(new Date(parseInt(a,10),0,1)).getTime())},b.commas=function(a){var b,c,d,e;return a===null?"n/a":(d=a<0?"-":"",b=Math.abs(a),c=Math.floor(b).toFixed(0),d+=c.replace(/(?=(?:\d{3})+$)(?!^)/g,","),e=b.toString(),e.length>c.length&&(d+=e.slice(c.length)),d)},b.pad2=function(a){return(a<10?"0":"")+a},b.labelSeries=function(a,c,d,e){var f,g,h,i,j,k,l,m,n,o,p;h=200*(c-a)/d,g=new Date(a),l=b.LABEL_SPECS[e];if(l===void 0){p=b.AUTO_LABEL_ORDER;for(n=0,o=p.length;n=k.span){l=k;break}}}l===void 0&&(l=b.LABEL_SPECS.second),f=l.start(g),j=[];while((m=f.getTime())<=c)m>=a&&j.push([l.fmt(f),m]),l.incr(f);return j},c=function(a){return{span:a*60*1e3,start:function(a){return new Date(a.getFullYear(),a.getMonth(),a.getDate(),a.getHours())},fmt:function(a){return""+b.pad2(a.getHours())+":"+b.pad2(a.getMinutes())},incr:function(b){return b.setMinutes(b.getMinutes()+a)}}},d=function(a){return{span:a*1e3,start:function(a){return new Date(a.getFullYear(),a.getMonth(),a.getDate(),a.getHours(),a.getMinutes())},fmt:function(a){return""+b.pad2(a.getHours())+":"+b.pad2(a.getMinutes())+":"+b.pad2(a.getSeconds())},incr:function(b){return b.setSeconds(b.getSeconds()+a)}}},b.LABEL_SPECS={year:{span:1728e7,start:function(a){return new Date(a.getFullYear(),0,1)},fmt:function(a){return""+a.getFullYear()},incr:function(a){return a.setFullYear(a.getFullYear()+1)}},month:{span:24192e5,start:function(a){return new Date(a.getFullYear(),a.getMonth(),1)},fmt:function(a){return""+a.getFullYear()+"-"+b.pad2(a.getMonth()+1)},incr:function(a){return a.setMonth(a.getMonth()+1)}},day:{span:864e5,start:function(a){return new Date(a.getFullYear(),a.getMonth(),a.getDate())},fmt:function(a){return""+a.getFullYear()+"-"+b.pad2(a.getMonth()+1)+"-"+b.pad2(a.getDate())},incr:function(a){return a.setDate(a.getDate()+1)}},hour:c(60),"30min":c(30),"15min":c(15),"10min":c(10),"5min":c(5),minute:c(1),"30sec":d(30),"15sec":d(15),"10sec":d(10),"5sec":d(5),second:d(1)},b.AUTO_LABEL_ORDER=["year","month","day","hour","30min","15min","10min","5min","minute","30sec","15sec","10sec","5sec","second"],window.Morris=b}).call(this);
\ No newline at end of file
diff --git a/test/test.html b/test/test.html
index ababc08..3d51404 100644
--- a/test/test.html
+++ b/test/test.html
@@ -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 @@
});
});
-
+