From bde431ac34e2a9e3e3662f1b5af2c6666a205743 Mon Sep 17 00:00:00 2001 From: Olly Smith Date: Sun, 18 Mar 2012 19:50:40 +0000 Subject: [PATCH] Merge prettifylabels() into commas(). Stop parsing times for labels when @options.parseTime is false. Tweak examples to show partial data series support. --- examples/quarters.html | 26 +-- examples/weeks.html | 26 +-- morris.coffee | 39 ++-- morris.js | 443 ++++++++++++++++++++++++----------------- morris.min.js | 2 +- 5 files changed, 306 insertions(+), 230 deletions(-) diff --git a/examples/quarters.html b/examples/quarters.html index 7e928fa..e1d95b7 100644 --- a/examples/quarters.html +++ b/examples/quarters.html @@ -28,19 +28,19 @@ var quarter_data = [ {"period": "2008 Q4", "licensed": 3155, "sorned": 681}, {"period": "2008 Q3", "licensed": 3190, "sorned": 667}, {"period": "2007 Q4", "licensed": 3226, "sorned": 620}, - {"period": "2006 Q4", "licensed": 3245, "sorned": 0}, - {"period": "2005 Q4", "licensed": 3289, "sorned": 0}, - {"period": "2004 Q4", "licensed": 3263, "sorned": 0}, - {"period": "2003 Q4", "licensed": 3189, "sorned": 0}, - {"period": "2002 Q4", "licensed": 3079, "sorned": 0}, - {"period": "2001 Q4", "licensed": 3085, "sorned": 0}, - {"period": "2000 Q4", "licensed": 3055, "sorned": 0}, - {"period": "1999 Q4", "licensed": 3063, "sorned": 0}, - {"period": "1998 Q4", "licensed": 2943, "sorned": 0}, - {"period": "1997 Q4", "licensed": 2806, "sorned": 0}, - {"period": "1996 Q4", "licensed": 2674, "sorned": 0}, - {"period": "1995 Q4", "licensed": 1702, "sorned": 0}, - {"period": "1994 Q4", "licensed": 1732, "sorned": 0} + {"period": "2006 Q4", "licensed": 3245, "sorned": null}, + {"period": "2005 Q4", "licensed": 3289, "sorned": null}, + {"period": "2004 Q4", "licensed": 3263, "sorned": null}, + {"period": "2003 Q4", "licensed": 3189, "sorned": null}, + {"period": "2002 Q4", "licensed": 3079, "sorned": null}, + {"period": "2001 Q4", "licensed": 3085, "sorned": null}, + {"period": "2000 Q4", "licensed": 3055, "sorned": null}, + {"period": "1999 Q4", "licensed": 3063, "sorned": null}, + {"period": "1998 Q4", "licensed": 2943, "sorned": null}, + {"period": "1997 Q4", "licensed": 2806, "sorned": null}, + {"period": "1996 Q4", "licensed": 2674, "sorned": null}, + {"period": "1995 Q4", "licensed": 1702, "sorned": null}, + {"period": "1994 Q4", "licensed": 1732, "sorned": null} ]; Morris.Line({ element: 'graph', diff --git a/examples/weeks.html b/examples/weeks.html index f2db24d..0e3943f 100644 --- a/examples/weeks.html +++ b/examples/weeks.html @@ -27,19 +27,19 @@ var week_data = [ {"period": "2011 W16", "licensed": 3155, "sorned": 681}, {"period": "2011 W15", "licensed": 3190, "sorned": 667}, {"period": "2011 W14", "licensed": 3226, "sorned": 620}, - {"period": "2011 W13", "licensed": 3245, "sorned": 0}, - {"period": "2011 W12", "licensed": 3289, "sorned": 0}, - {"period": "2011 W11", "licensed": 3263, "sorned": 0}, - {"period": "2011 W10", "licensed": 3189, "sorned": 0}, - {"period": "2011 W09", "licensed": 3079, "sorned": 0}, - {"period": "2011 W08", "licensed": 3085, "sorned": 0}, - {"period": "2011 W07", "licensed": 3055, "sorned": 0}, - {"period": "2011 W06", "licensed": 3063, "sorned": 0}, - {"period": "2011 W05", "licensed": 2943, "sorned": 0}, - {"period": "2011 W04", "licensed": 2806, "sorned": 0}, - {"period": "2011 W03", "licensed": 2674, "sorned": 0}, - {"period": "2011 W02", "licensed": 1702, "sorned": 0}, - {"period": "2011 W01", "licensed": 1732, "sorned": 0} + {"period": "2011 W13", "licensed": 3245, "sorned": null}, + {"period": "2011 W12", "licensed": 3289, "sorned": null}, + {"period": "2011 W11", "licensed": 3263, "sorned": null}, + {"period": "2011 W10", "licensed": 3189, "sorned": null}, + {"period": "2011 W09", "licensed": 3079, "sorned": null}, + {"period": "2011 W08", "licensed": 3085, "sorned": null}, + {"period": "2011 W07", "licensed": 3055, "sorned": null}, + {"period": "2011 W06", "licensed": 3063, "sorned": null}, + {"period": "2011 W05", "licensed": 2943, "sorned": null}, + {"period": "2011 W04", "licensed": 2806, "sorned": null}, + {"period": "2011 W03", "licensed": 2674, "sorned": null}, + {"period": "2011 W02", "licensed": 1702, "sorned": null}, + {"period": "2011 W01", "licensed": 1732, "sorned": null} ]; Morris.Line({ element: 'graph', diff --git a/morris.coffee b/morris.coffee index 6f49c35..79f94a0 100644 --- a/morris.coffee +++ b/morris.coffee @@ -86,11 +86,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 @@ -197,7 +198,7 @@ class Morris.Line for lineY in [firstY..lastY] by yInterval v = Math.floor(lineY) y = @transY(v) - @r.text(@left - @options.marginLeft/2, y, v + @options.units) + @r.text(@left - @options.marginLeft/2, y, @commas(v) + @options.units) .attr('font-size', @options.gridTextSize) .attr('fill', @options.gridTextColor) .attr('text-anchor', 'end') @@ -319,7 +320,7 @@ class Morris.Line @hoverSet.show() @xLabel.attr('text', @columnLabels[index]) for i in [0..@series.length-1] - @yLabels[i].attr('text', "#{@seriesLabels[i]}: #{@prettifylabel(@series[i][index])}#{@options.units}") + @yLabels[i].attr('text', "#{@seriesLabels[i]}: #{@commas(@series[i][index])}#{@options.units}") # recalculate hover box width maxLabelWidth = Math.max.apply null, $.map @yLabels, (l) -> l.getBBox().width @@ -423,23 +424,21 @@ class Morris.Line else new Date(parseInt(date, 10), 0, 1) - prettifylabel: (num) -> - if num == null - return "n/a" - return @commas(num) - # make long numbers prettier by inserting commas # eg: commas(1234567) -> '1,234,567' # commas: (num) -> - ret = if num < 0 then "-" else "" - absnum = Math.abs(num) - intnum = Math.floor(absnum).toFixed(0) - ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ',') - strabsnum = absnum.toString() - if strabsnum.length > intnum.length - ret += strabsnum.slice(intnum.length) - ret + if num is null + "n/a" + else + ret = if num < 0 then "-" else "" + absnum = Math.abs(num) + intnum = Math.floor(absnum).toFixed(0) + ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ',') + strabsnum = absnum.toString() + if strabsnum.length > intnum.length + ret += strabsnum.slice(intnum.length) + ret window.Morris = Morris # vim: set et ts=2 sw=2 sts=2 diff --git a/morris.js b/morris.js index 72d0f4b..c99c007 100644 --- a/morris.js +++ b/morris.js @@ -1,5 +1,6 @@ (function() { - var $, Morris; + var $, Morris, + __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; $ = jQuery; @@ -8,7 +9,11 @@ Morris.Line = (function() { function Line(options) { - if (!(this instanceof Morris.Line)) return new Morris.Line(options); + this.updateHilight = __bind(this.updateHilight, this); + this.hilight = __bind(this.hilight, this); + this.updateHover = __bind(this.updateHover, this); + this.transY = __bind(this.transY, this); + this.transX = __bind(this.transX, this); if (!(this instanceof Morris.Line)) return new Morris.Line(options); if (typeof options.element === 'string') { this.el = $(document.getElementById(options.element)); } else { @@ -55,7 +60,7 @@ }; Line.prototype.precalc = function() { - var ykey, ymax, ymin, _i, _j, _len, _ref, _ref2, _results, + var d, series_data, touchHandler, ykey, ymax, ymin, _i, _j, _k, _len, _len2, _ref, _ref2, _ref3, _results, _this = this; this.options.data.sort(function(a, b) { return (a[_this.options.xkey] < b[_this.options.xkey]) - (b[_this.options.xkey] < a[_this.options.xkey]); @@ -68,9 +73,13 @@ _ref = this.options.ykeys; for (_i = 0, _len = _ref.length; _i < _len; _i++) { ykey = _ref[_i]; - this.series.push($.map(this.options.data, function(d) { - return d[ykey]; - })); + series_data = []; + _ref2 = this.options.data; + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + d = _ref2[_j]; + series_data.push(d[ykey]); + } + this.series.push(series_data); } if (this.options.parseTime) { this.xvals = $.map(this.columnLabels, function(x) { @@ -79,17 +88,19 @@ } else { this.xvals = (function() { _results = []; - for (var _j = _ref2 = this.columnLabels.length - 1; _ref2 <= 0 ? _j <= 0 : _j >= 0; _ref2 <= 0 ? _j++ : _j--){ _results.push(_j); } + for (var _k = _ref3 = this.columnLabels.length - 1; _ref3 <= 0 ? _k <= 0 : _k >= 0; _ref3 <= 0 ? _k++ : _k--){ _results.push(_k); } 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) { @@ -107,42 +118,116 @@ 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) { - return this.options.ymin = Math.min(parseInt(this.options.ymin.slice(5), 10), ymin); + this.options.ymin = Math.min(parseInt(this.options.ymin.slice(5), 10), ymin); } else { - return this.options.ymin = ymin; + this.options.ymin = ymin; } } + 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(evt) { + return _this.updateHilight(evt.pageX); + }); + if (this.options.hideHover) { + this.el.mouseout(function(evt) { + return _this.hilight(null); + }); + } + touchHandler = function(evt) { + var touch; + touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0]; + _this.updateHilight(touch.pageX); + return touch; + }; + this.el.bind('touchstart', touchHandler); + this.el.bind('touchmove', touchHandler); + return this.el.bind('touchend', touchHandler); + }; + + Line.prototype.calc = function() { + var h, s, scoords, w, x, _i, _len, _ref, + _this = this; + w = this.el.width(); + h = this.el.height(); + if (this.elementWidth !== w || this.elementHeight !== h) { + 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 _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++) { + s = _ref[_i]; + scoords = []; + $.each(s, function(i, y) { + if (y === null) { + return scoords.push(null); + } else { + return scoords.push({ + x: _this.columns[i], + y: _this.transY(y) + }); + } + }); + this.seriesCoords.push(scoords); + } + return this.hoverMargins = $.map(this.columns.slice(1), function(x, i) { + return (x + _this.columns[i]) / 2; + }); + } + }; + + Line.prototype.transX = function(x) { + if (this.xvals.length === 1) { + return this.left + this.width / 2; + } else { + return this.left + (x - this.xmin) * this.dx; + } + }; + + Line.prototype.transY = function(y) { + return this.options.marginTop + this.height - (y - this.options.ymin) * this.dy; }; 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, - _this = this; this.el.empty(); this.r = new Raphael(this.el[0]); - 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); - left = maxYLabelWidth + this.options.marginLeft; - width = this.el.width() - left - this.options.marginRight; - height = this.el.height() - this.options.marginTop - this.options.marginBottom; - dx = width / (this.xmax - this.xmin); - dy = height / (this.options.ymax - this.options.ymin); - transX = function(x) { - if (_this.xvals.length === 1) { - return left + width / 2; - } else { - return left + (x - _this.xmin) * dx; - } - }; - transY = function(y) { - return _this.options.marginTop + height - (y - _this.options.ymin) * dy; - }; + this.calc(); + this.drawGrid(); + this.drawSeries(); + this.drawHover(); + return this.hilight(this.options.hideHover ? null : 0); + }; + + Line.prototype.drawGrid = function() { + var firstY, i, label, labelBox, labelText, lastY, lineY, prevLabelMargin, v, x1, x2, xLabelMargin, xpos, y, yInterval, _results; yInterval = (this.options.ymax - this.options.ymin) / (this.options.numLines - 1); firstY = Math.ceil(this.options.ymin / yInterval) * yInterval; lastY = Math.floor(this.options.ymax / yInterval) * yInterval; for (lineY = firstY; firstY <= lastY ? lineY <= lastY : lineY >= lastY; lineY += yInterval) { v = Math.floor(lineY); - y = transY(v); - this.r.text(left - this.options.marginLeft / 2, y, v + this.options.units).attr('font-size', this.options.gridTextSize).attr('fill', this.options.gridTextColor).attr('text-anchor', 'end'); - this.r.path("M" + left + "," + y + 'H' + (left + width)).attr('stroke', this.options.gridLineColor).attr('stroke-width', this.options.gridStrokeWidth); + y = this.transY(v); + this.r.text(this.left - this.options.marginLeft / 2, y, this.commas(v) + this.options.units).attr('font-size', this.options.gridTextSize).attr('fill', this.options.gridTextColor).attr('text-anchor', 'end'); + this.r.path("M" + this.left + "," + y + "H" + (this.left + this.width)).attr('stroke', this.options.gridLineColor).attr('stroke-width', this.options.gridStrokeWidth); } prevLabelMargin = null; xLabelMargin = 50; @@ -153,6 +238,7 @@ x1 = this.xmin; x2 = this.xmax; } + _results = []; for (i = x1; x1 <= x2 ? i <= x2 : i >= x2; x1 <= x2 ? i++ : i--) { if (this.options.parseTime) { xpos = new Date(i, 0, 1).getTime(); @@ -161,163 +247,61 @@ xpos = i; } 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); + label = this.r.text(this.transX(xpos), this.options.marginTop + this.height + this.options.marginBottom / 2, labelText).attr('font-size', this.options.gridTextSize).attr('fill', this.options.gridTextColor); labelBox = label.getBBox(); if (prevLabelMargin === null || prevLabelMargin <= labelBox.x) { - prevLabelMargin = labelBox.x + labelBox.width + xLabelMargin; + _results.push(prevLabelMargin = labelBox.x + labelBox.width + xLabelMargin); } else { - label.remove(); + _results.push(label.remove()); } } - columns = (function() { - var _i, _len, _ref, _results; - _ref = this.xvals; - _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - x = _ref[_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]; - seriesCoords.push($.map(s, function(y, i) { - return { - x: columns[i], - y: transY(y) - }; - })); - } - for (i = _ref2 = seriesCoords.length - 1; _ref2 <= 0 ? i <= 0 : i >= 0; _ref2 <= 0 ? i++ : i--) { - coords = seriesCoords[i]; + return _results; + }; + + Line.prototype.drawSeries = function() { + var c, circle, coords, i, path, _ref, _ref2, _results; + for (i = _ref = this.seriesCoords.length - 1; _ref <= 0 ? i <= 0 : i >= 0; _ref <= 0 ? i++ : i--) { + coords = this.seriesCoords[i]; if (coords.length > 1) { - path = this.createPath(coords, this.options.marginTop, left, this.options.marginTop + height, left + width); + path = this.createPath(coords, this.options.marginTop, this.left, this.options.marginTop + this.height, this.left + this.width); this.r.path(path).attr('stroke', this.options.lineColors[i]).attr('stroke-width', this.options.lineWidth); } } - seriesPoints = (function() { - var _ref3, _results; + this.seriesPoints = (function() { + var _ref2, _results; _results = []; - for (i = 0, _ref3 = seriesCoords.length - 1; 0 <= _ref3 ? i <= _ref3 : i >= _ref3; 0 <= _ref3 ? i++ : i--) { + for (i = 0, _ref2 = this.seriesCoords.length - 1; 0 <= _ref2 ? i <= _ref2 : i >= _ref2; 0 <= _ref2 ? 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]; - 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); - } - } - hoverHeight = this.options.hoverFontSize * 1.5 * (this.series.length + 1); - hover = this.r.rect(-10, -hoverHeight / 2 - this.options.hoverPaddingY, 20, 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); - xLabel = this.r.text(0, (this.options.hoverFontSize * 0.75) - hoverHeight / 2, '').attr('fill', this.options.hoverLabelColor).attr('font-weight', 'bold').attr('font-size', this.options.hoverFontSize); - hoverSet = this.r.set(); - 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--) { - 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; - 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--) { - 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) { - return l.getBBox().width; - })); - maxLabelWidth = Math.max(maxLabelWidth, xLabel.getBBox().width); - hover.attr('width', maxLabelWidth + _this.options.hoverPaddingX * 2); - hover.attr('x', -_this.options.hoverPaddingX - maxLabelWidth / 2); - yloc = Math.min.apply(null, $.map(_this.series, function(s) { - return transY(s[index]); - })); - if (yloc > hoverHeight + _this.options.hoverPaddingY * 2 + _this.options.hoverMargin + _this.options.marginTop) { - yloc = yloc - hoverHeight / 2 - _this.options.hoverPaddingY - _this.options.hoverMargin; - } else { - yloc = yloc + hoverHeight / 2 + _this.options.hoverPaddingY + _this.options.hoverMargin; - } - yloc = Math.max(_this.options.marginTop + hoverHeight / 2 + _this.options.hoverPaddingY, yloc); - yloc = Math.min(_this.options.marginTop + height - hoverHeight / 2 - _this.options.hoverPaddingY, yloc); - xloc = Math.min(left + width - maxLabelWidth / 2 - _this.options.hoverPaddingX, columns[index]); - xloc = Math.max(left + maxLabelWidth / 2 + _this.options.hoverPaddingX, xloc); - return hoverSet.attr('transform', "t" + xloc + "," + yloc); - }; - hideHover = function() { - return hoverSet.hide(); - }; - hoverMargins = $.map(columns.slice(1), function(x, i) { - return (x + columns[i]) / 2; - }); - prevHilight = null; - pointGrow = Raphael.animation({ - r: this.options.pointSize + 3 - }, 25, 'linear'); - pointShrink = Raphael.animation({ - r: this.options.pointSize - }, 25, 'linear'); - hilight = function(index) { - var i, _ref6, _ref7; - if (prevHilight !== null && prevHilight !== index) { - for (i = 0, _ref6 = seriesPoints.length - 1; 0 <= _ref6 ? i <= _ref6 : i >= _ref6; 0 <= _ref6 ? i++ : i--) { - seriesPoints[i][prevHilight].animate(pointShrink); + }).call(this); + _results = []; + for (i = _ref2 = this.seriesCoords.length - 1; _ref2 <= 0 ? i <= 0 : i >= 0; _ref2 <= 0 ? i++ : i--) { + _results.push((function() { + var _i, _len, _ref3, _results2; + _ref3 = this.seriesCoords[i]; + _results2 = []; + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + c = _ref3[_i]; + if (c === null) { + circle = null; + } else { + circle = this.r.circle(c.x, c.y, this.options.pointSize).attr('fill', this.options.lineColors[i]).attr('stroke-width', 1).attr('stroke', '#ffffff'); + } + _results2.push(this.seriesPoints[i].push(circle)); } - } - if (index !== null && prevHilight !== index) { - for (i = 0, _ref7 = seriesPoints.length - 1; 0 <= _ref7 ? i <= _ref7 : i >= _ref7; 0 <= _ref7 ? i++ : i--) { - seriesPoints[i][index].animate(pointGrow); - } - updateHover(index); - } - prevHilight = index; - if (index === null) return hideHover(); - }; - updateHilight = function(x) { - var hoverIndex, _ref6, _results; - x -= _this.el.offset().left; - _results = []; - for (hoverIndex = _ref6 = hoverMargins.length; _ref6 <= 0 ? hoverIndex <= 0 : hoverIndex >= 0; _ref6 <= 0 ? hoverIndex++ : hoverIndex--) { - if (hoverIndex === 0 || hoverMargins[hoverIndex - 1] > x) { - hilight(hoverIndex); - break; - } else { - _results.push(void 0); - } - } - return _results; - }; - this.el.mousemove(function(evt) { - return updateHilight(evt.pageX); - }); - if (this.options.hideHover) { - this.el.mouseout(function(evt) { - return hilight(null); - }); + return _results2; + }).call(this)); } - touchHandler = function(evt) { - var touch; - touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0]; - updateHilight(touch.pageX); - return touch; - }; - this.el.bind('touchstart', touchHandler); - this.el.bind('touchmove', touchHandler); - this.el.bind('touchend', touchHandler); - return hilight(this.options.hideHover ? null : 0); + return _results; }; - Line.prototype.createPath = function(coords, top, left, bottom, right) { - var c, g, grads, i, ix, lc, lg, path, x1, x2, y1, y2, _ref; + Line.prototype.createPath = function(all_coords, top, left, bottom, right) { + var c, coords, g, grads, i, ix, lc, lg, path, x1, x2, y1, y2, _ref; path = ""; + coords = $.map(all_coords, function(c) { + return c; + }); if (this.options.smooth) { grads = this.gradients(coords); for (i = 0, _ref = coords.length - 1; 0 <= _ref ? i <= _ref : i >= _ref; 0 <= _ref ? i++ : i--) { @@ -356,6 +340,93 @@ }); }; + Line.prototype.drawHover = function() { + var i, yLabel, _ref, _results; + 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 * 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.push(this.hover); + this.hoverSet.push(this.xLabel); + this.yLabels = []; + _results = []; + for (i = 0, _ref = this.series.length - 1; 0 <= _ref ? i <= _ref : i >= _ref; 0 <= _ref ? i++ : i--) { + yLabel = this.r.text(0, this.options.hoverFontSize * 1.5 * (i + 1.5) - this.hoverHeight / 2, '').attr('fill', this.options.lineColors[i]).attr('font-size', this.options.hoverFontSize); + this.yLabels.push(yLabel); + _results.push(this.hoverSet.push(yLabel)); + } + return _results; + }; + + Line.prototype.updateHover = function(index) { + var i, maxLabelWidth, xloc, yloc, _ref, + _this = this; + this.hoverSet.show(); + this.xLabel.attr('text', this.columnLabels[index]); + for (i = 0, _ref = this.series.length - 1; 0 <= _ref ? i <= _ref : i >= _ref; 0 <= _ref ? i++ : i--) { + this.yLabels[i].attr('text', "" + this.seriesLabels[i] + ": " + (this.commas(this.series[i][index])) + this.options.units); + } + maxLabelWidth = Math.max.apply(null, $.map(this.yLabels, function(l) { + return l.getBBox().width; + })); + maxLabelWidth = Math.max(maxLabelWidth, this.xLabel.getBBox().width); + this.hover.attr('width', maxLabelWidth + this.options.hoverPaddingX * 2); + this.hover.attr('x', -this.options.hoverPaddingX - maxLabelWidth / 2); + yloc = Math.min.apply(null, $.map(this.series, function(s) { + return _this.transY(s[index]); + })); + if (yloc > this.hoverHeight + this.options.hoverPaddingY * 2 + this.options.hoverMargin + this.options.marginTop) { + yloc = yloc - this.hoverHeight / 2 - this.options.hoverPaddingY - this.options.hoverMargin; + } else { + yloc = yloc + this.hoverHeight / 2 + this.options.hoverPaddingY + this.options.hoverMargin; + } + yloc = Math.max(this.options.marginTop + this.hoverHeight / 2 + this.options.hoverPaddingY, yloc); + yloc = Math.min(this.options.marginTop + this.height - this.hoverHeight / 2 - this.options.hoverPaddingY, yloc); + xloc = Math.min(this.left + this.width - maxLabelWidth / 2 - this.options.hoverPaddingX, this.columns[index]); + xloc = Math.max(this.left + maxLabelWidth / 2 + this.options.hoverPaddingX, xloc); + return this.hoverSet.attr('transform', "t" + xloc + "," + yloc); + }; + + Line.prototype.hideHover = function() { + return this.hoverSet.hide(); + }; + + Line.prototype.hilight = function(index) { + var i, _ref, _ref2; + if (this.prevHilight !== null && this.prevHilight !== index) { + for (i = 0, _ref = this.seriesPoints.length - 1; 0 <= _ref ? i <= _ref : i >= _ref; 0 <= _ref ? i++ : i--) { + if (this.seriesPoints[i][this.prevHilight]) { + this.seriesPoints[i][this.prevHilight].animate(this.pointShrink); + } + } + } + if (index !== null && this.prevHilight !== index) { + for (i = 0, _ref2 = this.seriesPoints.length - 1; 0 <= _ref2 ? i <= _ref2 : i >= _ref2; 0 <= _ref2 ? i++ : i--) { + if (this.seriesPoints[i][index]) { + this.seriesPoints[i][index].animate(this.pointGrow); + } + } + this.updateHover(index); + } + this.prevHilight = index; + if (index === null) return this.hideHover(); + }; + + Line.prototype.updateHilight = function(x) { + var hoverIndex, _ref, _results; + x -= this.el.offset().left; + _results = []; + for (hoverIndex = _ref = this.hoverMargins.length; _ref <= 0 ? hoverIndex <= 0 : hoverIndex >= 0; _ref <= 0 ? hoverIndex++ : hoverIndex--) { + if (hoverIndex === 0 || this.hoverMargins[hoverIndex - 1] > x) { + this.hilight(hoverIndex); + break; + } else { + _results.push(void 0); + } + } + return _results; + }; + Line.prototype.measureText = function(text, fontSize) { var ret, tt; if (fontSize == null) fontSize = 12; @@ -398,13 +469,19 @@ Line.prototype.commas = function(num) { var absnum, intnum, ret, strabsnum; - ret = num < 0 ? "-" : ""; - absnum = Math.abs(num); - intnum = Math.floor(absnum).toFixed(0); - ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ','); - strabsnum = absnum.toString(); - if (strabsnum.length > intnum.length) ret += strabsnum.slice(intnum.length); - return ret; + if (num === null) { + return "n/a"; + } else { + ret = num < 0 ? "-" : ""; + absnum = Math.abs(num); + intnum = Math.floor(absnum).toFixed(0); + ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ','); + strabsnum = absnum.toString(); + if (strabsnum.length > intnum.length) { + ret += strabsnum.slice(intnum.length); + } + return ret; + } }; return Line; diff --git a/morris.min.js b/morris.min.js index cf4a66f..a6e8a03 100644 --- a/morris.min.js +++ b/morris.min.js @@ -1 +1 @@ -((function(){var a,b;a=jQuery,b={},b.Line=function(){function c(c){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 b,c,d,e,f,g,h,i,j,k=this;this.options.data.sort(function(a,b){return(a[k.options.xkey]=0;i<=0?a++:a--)j.push(a);return j}.apply(this),this.columnLabels=a.map(this.columnLabels,function(a){return typeof a=="number"?k.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"&&(c=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),c):this.options.ymax=c);if(typeof this.options.ymin=="string"&&this.options.ymin.slice(0,4)==="auto")return d=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),d):this.options.ymin=d},c.prototype.redraw=function(){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,_,ba,bb,bc,bd,be=this;this.el.empty(),this.r=new Raphael(this.el[0]),w=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),u=w+this.options.marginLeft,L=this.el.width()-u-this.options.marginRight,i=this.el.height()-this.options.marginTop-this.options.marginBottom,f=L/(this.xmax-this.xmin),g=i/(this.options.ymax-this.options.ymin),G=function(a){return be.xvals.length===1?u+L/2:u+(a-be.xmin)*f},H=function(a){return be.options.marginTop+i-(a-be.options.ymin)*g},T=(this.options.ymax-this.options.ymin)/(this.options.numLines-1),h=Math.ceil(this.options.ymin/T)*T,t=Math.floor(this.options.ymax/T)*T;for(v=h;h<=t?v<=t:v>=t;v+=T)K=Math.floor(v),S=H(K),this.r.text(u-this.options.marginLeft/2,S,K+this.options.units).attr("font-size",this.options.gridTextSize).attr("fill",this.options.gridTextColor).attr("text-anchor","end"),this.r.path("M"+u+","+S+"H"+(u+L)).attr("stroke",this.options.gridLineColor).attr("stroke-width",this.options.gridStrokeWidth);B=null,Q=50,this.options.parseTime?(N=(new Date(this.xmin)).getFullYear(),O=(new Date(this.xmax)).getFullYear()):(N=this.xmin,O=this.xmax);for(p=N;N<=O?p<=O:p>=O;N<=O?p++:p--){if(this.options.parseTime){R=(new Date(p,0,1)).getTime();if(R=0;ba<=0?p++:p--)e=D[p],e.length>1&&(x=this.createPath(e,this.options.marginTop,u,this.options.marginTop+i,u+L),this.r.path(x).attr("stroke",this.options.lineColors[p]).attr("stroke-width",this.options.lineWidth));E=function(){var a,b;b=[];for(p=0,a=D.length-1;0<=a?p<=a:p>=a;0<=a?p++:p--)b.push([]);return b}();for(p=bb=D.length-1;bb<=0?p<=0:p>=0;bb<=0?p++:p--){bc=D[p];for(X=0,Z=bc.length;X=bd;0<=bd?p++:p--)U=this.r.text(0,this.options.hoverFontSize*1.5*(p+1.5)-m/2,"").attr("fill",this.options.lineColors[p]).attr("font-size",this.options.hoverFontSize),V.push(U),o.push(U);return J=function(b){var c,e,f,g,h;o.show(),P.attr("text",be.columnLabels[b]);for(c=0,h=be.series.length-1;0<=h?c<=h:c>=h;0<=h?c++:c--)V[c].attr("text",""+be.seriesLabels[c]+": "+be.commas(be.series[c][b])+be.options.units);return e=Math.max.apply(null,a.map(V,function(a){return a.getBBox().width})),e=Math.max(e,P.getBBox().width),l.attr("width",e+be.options.hoverPaddingX*2),l.attr("x",-be.options.hoverPaddingX-e/2),g=Math.min.apply(null,a.map(be.series,function(a){return H(a[b])})),g>m+be.options.hoverPaddingY*2+be.options.hoverMargin+be.options.marginTop?g=g-m/2-be.options.hoverPaddingY-be.options.hoverMargin:g=g+m/2+be.options.hoverPaddingY+be.options.hoverMargin,g=Math.max(be.options.marginTop+m/2+be.options.hoverPaddingY,g),g=Math.min(be.options.marginTop+i-m/2-be.options.hoverPaddingY,g),f=Math.min(u+L-e/2-be.options.hoverPaddingX,d[b]),f=Math.max(u+e/2+be.options.hoverPaddingX,f),o.attr("transform","t"+f+","+g)},j=function(){return o.hide()},n=a.map(d.slice(1),function(a,b){return(a+d[b])/2}),A=null,y=Raphael.animation({r:this.options.pointSize+3},25,"linear"),z=Raphael.animation({r:this.options.pointSize},25,"linear"),k=function(a){var b,c,d;if(A!==null&&A!==a)for(b=0,c=E.length-1;0<=c?b<=c:b>=c;0<=c?b++:b--)E[b][A].animate(z);if(a!==null&&A!==a){for(b=0,d=E.length-1;0<=d?b<=d:b>=d;0<=d?b++:b--)E[b][a].animate(y);J(a)}A=a;if(a===null)return j()},I=function(a){var b,c,d;a-=be.el.offset().left,d=[];for(b=c=n.length;c<=0?b<=0:b>=0;c<=0?b++:b--){if(b===0||n[b-1]>a){k(b);break}d.push(void 0)}return d},this.el.mousemove(function(a){return I(a.pageX)}),this.options.hideHover&&this.el.mouseout(function(a){return k(null)}),F=function(a){var b;return b=a.originalEvent.touches[0]||a.originalEvent.changedTouches[0],I(b.pageX),b},this.el.bind("touchstart",F),this.el.bind("touchmove",F),this.el.bind("touchend",F),k(this.options.hideHover?null:0)},c.prototype.createPath=function(b,c,d,e,f){var g,h,i,j,k,l,m,n,o,p,q,r,s;n="";if(this.options.smooth){i=this.gradients(b);for(j=0,s=b.length-1;0<=s?j<=s:j>=s;0<=s?j++:j--)g=b[j],j===0?n+="M"+g.x+","+g.y:(h=i[j],l=b[j-1],m=i[j-1],k=(g.x-l.x)/4,o=l.x+k,q=Math.min(e,l.y+k*m),p=g.x-k,r=Math.min(e,g.y-k*h),n+="C"+o+","+q+","+p+","+r+","+g.x+","+g.y)}else n="M"+a.map(b,function(a){return""+a.x+","+a.y}).join("L");return n},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.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.prototype.parseYear=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+) (\d+):(\d+)$/),i=a.match(/^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+(\.\d+)?)$/),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.floor((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))},c.prototype.commas=function(a){var b,c,d,e;return 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},c}(),window.Morris=b})).call(this); \ No newline at end of file +((function(){var a,b,c=function(a,b){return function(){return a.apply(b,arguments)}};a=jQuery,b={},b.Line=function(){function d(d){this.updateHilight=c(this.updateHilight,this),this.hilight=c(this.hilight,this),this.updateHover=c(this.updateHover,this),this.transY=c(this.transY,this),this.transX=c(this.transX,this);if(!(this instanceof b.Line))return new b.Line(d);typeof d.element=="string"?this.el=a(document.getElementById(d.element)):this.el=a(d.element),this.options=a.extend({},this.defaults,d);if(this.options.data===void 0||this.options.data.length===0)return;this.el.addClass("graph-initialised"),this.precalc(),this.redraw()}return d.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()}},d.prototype.precalc=function(){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q=this;this.options.data.sort(function(a,b){return(a[q.options.xkey]=0;o<=0?a++:a--)p.push(a);return p}.apply(this),this.options.parseTime&&(this.columnLabels=a.map(this.columnLabels,function(a){return typeof a=="number"?q.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"&&(f=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),f):this.options.ymax=f),typeof this.options.ymin=="string"&&this.options.ymin.slice(0,4)==="auto"&&(g=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),g):this.options.ymin=g),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 q.updateHilight(a.pageX)}),this.options.hideHover&&this.el.mouseout(function(a){return q.hilight(null)}),d=function(a){var b;return b=a.originalEvent.touches[0]||a.originalEvent.changedTouches[0],q.updateHilight(b.pageX),b},this.el.bind("touchstart",d),this.el.bind("touchmove",d),this.el.bind("touchend",d)},d.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=f;g+=o)i=Math.floor(g),n=this.transY(i),this.r.text(this.left-this.options.marginLeft/2,n,this.commas(i)+this.options.units).attr("font-size",this.options.gridTextSize).attr("fill",this.options.gridTextColor).attr("text-anchor","end"),this.r.path("M"+this.left+","+n+"H"+(this.left+this.width)).attr("stroke",this.options.gridLineColor).attr("stroke-width",this.options.gridStrokeWidth);h=null,l=50,this.options.parseTime?(j=(new Date(this.xmin)).getFullYear(),k=(new Date(this.xmax)).getFullYear()):(j=this.xmin,k=this.xmax),p=[];for(b=j;j<=k?b<=k:b>=k;j<=k?b++:b--){if(this.options.parseTime){m=(new Date(b,0,1)).getTime();if(m=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},d.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)})},d.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},d.prototype.updateHover=function(b){var c,d,e,f,g,h=this;this.hoverSet.show(),this.xLabel.attr("text",this.columnLabels[b]);for(c=0,g=this.series.length-1;0<=g?c<=g:c>=g;0<=g?c++:c--)this.yLabels[c].attr("text",""+this.seriesLabels[c]+": "+this.commas(this.series[c][b])+this.options.units);return d=Math.max.apply(null,a.map(this.yLabels,function(a){return a.getBBox().width})),d=Math.max(d,this.xLabel.getBBox().width),this.hover.attr("width",d+this.options.hoverPaddingX*2),this.hover.attr("x",-this.options.hoverPaddingX-d/2),f=Math.min.apply(null,a.map(this.series,function(a){return h.transY(a[b])})),f>this.hoverHeight+this.options.hoverPaddingY*2+this.options.hoverMargin+this.options.marginTop?f=f-this.hoverHeight/2-this.options.hoverPaddingY-this.options.hoverMargin:f=f+this.hoverHeight/2+this.options.hoverPaddingY+this.options.hoverMargin,f=Math.max(this.options.marginTop+this.hoverHeight/2+this.options.hoverPaddingY,f),f=Math.min(this.options.marginTop+this.height-this.hoverHeight/2-this.options.hoverPaddingY,f),e=Math.min(this.left+this.width-d/2-this.options.hoverPaddingX,this.columns[b]),e=Math.max(this.left+d/2+this.options.hoverPaddingX,e),this.hoverSet.attr("transform","t"+e+","+f)},d.prototype.hideHover=function(){return this.hoverSet.hide()},d.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()},d.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},d.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},d.prototype.parseYear=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+) (\d+):(\d+)$/),i=a.match(/^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+(\.\d+)?)$/),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.floor((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))},d.prototype.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)},d}(),window.Morris=b})).call(this); \ No newline at end of file