From fc4ff279a5dba3056868ea90d244c5ef3f528714 Mon Sep 17 00:00:00 2001 From: Olly Smith Date: Sun, 1 Apr 2012 22:29:37 +0100 Subject: [PATCH] Refactor x-axis labelling. --- examples/days.html | 18 ++-- morris.coffee | 237 +++++++++++++++++++++++++++----------------- morris.js | 239 +++++++++++++++++++++++++++++++-------------- morris.min.js | 2 +- test.html | 192 ++++++++++++++++++++++++++++++++++++ 5 files changed, 517 insertions(+), 171 deletions(-) create mode 100644 test.html diff --git a/examples/days.html b/examples/days.html index 4d57f05..6ea36b5 100644 --- a/examples/days.html +++ b/examples/days.html @@ -15,15 +15,15 @@ // data stolen from http://howmanyleft.co.uk/vehicle/jaguar_'e'_type var day_data = [ {"period": "2012-10-01", "licensed": 3407, "sorned": 660}, - {"period": "2011-08-12", "licensed": 3351, "sorned": 629}, - {"period": "2011-03-03", "licensed": 3269, "sorned": 618}, - {"period": "2010-08-08", "licensed": 3246, "sorned": 661}, - {"period": "2010-05-10", "licensed": 3257, "sorned": 667}, - {"period": "2010-03-14", "licensed": 3248, "sorned": 627}, - {"period": "2010-01-10", "licensed": 3171, "sorned": 660}, - {"period": "2009-12-10", "licensed": 3171, "sorned": 676}, - {"period": "2009-10-07", "licensed": 3201, "sorned": 656}, - {"period": "2009-09-25", "licensed": 3215, "sorned": 622}, + {"period": "2012-09-30", "licensed": 3351, "sorned": 629}, + {"period": "2012-09-29", "licensed": 3269, "sorned": 618}, + {"period": "2012-09-20", "licensed": 3246, "sorned": 661}, + {"period": "2012-09-19", "licensed": 3257, "sorned": 667}, + {"period": "2012-09-18", "licensed": 3248, "sorned": 627}, + {"period": "2012-09-17", "licensed": 3171, "sorned": 660}, + {"period": "2012-09-16", "licensed": 3171, "sorned": 676}, + {"period": "2012-09-15", "licensed": 3201, "sorned": 656}, + {"period": "2012-09-10", "licensed": 3215, "sorned": 622}, ]; Morris.Line({ element: 'graph', diff --git a/morris.coffee b/morris.coffee index 050731e..79b9eba 100644 --- a/morris.coffee +++ b/morris.coffee @@ -82,7 +82,7 @@ class Morris.Line # translate x labels into nominal dates # note: currently using decimal years to specify dates if @options.parseTime - @xvals = $.map @columnLabels, (x) => @parseDate x + @xvals = $.map @columnLabels, (x) -> Morris.parseDate x else @xvals = [(@columnLabels.length-1)..0] # translate column labels, if they're timestamps @@ -198,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, @commas(v) + @options.units) + @r.text(@left - @options.marginLeft/2, y, Morris.commas(v) + @options.units) .attr('font-size', @options.gridTextSize) .attr('fill', @options.gridTextColor) .attr('text-anchor', 'end') @@ -207,23 +207,11 @@ class Morris.Line .attr('stroke-width', @options.gridStrokeWidth) ## draw x axis labels - prevLabelMargin = null + ypos = @options.marginTop + @height + @options.marginBottom / 2 xLabelMargin = 50 # make this an option? - if @options.parseTime - x1 = new Date(@xmin).getFullYear() - x2 = new Date(@xmax).getFullYear() - else - x1 = 0 - x2 = @columnLabels.length - for i in [x1..x2] - if @options.parseTime - xpos = new Date(i, 0, 1).getTime() - if xpos < @xmin - continue - 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) + prevLabelMargin = null + drawLabel = (labelText, xpos) => + label = @r.text(@transX(xpos), ypos, labelText) .attr('font-size', @options.gridTextSize) .attr('fill', @options.gridTextColor) labelBox = label.getBBox() @@ -232,6 +220,13 @@ class Morris.Line prevLabelMargin = labelBox.x + labelBox.width + xLabelMargin else label.remove() + if @options.parseTime + for l in Morris.labelSeries(@xmin, @xmax, @width, xLabelMargin) + 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 # @@ -320,7 +315,7 @@ class Morris.Line @hoverSet.show() @xLabel.attr('text', @columnLabels[index]) for i in [0..@series.length-1] - @yLabels[i].attr('text', "#{@seriesLabels[i]}: #{@commas(@series[i][index])}#{@options.units}") + @yLabels[i].attr('text', "#{@seriesLabels[i]}: #{Morris.commas(@series[i][index])}#{@options.units}") # recalculate hover box width maxLabelWidth = Math.max.apply null, $.map @yLabels, (l) -> l.getBBox().width @@ -370,75 +365,143 @@ class Morris.Line tt.remove() return ret - parseDate: (date) -> - if typeof date is 'number' - return date - m = date.match /^(\d+) Q(\d)$/ - n = date.match /^(\d+)-(\d+)$/ - o = date.match /^(\d+)-(\d+)-(\d+)$/ - p = date.match /^(\d+) W(\d+)$/ - q = date.match /^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)Z?$/ - r = date.match /^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)Z?$/ - if m - new Date( - parseInt(m[1], 10), - parseInt(m[2], 10) * 3 - 1, - 1).getTime() - else if n - new Date( - parseInt(n[1], 10), - parseInt(n[2], 10) - 1, - 1).getTime() - else if o - new Date( - parseInt(o[1], 10), - parseInt(o[2], 10) - 1, - parseInt(o[3], 10)).getTime() - else if p - # calculate number of weeks in year given - ret = new Date(parseInt(p[1], 10), 0, 1); - # first thursday in year (ISO 8601 standard) - if ret.getDay() isnt 4 - ret.setMonth(0, 1 + ((4 - ret.getDay()) + 7) % 7); - # add weeks - ret.getTime() + parseInt(p[2], 10) * 604800000 - else if q - new Date( - parseInt(q[1], 10), - parseInt(q[2], 10) - 1, - parseInt(q[3], 10), - parseInt(q[4], 10), - parseInt(q[5], 10)).getTime() - else if r - secs = parseFloat(r[6]) - isecs = Math.floor(secs) - msecs = Math.floor((secs - isecs) * 1000) - new Date( - parseInt(r[1], 10), - parseInt(r[2], 10) - 1, - parseInt(r[3], 10), - parseInt(r[4], 10), - parseInt(r[5], 10), - isecs, - msecs).getTime() - else - new Date(parseInt(date, 10), 0, 1) +# parse a date into a javascript timestamp +# +Morris.parseDate = (date) -> + if typeof date is 'number' + return date + m = date.match /^(\d+) Q(\d)$/ + n = date.match /^(\d+)-(\d+)$/ + o = date.match /^(\d+)-(\d+)-(\d+)$/ + p = date.match /^(\d+) W(\d+)$/ + q = date.match /^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)Z?$/ + r = date.match /^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)Z?$/ + if m + new Date( + parseInt(m[1], 10), + parseInt(m[2], 10) * 3 - 1, + 1).getTime() + else if n + new Date( + parseInt(n[1], 10), + parseInt(n[2], 10) - 1, + 1).getTime() + else if o + new Date( + parseInt(o[1], 10), + parseInt(o[2], 10) - 1, + parseInt(o[3], 10)).getTime() + else if p + # calculate number of weeks in year given + ret = new Date(parseInt(p[1], 10), 0, 1); + # first thursday in year (ISO 8601 standard) + if ret.getDay() isnt 4 + ret.setMonth(0, 1 + ((4 - ret.getDay()) + 7) % 7); + # add weeks + ret.getTime() + parseInt(p[2], 10) * 604800000 + else if q + new Date( + parseInt(q[1], 10), + parseInt(q[2], 10) - 1, + parseInt(q[3], 10), + parseInt(q[4], 10), + parseInt(q[5], 10)).getTime() + else if r + secs = parseFloat(r[6]) + isecs = Math.floor(secs) + msecs = Math.round((secs - isecs) * 1000) + new Date( + parseInt(r[1], 10), + parseInt(r[2], 10) - 1, + parseInt(r[3], 10), + parseInt(r[4], 10), + parseInt(r[5], 10), + isecs, + msecs).getTime() + else + new Date(parseInt(date, 10), 0, 1).getTime() - # make long numbers prettier by inserting commas - # eg: commas(1234567) -> '1,234,567' - # - commas: (num) -> - 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 +# make long numbers prettier by inserting commas +# eg: commas(1234567) -> '1,234,567' +# +Morris.commas = (num) -> + 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 + +# zero-pad numbers to two characters wide +# +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) -> + 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 + +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) + } + +Morris.LABEL_SPECS = [ + { + 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) + } + { + 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) + } + { + 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) +] window.Morris = Morris # vim: set et ts=2 sw=2 sts=2 diff --git a/morris.js b/morris.js index 1213d05..e9220aa 100644 --- a/morris.js +++ b/morris.js @@ -1,5 +1,5 @@ (function() { - var $, Morris, + var $, Morris, minutesSpecHelper, secondsSpecHelper, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; $ = jQuery; @@ -83,7 +83,7 @@ } if (this.options.parseTime) { this.xvals = $.map(this.columnLabels, function(x) { - return _this.parseDate(x); + return Morris.parseDate(x); }); } else { this.xvals = (function() { @@ -219,43 +219,46 @@ }; Line.prototype.drawGrid = function() { - var firstY, i, label, labelBox, labelText, lastY, lineY, prevLabelMargin, v, x1, x2, xLabelMargin, xpos, y, yInterval, _results; + var drawLabel, firstY, i, l, labelText, lastY, lineY, prevLabelMargin, v, xLabelMargin, y, yInterval, ypos, _i, _len, _ref, _ref2, _results, _results2, + _this = this; 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 = 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.text(this.left - this.options.marginLeft / 2, y, Morris.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; + ypos = this.options.marginTop + this.height + this.options.marginBottom / 2; xLabelMargin = 50; - if (this.options.parseTime) { - x1 = new Date(this.xmin).getFullYear(); - x2 = new Date(this.xmax).getFullYear(); - } else { - x1 = 0; - x2 = this.columnLabels.length; - } - _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(); - if (xpos < this.xmin) continue; - } else { - xpos = i; - } - labelText = this.options.parseTime ? i : this.columnLabels[this.columnLabels.length - i - 1]; - 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); + prevLabelMargin = null; + drawLabel = function(labelText, xpos) { + var label, labelBox; + label = _this.r.text(_this.transX(xpos), ypos, labelText).attr('font-size', _this.options.gridTextSize).attr('fill', _this.options.gridTextColor); labelBox = label.getBBox(); if (prevLabelMargin === null || prevLabelMargin <= labelBox.x) { - _results.push(prevLabelMargin = labelBox.x + labelBox.width + xLabelMargin); + return prevLabelMargin = labelBox.x + labelBox.width + xLabelMargin; } else { - _results.push(label.remove()); + return label.remove(); } + }; + 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])); + } + return _results; + } else { + _results2 = []; + for (i = 0, _ref2 = this.columnLabels.length; 0 <= _ref2 ? i <= _ref2 : i >= _ref2; 0 <= _ref2 ? i++ : i--) { + labelText = this.columnLabels[this.columnLabels.length - i - 1]; + _results2.push(drawLabel(labelText, i)); + } + return _results2; } - return _results; }; Line.prototype.drawSeries = function() { @@ -364,7 +367,7 @@ 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); + this.yLabels[i].attr('text', "" + this.seriesLabels[i] + ": " + (Morris.commas(this.series[i][index])) + this.options.units); } maxLabelWidth = Math.max.apply(null, $.map(this.yLabels, function(l) { return l.getBBox().width; @@ -436,58 +439,146 @@ return ret; }; - Line.prototype.parseDate = function(date) { - var isecs, m, msecs, n, o, p, q, r, ret, secs; - if (typeof date === 'number') return date; - m = date.match(/^(\d+) Q(\d)$/); - n = date.match(/^(\d+)-(\d+)$/); - o = date.match(/^(\d+)-(\d+)-(\d+)$/); - p = date.match(/^(\d+) W(\d+)$/); - q = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)Z?$/); - r = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)Z?$/); - if (m) { - return new Date(parseInt(m[1], 10), parseInt(m[2], 10) * 3 - 1, 1).getTime(); - } else if (n) { - return new Date(parseInt(n[1], 10), parseInt(n[2], 10) - 1, 1).getTime(); - } else if (o) { - return new Date(parseInt(o[1], 10), parseInt(o[2], 10) - 1, parseInt(o[3], 10)).getTime(); - } else if (p) { - ret = new Date(parseInt(p[1], 10), 0, 1); - if (ret.getDay() !== 4) ret.setMonth(0, 1 + ((4 - ret.getDay()) + 7) % 7); - return ret.getTime() + parseInt(p[2], 10) * 604800000; - } else if (q) { - return new Date(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10)).getTime(); - } else if (r) { - secs = parseFloat(r[6]); - isecs = Math.floor(secs); - msecs = Math.floor((secs - isecs) * 1000); - return new Date(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10), isecs, msecs).getTime(); - } else { - return new Date(parseInt(date, 10), 0, 1); - } - }; - - Line.prototype.commas = function(num) { - var absnum, intnum, ret, strabsnum; - 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; })(); + Morris.parseDate = function(date) { + var isecs, m, msecs, n, o, p, q, r, ret, secs; + if (typeof date === 'number') return date; + m = date.match(/^(\d+) Q(\d)$/); + n = date.match(/^(\d+)-(\d+)$/); + o = date.match(/^(\d+)-(\d+)-(\d+)$/); + p = date.match(/^(\d+) W(\d+)$/); + q = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)Z?$/); + r = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)Z?$/); + if (m) { + return new Date(parseInt(m[1], 10), parseInt(m[2], 10) * 3 - 1, 1).getTime(); + } else if (n) { + return new Date(parseInt(n[1], 10), parseInt(n[2], 10) - 1, 1).getTime(); + } else if (o) { + return new Date(parseInt(o[1], 10), parseInt(o[2], 10) - 1, parseInt(o[3], 10)).getTime(); + } else if (p) { + ret = new Date(parseInt(p[1], 10), 0, 1); + if (ret.getDay() !== 4) ret.setMonth(0, 1 + ((4 - ret.getDay()) + 7) % 7); + return ret.getTime() + parseInt(p[2], 10) * 604800000; + } else if (q) { + return new Date(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10)).getTime(); + } else if (r) { + secs = parseFloat(r[6]); + isecs = Math.floor(secs); + msecs = Math.round((secs - isecs) * 1000); + return new Date(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10), isecs, msecs).getTime(); + } else { + return new Date(parseInt(date, 10), 0, 1).getTime(); + } + }; + + Morris.commas = function(num) { + var absnum, intnum, ret, strabsnum; + 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; + } + }; + + Morris.pad2 = function(number) { + return (number < 10 ? '0' : '') + number; + }; + + Morris.labelSeries = function(dmin, dmax, pxwidth) { + var d, d0, ddensity, ret, s, 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); + } + return ret; + } + } + }; + + minutesSpecHelper = function(interval) { + return { + span: interval * 60 * 1000, + start: function(d) { + return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours()); + }, + fmt: function(d) { + return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes())); + }, + incr: function(d) { + return d.setMinutes(d.getMinutes() + interval); + } + }; + }; + + secondsSpecHelper = function(interval) { + return { + span: interval * 1000, + start: function(d) { + return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes()); + }, + fmt: function(d) { + return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes())) + ":" + (Morris.pad2(d.getSeconds())); + }, + incr: function(d) { + return d.setSeconds(d.getSeconds() + interval); + } + }; + }; + + Morris.LABEL_SPECS = [ + { + span: 17280000000, + start: function(d) { + return new Date(d.getFullYear(), 0, 1); + }, + fmt: function(d) { + return "" + (d.getFullYear()); + }, + incr: function(d) { + return d.setFullYear(d.getFullYear() + 1); + } + }, { + span: 2419200000, + start: function(d) { + return new Date(d.getFullYear(), d.getMonth(), 1); + }, + fmt: function(d) { + return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1)); + }, + incr: function(d) { + return d.setMonth(d.getMonth() + 1); + } + }, { + span: 86400000, + start: function(d) { + return new Date(d.getFullYear(), d.getMonth(), d.getDate()); + }, + fmt: function(d) { + return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1)) + "-" + (Morris.pad2(d.getDate())); + }, + 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) + ]; + window.Morris = Morris; }).call(this); diff --git a/morris.min.js b/morris.min.js index 25156ed..de1122b 100644 --- a/morris.min.js +++ b/morris.min.js @@ -1 +1 @@ -(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=0,k=this.columnLabels.length),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.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.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 +(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 diff --git a/test.html b/test.html new file mode 100644 index 0000000..3a50ffb --- /dev/null +++ b/test.html @@ -0,0 +1,192 @@ + + + + + + + + + + + +

Morris.js tests

+

+
+

+
    +
    test markup, will be hidden
    + + \ No newline at end of file