From f72b14f6197fd3e23289bf3ec49f5a3b8eb1e7c7 Mon Sep 17 00:00:00 2001 From: Olly Smith Date: Sun, 28 Oct 2012 18:55:37 +0000 Subject: [PATCH] Initial area charts. --- examples/area.html | 29 ++ grunt.js | 8 +- lib/morris.area.coffee | 38 +++ lib/morris.grid.coffee | 21 +- lib/morris.line.coffee | 36 ++- morris.js | 616 ++++++++++++++++++++++++----------------- morris.min.js | 2 +- 7 files changed, 472 insertions(+), 278 deletions(-) create mode 100644 examples/area.html create mode 100644 lib/morris.area.coffee diff --git a/examples/area.html b/examples/area.html new file mode 100644 index 0000000..c3c71f5 --- /dev/null +++ b/examples/area.html @@ -0,0 +1,29 @@ + + + + + + + + + + + +

Area charts

+
+
+// Use Morris.Area instead of Morris.Line
+Morris.Area({
+  element: 'graph',
+  data: [
+    {x: '2011 Q1', y: 3, z: 3},
+    {x: '2011 Q2', y: 2, z: 0},
+    {x: '2011 Q3', y: 0, z: 2},
+    {x: '2011 Q4', y: 4, z: 4}
+  ],
+  xkey: 'x',
+  ykeys: ['y', 'z'],
+  labels: ['Y', 'Z']
+});
+
+ diff --git a/grunt.js b/grunt.js index df0e6e9..330fd37 100644 --- a/grunt.js +++ b/grunt.js @@ -13,7 +13,13 @@ module.exports = function (grunt) { } }, concat: { - 'build/morris.coffee': ['lib/**/*.coffee'], + 'build/morris.coffee': [ + 'lib/morris.coffee', + 'lib/morris.grid.coffee', + 'lib/morris.line.coffee', + 'lib/morris.area.coffee', + 'lib/morris.donut.coffee' + ], 'build/spec.coffee': ['spec/support/**/*.coffee', 'spec/lib/**/*.coffee'] }, min: { diff --git a/lib/morris.area.coffee b/lib/morris.area.coffee new file mode 100644 index 0000000..53b8130 --- /dev/null +++ b/lib/morris.area.coffee @@ -0,0 +1,38 @@ +class Morris.Area extends Morris.Line + # Initialise + # + constructor: (options) -> + return new Morris.Area(options) unless (@ instanceof Morris.Area) + @cumulative = true + super(options) + + # calculate series data point coordinates + # + # @private + calcPoints: -> + for row in @data + row._x = @transX(row.x) + total = 0 + row._y = for y in row.y + total += (y || 0) + @transY(total) + + # draw the data series + # + # @private + drawSeries: -> + for i in [@options.ykeys.length-1..0] + path = @paths[i] + if path isnt null + path = path + "L#{@transX(@xmax)},#{@bottom}L#{@transX(@xmin)},#{@bottom}Z" + @r.path(path) + .attr('fill', @fillForSeries(i)) + .attr('stroke-width', 0) + super() + + fillForSeries: (i) -> + color = Raphael.rgb2hsl @colorForSeries(i) + Raphael.hsl( + color.h, + Math.min(255, color.s * 0.75), + Math.min(255, color.l * 1.25)) diff --git a/lib/morris.grid.coffee b/lib/morris.grid.coffee index 989c4d4..f8462ac 100644 --- a/lib/morris.grid.coffee +++ b/lib/morris.grid.coffee @@ -55,8 +55,8 @@ class Morris.Grid extends Morris.EventEmitter # Update the data series and redraw the chart. # setData: (data, redraw = true) -> - ymax = null - ymin = null + ymax = if @cumulative then 0 else null + ymin = if @cumulative then 0 else null @data = $.map data, (row, index) => ret = {} ret.label = row[@options.xkey] @@ -68,16 +68,23 @@ class Morris.Grid extends Morris.EventEmitter ret.label = new Date(ret.label).toString() else ret.x = index - ret.y = for ykey in @options.ykeys + total = 0 + ret.y = for ykey, idx in @options.ykeys yval = row[ykey] yval = parseFloat(yval) if typeof yval is 'string' yval = null unless typeof yval is 'number' unless yval is null - if ymax is null - ymax = ymin = yval + if @cumulative + total += yval else - ymax = Math.max(yval, ymax) - ymin = Math.min(yval, ymin) + if ymax is null + ymax = ymin = yval + else + ymax = Math.max(yval, ymax) + ymin = Math.min(yval, ymin) + if @cumulative and total isnt null + ymax = Math.max(total, ymax) + ymin = Math.min(total, ymin) yval ret diff --git a/lib/morris.line.coffee b/lib/morris.line.coffee index b4091ff..0ef9d7b 100644 --- a/lib/morris.line.coffee +++ b/lib/morris.line.coffee @@ -59,7 +59,14 @@ class Morris.Line extends Morris.Grid # # @private calc: -> - # calculate series data point coordinates + @calcPoints() + @generatePaths() + @calcHoverMargins() + + # calculate series data point coordinates + # + # @private + calcPoints: -> for row in @data row._x = @transX(row.x) row._y = for y in row.y @@ -67,9 +74,25 @@ class Morris.Line extends Morris.Grid null else @transY(y) - # calculate hover margins + + # calculate hover margins + # + # @private + calcHoverMargins: -> @hoverMargins = $.map @data.slice(1), (r, i) => (r._x + @data[i]._x) / 2 + # generate paths for series lines + # + # @private + generatePaths: -> + @paths = for i in [0...@options.ykeys.length] + smooth = @options.smooth is true or @options.ykeys[i] in @options.smooth + coords = ({x: r._x, y: r._y[i]} for r in @data when r._y[i] isnt null) + if coords.length > 1 + @createPath coords, smooth + else + null + # Draws the line chart. # draw: -> @@ -116,11 +139,8 @@ class Morris.Line extends Morris.Grid # @private drawSeries: -> for i in [@options.ykeys.length-1..0] - coords = ({x: r._x, y: r._y[i]} for r in @data when r._y[i] isnt null) - smooth = @options.smooth is true or - $.inArray(@options.ykeys[i], @options.smooth) > -1 - if coords.length > 1 - path = @createPath coords, @bottom, smooth + path = @paths[i] + if path isnt null @r.path(path) .attr('stroke', @colorForSeries(i)) .attr('stroke-width', @options.lineWidth) @@ -213,7 +233,7 @@ class Morris.Line extends Morris.Grid @hover.attr 'width', maxLabelWidth + @options.hoverPaddingX * 2 @hover.attr 'x', -@options.hoverPaddingX - maxLabelWidth / 2 # move to y pos - yloc = Math.min.apply null, row.y + yloc = Math.min.apply null, row._y if yloc > @hoverHeight + @options.hoverPaddingY * 2 + @options.hoverMargin + @top yloc = yloc - @hoverHeight / 2 - @options.hoverPaddingY - @options.hoverMargin else diff --git a/morris.js b/morris.js index 8ffe404..e849d4a 100644 --- a/morris.js +++ b/morris.js @@ -1,9 +1,10 @@ (function() { var $, Morris, minutesSpecHelper, secondsSpecHelper, __slice = [].slice, - __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; Morris = window.Morris = {}; @@ -62,227 +63,6 @@ return (number < 10 ? '0' : '') + number; }; - Morris.Donut = (function() { - - Donut.prototype.defaults = { - colors: ['#0B62A4', '#3980B5', '#679DC6', '#95BBD7', '#B0CCE1', '#095791', '#095085', '#083E67', '#052C48', '#042135'], - formatter: Morris.commas - }; - - function Donut(options) { - this.select = __bind(this.select, this); - if (!(this instanceof Morris.Donut)) { - return new Morris.Donut(options); - } - if (typeof options.element === 'string') { - this.el = $(document.getElementById(options.element)); - } else { - this.el = $(options.element); - } - this.options = $.extend({}, this.defaults, options); - if (this.el === null || this.el.length === 0) { - throw new Error("Graph placeholder not found."); - } - if (options.data === void 0 || options.data.length === 0) { - return; - } - this.data = options.data; - this.el.addClass('graph-initialised'); - this.redraw(); - } - - Donut.prototype.redraw = function() { - var C, cx, cy, d, idx, last, max_value, min, next, seg, total, w, x, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results; - this.el.empty(); - this.r = new Raphael(this.el[0]); - cx = this.el.width() / 2; - cy = this.el.height() / 2; - w = (Math.min(cx, cy) - 10) / 3; - total = 0; - _ref = this.data; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - x = _ref[_i]; - total += x.value; - } - min = 5 / (2 * w); - C = 1.9999 * Math.PI - min * this.data.length; - last = 0; - idx = 0; - this.segments = []; - _ref1 = this.data; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - d = _ref1[_j]; - next = last + min + C * (d.value / total); - seg = new Morris.DonutSegment(cx, cy, w * 2, w, last, next, this.options.colors[idx % this.options.colors.length], d); - seg.render(this.r); - this.segments.push(seg); - seg.on('hover', this.select); - last = next; - idx += 1; - } - this.text1 = this.r.text(cx, cy - 10, '').attr({ - 'font-size': 15, - 'font-weight': 800 - }); - this.text2 = this.r.text(cx, cy + 10, '').attr({ - 'font-size': 14 - }); - max_value = Math.max.apply(null, (function() { - var _k, _len2, _ref2, _results; - _ref2 = this.data; - _results = []; - for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { - d = _ref2[_k]; - _results.push(d.value); - } - return _results; - }).call(this)); - idx = 0; - _ref2 = this.data; - _results = []; - for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { - d = _ref2[_k]; - if (d.value === max_value) { - this.select(idx); - break; - } - _results.push(idx += 1); - } - return _results; - }; - - Donut.prototype.select = function(idx) { - var s, segment, _i, _len, _ref; - _ref = this.segments; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - s = _ref[_i]; - s.deselect(); - } - if (typeof idx === 'number') { - segment = this.segments[idx]; - } else { - segment = idx; - } - segment.select(); - return this.setLabels(segment.data.label, this.options.formatter(segment.data.value)); - }; - - Donut.prototype.setLabels = function(label1, label2) { - var inner, maxHeightBottom, maxHeightTop, maxWidth, text1bbox, text1scale, text2bbox, text2scale; - inner = (Math.min(this.el.width() / 2, this.el.height() / 2) - 10) * 2 / 3; - maxWidth = 1.8 * inner; - maxHeightTop = inner / 2; - maxHeightBottom = inner / 3; - this.text1.attr({ - text: label1, - transform: '' - }); - text1bbox = this.text1.getBBox(); - text1scale = Math.min(maxWidth / text1bbox.width, maxHeightTop / text1bbox.height); - this.text1.attr({ - transform: "S" + text1scale + "," + text1scale + "," + (text1bbox.x + text1bbox.width / 2) + "," + (text1bbox.y + text1bbox.height) - }); - this.text2.attr({ - text: label2, - transform: '' - }); - text2bbox = this.text2.getBBox(); - text2scale = Math.min(maxWidth / text2bbox.width, maxHeightBottom / text2bbox.height); - return this.text2.attr({ - transform: "S" + text2scale + "," + text2scale + "," + (text2bbox.x + text2bbox.width / 2) + "," + text2bbox.y - }); - }; - - return Donut; - - })(); - - Morris.DonutSegment = (function(_super) { - - __extends(DonutSegment, _super); - - function DonutSegment(cx, cy, inner, outer, p0, p1, color, data) { - this.cx = cx; - this.cy = cy; - this.inner = inner; - this.outer = outer; - this.color = color; - this.data = data; - this.deselect = __bind(this.deselect, this); - - this.select = __bind(this.select, this); - - this.sin_p0 = Math.sin(p0); - this.cos_p0 = Math.cos(p0); - this.sin_p1 = Math.sin(p1); - this.cos_p1 = Math.cos(p1); - this.long = (p1 - p0) > Math.PI ? 1 : 0; - this.path = this.calcSegment(this.inner + 3, this.inner + this.outer - 5); - this.selectedPath = this.calcSegment(this.inner + 3, this.inner + this.outer); - this.hilight = this.calcArc(this.inner); - } - - DonutSegment.prototype.calcArcPoints = function(r) { - return [this.cx + r * this.sin_p0, this.cy + r * this.cos_p0, this.cx + r * this.sin_p1, this.cy + r * this.cos_p1]; - }; - - DonutSegment.prototype.calcSegment = function(r1, r2) { - var ix0, ix1, iy0, iy1, ox0, ox1, oy0, oy1, _ref, _ref1; - _ref = this.calcArcPoints(r1), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3]; - _ref1 = this.calcArcPoints(r2), ox0 = _ref1[0], oy0 = _ref1[1], ox1 = _ref1[2], oy1 = _ref1[3]; - return ("M" + ix0 + "," + iy0) + ("A" + r1 + "," + r1 + ",0," + this.long + ",0," + ix1 + "," + iy1) + ("L" + ox1 + "," + oy1) + ("A" + r2 + "," + r2 + ",0," + this.long + ",1," + ox0 + "," + oy0) + "Z"; - }; - - DonutSegment.prototype.calcArc = function(r) { - var ix0, ix1, iy0, iy1, _ref; - _ref = this.calcArcPoints(r), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3]; - return ("M" + ix0 + "," + iy0) + ("A" + r + "," + r + ",0," + this.long + ",0," + ix1 + "," + iy1); - }; - - DonutSegment.prototype.render = function(r) { - var _this = this; - this.arc = r.path(this.hilight).attr({ - stroke: this.color, - 'stroke-width': 2, - opacity: 0 - }); - return this.seg = r.path(this.path).attr({ - fill: this.color, - stroke: 'white', - 'stroke-width': 3 - }).hover(function() { - return _this.fire('hover', _this); - }); - }; - - DonutSegment.prototype.select = function() { - if (!this.selected) { - this.seg.animate({ - path: this.selectedPath - }, 150, '<>'); - this.arc.animate({ - opacity: 1 - }, 150, '<>'); - return this.selected = true; - } - }; - - DonutSegment.prototype.deselect = function() { - if (this.selected) { - this.seg.animate({ - path: this.path - }, 150, '<>'); - this.arc.animate({ - opacity: 0 - }, 150, '<>'); - return this.selected = false; - } - }; - - return DonutSegment; - - })(Morris.EventEmitter); - Morris.Grid = (function(_super) { __extends(Grid, _super); @@ -334,10 +114,10 @@ if (redraw == null) { redraw = true; } - ymax = null; - ymin = null; + ymax = this.cumulative ? 0 : null; + ymin = this.cumulative ? 0 : null; this.data = $.map(data, function(row, index) { - var ret, ykey, yval; + var idx, ret, total, ykey, yval; ret = {}; ret.label = row[_this.options.xkey]; if (_this.options.parseTime) { @@ -350,12 +130,13 @@ } else { ret.x = index; } + total = 0; ret.y = (function() { var _i, _len, _ref, _results; _ref = this.options.ykeys; _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - ykey = _ref[_i]; + for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) { + ykey = _ref[idx]; yval = row[ykey]; if (typeof yval === 'string') { yval = parseFloat(yval); @@ -364,13 +145,21 @@ yval = null; } if (yval !== null) { - if (ymax === null) { - ymax = ymin = yval; + if (this.cumulative) { + total += yval; } else { - ymax = Math.max(yval, ymax); - ymin = Math.min(yval, ymin); + if (ymax === null) { + ymax = ymin = yval; + } else { + ymax = Math.max(yval, ymax); + ymin = Math.min(yval, ymin); + } } } + if (this.cumulative && total !== null) { + ymax = Math.max(total, ymax); + ymin = Math.min(total, ymin); + } _results.push(yval); } return _results; @@ -644,32 +433,75 @@ }; Line.prototype.calc = function() { - var row, y, _i, _len, _ref, - _this = this; + this.calcPoints(); + this.generatePaths(); + return this.calcHoverMargins(); + }; + + Line.prototype.calcPoints = function() { + var row, y, _i, _len, _ref, _results; _ref = this.data; + _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { row = _ref[_i]; row._x = this.transX(row.x); - row._y = (function() { - var _j, _len1, _ref1, _results; + _results.push(row._y = (function() { + var _j, _len1, _ref1, _results1; _ref1 = row.y; - _results = []; + _results1 = []; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { y = _ref1[_j]; if (y === null) { - _results.push(null); + _results1.push(null); } else { - _results.push(this.transY(y)); + _results1.push(this.transY(y)); } } - return _results; - }).call(this); + return _results1; + }).call(this)); } + return _results; + }; + + Line.prototype.calcHoverMargins = function() { + var _this = this; return this.hoverMargins = $.map(this.data.slice(1), function(r, i) { return (r._x + _this.data[i]._x) / 2; }); }; + Line.prototype.generatePaths = function() { + var coords, i, r, smooth; + return this.paths = (function() { + var _i, _ref, _ref1, _results; + _results = []; + for (i = _i = 0, _ref = this.options.ykeys.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) { + smooth = this.options.smooth === true || (_ref1 = this.options.ykeys[i], __indexOf.call(this.options.smooth, _ref1) >= 0); + coords = (function() { + var _j, _len, _ref2, _results1; + _ref2 = this.data; + _results1 = []; + for (_j = 0, _len = _ref2.length; _j < _len; _j++) { + r = _ref2[_j]; + if (r._y[i] !== null) { + _results1.push({ + x: r._x, + y: r._y[i] + }); + } + } + return _results1; + }).call(this); + if (coords.length > 1) { + _results.push(this.createPath(coords, smooth)); + } else { + _results.push(null); + } + } + return _results; + }).call(this); + }; + Line.prototype.draw = function() { this.drawXAxis(); this.drawSeries(); @@ -717,26 +549,10 @@ }; Line.prototype.drawSeries = function() { - var circle, coords, i, path, r, row, smooth, _i, _j, _ref, _ref1, _results; + var circle, i, path, row, _i, _j, _ref, _ref1, _results; for (i = _i = _ref = this.options.ykeys.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) { - coords = (function() { - var _j, _len, _ref1, _results; - _ref1 = this.data; - _results = []; - for (_j = 0, _len = _ref1.length; _j < _len; _j++) { - r = _ref1[_j]; - if (r._y[i] !== null) { - _results.push({ - x: r._x, - y: r._y[i] - }); - } - } - return _results; - }).call(this); - smooth = this.options.smooth === true || $.inArray(this.options.ykeys[i], this.options.smooth) > -1; - if (coords.length > 1) { - path = this.createPath(coords, this.bottom, smooth); + path = this.paths[i]; + if (path !== null) { this.r.path(path).attr('stroke', this.colorForSeries(i)).attr('stroke-width', this.options.lineWidth); } } @@ -844,7 +660,7 @@ 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, row.y); + yloc = Math.min.apply(null, row._y); if (yloc > this.hoverHeight + this.options.hoverPaddingY * 2 + this.options.hoverMargin + this.top) { yloc = yloc - this.hoverHeight / 2 - this.options.hoverPaddingY - this.options.hoverMargin; } else { @@ -1032,4 +848,282 @@ Morris.AUTO_LABEL_ORDER = ["year", "month", "day", "hour", "30min", "15min", "10min", "5min", "minute", "30sec", "15sec", "10sec", "5sec", "second"]; + Morris.Area = (function(_super) { + + __extends(Area, _super); + + function Area(options) { + if (!(this instanceof Morris.Area)) { + return new Morris.Area(options); + } + this.cumulative = true; + Area.__super__.constructor.call(this, options); + } + + Area.prototype.calcPoints = function() { + var row, total, y, _i, _len, _ref, _results; + _ref = this.data; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + row = _ref[_i]; + row._x = this.transX(row.x); + total = 0; + _results.push(row._y = (function() { + var _j, _len1, _ref1, _results1; + _ref1 = row.y; + _results1 = []; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + y = _ref1[_j]; + total += y || 0; + _results1.push(this.transY(total)); + } + return _results1; + }).call(this)); + } + return _results; + }; + + Area.prototype.drawSeries = function() { + var i, path, _i, _ref; + for (i = _i = _ref = this.options.ykeys.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) { + path = this.paths[i]; + if (path !== null) { + path = path + ("L" + (this.transX(this.xmax)) + "," + this.bottom + "L" + (this.transX(this.xmin)) + "," + this.bottom + "Z"); + this.r.path(path).attr('fill', this.fillForSeries(i)).attr('stroke-width', 0); + } + } + return Area.__super__.drawSeries.call(this); + }; + + Area.prototype.fillForSeries = function(i) { + var color; + color = Raphael.rgb2hsl(this.colorForSeries(i)); + return Raphael.hsl(color.h, Math.min(255, color.s * 0.75), Math.min(255, color.l * 1.25)); + }; + + return Area; + + })(Morris.Line); + + Morris.Donut = (function() { + + Donut.prototype.defaults = { + colors: ['#0B62A4', '#3980B5', '#679DC6', '#95BBD7', '#B0CCE1', '#095791', '#095085', '#083E67', '#052C48', '#042135'], + formatter: Morris.commas + }; + + function Donut(options) { + this.select = __bind(this.select, this); + if (!(this instanceof Morris.Donut)) { + return new Morris.Donut(options); + } + if (typeof options.element === 'string') { + this.el = $(document.getElementById(options.element)); + } else { + this.el = $(options.element); + } + this.options = $.extend({}, this.defaults, options); + if (this.el === null || this.el.length === 0) { + throw new Error("Graph placeholder not found."); + } + if (options.data === void 0 || options.data.length === 0) { + return; + } + this.data = options.data; + this.el.addClass('graph-initialised'); + this.redraw(); + } + + Donut.prototype.redraw = function() { + var C, cx, cy, d, idx, last, max_value, min, next, seg, total, w, x, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results; + this.el.empty(); + this.r = new Raphael(this.el[0]); + cx = this.el.width() / 2; + cy = this.el.height() / 2; + w = (Math.min(cx, cy) - 10) / 3; + total = 0; + _ref = this.data; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + x = _ref[_i]; + total += x.value; + } + min = 5 / (2 * w); + C = 1.9999 * Math.PI - min * this.data.length; + last = 0; + idx = 0; + this.segments = []; + _ref1 = this.data; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + d = _ref1[_j]; + next = last + min + C * (d.value / total); + seg = new Morris.DonutSegment(cx, cy, w * 2, w, last, next, this.options.colors[idx % this.options.colors.length], d); + seg.render(this.r); + this.segments.push(seg); + seg.on('hover', this.select); + last = next; + idx += 1; + } + this.text1 = this.r.text(cx, cy - 10, '').attr({ + 'font-size': 15, + 'font-weight': 800 + }); + this.text2 = this.r.text(cx, cy + 10, '').attr({ + 'font-size': 14 + }); + max_value = Math.max.apply(null, (function() { + var _k, _len2, _ref2, _results; + _ref2 = this.data; + _results = []; + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + d = _ref2[_k]; + _results.push(d.value); + } + return _results; + }).call(this)); + idx = 0; + _ref2 = this.data; + _results = []; + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + d = _ref2[_k]; + if (d.value === max_value) { + this.select(idx); + break; + } + _results.push(idx += 1); + } + return _results; + }; + + Donut.prototype.select = function(idx) { + var s, segment, _i, _len, _ref; + _ref = this.segments; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + s = _ref[_i]; + s.deselect(); + } + if (typeof idx === 'number') { + segment = this.segments[idx]; + } else { + segment = idx; + } + segment.select(); + return this.setLabels(segment.data.label, this.options.formatter(segment.data.value)); + }; + + Donut.prototype.setLabels = function(label1, label2) { + var inner, maxHeightBottom, maxHeightTop, maxWidth, text1bbox, text1scale, text2bbox, text2scale; + inner = (Math.min(this.el.width() / 2, this.el.height() / 2) - 10) * 2 / 3; + maxWidth = 1.8 * inner; + maxHeightTop = inner / 2; + maxHeightBottom = inner / 3; + this.text1.attr({ + text: label1, + transform: '' + }); + text1bbox = this.text1.getBBox(); + text1scale = Math.min(maxWidth / text1bbox.width, maxHeightTop / text1bbox.height); + this.text1.attr({ + transform: "S" + text1scale + "," + text1scale + "," + (text1bbox.x + text1bbox.width / 2) + "," + (text1bbox.y + text1bbox.height) + }); + this.text2.attr({ + text: label2, + transform: '' + }); + text2bbox = this.text2.getBBox(); + text2scale = Math.min(maxWidth / text2bbox.width, maxHeightBottom / text2bbox.height); + return this.text2.attr({ + transform: "S" + text2scale + "," + text2scale + "," + (text2bbox.x + text2bbox.width / 2) + "," + text2bbox.y + }); + }; + + return Donut; + + })(); + + Morris.DonutSegment = (function(_super) { + + __extends(DonutSegment, _super); + + function DonutSegment(cx, cy, inner, outer, p0, p1, color, data) { + this.cx = cx; + this.cy = cy; + this.inner = inner; + this.outer = outer; + this.color = color; + this.data = data; + this.deselect = __bind(this.deselect, this); + + this.select = __bind(this.select, this); + + this.sin_p0 = Math.sin(p0); + this.cos_p0 = Math.cos(p0); + this.sin_p1 = Math.sin(p1); + this.cos_p1 = Math.cos(p1); + this.long = (p1 - p0) > Math.PI ? 1 : 0; + this.path = this.calcSegment(this.inner + 3, this.inner + this.outer - 5); + this.selectedPath = this.calcSegment(this.inner + 3, this.inner + this.outer); + this.hilight = this.calcArc(this.inner); + } + + DonutSegment.prototype.calcArcPoints = function(r) { + return [this.cx + r * this.sin_p0, this.cy + r * this.cos_p0, this.cx + r * this.sin_p1, this.cy + r * this.cos_p1]; + }; + + DonutSegment.prototype.calcSegment = function(r1, r2) { + var ix0, ix1, iy0, iy1, ox0, ox1, oy0, oy1, _ref, _ref1; + _ref = this.calcArcPoints(r1), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3]; + _ref1 = this.calcArcPoints(r2), ox0 = _ref1[0], oy0 = _ref1[1], ox1 = _ref1[2], oy1 = _ref1[3]; + return ("M" + ix0 + "," + iy0) + ("A" + r1 + "," + r1 + ",0," + this.long + ",0," + ix1 + "," + iy1) + ("L" + ox1 + "," + oy1) + ("A" + r2 + "," + r2 + ",0," + this.long + ",1," + ox0 + "," + oy0) + "Z"; + }; + + DonutSegment.prototype.calcArc = function(r) { + var ix0, ix1, iy0, iy1, _ref; + _ref = this.calcArcPoints(r), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3]; + return ("M" + ix0 + "," + iy0) + ("A" + r + "," + r + ",0," + this.long + ",0," + ix1 + "," + iy1); + }; + + DonutSegment.prototype.render = function(r) { + var _this = this; + this.arc = r.path(this.hilight).attr({ + stroke: this.color, + 'stroke-width': 2, + opacity: 0 + }); + return this.seg = r.path(this.path).attr({ + fill: this.color, + stroke: 'white', + 'stroke-width': 3 + }).hover(function() { + return _this.fire('hover', _this); + }); + }; + + DonutSegment.prototype.select = function() { + if (!this.selected) { + this.seg.animate({ + path: this.selectedPath + }, 150, '<>'); + this.arc.animate({ + opacity: 1 + }, 150, '<>'); + return this.selected = true; + } + }; + + DonutSegment.prototype.deselect = function() { + if (this.selected) { + this.seg.animate({ + path: this.path + }, 150, '<>'); + this.arc.animate({ + opacity: 0 + }, 150, '<>'); + return this.selected = false; + } + }; + + return DonutSegment; + + })(Morris.EventEmitter); + }).call(this); diff --git a/morris.min.js b/morris.min.js index 8d8ed3b..90929ca 100644 --- a/morris.min.js +++ b/morris.min.js @@ -1 +1 @@ -(function(){var e,t,n,r,i=[].slice,s=function(e,t){return function(){return e.apply(t,arguments)}},o={}.hasOwnProperty,u=function(e,t){function r(){this.constructor=e}for(var n in t)o.call(t,n)&&(e[n]=t[n]);return r.prototype=t.prototype,e.prototype=new r,e.__super__=t.prototype,e};t=window.Morris={},e=jQuery,t.EventEmitter=function(){function e(){}return e.prototype.on=function(e,t){return this.handlers==null&&(this.handlers={}),this.handlers[e]==null&&(this.handlers[e]=[]),this.handlers[e].push(t)},e.prototype.fire=function(){var e,t,n,r,s,o,u;n=arguments[0],e=2<=arguments.length?i.call(arguments,1):[];if(this.handlers!=null&&this.handlers[n]!=null){o=this.handlers[n],u=[];for(r=0,s=o.length;rn.length&&(r+=i.slice(n.length)),r)},t.pad2=function(e){return(e<10?"0":"")+e},t.Donut=function(){function n(n){this.select=s(this.select,this);if(!(this instanceof t.Donut))return new t.Donut(n);typeof n.element=="string"?this.el=e(document.getElementById(n.element)):this.el=e(n.element),this.options=e.extend({},this.defaults,n);if(this.el===null||this.el.length===0)throw new Error("Graph placeholder not found.");if(n.data===void 0||n.data.length===0)return;this.data=n.data,this.el.addClass("graph-initialised"),this.redraw()}return n.prototype.defaults={colors:["#0B62A4","#3980B5","#679DC6","#95BBD7","#B0CCE1","#095791","#095085","#083E67","#052C48","#042135"],formatter:t.commas},n.prototype.redraw=function(){var e,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,x;this.el.empty(),this.r=new Raphael(this.el[0]),n=this.el.width()/2,r=this.el.height()/2,h=(Math.min(n,r)-10)/3,c=0,w=this.data;for(d=0,g=w.length;dMath.PI?1:0,this.path=this.calcSegment(this.inner+3,this.inner+this.outer-5),this.selectedPath=this.calcSegment(this.inner+3,this.inner+this.outer),this.hilight=this.calcArc(this.inner)}return u(t,e),t.prototype.calcArcPoints=function(e){return[this.cx+e*this.sin_p0,this.cy+e*this.cos_p0,this.cx+e*this.sin_p1,this.cy+e*this.cos_p1]},t.prototype.calcSegment=function(e,t){var n,r,i,s,o,u,a,f,l,c;return l=this.calcArcPoints(e),n=l[0],i=l[1],r=l[2],s=l[3],c=this.calcArcPoints(t),o=c[0],a=c[1],u=c[2],f=c[3],"M"+n+","+i+("A"+e+","+e+",0,"+this.long+",0,"+r+","+s)+("L"+u+","+f)+("A"+t+","+t+",0,"+this.long+",1,"+o+","+a)+"Z"},t.prototype.calcArc=function(e){var t,n,r,i,s;return s=this.calcArcPoints(e),t=s[0],r=s[1],n=s[2],i=s[3],"M"+t+","+r+("A"+e+","+e+",0,"+this.long+",0,"+n+","+i)},t.prototype.render=function(e){var t=this;return this.arc=e.path(this.hilight).attr({stroke:this.color,"stroke-width":2,opacity:0}),this.seg=e.path(this.path).attr({fill:this.color,stroke:"white","stroke-width":3}).hover(function(){return t.fire("hover",t)})},t.prototype.select=function(){if(!this.selected)return this.seg.animate({path:this.selectedPath},150,"<>"),this.arc.animate({opacity:1},150,"<>"),this.selected=!0},t.prototype.deselect=function(){if(this.selected)return this.seg.animate({path:this.path},150,"<>"),this.arc.animate({opacity:0},150,"<>"),this.selected=!1},t}(t.EventEmitter),t.Grid=function(n){function r(t){typeof t.element=="string"?this.el=e(document.getElementById(t.element)):this.el=e(t.element);if(this.el===null||this.el.length===0)throw new Error("Graph container element not found");this.options=e.extend({},this.gridDefaults,this.defaults||{},t);if(this.options.data===void 0||this.options.data.length===0)return;typeof this.options.units=="string"&&(this.options.postUnits=t.units),this.r=new Raphael(this.el[0]),this.elementWidth=null,this.elementHeight=null,this.dirty=!1,this.init&&this.init(),this.setData(this.options.data)}return u(r,n),r.prototype.gridDefaults={dateFormat:null,gridLineColor:"#aaa",gridStrokeWidth:.5,gridTextColor:"#888",gridTextSize:12,numLines:5,padding:25,parseTime:!0,postUnits:"",preUnits:"",ymax:"auto",ymin:"auto 0"},r.prototype.setData=function(n,r){var i,s,o=this;r==null&&(r=!0),i=null,s=null,this.data=e.map(n,function(e,n){var r,u,a;return r={},r.label=e[o.options.xkey],o.options.parseTime?(r.x=t.parseDate(r.label),o.options.dateFormat?r.label=o.options.dateFormat(r.x):typeof r.label=="number"&&(r.label=(new Date(r.label)).toString())):r.x=n,r.y=function(){var t,n,r,o;r=this.options.ykeys,o=[];for(t=0,n=r.length;tt.x)-(t.x>e.x)})),this.xmin=this.data[0].x,this.xmax=this.data[this.data.length-1].x,this.xmin===this.xmax&&(this.xmin-=1,this.xmax+=1),typeof this.options.ymax=="string"?this.options.ymax.slice(0,4)==="auto"?this.options.ymax.length>5?(this.ymax=parseInt(this.options.ymax.slice(5),10),i!==null&&(this.ymax=Math.max(i,this.ymax))):this.ymax=i!==null?i:0:this.ymax=parseInt(this.options.ymax,10):this.ymax=this.options.ymax,typeof this.options.ymin=="string"?this.options.ymin.slice(0,4)==="auto"?this.options.ymin.length>5?(this.ymin=parseInt(this.options.ymin.slice(5),10),s!==null&&(this.ymin=Math.min(s,this.ymin))):this.ymin=s!==null?s:0:this.ymin=parseInt(this.options.ymin,10):this.ymin=this.options.ymin,this.ymin===this.ymax&&(s&&(this.ymin-=1),this.ymax+=1),this.yInterval=(this.ymax-this.ymin)/(this.options.numLines-1),this.yInterval>0&&this.yInterval<1?this.precision=-Math.floor(Math.log(this.yInterval)/Math.log(10)):this.precision=0,this.dirty=!0;if(r)return this.redraw()},r.prototype._calc=function(){var e,t,n;n=this.el.width(),e=this.el.height();if(this.elementWidth!==n||this.elementHeight!==e||this.dirty){this.elementWidth=n,this.elementHeight=e,this.dirty=!1,t=Math.max(this.measureText(this.yAxisFormat(this.ymin),this.options.gridTextSize).width,this.measureText(this.yAxisFormat(this.ymax),this.options.gridTextSize).width),this.left=t+this.options.padding,this.right=this.elementWidth-this.options.padding,this.top=this.options.padding,this.bottom=this.elementHeight-this.options.padding-1.5*this.options.gridTextSize,this.width=this.right-this.left,this.height=this.bottom-this.top,this.dx=this.width/(this.xmax-this.xmin),this.dy=this.height/(this.ymax-this.ymin);if(this.calc)return this.calc()}},r.prototype.transY=function(e){return this.bottom-(e-this.ymin)*this.dy},r.prototype.transX=function(e){return this.data.length===1?(this.left+this.right)/2:this.left+(e-this.xmin)*this.dx},r.prototype.redraw=function(){this.r.clear(),this._calc(),this.drawGrid();if(this.draw)return this.draw()},r.prototype.drawGrid=function(){var e,t,n,r,i,s,o,u;e=this.ymin,t=this.ymax,u=[];for(n=s=e,o=this.yInterval;e<=t?s<=t:s>=t;n=s+=o)r=parseFloat(n.toFixed(this.precision)),i=this.transY(r),this.r.text(this.left-this.options.padding/2,i,this.yAxisFormat(r)).attr("font-size",this.options.gridTextSize).attr("fill",this.options.gridTextColor).attr("text-anchor","end"),u.push(this.r.path("M"+this.left+","+i+"H"+(this.left+this.width)).attr("stroke",this.options.gridLineColor).attr("stroke-width",this.options.gridStrokeWidth));return u},r.prototype.measureText=function(e,t){var n,r;return t==null&&(t=12),r=this.r.text(100,100,e).attr("font-size",t),n=r.getBBox(),r.remove(),n},r.prototype.yAxisFormat=function(e){return this.yLabelFormat(e)},r.prototype.yLabelFormat=function(e){return""+this.options.preUnits+t.commas(e)+this.options.postUnits},r}(t.EventEmitter),t.parseDate=function(e){var t,n,r,i,s,o,u,a,f,l,c;return typeof e=="number"?e:(n=e.match(/^(\d+) Q(\d)$/),i=e.match(/^(\d+)-(\d+)$/),s=e.match(/^(\d+)-(\d+)-(\d+)$/),u=e.match(/^(\d+) W(\d+)$/),a=e.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)(Z|([+-])(\d\d):?(\d\d))?$/),f=e.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)(Z|([+-])(\d\d):?(\d\d))?$/),n?(new Date(parseInt(n[1],10),parseInt(n[2],10)*3-1,1)).getTime():i?(new Date(parseInt(i[1],10),parseInt(i[2],10)-1,1)).getTime():s?(new Date(parseInt(s[1],10),parseInt(s[2],10)-1,parseInt(s[3],10))).getTime():u?(l=new Date(parseInt(u[1],10),0,1),l.getDay()!==4&&l.setMonth(0,1+(4-l.getDay()+7)%7),l.getTime()+parseInt(u[2],10)*6048e5):a?a[6]?(o=0,a[6]!=="Z"&&(o=parseInt(a[8],10)*60+parseInt(a[9],10),a[7]==="+"&&(o=0-o)),Date.UTC(parseInt(a[1],10),parseInt(a[2],10)-1,parseInt(a[3],10),parseInt(a[4],10),parseInt(a[5],10)+o)):(new Date(parseInt(a[1],10),parseInt(a[2],10)-1,parseInt(a[3],10),parseInt(a[4],10),parseInt(a[5],10))).getTime():f?(c=parseFloat(f[6]),t=Math.floor(c),r=Math.round((c-t)*1e3),f[8]?(o=0,f[8]!=="Z"&&(o=parseInt(f[10],10)*60+parseInt(f[11],10),f[9]==="+"&&(o=0-o)),Date.UTC(parseInt(f[1],10),parseInt(f[2],10)-1,parseInt(f[3],10),parseInt(f[4],10),parseInt(f[5],10)+o,t,r)):(new Date(parseInt(f[1],10),parseInt(f[2],10)-1,parseInt(f[3],10),parseInt(f[4],10),parseInt(f[5],10),t,r)).getTime()):(new Date(parseInt(e,10),0,1)).getTime())},t.Line=function(n){function r(e){this.updateHilight=s(this.updateHilight,this),this.hilight=s(this.hilight,this),this.updateHover=s(this.updateHover,this);if(!(this instanceof t.Line))return new t.Line(e);r.__super__.constructor.call(this,e)}return u(r,n),r.prototype.init=function(){var e,t=this;return this.pointGrow=Raphael.animation({r:this.options.pointSize+3},25,"linear"),this.pointShrink=Raphael.animation({r:this.options.pointSize},25,"linear"),this.prevHilight=null,this.el.mousemove(function(e){return t.updateHilight(e.pageX)}),this.options.hideHover&&this.el.mouseout(function(e){return t.hilight(null)}),e=function(e){var n;return n=e.originalEvent.touches[0]||e.originalEvent.changedTouches[0],t.updateHilight(n.pageX),n},this.el.bind("touchstart",e),this.el.bind("touchmove",e),this.el.bind("touchend",e)},r.prototype.defaults={lineWidth:3,pointSize:4,lineColors:["#0b62a4","#7A92A3","#4da74d","#afd8f8","#edc240","#cb4b4b","#9440ed"],pointWidths:[1],pointStrokeColors:["#ffffff"],pointFillColors:[],hoverPaddingX:10,hoverPaddingY:5,hoverMargin:10,hoverFillColor:"#fff",hoverBorderColor:"#ccc",hoverBorderWidth:2,hoverOpacity:.95,hoverLabelColor:"#444",hoverFontSize:12,smooth:!0,hideHover:!1,xLabels:"auto",xLabelFormat:null},r.prototype.calc=function(){var t,n,r,i,s,o=this;s=this.data;for(r=0,i=s.length;r=0&&i.x+i.width=0;r=l<=0?++a:--a)n=function(){var e,t,n,i;n=this.data,i=[];for(e=0,t=n.length;e-1,n.length>1&&(i=this.createPath(n,this.bottom,u),this.r.path(i).attr("stroke",this.colorForSeries(r)).attr("stroke-width",this.options.lineWidth));this.seriesPoints=function(){var e,t,n;n=[];for(r=e=0,t=this.options.ykeys.length;0<=t?et;r=0<=t?++e:--e)n.push([]);return n}.call(this),h=[];for(r=f=c=this.options.ykeys.length-1;c<=0?f<=0:f>=0;r=c<=0?++f:--f)h.push(function(){var e,n,i,s;i=this.data,s=[];for(e=0,n=i.length;e=m;o=0<=m?++v:--v)r=t[o],o===0?l+="M"+r.x+","+r.y:(i=s[o],a=t[o-1],f=s[o-1],u=(r.x-a.x)/4,c=a.x+u,p=Math.min(this.bottom,a.y+u*f),h=r.x-u,d=Math.min(this.bottom,r.y-u*i),l+="C"+c+","+p+","+h+","+d+","+r.x+","+r.y)}else l="M"+e.map(t,function(e){return""+e.x+","+e.y}).join("L");return l},r.prototype.gradients=function(t){return e.map(t,function(e,n){return n===0?(t[1].y-e.y)/(t[1].x-e.x):n===t.length-1?(e.y-t[n-1].y)/(e.x-t[n-1].x):(t[n+1].y-t[n-1].y)/(t[n+1].x-t[n-1].x)})},r.prototype.drawHover=function(){var e,t,n,r,i;this.hoverHeight=this.options.hoverFontSize*1.5*(this.options.ykeys.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=[],i=[];for(e=n=0,r=this.options.ykeys.length;0<=r?nr;e=0<=r?++n:--n)t=this.r.text(0,this.options.hoverFontSize*1.5*(e+1.5)-this.hoverHeight/2,"").attr("fill",this.colorForSeries(e)).attr("font-size",this.options.hoverFontSize),this.yLabels.push(t),i.push(this.hoverSet.push(t));return i},r.prototype.updateHover=function(t){var n,r,i,s,o,u,a,f,l;this.hoverSet.show(),i=this.data[t],this.xLabel.attr("text",i.label),l=i.y;for(n=a=0,f=l.length;athis.hoverHeight+this.options.hoverPaddingY*2+this.options.hoverMargin+this.top?u=u-this.hoverHeight/2-this.options.hoverPaddingY-this.options.hoverMargin:u=u+this.hoverHeight/2+this.options.hoverPaddingY+this.options.hoverMargin,u=Math.max(this.top+this.hoverHeight/2+this.options.hoverPaddingY,u),u=Math.min(this.bottom-this.hoverHeight/2-this.options.hoverPaddingY,u),s=Math.min(this.right-r/2-this.options.hoverPaddingX,this.data[t]._x),s=Math.max(this.left+r/2+this.options.hoverPaddingX,s),this.hoverSet.attr("transform","t"+s+","+u)},r.prototype.hideHover=function(){return this.hoverSet.hide()},r.prototype.hilight=function(e){var t,n,r,i,s;if(this.prevHilight!==null&&this.prevHilight!==e)for(t=n=0,i=this.seriesPoints.length-1;0<=i?n<=i:n>=i;t=0<=i?++n:--n)this.seriesPoints[t][this.prevHilight]&&this.seriesPoints[t][this.prevHilight].animate(this.pointShrink);if(e!==null&&this.prevHilight!==e){for(t=r=0,s=this.seriesPoints.length-1;0<=s?r<=s:r>=s;t=0<=s?++r:--r)this.seriesPoints[t][e]&&this.seriesPoints[t][e].animate(this.pointGrow);this.updateHover(e)}this.prevHilight=e;if(e===null)return this.hideHover()},r.prototype.updateHilight=function(e){var t,n,r;e-=this.el.offset().left;for(t=n=0,r=this.hoverMargins.length;0<=r?nr;t=0<=r?++n:--n)if(this.hoverMargins[t]>e)break;return this.hilight(t)},r.prototype.colorForSeries=function(e){return this.options.lineColors[e%this.options.lineColors.length]},r.prototype.strokeWidthForSeries=function(e){return this.options.pointWidths[e%this.options.pointWidths.length]},r.prototype.strokeForSeries=function(e){return this.options.pointStrokeColors[e%this.options.pointStrokeColors.length]},r.prototype.pointFillColorForSeries=function(e){return this.options.pointFillColors[e%this.options.pointFillColors.length]},r}(t.Grid),t.labelSeries=function(n,r,i,s,o){var u,a,f,l,c,h,p,d,v,m,g;f=200*(r-n)/i,a=new Date(n),p=t.LABEL_SPECS[s];if(p===void 0){g=t.AUTO_LABEL_ORDER;for(v=0,m=g.length;v=h.span){p=h;break}}}p===void 0&&(p=t.LABEL_SPECS.second),o&&(p=e.extend({},p,{fmt:o})),u=p.start(a),c=[];while((d=u.getTime())<=r)d>=n&&c.push([p.fmt(u),d]),p.incr(u);return c},n=function(e){return{span:e*60*1e3,start:function(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours())},fmt:function(e){return""+t.pad2(e.getHours())+":"+t.pad2(e.getMinutes())},incr:function(t){return t.setMinutes(t.getMinutes()+e)}}},r=function(e){return{span:e*1e3,start:function(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes())},fmt:function(e){return""+t.pad2(e.getHours())+":"+t.pad2(e.getMinutes())+":"+t.pad2(e.getSeconds())},incr:function(t){return t.setSeconds(t.getSeconds()+e)}}},t.LABEL_SPECS={year:{span:1728e7,start:function(e){return new Date(e.getFullYear(),0,1)},fmt:function(e){return""+e.getFullYear()},incr:function(e){return e.setFullYear(e.getFullYear()+1)}},month:{span:24192e5,start:function(e){return new Date(e.getFullYear(),e.getMonth(),1)},fmt:function(e){return""+e.getFullYear()+"-"+t.pad2(e.getMonth()+1)},incr:function(e){return e.setMonth(e.getMonth()+1)}},day:{span:864e5,start:function(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate())},fmt:function(e){return""+e.getFullYear()+"-"+t.pad2(e.getMonth()+1)+"-"+t.pad2(e.getDate())},incr:function(e){return e.setDate(e.getDate()+1)}},hour:n(60),"30min":n(30),"15min":n(15),"10min":n(10),"5min":n(5),minute:n(1),"30sec":r(30),"15sec":r(15),"10sec":r(10),"5sec":r(5),second:r(1)},t.AUTO_LABEL_ORDER=["year","month","day","hour","30min","15min","10min","5min","minute","30sec","15sec","10sec","5sec","second"]}).call(this); \ No newline at end of file +(function(){var e,t,n,r,i=[].slice,s={}.hasOwnProperty,o=function(e,t){function r(){this.constructor=e}for(var n in t)s.call(t,n)&&(e[n]=t[n]);return r.prototype=t.prototype,e.prototype=new r,e.__super__=t.prototype,e},u=function(e,t){return function(){return e.apply(t,arguments)}},a=[].indexOf||function(e){for(var t=0,n=this.length;tn.length&&(r+=i.slice(n.length)),r)},t.pad2=function(e){return(e<10?"0":"")+e},t.Grid=function(n){function r(t){typeof t.element=="string"?this.el=e(document.getElementById(t.element)):this.el=e(t.element);if(this.el===null||this.el.length===0)throw new Error("Graph container element not found");this.options=e.extend({},this.gridDefaults,this.defaults||{},t);if(this.options.data===void 0||this.options.data.length===0)return;typeof this.options.units=="string"&&(this.options.postUnits=t.units),this.r=new Raphael(this.el[0]),this.elementWidth=null,this.elementHeight=null,this.dirty=!1,this.init&&this.init(),this.setData(this.options.data)}return o(r,n),r.prototype.gridDefaults={dateFormat:null,gridLineColor:"#aaa",gridStrokeWidth:.5,gridTextColor:"#888",gridTextSize:12,numLines:5,padding:25,parseTime:!0,postUnits:"",preUnits:"",ymax:"auto",ymin:"auto 0"},r.prototype.setData=function(n,r){var i,s,o=this;r==null&&(r=!0),i=this.cumulative?0:null,s=this.cumulative?0:null,this.data=e.map(n,function(e,n){var r,u,a,f,l;return u={},u.label=e[o.options.xkey],o.options.parseTime?(u.x=t.parseDate(u.label),o.options.dateFormat?u.label=o.options.dateFormat(u.x):typeof u.label=="number"&&(u.label=(new Date(u.label)).toString())):u.x=n,a=0,u.y=function(){var t,n,o,u;o=this.options.ykeys,u=[];for(r=t=0,n=o.length;tt.x)-(t.x>e.x)})),this.xmin=this.data[0].x,this.xmax=this.data[this.data.length-1].x,this.xmin===this.xmax&&(this.xmin-=1,this.xmax+=1),typeof this.options.ymax=="string"?this.options.ymax.slice(0,4)==="auto"?this.options.ymax.length>5?(this.ymax=parseInt(this.options.ymax.slice(5),10),i!==null&&(this.ymax=Math.max(i,this.ymax))):this.ymax=i!==null?i:0:this.ymax=parseInt(this.options.ymax,10):this.ymax=this.options.ymax,typeof this.options.ymin=="string"?this.options.ymin.slice(0,4)==="auto"?this.options.ymin.length>5?(this.ymin=parseInt(this.options.ymin.slice(5),10),s!==null&&(this.ymin=Math.min(s,this.ymin))):this.ymin=s!==null?s:0:this.ymin=parseInt(this.options.ymin,10):this.ymin=this.options.ymin,this.ymin===this.ymax&&(s&&(this.ymin-=1),this.ymax+=1),this.yInterval=(this.ymax-this.ymin)/(this.options.numLines-1),this.yInterval>0&&this.yInterval<1?this.precision=-Math.floor(Math.log(this.yInterval)/Math.log(10)):this.precision=0,this.dirty=!0;if(r)return this.redraw()},r.prototype._calc=function(){var e,t,n;n=this.el.width(),e=this.el.height();if(this.elementWidth!==n||this.elementHeight!==e||this.dirty){this.elementWidth=n,this.elementHeight=e,this.dirty=!1,t=Math.max(this.measureText(this.yAxisFormat(this.ymin),this.options.gridTextSize).width,this.measureText(this.yAxisFormat(this.ymax),this.options.gridTextSize).width),this.left=t+this.options.padding,this.right=this.elementWidth-this.options.padding,this.top=this.options.padding,this.bottom=this.elementHeight-this.options.padding-1.5*this.options.gridTextSize,this.width=this.right-this.left,this.height=this.bottom-this.top,this.dx=this.width/(this.xmax-this.xmin),this.dy=this.height/(this.ymax-this.ymin);if(this.calc)return this.calc()}},r.prototype.transY=function(e){return this.bottom-(e-this.ymin)*this.dy},r.prototype.transX=function(e){return this.data.length===1?(this.left+this.right)/2:this.left+(e-this.xmin)*this.dx},r.prototype.redraw=function(){this.r.clear(),this._calc(),this.drawGrid();if(this.draw)return this.draw()},r.prototype.drawGrid=function(){var e,t,n,r,i,s,o,u;e=this.ymin,t=this.ymax,u=[];for(n=s=e,o=this.yInterval;e<=t?s<=t:s>=t;n=s+=o)r=parseFloat(n.toFixed(this.precision)),i=this.transY(r),this.r.text(this.left-this.options.padding/2,i,this.yAxisFormat(r)).attr("font-size",this.options.gridTextSize).attr("fill",this.options.gridTextColor).attr("text-anchor","end"),u.push(this.r.path("M"+this.left+","+i+"H"+(this.left+this.width)).attr("stroke",this.options.gridLineColor).attr("stroke-width",this.options.gridStrokeWidth));return u},r.prototype.measureText=function(e,t){var n,r;return t==null&&(t=12),r=this.r.text(100,100,e).attr("font-size",t),n=r.getBBox(),r.remove(),n},r.prototype.yAxisFormat=function(e){return this.yLabelFormat(e)},r.prototype.yLabelFormat=function(e){return""+this.options.preUnits+t.commas(e)+this.options.postUnits},r}(t.EventEmitter),t.parseDate=function(e){var t,n,r,i,s,o,u,a,f,l,c;return typeof e=="number"?e:(n=e.match(/^(\d+) Q(\d)$/),i=e.match(/^(\d+)-(\d+)$/),s=e.match(/^(\d+)-(\d+)-(\d+)$/),u=e.match(/^(\d+) W(\d+)$/),a=e.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)(Z|([+-])(\d\d):?(\d\d))?$/),f=e.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)(Z|([+-])(\d\d):?(\d\d))?$/),n?(new Date(parseInt(n[1],10),parseInt(n[2],10)*3-1,1)).getTime():i?(new Date(parseInt(i[1],10),parseInt(i[2],10)-1,1)).getTime():s?(new Date(parseInt(s[1],10),parseInt(s[2],10)-1,parseInt(s[3],10))).getTime():u?(l=new Date(parseInt(u[1],10),0,1),l.getDay()!==4&&l.setMonth(0,1+(4-l.getDay()+7)%7),l.getTime()+parseInt(u[2],10)*6048e5):a?a[6]?(o=0,a[6]!=="Z"&&(o=parseInt(a[8],10)*60+parseInt(a[9],10),a[7]==="+"&&(o=0-o)),Date.UTC(parseInt(a[1],10),parseInt(a[2],10)-1,parseInt(a[3],10),parseInt(a[4],10),parseInt(a[5],10)+o)):(new Date(parseInt(a[1],10),parseInt(a[2],10)-1,parseInt(a[3],10),parseInt(a[4],10),parseInt(a[5],10))).getTime():f?(c=parseFloat(f[6]),t=Math.floor(c),r=Math.round((c-t)*1e3),f[8]?(o=0,f[8]!=="Z"&&(o=parseInt(f[10],10)*60+parseInt(f[11],10),f[9]==="+"&&(o=0-o)),Date.UTC(parseInt(f[1],10),parseInt(f[2],10)-1,parseInt(f[3],10),parseInt(f[4],10),parseInt(f[5],10)+o,t,r)):(new Date(parseInt(f[1],10),parseInt(f[2],10)-1,parseInt(f[3],10),parseInt(f[4],10),parseInt(f[5],10),t,r)).getTime()):(new Date(parseInt(e,10),0,1)).getTime())},t.Line=function(n){function r(e){this.updateHilight=u(this.updateHilight,this),this.hilight=u(this.hilight,this),this.updateHover=u(this.updateHover,this);if(!(this instanceof t.Line))return new t.Line(e);r.__super__.constructor.call(this,e)}return o(r,n),r.prototype.init=function(){var e,t=this;return this.pointGrow=Raphael.animation({r:this.options.pointSize+3},25,"linear"),this.pointShrink=Raphael.animation({r:this.options.pointSize},25,"linear"),this.prevHilight=null,this.el.mousemove(function(e){return t.updateHilight(e.pageX)}),this.options.hideHover&&this.el.mouseout(function(e){return t.hilight(null)}),e=function(e){var n;return n=e.originalEvent.touches[0]||e.originalEvent.changedTouches[0],t.updateHilight(n.pageX),n},this.el.bind("touchstart",e),this.el.bind("touchmove",e),this.el.bind("touchend",e)},r.prototype.defaults={lineWidth:3,pointSize:4,lineColors:["#0b62a4","#7A92A3","#4da74d","#afd8f8","#edc240","#cb4b4b","#9440ed"],pointWidths:[1],pointStrokeColors:["#ffffff"],pointFillColors:[],hoverPaddingX:10,hoverPaddingY:5,hoverMargin:10,hoverFillColor:"#fff",hoverBorderColor:"#ccc",hoverBorderWidth:2,hoverOpacity:.95,hoverLabelColor:"#444",hoverFontSize:12,smooth:!0,hideHover:!1,xLabels:"auto",xLabelFormat:null},r.prototype.calc=function(){return this.calcPoints(),this.generatePaths(),this.calcHoverMargins()},r.prototype.calcPoints=function(){var e,t,n,r,i,s;i=this.data,s=[];for(n=0,r=i.length;ns;t=0<=s?++i:--i)r=this.options.smooth===!0||(o=this.options.ykeys[t],a.call(this.options.smooth,o)>=0),e=function(){var e,r,i,s;i=this.data,s=[];for(e=0,r=i.length;e1?u.push(this.createPath(e,r)):u.push(null);return u}.call(this)},r.prototype.draw=function(){return this.drawXAxis(),this.drawSeries(),this.drawHover(),this.hilight(this.options.hideHover?null:this.data.length-1)},r.prototype.drawXAxis=function(){var e,n,r,i,s,o,u,a,f,l,c,h,p,d,v=this;o=this.bottom+this.options.gridTextSize*1.25,s=50,r=null,e=function(e,t){var n,i;return n=v.r.text(v.transX(t),o,e).attr("font-size",v.options.gridTextSize).attr("fill",v.options.gridTextColor),i=n.getBBox(),(r===null||r<=i.x)&&i.x>=0&&i.x+i.width=0;t=o<=0?++i:--i)n=this.paths[t],n!==null&&this.r.path(n).attr("stroke",this.colorForSeries(t)).attr("stroke-width",this.options.lineWidth);this.seriesPoints=function(){var e,n,r;r=[];for(t=e=0,n=this.options.ykeys.length;0<=n?en;t=0<=n?++e:--e)r.push([]);return r}.call(this),a=[];for(t=s=u=this.options.ykeys.length-1;u<=0?s<=0:s>=0;t=u<=0?++s:--s)a.push(function(){var n,i,s,o;s=this.data,o=[];for(n=0,i=s.length;n=m;o=0<=m?++v:--v)r=t[o],o===0?l+="M"+r.x+","+r.y:(i=s[o],a=t[o-1],f=s[o-1],u=(r.x-a.x)/4,c=a.x+u,p=Math.min(this.bottom,a.y+u*f),h=r.x-u,d=Math.min(this.bottom,r.y-u*i),l+="C"+c+","+p+","+h+","+d+","+r.x+","+r.y)}else l="M"+e.map(t,function(e){return""+e.x+","+e.y}).join("L");return l},r.prototype.gradients=function(t){return e.map(t,function(e,n){return n===0?(t[1].y-e.y)/(t[1].x-e.x):n===t.length-1?(e.y-t[n-1].y)/(e.x-t[n-1].x):(t[n+1].y-t[n-1].y)/(t[n+1].x-t[n-1].x)})},r.prototype.drawHover=function(){var e,t,n,r,i;this.hoverHeight=this.options.hoverFontSize*1.5*(this.options.ykeys.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=[],i=[];for(e=n=0,r=this.options.ykeys.length;0<=r?nr;e=0<=r?++n:--n)t=this.r.text(0,this.options.hoverFontSize*1.5*(e+1.5)-this.hoverHeight/2,"").attr("fill",this.colorForSeries(e)).attr("font-size",this.options.hoverFontSize),this.yLabels.push(t),i.push(this.hoverSet.push(t));return i},r.prototype.updateHover=function(t){var n,r,i,s,o,u,a,f,l;this.hoverSet.show(),i=this.data[t],this.xLabel.attr("text",i.label),l=i.y;for(n=a=0,f=l.length;athis.hoverHeight+this.options.hoverPaddingY*2+this.options.hoverMargin+this.top?u=u-this.hoverHeight/2-this.options.hoverPaddingY-this.options.hoverMargin:u=u+this.hoverHeight/2+this.options.hoverPaddingY+this.options.hoverMargin,u=Math.max(this.top+this.hoverHeight/2+this.options.hoverPaddingY,u),u=Math.min(this.bottom-this.hoverHeight/2-this.options.hoverPaddingY,u),s=Math.min(this.right-r/2-this.options.hoverPaddingX,this.data[t]._x),s=Math.max(this.left+r/2+this.options.hoverPaddingX,s),this.hoverSet.attr("transform","t"+s+","+u)},r.prototype.hideHover=function(){return this.hoverSet.hide()},r.prototype.hilight=function(e){var t,n,r,i,s;if(this.prevHilight!==null&&this.prevHilight!==e)for(t=n=0,i=this.seriesPoints.length-1;0<=i?n<=i:n>=i;t=0<=i?++n:--n)this.seriesPoints[t][this.prevHilight]&&this.seriesPoints[t][this.prevHilight].animate(this.pointShrink);if(e!==null&&this.prevHilight!==e){for(t=r=0,s=this.seriesPoints.length-1;0<=s?r<=s:r>=s;t=0<=s?++r:--r)this.seriesPoints[t][e]&&this.seriesPoints[t][e].animate(this.pointGrow);this.updateHover(e)}this.prevHilight=e;if(e===null)return this.hideHover()},r.prototype.updateHilight=function(e){var t,n,r;e-=this.el.offset().left;for(t=n=0,r=this.hoverMargins.length;0<=r?nr;t=0<=r?++n:--n)if(this.hoverMargins[t]>e)break;return this.hilight(t)},r.prototype.colorForSeries=function(e){return this.options.lineColors[e%this.options.lineColors.length]},r.prototype.strokeWidthForSeries=function(e){return this.options.pointWidths[e%this.options.pointWidths.length]},r.prototype.strokeForSeries=function(e){return this.options.pointStrokeColors[e%this.options.pointStrokeColors.length]},r.prototype.pointFillColorForSeries=function(e){return this.options.pointFillColors[e%this.options.pointFillColors.length]},r}(t.Grid),t.labelSeries=function(n,r,i,s,o){var u,a,f,l,c,h,p,d,v,m,g;f=200*(r-n)/i,a=new Date(n),p=t.LABEL_SPECS[s];if(p===void 0){g=t.AUTO_LABEL_ORDER;for(v=0,m=g.length;v=h.span){p=h;break}}}p===void 0&&(p=t.LABEL_SPECS.second),o&&(p=e.extend({},p,{fmt:o})),u=p.start(a),c=[];while((d=u.getTime())<=r)d>=n&&c.push([p.fmt(u),d]),p.incr(u);return c},n=function(e){return{span:e*60*1e3,start:function(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours())},fmt:function(e){return""+t.pad2(e.getHours())+":"+t.pad2(e.getMinutes())},incr:function(t){return t.setMinutes(t.getMinutes()+e)}}},r=function(e){return{span:e*1e3,start:function(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes())},fmt:function(e){return""+t.pad2(e.getHours())+":"+t.pad2(e.getMinutes())+":"+t.pad2(e.getSeconds())},incr:function(t){return t.setSeconds(t.getSeconds()+e)}}},t.LABEL_SPECS={year:{span:1728e7,start:function(e){return new Date(e.getFullYear(),0,1)},fmt:function(e){return""+e.getFullYear()},incr:function(e){return e.setFullYear(e.getFullYear()+1)}},month:{span:24192e5,start:function(e){return new Date(e.getFullYear(),e.getMonth(),1)},fmt:function(e){return""+e.getFullYear()+"-"+t.pad2(e.getMonth()+1)},incr:function(e){return e.setMonth(e.getMonth()+1)}},day:{span:864e5,start:function(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate())},fmt:function(e){return""+e.getFullYear()+"-"+t.pad2(e.getMonth()+1)+"-"+t.pad2(e.getDate())},incr:function(e){return e.setDate(e.getDate()+1)}},hour:n(60),"30min":n(30),"15min":n(15),"10min":n(10),"5min":n(5),minute:n(1),"30sec":r(30),"15sec":r(15),"10sec":r(10),"5sec":r(5),second:r(1)},t.AUTO_LABEL_ORDER=["year","month","day","hour","30min","15min","10min","5min","minute","30sec","15sec","10sec","5sec","second"],t.Area=function(e){function n(e){if(!(this instanceof t.Area))return new t.Area(e);this.cumulative=!0,n.__super__.constructor.call(this,e)}return o(n,e),n.prototype.calcPoints=function(){var e,t,n,r,i,s,o;s=this.data,o=[];for(r=0,i=s.length;r=0;e=i<=0?++r:--r)t=this.paths[e],t!==null&&(t+="L"+this.transX(this.xmax)+","+this.bottom+"L"+this.transX(this.xmin)+","+this.bottom+"Z",this.r.path(t).attr("fill",this.fillForSeries(e)).attr("stroke-width",0));return n.__super__.drawSeries.call(this)},n.prototype.fillForSeries=function(e){var t;return t=Raphael.rgb2hsl(this.colorForSeries(e)),Raphael.hsl(t.h,Math.min(255,t.s*.75),Math.min(255,t.l*1.25))},n}(t.Line),t.Donut=function(){function n(n){this.select=u(this.select,this);if(!(this instanceof t.Donut))return new t.Donut(n);typeof n.element=="string"?this.el=e(document.getElementById(n.element)):this.el=e(n.element),this.options=e.extend({},this.defaults,n);if(this.el===null||this.el.length===0)throw new Error("Graph placeholder not found.");if(n.data===void 0||n.data.length===0)return;this.data=n.data,this.el.addClass("graph-initialised"),this.redraw()}return n.prototype.defaults={colors:["#0B62A4","#3980B5","#679DC6","#95BBD7","#B0CCE1","#095791","#095085","#083E67","#052C48","#042135"],formatter:t.commas},n.prototype.redraw=function(){var e,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,x;this.el.empty(),this.r=new Raphael(this.el[0]),n=this.el.width()/2,r=this.el.height()/2,h=(Math.min(n,r)-10)/3,c=0,w=this.data;for(d=0,g=w.length;dMath.PI?1:0,this.path=this.calcSegment(this.inner+3,this.inner+this.outer-5),this.selectedPath=this.calcSegment(this.inner+3,this.inner+this.outer),this.hilight=this.calcArc(this.inner)}return o(t,e),t.prototype.calcArcPoints=function(e){return[this.cx+e*this.sin_p0,this.cy+e*this.cos_p0,this.cx+e*this.sin_p1,this.cy+e*this.cos_p1]},t.prototype.calcSegment=function(e,t){var n,r,i,s,o,u,a,f,l,c;return l=this.calcArcPoints(e),n=l[0],i=l[1],r=l[2],s=l[3],c=this.calcArcPoints(t),o=c[0],a=c[1],u=c[2],f=c[3],"M"+n+","+i+("A"+e+","+e+",0,"+this.long+",0,"+r+","+s)+("L"+u+","+f)+("A"+t+","+t+",0,"+this.long+",1,"+o+","+a)+"Z"},t.prototype.calcArc=function(e){var t,n,r,i,s;return s=this.calcArcPoints(e),t=s[0],r=s[1],n=s[2],i=s[3],"M"+t+","+r+("A"+e+","+e+",0,"+this.long+",0,"+n+","+i)},t.prototype.render=function(e){var t=this;return this.arc=e.path(this.hilight).attr({stroke:this.color,"stroke-width":2,opacity:0}),this.seg=e.path(this.path).attr({fill:this.color,stroke:"white","stroke-width":3}).hover(function(){return t.fire("hover",t)})},t.prototype.select=function(){if(!this.selected)return this.seg.animate({path:this.selectedPath},150,"<>"),this.arc.animate({opacity:1},150,"<>"),this.selected=!0},t.prototype.deselect=function(){if(this.selected)return this.seg.animate({path:this.path},150,"<>"),this.arc.animate({opacity:0},150,"<>"),this.selected=!1},t}(t.EventEmitter)}).call(this); \ No newline at end of file