mirror of
https://github.com/morrisjs/morris.js.git
synced 2024-11-10 21:36:34 +01:00
add support for xlabelMargin and differn xlabel ([year], month, day)
This commit is contained in:
parent
3fa0ba6dff
commit
9c4ce4f236
@ -60,6 +60,8 @@ class Morris.Line
|
||||
hideHover: false
|
||||
parseTime: true
|
||||
units: ''
|
||||
xlabel: 'year'
|
||||
xlabelMargin: 50
|
||||
dateFormat: (x) -> new Date(x).toString()
|
||||
|
||||
# Do any necessary pre-processing for a new dataset
|
||||
@ -83,11 +85,12 @@ class Morris.Line
|
||||
else
|
||||
@xvals = [(@columnLabels.length-1)..0]
|
||||
# translate column labels, if they're timestamps
|
||||
@columnLabels = $.map @columnLabels, (d) =>
|
||||
if typeof d is 'number'
|
||||
@options.dateFormat(d)
|
||||
else
|
||||
d
|
||||
if @options.parseTime
|
||||
@columnLabels = $.map @columnLabels, (d) =>
|
||||
if typeof d is 'number'
|
||||
@options.dateFormat(d)
|
||||
else
|
||||
d
|
||||
@xmin = Math.min.apply null, @xvals
|
||||
@xmax = Math.max.apply null, @xvals
|
||||
if @xmin is @xmax
|
||||
@ -154,24 +157,44 @@ class Morris.Line
|
||||
|
||||
## draw x axis labels
|
||||
prevLabelMargin = null
|
||||
xLabelMargin = 50 # make this an option?
|
||||
if @options.parseTime
|
||||
x1 = new Date(@xmin).getFullYear()
|
||||
x2 = new Date(@xmax).getFullYear()
|
||||
else
|
||||
x1 = @xmin
|
||||
x2 = @xmax
|
||||
for i in [x1..x2]
|
||||
if @options.parseTime
|
||||
xpos = new Date(i, 0, 1).getTime()
|
||||
if xpos < @xmin
|
||||
continue
|
||||
xLabelMargin = @options.xlabelMargin # make this an option?
|
||||
xLabel = @options.xlabel
|
||||
nextLabel = (cur) -> # cur is a Date()
|
||||
switch xLabel
|
||||
when 'day'
|
||||
new Date(cur.getFullYear(), cur.getMonth(), cur.getDate() + 1, 0)
|
||||
when 'month'
|
||||
if cur.getMonth() == 11
|
||||
new Date(cur.getFullYear() + 1, 0, 1)
|
||||
else
|
||||
new Date(cur.getFullYear(), cur.getMonth() + 1, 1)
|
||||
else # default: year
|
||||
new Date(cur.getFullYear() + 1, 0, 1)
|
||||
startLabel = (cur) -> # cur is a Date()
|
||||
if xLabel == 'day' and cur.getHours() == 0
|
||||
cur
|
||||
else if xLabel == 'month' and cur.getDate() == 1
|
||||
cur
|
||||
else if xLabel == 'year' and cur.getDate() == 1 && cur.getMonth() == 0
|
||||
cur
|
||||
else
|
||||
xpos = i
|
||||
labelText = if @options.parseTime then i else @columnLabels[@columnLabels.length-i-1]
|
||||
label = @r.text(transX(xpos), @options.marginTop + height + @options.marginBottom / 2, labelText)
|
||||
.attr('font-size', @options.gridTextSize)
|
||||
.attr('fill', @options.gridTextColor)
|
||||
nextLabel(cur)
|
||||
labelText = (cur) -> # cur is still a Date()
|
||||
switch xLabel
|
||||
when 'day'
|
||||
d = cur.getDate().toString()
|
||||
if d.length == 2 then d else '0' + d
|
||||
when 'month'
|
||||
m = (cur.getMonth() + 1).toString()
|
||||
if m.length == 2 then m else '0' + m
|
||||
else cur.getFullYear()
|
||||
|
||||
r = @r
|
||||
options = @options
|
||||
renderLabel = (xpos, text) ->
|
||||
label = r.text(transX(xpos), options.marginTop + height + options.marginBottom / 2, text)
|
||||
.attr('font-size', options.gridTextSize)
|
||||
.attr('fill', options.gridTextColor)
|
||||
labelBox = label.getBBox()
|
||||
# ensure a minimum of `xLabelMargin` pixels between labels
|
||||
if prevLabelMargin is null or prevLabelMargin <= labelBox.x
|
||||
@ -179,6 +202,20 @@ class Morris.Line
|
||||
else
|
||||
label.remove()
|
||||
|
||||
if @options.parseTime
|
||||
start = startLabel(new Date(@xmin))
|
||||
end = new Date(@xmax)
|
||||
cur = start
|
||||
while cur <= end
|
||||
xpos = cur.getTime()
|
||||
if xpos < @xmin
|
||||
continue
|
||||
renderLabel(xpos, labelText cur)
|
||||
cur = nextLabel cur
|
||||
else
|
||||
for i in [@xmin..@xmax]
|
||||
renderLabel(i, @columnLabels[@columnLabels.length-i-1])
|
||||
|
||||
# draw the actual series
|
||||
columns = (transX(x) for x in @xvals)
|
||||
seriesCoords = []
|
||||
|
154
morris.js
154
morris.js
@ -49,6 +49,8 @@
|
||||
hideHover: false,
|
||||
parseTime: true,
|
||||
units: '',
|
||||
xlabel: 'year',
|
||||
xlabelMargin: 50,
|
||||
dateFormat: function(x) {
|
||||
return new Date(x).toString();
|
||||
}
|
||||
@ -83,13 +85,15 @@
|
||||
return _results;
|
||||
}).apply(this);
|
||||
}
|
||||
this.columnLabels = $.map(this.columnLabels, function(d) {
|
||||
if (typeof d === 'number') {
|
||||
return _this.options.dateFormat(d);
|
||||
} else {
|
||||
return d;
|
||||
}
|
||||
});
|
||||
if (this.options.parseTime) {
|
||||
this.columnLabels = $.map(this.columnLabels, function(d) {
|
||||
if (typeof d === 'number') {
|
||||
return _this.options.dateFormat(d);
|
||||
} else {
|
||||
return d;
|
||||
}
|
||||
});
|
||||
}
|
||||
this.xmin = Math.min.apply(null, this.xvals);
|
||||
this.xmax = Math.max.apply(null, this.xvals);
|
||||
if (this.xmin === this.xmax) {
|
||||
@ -115,7 +119,7 @@
|
||||
};
|
||||
|
||||
Line.prototype.redraw = function() {
|
||||
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,
|
||||
var c, circle, columns, coords, cur, dx, dy, end, firstY, height, hideHover, hilight, hover, hoverHeight, hoverMargins, hoverSet, i, labelText, lastY, left, lineY, maxYLabelWidth, nextLabel, options, path, pointGrow, pointShrink, prevHilight, prevLabelMargin, r, renderLabel, s, seriesCoords, seriesPoints, start, startLabel, touchHandler, transX, transY, updateHilight, updateHover, v, width, x, xLabel, xLabelMargin, xpos, y, yInterval, yLabel, yLabels, _i, _j, _len, _len2, _ref, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7,
|
||||
_this = this;
|
||||
this.el.empty();
|
||||
this.r = new Raphael(this.el[0]);
|
||||
@ -145,44 +149,98 @@
|
||||
this.r.path("M" + left + "," + y + 'H' + (left + width)).attr('stroke', this.options.gridLineColor).attr('stroke-width', this.options.gridStrokeWidth);
|
||||
}
|
||||
prevLabelMargin = null;
|
||||
xLabelMargin = 50;
|
||||
if (this.options.parseTime) {
|
||||
x1 = new Date(this.xmin).getFullYear();
|
||||
x2 = new Date(this.xmax).getFullYear();
|
||||
} else {
|
||||
x1 = this.xmin;
|
||||
x2 = this.xmax;
|
||||
}
|
||||
for (i = x1; x1 <= x2 ? i <= x2 : i >= x2; x1 <= x2 ? i++ : i--) {
|
||||
if (this.options.parseTime) {
|
||||
xpos = new Date(i, 0, 1).getTime();
|
||||
if (xpos < this.xmin) continue;
|
||||
} else {
|
||||
xpos = i;
|
||||
xLabelMargin = this.options.xlabelMargin;
|
||||
xLabel = this.options.xlabel;
|
||||
nextLabel = function(cur) {
|
||||
switch (xLabel) {
|
||||
case 'day':
|
||||
return new Date(cur.getFullYear(), cur.getMonth(), cur.getDate() + 1, 0);
|
||||
case 'month':
|
||||
if (cur.getMonth() === 11) {
|
||||
return new Date(cur.getFullYear() + 1, 0, 1);
|
||||
} else {
|
||||
return new Date(cur.getFullYear(), cur.getMonth() + 1, 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return new Date(cur.getFullYear() + 1, 0, 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);
|
||||
};
|
||||
startLabel = function(cur) {
|
||||
if (xLabel === 'day' && cur.getHours() === 0) {
|
||||
return cur;
|
||||
} else if (xLabel === 'month' && cur.getDate() === 1) {
|
||||
return cur;
|
||||
} else if (xLabel === 'year' && cur.getDate() === 1 && cur.getMonth() === 0) {
|
||||
return cur;
|
||||
} else {
|
||||
return nextLabel(cur);
|
||||
}
|
||||
};
|
||||
labelText = function(cur) {
|
||||
var d, m;
|
||||
switch (xLabel) {
|
||||
case 'day':
|
||||
d = cur.getDate().toString();
|
||||
if (d.length === 2) {
|
||||
return d;
|
||||
} else {
|
||||
return '0' + d;
|
||||
}
|
||||
break;
|
||||
case 'month':
|
||||
m = (cur.getMonth() + 1).toString();
|
||||
if (m.length === 2) {
|
||||
return m;
|
||||
} else {
|
||||
return '0' + m;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return cur.getFullYear();
|
||||
}
|
||||
};
|
||||
r = this.r;
|
||||
options = this.options;
|
||||
renderLabel = function(xpos, text) {
|
||||
var label, labelBox;
|
||||
label = r.text(transX(xpos), options.marginTop + height + options.marginBottom / 2, text).attr('font-size', options.gridTextSize).attr('fill', options.gridTextColor);
|
||||
labelBox = label.getBBox();
|
||||
if (prevLabelMargin === null || prevLabelMargin <= labelBox.x) {
|
||||
prevLabelMargin = labelBox.x + labelBox.width + xLabelMargin;
|
||||
return prevLabelMargin = labelBox.x + labelBox.width + xLabelMargin;
|
||||
} else {
|
||||
label.remove();
|
||||
return label.remove();
|
||||
}
|
||||
};
|
||||
if (this.options.parseTime) {
|
||||
start = startLabel(new Date(this.xmin));
|
||||
end = new Date(this.xmax);
|
||||
cur = start;
|
||||
while (cur <= end) {
|
||||
xpos = cur.getTime();
|
||||
if (xpos < this.xmin) continue;
|
||||
renderLabel(xpos, labelText(cur));
|
||||
cur = nextLabel(cur);
|
||||
}
|
||||
} else {
|
||||
for (i = _ref = this.xmin, _ref2 = this.xmax; _ref <= _ref2 ? i <= _ref2 : i >= _ref2; _ref <= _ref2 ? i++ : i--) {
|
||||
renderLabel(i, this.columnLabels[this.columnLabels.length - i - 1]);
|
||||
}
|
||||
}
|
||||
columns = (function() {
|
||||
var _i, _len, _ref, _results;
|
||||
_ref = this.xvals;
|
||||
var _i, _len, _ref3, _results;
|
||||
_ref3 = this.xvals;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
x = _ref[_i];
|
||||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
|
||||
x = _ref3[_i];
|
||||
_results.push(transX(x));
|
||||
}
|
||||
return _results;
|
||||
}).call(this);
|
||||
seriesCoords = [];
|
||||
_ref = this.series;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
s = _ref[_i];
|
||||
_ref3 = this.series;
|
||||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
|
||||
s = _ref3[_i];
|
||||
seriesCoords.push($.map(s, function(y, i) {
|
||||
return {
|
||||
x: columns[i],
|
||||
@ -190,7 +248,7 @@
|
||||
};
|
||||
}));
|
||||
}
|
||||
for (i = _ref2 = seriesCoords.length - 1; _ref2 <= 0 ? i <= 0 : i >= 0; _ref2 <= 0 ? i++ : i--) {
|
||||
for (i = _ref4 = seriesCoords.length - 1; _ref4 <= 0 ? i <= 0 : i >= 0; _ref4 <= 0 ? i++ : i--) {
|
||||
coords = seriesCoords[i];
|
||||
if (coords.length > 1) {
|
||||
path = this.createPath(coords, this.options.marginTop, left, this.options.marginTop + height, left + width);
|
||||
@ -198,17 +256,17 @@
|
||||
}
|
||||
}
|
||||
seriesPoints = (function() {
|
||||
var _ref3, _results;
|
||||
var _ref5, _results;
|
||||
_results = [];
|
||||
for (i = 0, _ref3 = seriesCoords.length - 1; 0 <= _ref3 ? i <= _ref3 : i >= _ref3; 0 <= _ref3 ? i++ : i--) {
|
||||
for (i = 0, _ref5 = seriesCoords.length - 1; 0 <= _ref5 ? i <= _ref5 : i >= _ref5; 0 <= _ref5 ? i++ : i--) {
|
||||
_results.push([]);
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
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];
|
||||
for (i = _ref5 = seriesCoords.length - 1; _ref5 <= 0 ? i <= 0 : i >= 0; _ref5 <= 0 ? i++ : i--) {
|
||||
_ref6 = seriesCoords[i];
|
||||
for (_j = 0, _len2 = _ref6.length; _j < _len2; _j++) {
|
||||
c = _ref6[_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);
|
||||
}
|
||||
@ -220,16 +278,16 @@
|
||||
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--) {
|
||||
for (i = 0, _ref7 = this.series.length - 1; 0 <= _ref7 ? i <= _ref7 : i >= _ref7; 0 <= _ref7 ? 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;
|
||||
var i, maxLabelWidth, xloc, yloc, _ref8;
|
||||
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--) {
|
||||
for (i = 0, _ref8 = _this.series.length - 1; 0 <= _ref8 ? i <= _ref8 : i >= _ref8; 0 <= _ref8 ? 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) {
|
||||
@ -266,14 +324,14 @@
|
||||
r: this.options.pointSize
|
||||
}, 25, 'linear');
|
||||
hilight = function(index) {
|
||||
var i, _ref6, _ref7;
|
||||
var i, _ref8, _ref9;
|
||||
if (prevHilight !== null && prevHilight !== index) {
|
||||
for (i = 0, _ref6 = seriesPoints.length - 1; 0 <= _ref6 ? i <= _ref6 : i >= _ref6; 0 <= _ref6 ? i++ : i--) {
|
||||
for (i = 0, _ref8 = seriesPoints.length - 1; 0 <= _ref8 ? i <= _ref8 : i >= _ref8; 0 <= _ref8 ? 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--) {
|
||||
for (i = 0, _ref9 = seriesPoints.length - 1; 0 <= _ref9 ? i <= _ref9 : i >= _ref9; 0 <= _ref9 ? i++ : i--) {
|
||||
seriesPoints[i][index].animate(pointGrow);
|
||||
}
|
||||
updateHover(index);
|
||||
@ -282,10 +340,10 @@
|
||||
if (index === null) return hideHover();
|
||||
};
|
||||
updateHilight = function(x) {
|
||||
var hoverIndex, _ref6, _results;
|
||||
var hoverIndex, _ref8, _results;
|
||||
x -= _this.el.offset().left;
|
||||
_results = [];
|
||||
for (hoverIndex = _ref6 = hoverMargins.length; _ref6 <= 0 ? hoverIndex <= 0 : hoverIndex >= 0; _ref6 <= 0 ? hoverIndex++ : hoverIndex--) {
|
||||
for (hoverIndex = _ref8 = hoverMargins.length; _ref8 <= 0 ? hoverIndex <= 0 : hoverIndex >= 0; _ref8 <= 0 ? hoverIndex++ : hoverIndex--) {
|
||||
if (hoverIndex === 0 || hoverMargins[hoverIndex - 1] > x) {
|
||||
hilight(hoverIndex);
|
||||
break;
|
||||
|
2
morris.min.js
vendored
2
morris.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user