fmsystem-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Fmsystem-commits] [16367]


From: nelson . guerra
Subject: [Fmsystem-commits] [16367]
Date: Tue, 21 Feb 2017 14:17:02 -0500 (EST)

Revision: 16367
          http://svn.sv.gnu.org/viewvc/?view=rev&root=fmsystem&revision=16367
Author:   nelson224
Date:     2017-02-21 14:17:02 -0500 (Tue, 21 Feb 2017)
Log Message:
-----------


Added Paths:
-----------
    branches/dev-syncromind-2/phpgwapi/js/chart/
    branches/dev-syncromind-2/phpgwapi/js/chart/Chart.js
    branches/dev-syncromind-2/phpgwapi/js/chart/Chart.min.js

Added: branches/dev-syncromind-2/phpgwapi/js/chart/Chart.js
===================================================================
--- branches/dev-syncromind-2/phpgwapi/js/chart/Chart.js                        
        (rev 0)
+++ branches/dev-syncromind-2/phpgwapi/js/chart/Chart.js        2017-02-21 
19:17:02 UTC (rev 16367)
@@ -0,0 +1,12269 @@
+/*!
+ * Chart.js
+ * http://chartjs.org/
+ * Version: 2.5.0
+ *
+ * Copyright 2017 Nick Downie
+ * Released under the MIT license
+ * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
+ */
+(function(f){if(typeof exports==="object"&&typeof 
module!=="undefined"){module.exports=f()}else if(typeof 
define==="function"&&define.amd){define([],f)}else{var g;if(typeof 
window!=="undefined"){g=window}else if(typeof 
global!=="undefined"){g=global}else if(typeof 
self!=="undefined"){g=self}else{g=this}g.Chart = f()}})(function(){var 
define,module,exports;return (function e(t,n,r){function 
s(o,u){if(!n[o]){if(!t[o]){var a=typeof 
require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var 
f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var 
l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return 
s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof 
require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return 
s})({1:[function(require,module,exports){
+
+},{}],2:[function(require,module,exports){
+/* MIT license */
+var colorNames = require(6);
+
+module.exports = {
+   getRgba: getRgba,
+   getHsla: getHsla,
+   getRgb: getRgb,
+   getHsl: getHsl,
+   getHwb: getHwb,
+   getAlpha: getAlpha,
+
+   hexString: hexString,
+   rgbString: rgbString,
+   rgbaString: rgbaString,
+   percentString: percentString,
+   percentaString: percentaString,
+   hslString: hslString,
+   hslaString: hslaString,
+   hwbString: hwbString,
+   keyword: keyword
+}
+
+function getRgba(string) {
+   if (!string) {
+      return;
+   }
+   var abbr =  /^#([a-fA-F0-9]{3})$/,
+       hex =  /^#([a-fA-F0-9]{6})$/,
+       rgba = 
/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,
+       per = 
/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,
+       keyword = /(\w+)/;
+
+   var rgb = [0, 0, 0],
+       a = 1,
+       match = string.match(abbr);
+   if (match) {
+      match = match[1];
+      for (var i = 0; i < rgb.length; i++) {
+         rgb[i] = parseInt(match[i] + match[i], 16);
+      }
+   }
+   else if (match = string.match(hex)) {
+      match = match[1];
+      for (var i = 0; i < rgb.length; i++) {
+         rgb[i] = parseInt(match.slice(i * 2, i * 2 + 2), 16);
+      }
+   }
+   else if (match = string.match(rgba)) {
+      for (var i = 0; i < rgb.length; i++) {
+         rgb[i] = parseInt(match[i + 1]);
+      }
+      a = parseFloat(match[4]);
+   }
+   else if (match = string.match(per)) {
+      for (var i = 0; i < rgb.length; i++) {
+         rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55);
+      }
+      a = parseFloat(match[4]);
+   }
+   else if (match = string.match(keyword)) {
+      if (match[1] == "transparent") {
+         return [0, 0, 0, 0];
+      }
+      rgb = colorNames[match[1]];
+      if (!rgb) {
+         return;
+      }
+   }
+
+   for (var i = 0; i < rgb.length; i++) {
+      rgb[i] = scale(rgb[i], 0, 255);
+   }
+   if (!a && a != 0) {
+      a = 1;
+   }
+   else {
+      a = scale(a, 0, 1);
+   }
+   rgb[3] = a;
+   return rgb;
+}
+
+function getHsla(string) {
+   if (!string) {
+      return;
+   }
+   var hsl = 
/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/;
+   var match = string.match(hsl);
+   if (match) {
+      var alpha = parseFloat(match[4]);
+      var h = scale(parseInt(match[1]), 0, 360),
+          s = scale(parseFloat(match[2]), 0, 100),
+          l = scale(parseFloat(match[3]), 0, 100),
+          a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);
+      return [h, s, l, a];
+   }
+}
+
+function getHwb(string) {
+   if (!string) {
+      return;
+   }
+   var hwb = 
/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/;
+   var match = string.match(hwb);
+   if (match) {
+    var alpha = parseFloat(match[4]);
+      var h = scale(parseInt(match[1]), 0, 360),
+          w = scale(parseFloat(match[2]), 0, 100),
+          b = scale(parseFloat(match[3]), 0, 100),
+          a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);
+      return [h, w, b, a];
+   }
+}
+
+function getRgb(string) {
+   var rgba = getRgba(string);
+   return rgba && rgba.slice(0, 3);
+}
+
+function getHsl(string) {
+  var hsla = getHsla(string);
+  return hsla && hsla.slice(0, 3);
+}
+
+function getAlpha(string) {
+   var vals = getRgba(string);
+   if (vals) {
+      return vals[3];
+   }
+   else if (vals = getHsla(string)) {
+      return vals[3];
+   }
+   else if (vals = getHwb(string)) {
+      return vals[3];
+   }
+}
+
+// generators
+function hexString(rgb) {
+   return "#" + hexDouble(rgb[0]) + hexDouble(rgb[1])
+              + hexDouble(rgb[2]);
+}
+
+function rgbString(rgba, alpha) {
+   if (alpha < 1 || (rgba[3] && rgba[3] < 1)) {
+      return rgbaString(rgba, alpha);
+   }
+   return "rgb(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ")";
+}
+
+function rgbaString(rgba, alpha) {
+   if (alpha === undefined) {
+      alpha = (rgba[3] !== undefined ? rgba[3] : 1);
+   }
+   return "rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2]
+           + ", " + alpha + ")";
+}
+
+function percentString(rgba, alpha) {
+   if (alpha < 1 || (rgba[3] && rgba[3] < 1)) {
+      return percentaString(rgba, alpha);
+   }
+   var r = Math.round(rgba[0]/255 * 100),
+       g = Math.round(rgba[1]/255 * 100),
+       b = Math.round(rgba[2]/255 * 100);
+
+   return "rgb(" + r + "%, " + g + "%, " + b + "%)";
+}
+
+function percentaString(rgba, alpha) {
+   var r = Math.round(rgba[0]/255 * 100),
+       g = Math.round(rgba[1]/255 * 100),
+       b = Math.round(rgba[2]/255 * 100);
+   return "rgba(" + r + "%, " + g + "%, " + b + "%, " + (alpha || rgba[3] || 
1) + ")";
+}
+
+function hslString(hsla, alpha) {
+   if (alpha < 1 || (hsla[3] && hsla[3] < 1)) {
+      return hslaString(hsla, alpha);
+   }
+   return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)";
+}
+
+function hslaString(hsla, alpha) {
+   if (alpha === undefined) {
+      alpha = (hsla[3] !== undefined ? hsla[3] : 1);
+   }
+   return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, "
+           + alpha + ")";
+}
+
+// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha 
specific syntax
+// (hwb have alpha optional & 1 is default value)
+function hwbString(hwb, alpha) {
+   if (alpha === undefined) {
+      alpha = (hwb[3] !== undefined ? hwb[3] : 1);
+   }
+   return "hwb(" + hwb[0] + ", " + hwb[1] + "%, " + hwb[2] + "%"
+           + (alpha !== undefined && alpha !== 1 ? ", " + alpha : "") + ")";
+}
+
+function keyword(rgb) {
+  return reverseNames[rgb.slice(0, 3)];
+}
+
+// helpers
+function scale(num, min, max) {
+   return Math.min(Math.max(min, num), max);
+}
+
+function hexDouble(num) {
+  var str = num.toString(16).toUpperCase();
+  return (str.length < 2) ? "0" + str : str;
+}
+
+
+//create a list of reverse color names
+var reverseNames = {};
+for (var name in colorNames) {
+   reverseNames[colorNames[name]] = name;
+}
+
+},{"6":6}],3:[function(require,module,exports){
+/* MIT license */
+var convert = require(5);
+var string = require(2);
+
+var Color = function (obj) {
+       if (obj instanceof Color) {
+               return obj;
+       }
+       if (!(this instanceof Color)) {
+               return new Color(obj);
+       }
+
+       this.values = {
+               rgb: [0, 0, 0],
+               hsl: [0, 0, 0],
+               hsv: [0, 0, 0],
+               hwb: [0, 0, 0],
+               cmyk: [0, 0, 0, 0],
+               alpha: 1
+       };
+
+       // parse Color() argument
+       var vals;
+       if (typeof obj === 'string') {
+               vals = string.getRgba(obj);
+               if (vals) {
+                       this.setValues('rgb', vals);
+               } else if (vals = string.getHsla(obj)) {
+                       this.setValues('hsl', vals);
+               } else if (vals = string.getHwb(obj)) {
+                       this.setValues('hwb', vals);
+               } else {
+                       throw new Error('Unable to parse color from string "' + 
obj + '"');
+               }
+       } else if (typeof obj === 'object') {
+               vals = obj;
+               if (vals.r !== undefined || vals.red !== undefined) {
+                       this.setValues('rgb', vals);
+               } else if (vals.l !== undefined || vals.lightness !== 
undefined) {
+                       this.setValues('hsl', vals);
+               } else if (vals.v !== undefined || vals.value !== undefined) {
+                       this.setValues('hsv', vals);
+               } else if (vals.w !== undefined || vals.whiteness !== 
undefined) {
+                       this.setValues('hwb', vals);
+               } else if (vals.c !== undefined || vals.cyan !== undefined) {
+                       this.setValues('cmyk', vals);
+               } else {
+                       throw new Error('Unable to parse color from object ' + 
JSON.stringify(obj));
+               }
+       }
+};
+
+Color.prototype = {
+       rgb: function () {
+               return this.setSpace('rgb', arguments);
+       },
+       hsl: function () {
+               return this.setSpace('hsl', arguments);
+       },
+       hsv: function () {
+               return this.setSpace('hsv', arguments);
+       },
+       hwb: function () {
+               return this.setSpace('hwb', arguments);
+       },
+       cmyk: function () {
+               return this.setSpace('cmyk', arguments);
+       },
+
+       rgbArray: function () {
+               return this.values.rgb;
+       },
+       hslArray: function () {
+               return this.values.hsl;
+       },
+       hsvArray: function () {
+               return this.values.hsv;
+       },
+       hwbArray: function () {
+               var values = this.values;
+               if (values.alpha !== 1) {
+                       return values.hwb.concat([values.alpha]);
+               }
+               return values.hwb;
+       },
+       cmykArray: function () {
+               return this.values.cmyk;
+       },
+       rgbaArray: function () {
+               var values = this.values;
+               return values.rgb.concat([values.alpha]);
+       },
+       hslaArray: function () {
+               var values = this.values;
+               return values.hsl.concat([values.alpha]);
+       },
+       alpha: function (val) {
+               if (val === undefined) {
+                       return this.values.alpha;
+               }
+               this.setValues('alpha', val);
+               return this;
+       },
+
+       red: function (val) {
+               return this.setChannel('rgb', 0, val);
+       },
+       green: function (val) {
+               return this.setChannel('rgb', 1, val);
+       },
+       blue: function (val) {
+               return this.setChannel('rgb', 2, val);
+       },
+       hue: function (val) {
+               if (val) {
+                       val %= 360;
+                       val = val < 0 ? 360 + val : val;
+               }
+               return this.setChannel('hsl', 0, val);
+       },
+       saturation: function (val) {
+               return this.setChannel('hsl', 1, val);
+       },
+       lightness: function (val) {
+               return this.setChannel('hsl', 2, val);
+       },
+       saturationv: function (val) {
+               return this.setChannel('hsv', 1, val);
+       },
+       whiteness: function (val) {
+               return this.setChannel('hwb', 1, val);
+       },
+       blackness: function (val) {
+               return this.setChannel('hwb', 2, val);
+       },
+       value: function (val) {
+               return this.setChannel('hsv', 2, val);
+       },
+       cyan: function (val) {
+               return this.setChannel('cmyk', 0, val);
+       },
+       magenta: function (val) {
+               return this.setChannel('cmyk', 1, val);
+       },
+       yellow: function (val) {
+               return this.setChannel('cmyk', 2, val);
+       },
+       black: function (val) {
+               return this.setChannel('cmyk', 3, val);
+       },
+
+       hexString: function () {
+               return string.hexString(this.values.rgb);
+       },
+       rgbString: function () {
+               return string.rgbString(this.values.rgb, this.values.alpha);
+       },
+       rgbaString: function () {
+               return string.rgbaString(this.values.rgb, this.values.alpha);
+       },
+       percentString: function () {
+               return string.percentString(this.values.rgb, this.values.alpha);
+       },
+       hslString: function () {
+               return string.hslString(this.values.hsl, this.values.alpha);
+       },
+       hslaString: function () {
+               return string.hslaString(this.values.hsl, this.values.alpha);
+       },
+       hwbString: function () {
+               return string.hwbString(this.values.hwb, this.values.alpha);
+       },
+       keyword: function () {
+               return string.keyword(this.values.rgb, this.values.alpha);
+       },
+
+       rgbNumber: function () {
+               var rgb = this.values.rgb;
+               return (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
+       },
+
+       luminosity: function () {
+               // http://www.w3.org/TR/WCAG20/#relativeluminancedef
+               var rgb = this.values.rgb;
+               var lum = [];
+               for (var i = 0; i < rgb.length; i++) {
+                       var chan = rgb[i] / 255;
+                       lum[i] = (chan <= 0.03928) ? chan / 12.92 : 
Math.pow(((chan + 0.055) / 1.055), 2.4);
+               }
+               return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2];
+       },
+
+       contrast: function (color2) {
+               // http://www.w3.org/TR/WCAG20/#contrast-ratiodef
+               var lum1 = this.luminosity();
+               var lum2 = color2.luminosity();
+               if (lum1 > lum2) {
+                       return (lum1 + 0.05) / (lum2 + 0.05);
+               }
+               return (lum2 + 0.05) / (lum1 + 0.05);
+       },
+
+       level: function (color2) {
+               var contrastRatio = this.contrast(color2);
+               if (contrastRatio >= 7.1) {
+                       return 'AAA';
+               }
+
+               return (contrastRatio >= 4.5) ? 'AA' : '';
+       },
+
+       dark: function () {
+               // YIQ equation from 
http://24ways.org/2010/calculating-color-contrast
+               var rgb = this.values.rgb;
+               var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000;
+               return yiq < 128;
+       },
+
+       light: function () {
+               return !this.dark();
+       },
+
+       negate: function () {
+               var rgb = [];
+               for (var i = 0; i < 3; i++) {
+                       rgb[i] = 255 - this.values.rgb[i];
+               }
+               this.setValues('rgb', rgb);
+               return this;
+       },
+
+       lighten: function (ratio) {
+               var hsl = this.values.hsl;
+               hsl[2] += hsl[2] * ratio;
+               this.setValues('hsl', hsl);
+               return this;
+       },
+
+       darken: function (ratio) {
+               var hsl = this.values.hsl;
+               hsl[2] -= hsl[2] * ratio;
+               this.setValues('hsl', hsl);
+               return this;
+       },
+
+       saturate: function (ratio) {
+               var hsl = this.values.hsl;
+               hsl[1] += hsl[1] * ratio;
+               this.setValues('hsl', hsl);
+               return this;
+       },
+
+       desaturate: function (ratio) {
+               var hsl = this.values.hsl;
+               hsl[1] -= hsl[1] * ratio;
+               this.setValues('hsl', hsl);
+               return this;
+       },
+
+       whiten: function (ratio) {
+               var hwb = this.values.hwb;
+               hwb[1] += hwb[1] * ratio;
+               this.setValues('hwb', hwb);
+               return this;
+       },
+
+       blacken: function (ratio) {
+               var hwb = this.values.hwb;
+               hwb[2] += hwb[2] * ratio;
+               this.setValues('hwb', hwb);
+               return this;
+       },
+
+       greyscale: function () {
+               var rgb = this.values.rgb;
+               // 
http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
+               var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11;
+               this.setValues('rgb', [val, val, val]);
+               return this;
+       },
+
+       clearer: function (ratio) {
+               var alpha = this.values.alpha;
+               this.setValues('alpha', alpha - (alpha * ratio));
+               return this;
+       },
+
+       opaquer: function (ratio) {
+               var alpha = this.values.alpha;
+               this.setValues('alpha', alpha + (alpha * ratio));
+               return this;
+       },
+
+       rotate: function (degrees) {
+               var hsl = this.values.hsl;
+               var hue = (hsl[0] + degrees) % 360;
+               hsl[0] = hue < 0 ? 360 + hue : hue;
+               this.setValues('hsl', hsl);
+               return this;
+       },
+
+       /**
+        * Ported from sass implementation in C
+        * 
https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209
+        */
+       mix: function (mixinColor, weight) {
+               var color1 = this;
+               var color2 = mixinColor;
+               var p = weight === undefined ? 0.5 : weight;
+
+               var w = 2 * p - 1;
+               var a = color1.alpha() - color2.alpha();
+
+               var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 
2.0;
+               var w2 = 1 - w1;
+
+               return this
+                       .rgb(
+                               w1 * color1.red() + w2 * color2.red(),
+                               w1 * color1.green() + w2 * color2.green(),
+                               w1 * color1.blue() + w2 * color2.blue()
+                       )
+                       .alpha(color1.alpha() * p + color2.alpha() * (1 - p));
+       },
+
+       toJSON: function () {
+               return this.rgb();
+       },
+
+       clone: function () {
+               // NOTE(SB): using node-clone creates a dependency to Buffer 
when using browserify,
+               // making the final build way to big to embed in Chart.js. So 
let's do it manually,
+               // assuming that values to clone are 1 dimension arrays 
containing only numbers,
+               // except 'alpha' which is a number.
+               var result = new Color();
+               var source = this.values;
+               var target = result.values;
+               var value, type;
+
+               for (var prop in source) {
+                       if (source.hasOwnProperty(prop)) {
+                               value = source[prop];
+                               type = ({}).toString.call(value);
+                               if (type === '[object Array]') {
+                                       target[prop] = value.slice(0);
+                               } else if (type === '[object Number]') {
+                                       target[prop] = value;
+                               } else {
+                                       console.error('unexpected color 
value:', value);
+                               }
+                       }
+               }
+
+               return result;
+       }
+};
+
+Color.prototype.spaces = {
+       rgb: ['red', 'green', 'blue'],
+       hsl: ['hue', 'saturation', 'lightness'],
+       hsv: ['hue', 'saturation', 'value'],
+       hwb: ['hue', 'whiteness', 'blackness'],
+       cmyk: ['cyan', 'magenta', 'yellow', 'black']
+};
+
+Color.prototype.maxes = {
+       rgb: [255, 255, 255],
+       hsl: [360, 100, 100],
+       hsv: [360, 100, 100],
+       hwb: [360, 100, 100],
+       cmyk: [100, 100, 100, 100]
+};
+
+Color.prototype.getValues = function (space) {
+       var values = this.values;
+       var vals = {};
+
+       for (var i = 0; i < space.length; i++) {
+               vals[space.charAt(i)] = values[space][i];
+       }
+
+       if (values.alpha !== 1) {
+               vals.a = values.alpha;
+       }
+
+       // {r: 255, g: 255, b: 255, a: 0.4}
+       return vals;
+};
+
+Color.prototype.setValues = function (space, vals) {
+       var values = this.values;
+       var spaces = this.spaces;
+       var maxes = this.maxes;
+       var alpha = 1;
+       var i;
+
+       if (space === 'alpha') {
+               alpha = vals;
+       } else if (vals.length) {
+               // [10, 10, 10]
+               values[space] = vals.slice(0, space.length);
+               alpha = vals[space.length];
+       } else if (vals[space.charAt(0)] !== undefined) {
+               // {r: 10, g: 10, b: 10}
+               for (i = 0; i < space.length; i++) {
+                       values[space][i] = vals[space.charAt(i)];
+               }
+
+               alpha = vals.a;
+       } else if (vals[spaces[space][0]] !== undefined) {
+               // {red: 10, green: 10, blue: 10}
+               var chans = spaces[space];
+
+               for (i = 0; i < space.length; i++) {
+                       values[space][i] = vals[chans[i]];
+               }
+
+               alpha = vals.alpha;
+       }
+
+       values.alpha = Math.max(0, Math.min(1, (alpha === undefined ? 
values.alpha : alpha)));
+
+       if (space === 'alpha') {
+               return false;
+       }
+
+       var capped;
+
+       // cap values of the space prior converting all values
+       for (i = 0; i < space.length; i++) {
+               capped = Math.max(0, Math.min(maxes[space][i], 
values[space][i]));
+               values[space][i] = Math.round(capped);
+       }
+
+       // convert to all the other color spaces
+       for (var sname in spaces) {
+               if (sname !== space) {
+                       values[sname] = convert[space][sname](values[space]);
+               }
+       }
+
+       return true;
+};
+
+Color.prototype.setSpace = function (space, args) {
+       var vals = args[0];
+
+       if (vals === undefined) {
+               // color.rgb()
+               return this.getValues(space);
+       }
+
+       // color.rgb(10, 10, 10)
+       if (typeof vals === 'number') {
+               vals = Array.prototype.slice.call(args);
+       }
+
+       this.setValues(space, vals);
+       return this;
+};
+
+Color.prototype.setChannel = function (space, index, val) {
+       var svalues = this.values[space];
+       if (val === undefined) {
+               // color.red()
+               return svalues[index];
+       } else if (val === svalues[index]) {
+               // color.red(color.red())
+               return this;
+       }
+
+       // color.red(100)
+       svalues[index] = val;
+       this.setValues(space, svalues);
+
+       return this;
+};
+
+if (typeof window !== 'undefined') {
+       window.Color = Color;
+}
+
+module.exports = Color;
+
+},{"2":2,"5":5}],4:[function(require,module,exports){
+/* MIT license */
+
+module.exports = {
+  rgb2hsl: rgb2hsl,
+  rgb2hsv: rgb2hsv,
+  rgb2hwb: rgb2hwb,
+  rgb2cmyk: rgb2cmyk,
+  rgb2keyword: rgb2keyword,
+  rgb2xyz: rgb2xyz,
+  rgb2lab: rgb2lab,
+  rgb2lch: rgb2lch,
+
+  hsl2rgb: hsl2rgb,
+  hsl2hsv: hsl2hsv,
+  hsl2hwb: hsl2hwb,
+  hsl2cmyk: hsl2cmyk,
+  hsl2keyword: hsl2keyword,
+
+  hsv2rgb: hsv2rgb,
+  hsv2hsl: hsv2hsl,
+  hsv2hwb: hsv2hwb,
+  hsv2cmyk: hsv2cmyk,
+  hsv2keyword: hsv2keyword,
+
+  hwb2rgb: hwb2rgb,
+  hwb2hsl: hwb2hsl,
+  hwb2hsv: hwb2hsv,
+  hwb2cmyk: hwb2cmyk,
+  hwb2keyword: hwb2keyword,
+
+  cmyk2rgb: cmyk2rgb,
+  cmyk2hsl: cmyk2hsl,
+  cmyk2hsv: cmyk2hsv,
+  cmyk2hwb: cmyk2hwb,
+  cmyk2keyword: cmyk2keyword,
+
+  keyword2rgb: keyword2rgb,
+  keyword2hsl: keyword2hsl,
+  keyword2hsv: keyword2hsv,
+  keyword2hwb: keyword2hwb,
+  keyword2cmyk: keyword2cmyk,
+  keyword2lab: keyword2lab,
+  keyword2xyz: keyword2xyz,
+
+  xyz2rgb: xyz2rgb,
+  xyz2lab: xyz2lab,
+  xyz2lch: xyz2lch,
+
+  lab2xyz: lab2xyz,
+  lab2rgb: lab2rgb,
+  lab2lch: lab2lch,
+
+  lch2lab: lch2lab,
+  lch2xyz: lch2xyz,
+  lch2rgb: lch2rgb
+}
+
+
+function rgb2hsl(rgb) {
+  var r = rgb[0]/255,
+      g = rgb[1]/255,
+      b = rgb[2]/255,
+      min = Math.min(r, g, b),
+      max = Math.max(r, g, b),
+      delta = max - min,
+      h, s, l;
+
+  if (max == min)
+    h = 0;
+  else if (r == max)
+    h = (g - b) / delta;
+  else if (g == max)
+    h = 2 + (b - r) / delta;
+  else if (b == max)
+    h = 4 + (r - g)/ delta;
+
+  h = Math.min(h * 60, 360);
+
+  if (h < 0)
+    h += 360;
+
+  l = (min + max) / 2;
+
+  if (max == min)
+    s = 0;
+  else if (l <= 0.5)
+    s = delta / (max + min);
+  else
+    s = delta / (2 - max - min);
+
+  return [h, s * 100, l * 100];
+}
+
+function rgb2hsv(rgb) {
+  var r = rgb[0],
+      g = rgb[1],
+      b = rgb[2],
+      min = Math.min(r, g, b),
+      max = Math.max(r, g, b),
+      delta = max - min,
+      h, s, v;
+
+  if (max == 0)
+    s = 0;
+  else
+    s = (delta/max * 1000)/10;
+
+  if (max == min)
+    h = 0;
+  else if (r == max)
+    h = (g - b) / delta;
+  else if (g == max)
+    h = 2 + (b - r) / delta;
+  else if (b == max)
+    h = 4 + (r - g) / delta;
+
+  h = Math.min(h * 60, 360);
+
+  if (h < 0)
+    h += 360;
+
+  v = ((max / 255) * 1000) / 10;
+
+  return [h, s, v];
+}
+
+function rgb2hwb(rgb) {
+  var r = rgb[0],
+      g = rgb[1],
+      b = rgb[2],
+      h = rgb2hsl(rgb)[0],
+      w = 1/255 * Math.min(r, Math.min(g, b)),
+      b = 1 - 1/255 * Math.max(r, Math.max(g, b));
+
+  return [h, w * 100, b * 100];
+}
+
+function rgb2cmyk(rgb) {
+  var r = rgb[0] / 255,
+      g = rgb[1] / 255,
+      b = rgb[2] / 255,
+      c, m, y, k;
+
+  k = Math.min(1 - r, 1 - g, 1 - b);
+  c = (1 - r - k) / (1 - k) || 0;
+  m = (1 - g - k) / (1 - k) || 0;
+  y = (1 - b - k) / (1 - k) || 0;
+  return [c * 100, m * 100, y * 100, k * 100];
+}
+
+function rgb2keyword(rgb) {
+  return reverseKeywords[JSON.stringify(rgb)];
+}
+
+function rgb2xyz(rgb) {
+  var r = rgb[0] / 255,
+      g = rgb[1] / 255,
+      b = rgb[2] / 255;
+
+  // assume sRGB
+  r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92);
+  g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92);
+  b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92);
+
+  var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
+  var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
+  var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
+
+  return [x * 100, y *100, z * 100];
+}
+
+function rgb2lab(rgb) {
+  var xyz = rgb2xyz(rgb),
+        x = xyz[0],
+        y = xyz[1],
+        z = xyz[2],
+        l, a, b;
+
+  x /= 95.047;
+  y /= 100;
+  z /= 108.883;
+
+  x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);
+  y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);
+  z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);
+
+  l = (116 * y) - 16;
+  a = 500 * (x - y);
+  b = 200 * (y - z);
+
+  return [l, a, b];
+}
+
+function rgb2lch(args) {
+  return lab2lch(rgb2lab(args));
+}
+
+function hsl2rgb(hsl) {
+  var h = hsl[0] / 360,
+      s = hsl[1] / 100,
+      l = hsl[2] / 100,
+      t1, t2, t3, rgb, val;
+
+  if (s == 0) {
+    val = l * 255;
+    return [val, val, val];
+  }
+
+  if (l < 0.5)
+    t2 = l * (1 + s);
+  else
+    t2 = l + s - l * s;
+  t1 = 2 * l - t2;
+
+  rgb = [0, 0, 0];
+  for (var i = 0; i < 3; i++) {
+    t3 = h + 1 / 3 * - (i - 1);
+    t3 < 0 && t3++;
+    t3 > 1 && t3--;
+
+    if (6 * t3 < 1)
+      val = t1 + (t2 - t1) * 6 * t3;
+    else if (2 * t3 < 1)
+      val = t2;
+    else if (3 * t3 < 2)
+      val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
+    else
+      val = t1;
+
+    rgb[i] = val * 255;
+  }
+
+  return rgb;
+}
+
+function hsl2hsv(hsl) {
+  var h = hsl[0],
+      s = hsl[1] / 100,
+      l = hsl[2] / 100,
+      sv, v;
+
+  if(l === 0) {
+      // no need to do calc on black
+      // also avoids divide by 0 error
+      return [0, 0, 0];
+  }
+
+  l *= 2;
+  s *= (l <= 1) ? l : 2 - l;
+  v = (l + s) / 2;
+  sv = (2 * s) / (l + s);
+  return [h, sv * 100, v * 100];
+}
+
+function hsl2hwb(args) {
+  return rgb2hwb(hsl2rgb(args));
+}
+
+function hsl2cmyk(args) {
+  return rgb2cmyk(hsl2rgb(args));
+}
+
+function hsl2keyword(args) {
+  return rgb2keyword(hsl2rgb(args));
+}
+
+
+function hsv2rgb(hsv) {
+  var h = hsv[0] / 60,
+      s = hsv[1] / 100,
+      v = hsv[2] / 100,
+      hi = Math.floor(h) % 6;
+
+  var f = h - Math.floor(h),
+      p = 255 * v * (1 - s),
+      q = 255 * v * (1 - (s * f)),
+      t = 255 * v * (1 - (s * (1 - f))),
+      v = 255 * v;
+
+  switch(hi) {
+    case 0:
+      return [v, t, p];
+    case 1:
+      return [q, v, p];
+    case 2:
+      return [p, v, t];
+    case 3:
+      return [p, q, v];
+    case 4:
+      return [t, p, v];
+    case 5:
+      return [v, p, q];
+  }
+}
+
+function hsv2hsl(hsv) {
+  var h = hsv[0],
+      s = hsv[1] / 100,
+      v = hsv[2] / 100,
+      sl, l;
+
+  l = (2 - s) * v;
+  sl = s * v;
+  sl /= (l <= 1) ? l : 2 - l;
+  sl = sl || 0;
+  l /= 2;
+  return [h, sl * 100, l * 100];
+}
+
+function hsv2hwb(args) {
+  return rgb2hwb(hsv2rgb(args))
+}
+
+function hsv2cmyk(args) {
+  return rgb2cmyk(hsv2rgb(args));
+}
+
+function hsv2keyword(args) {
+  return rgb2keyword(hsv2rgb(args));
+}
+
+// http://dev.w3.org/csswg/css-color/#hwb-to-rgb
+function hwb2rgb(hwb) {
+  var h = hwb[0] / 360,
+      wh = hwb[1] / 100,
+      bl = hwb[2] / 100,
+      ratio = wh + bl,
+      i, v, f, n;
+
+  // wh + bl cant be > 1
+  if (ratio > 1) {
+    wh /= ratio;
+    bl /= ratio;
+  }
+
+  i = Math.floor(6 * h);
+  v = 1 - bl;
+  f = 6 * h - i;
+  if ((i & 0x01) != 0) {
+    f = 1 - f;
+  }
+  n = wh + f * (v - wh);  // linear interpolation
+
+  switch (i) {
+    default:
+    case 6:
+    case 0: r = v; g = n; b = wh; break;
+    case 1: r = n; g = v; b = wh; break;
+    case 2: r = wh; g = v; b = n; break;
+    case 3: r = wh; g = n; b = v; break;
+    case 4: r = n; g = wh; b = v; break;
+    case 5: r = v; g = wh; b = n; break;
+  }
+
+  return [r * 255, g * 255, b * 255];
+}
+
+function hwb2hsl(args) {
+  return rgb2hsl(hwb2rgb(args));
+}
+
+function hwb2hsv(args) {
+  return rgb2hsv(hwb2rgb(args));
+}
+
+function hwb2cmyk(args) {
+  return rgb2cmyk(hwb2rgb(args));
+}
+
+function hwb2keyword(args) {
+  return rgb2keyword(hwb2rgb(args));
+}
+
+function cmyk2rgb(cmyk) {
+  var c = cmyk[0] / 100,
+      m = cmyk[1] / 100,
+      y = cmyk[2] / 100,
+      k = cmyk[3] / 100,
+      r, g, b;
+
+  r = 1 - Math.min(1, c * (1 - k) + k);
+  g = 1 - Math.min(1, m * (1 - k) + k);
+  b = 1 - Math.min(1, y * (1 - k) + k);
+  return [r * 255, g * 255, b * 255];
+}
+
+function cmyk2hsl(args) {
+  return rgb2hsl(cmyk2rgb(args));
+}
+
+function cmyk2hsv(args) {
+  return rgb2hsv(cmyk2rgb(args));
+}
+
+function cmyk2hwb(args) {
+  return rgb2hwb(cmyk2rgb(args));
+}
+
+function cmyk2keyword(args) {
+  return rgb2keyword(cmyk2rgb(args));
+}
+
+
+function xyz2rgb(xyz) {
+  var x = xyz[0] / 100,
+      y = xyz[1] / 100,
+      z = xyz[2] / 100,
+      r, g, b;
+
+  r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
+  g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
+  b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);
+
+  // assume sRGB
+  r = r > 0.0031308 ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055)
+    : r = (r * 12.92);
+
+  g = g > 0.0031308 ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055)
+    : g = (g * 12.92);
+
+  b = b > 0.0031308 ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055)
+    : b = (b * 12.92);
+
+  r = Math.min(Math.max(0, r), 1);
+  g = Math.min(Math.max(0, g), 1);
+  b = Math.min(Math.max(0, b), 1);
+
+  return [r * 255, g * 255, b * 255];
+}
+
+function xyz2lab(xyz) {
+  var x = xyz[0],
+      y = xyz[1],
+      z = xyz[2],
+      l, a, b;
+
+  x /= 95.047;
+  y /= 100;
+  z /= 108.883;
+
+  x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);
+  y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);
+  z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);
+
+  l = (116 * y) - 16;
+  a = 500 * (x - y);
+  b = 200 * (y - z);
+
+  return [l, a, b];
+}
+
+function xyz2lch(args) {
+  return lab2lch(xyz2lab(args));
+}
+
+function lab2xyz(lab) {
+  var l = lab[0],
+      a = lab[1],
+      b = lab[2],
+      x, y, z, y2;
+
+  if (l <= 8) {
+    y = (l * 100) / 903.3;
+    y2 = (7.787 * (y / 100)) + (16 / 116);
+  } else {
+    y = 100 * Math.pow((l + 16) / 116, 3);
+    y2 = Math.pow(y / 100, 1/3);
+  }
+
+  x = x / 95.047 <= 0.008856 ? x = (95.047 * ((a / 500) + y2 - (16 / 116))) / 
7.787 : 95.047 * Math.pow((a / 500) + y2, 3);
+
+  z = z / 108.883 <= 0.008859 ? z = (108.883 * (y2 - (b / 200) - (16 / 116))) 
/ 7.787 : 108.883 * Math.pow(y2 - (b / 200), 3);
+
+  return [x, y, z];
+}
+
+function lab2lch(lab) {
+  var l = lab[0],
+      a = lab[1],
+      b = lab[2],
+      hr, h, c;
+
+  hr = Math.atan2(b, a);
+  h = hr * 360 / 2 / Math.PI;
+  if (h < 0) {
+    h += 360;
+  }
+  c = Math.sqrt(a * a + b * b);
+  return [l, c, h];
+}
+
+function lab2rgb(args) {
+  return xyz2rgb(lab2xyz(args));
+}
+
+function lch2lab(lch) {
+  var l = lch[0],
+      c = lch[1],
+      h = lch[2],
+      a, b, hr;
+
+  hr = h / 360 * 2 * Math.PI;
+  a = c * Math.cos(hr);
+  b = c * Math.sin(hr);
+  return [l, a, b];
+}
+
+function lch2xyz(args) {
+  return lab2xyz(lch2lab(args));
+}
+
+function lch2rgb(args) {
+  return lab2rgb(lch2lab(args));
+}
+
+function keyword2rgb(keyword) {
+  return cssKeywords[keyword];
+}
+
+function keyword2hsl(args) {
+  return rgb2hsl(keyword2rgb(args));
+}
+
+function keyword2hsv(args) {
+  return rgb2hsv(keyword2rgb(args));
+}
+
+function keyword2hwb(args) {
+  return rgb2hwb(keyword2rgb(args));
+}
+
+function keyword2cmyk(args) {
+  return rgb2cmyk(keyword2rgb(args));
+}
+
+function keyword2lab(args) {
+  return rgb2lab(keyword2rgb(args));
+}
+
+function keyword2xyz(args) {
+  return rgb2xyz(keyword2rgb(args));
+}
+
+var cssKeywords = {
+  aliceblue:  [240,248,255],
+  antiquewhite: [250,235,215],
+  aqua: [0,255,255],
+  aquamarine: [127,255,212],
+  azure:  [240,255,255],
+  beige:  [245,245,220],
+  bisque: [255,228,196],
+  black:  [0,0,0],
+  blanchedalmond: [255,235,205],
+  blue: [0,0,255],
+  blueviolet: [138,43,226],
+  brown:  [165,42,42],
+  burlywood:  [222,184,135],
+  cadetblue:  [95,158,160],
+  chartreuse: [127,255,0],
+  chocolate:  [210,105,30],
+  coral:  [255,127,80],
+  cornflowerblue: [100,149,237],
+  cornsilk: [255,248,220],
+  crimson:  [220,20,60],
+  cyan: [0,255,255],
+  darkblue: [0,0,139],
+  darkcyan: [0,139,139],
+  darkgoldenrod:  [184,134,11],
+  darkgray: [169,169,169],
+  darkgreen:  [0,100,0],
+  darkgrey: [169,169,169],
+  darkkhaki:  [189,183,107],
+  darkmagenta:  [139,0,139],
+  darkolivegreen: [85,107,47],
+  darkorange: [255,140,0],
+  darkorchid: [153,50,204],
+  darkred:  [139,0,0],
+  darksalmon: [233,150,122],
+  darkseagreen: [143,188,143],
+  darkslateblue:  [72,61,139],
+  darkslategray:  [47,79,79],
+  darkslategrey:  [47,79,79],
+  darkturquoise:  [0,206,209],
+  darkviolet: [148,0,211],
+  deeppink: [255,20,147],
+  deepskyblue:  [0,191,255],
+  dimgray:  [105,105,105],
+  dimgrey:  [105,105,105],
+  dodgerblue: [30,144,255],
+  firebrick:  [178,34,34],
+  floralwhite:  [255,250,240],
+  forestgreen:  [34,139,34],
+  fuchsia:  [255,0,255],
+  gainsboro:  [220,220,220],
+  ghostwhite: [248,248,255],
+  gold: [255,215,0],
+  goldenrod:  [218,165,32],
+  gray: [128,128,128],
+  green:  [0,128,0],
+  greenyellow:  [173,255,47],
+  grey: [128,128,128],
+  honeydew: [240,255,240],
+  hotpink:  [255,105,180],
+  indianred:  [205,92,92],
+  indigo: [75,0,130],
+  ivory:  [255,255,240],
+  khaki:  [240,230,140],
+  lavender: [230,230,250],
+  lavenderblush:  [255,240,245],
+  lawngreen:  [124,252,0],
+  lemonchiffon: [255,250,205],
+  lightblue:  [173,216,230],
+  lightcoral: [240,128,128],
+  lightcyan:  [224,255,255],
+  lightgoldenrodyellow: [250,250,210],
+  lightgray:  [211,211,211],
+  lightgreen: [144,238,144],
+  lightgrey:  [211,211,211],
+  lightpink:  [255,182,193],
+  lightsalmon:  [255,160,122],
+  lightseagreen:  [32,178,170],
+  lightskyblue: [135,206,250],
+  lightslategray: [119,136,153],
+  lightslategrey: [119,136,153],
+  lightsteelblue: [176,196,222],
+  lightyellow:  [255,255,224],
+  lime: [0,255,0],
+  limegreen:  [50,205,50],
+  linen:  [250,240,230],
+  magenta:  [255,0,255],
+  maroon: [128,0,0],
+  mediumaquamarine: [102,205,170],
+  mediumblue: [0,0,205],
+  mediumorchid: [186,85,211],
+  mediumpurple: [147,112,219],
+  mediumseagreen: [60,179,113],
+  mediumslateblue:  [123,104,238],
+  mediumspringgreen:  [0,250,154],
+  mediumturquoise:  [72,209,204],
+  mediumvioletred:  [199,21,133],
+  midnightblue: [25,25,112],
+  mintcream:  [245,255,250],
+  mistyrose:  [255,228,225],
+  moccasin: [255,228,181],
+  navajowhite:  [255,222,173],
+  navy: [0,0,128],
+  oldlace:  [253,245,230],
+  olive:  [128,128,0],
+  olivedrab:  [107,142,35],
+  orange: [255,165,0],
+  orangered:  [255,69,0],
+  orchid: [218,112,214],
+  palegoldenrod:  [238,232,170],
+  palegreen:  [152,251,152],
+  paleturquoise:  [175,238,238],
+  palevioletred:  [219,112,147],
+  papayawhip: [255,239,213],
+  peachpuff:  [255,218,185],
+  peru: [205,133,63],
+  pink: [255,192,203],
+  plum: [221,160,221],
+  powderblue: [176,224,230],
+  purple: [128,0,128],
+  rebeccapurple: [102, 51, 153],
+  red:  [255,0,0],
+  rosybrown:  [188,143,143],
+  royalblue:  [65,105,225],
+  saddlebrown:  [139,69,19],
+  salmon: [250,128,114],
+  sandybrown: [244,164,96],
+  seagreen: [46,139,87],
+  seashell: [255,245,238],
+  sienna: [160,82,45],
+  silver: [192,192,192],
+  skyblue:  [135,206,235],
+  slateblue:  [106,90,205],
+  slategray:  [112,128,144],
+  slategrey:  [112,128,144],
+  snow: [255,250,250],
+  springgreen:  [0,255,127],
+  steelblue:  [70,130,180],
+  tan:  [210,180,140],
+  teal: [0,128,128],
+  thistle:  [216,191,216],
+  tomato: [255,99,71],
+  turquoise:  [64,224,208],
+  violet: [238,130,238],
+  wheat:  [245,222,179],
+  white:  [255,255,255],
+  whitesmoke: [245,245,245],
+  yellow: [255,255,0],
+  yellowgreen:  [154,205,50]
+};
+
+var reverseKeywords = {};
+for (var key in cssKeywords) {
+  reverseKeywords[JSON.stringify(cssKeywords[key])] = key;
+}
+
+},{}],5:[function(require,module,exports){
+var conversions = require(4);
+
+var convert = function() {
+   return new Converter();
+}
+
+for (var func in conversions) {
+  // export Raw versions
+  convert[func + "Raw"] =  (function(func) {
+    // accept array or plain args
+    return function(arg) {
+      if (typeof arg == "number")
+        arg = Array.prototype.slice.call(arguments);
+      return conversions[func](arg);
+    }
+  })(func);
+
+  var pair = /(\w+)2(\w+)/.exec(func),
+      from = pair[1],
+      to = pair[2];
+
+  // export rgb2hsl and ["rgb"]["hsl"]
+  convert[from] = convert[from] || {};
+
+  convert[from][to] = convert[func] = (function(func) { 
+    return function(arg) {
+      if (typeof arg == "number")
+        arg = Array.prototype.slice.call(arguments);
+      
+      var val = conversions[func](arg);
+      if (typeof val == "string" || val === undefined)
+        return val; // keyword
+
+      for (var i = 0; i < val.length; i++)
+        val[i] = Math.round(val[i]);
+      return val;
+    }
+  })(func);
+}
+
+
+/* Converter does lazy conversion and caching */
+var Converter = function() {
+   this.convs = {};
+};
+
+/* Either get the values for a space or
+  set the values for a space, depending on args */
+Converter.prototype.routeSpace = function(space, args) {
+   var values = args[0];
+   if (values === undefined) {
+      // color.rgb()
+      return this.getValues(space);
+   }
+   // color.rgb(10, 10, 10)
+   if (typeof values == "number") {
+      values = Array.prototype.slice.call(args);        
+   }
+
+   return this.setValues(space, values);
+};
+  
+/* Set the values for a space, invalidating cache */
+Converter.prototype.setValues = function(space, values) {
+   this.space = space;
+   this.convs = {};
+   this.convs[space] = values;
+   return this;
+};
+
+/* Get the values for a space. If there's already
+  a conversion for the space, fetch it, otherwise
+  compute it */
+Converter.prototype.getValues = function(space) {
+   var vals = this.convs[space];
+   if (!vals) {
+      var fspace = this.space,
+          from = this.convs[fspace];
+      vals = convert[fspace][space](from);
+
+      this.convs[space] = vals;
+   }
+  return vals;
+};
+
+["rgb", "hsl", "hsv", "cmyk", "keyword"].forEach(function(space) {
+   Converter.prototype[space] = function(vals) {
+      return this.routeSpace(space, arguments);
+   }
+});
+
+module.exports = convert;
+},{"4":4}],6:[function(require,module,exports){
+module.exports = {
+       "aliceblue": [240, 248, 255],
+       "antiquewhite": [250, 235, 215],
+       "aqua": [0, 255, 255],
+       "aquamarine": [127, 255, 212],
+       "azure": [240, 255, 255],
+       "beige": [245, 245, 220],
+       "bisque": [255, 228, 196],
+       "black": [0, 0, 0],
+       "blanchedalmond": [255, 235, 205],
+       "blue": [0, 0, 255],
+       "blueviolet": [138, 43, 226],
+       "brown": [165, 42, 42],
+       "burlywood": [222, 184, 135],
+       "cadetblue": [95, 158, 160],
+       "chartreuse": [127, 255, 0],
+       "chocolate": [210, 105, 30],
+       "coral": [255, 127, 80],
+       "cornflowerblue": [100, 149, 237],
+       "cornsilk": [255, 248, 220],
+       "crimson": [220, 20, 60],
+       "cyan": [0, 255, 255],
+       "darkblue": [0, 0, 139],
+       "darkcyan": [0, 139, 139],
+       "darkgoldenrod": [184, 134, 11],
+       "darkgray": [169, 169, 169],
+       "darkgreen": [0, 100, 0],
+       "darkgrey": [169, 169, 169],
+       "darkkhaki": [189, 183, 107],
+       "darkmagenta": [139, 0, 139],
+       "darkolivegreen": [85, 107, 47],
+       "darkorange": [255, 140, 0],
+       "darkorchid": [153, 50, 204],
+       "darkred": [139, 0, 0],
+       "darksalmon": [233, 150, 122],
+       "darkseagreen": [143, 188, 143],
+       "darkslateblue": [72, 61, 139],
+       "darkslategray": [47, 79, 79],
+       "darkslategrey": [47, 79, 79],
+       "darkturquoise": [0, 206, 209],
+       "darkviolet": [148, 0, 211],
+       "deeppink": [255, 20, 147],
+       "deepskyblue": [0, 191, 255],
+       "dimgray": [105, 105, 105],
+       "dimgrey": [105, 105, 105],
+       "dodgerblue": [30, 144, 255],
+       "firebrick": [178, 34, 34],
+       "floralwhite": [255, 250, 240],
+       "forestgreen": [34, 139, 34],
+       "fuchsia": [255, 0, 255],
+       "gainsboro": [220, 220, 220],
+       "ghostwhite": [248, 248, 255],
+       "gold": [255, 215, 0],
+       "goldenrod": [218, 165, 32],
+       "gray": [128, 128, 128],
+       "green": [0, 128, 0],
+       "greenyellow": [173, 255, 47],
+       "grey": [128, 128, 128],
+       "honeydew": [240, 255, 240],
+       "hotpink": [255, 105, 180],
+       "indianred": [205, 92, 92],
+       "indigo": [75, 0, 130],
+       "ivory": [255, 255, 240],
+       "khaki": [240, 230, 140],
+       "lavender": [230, 230, 250],
+       "lavenderblush": [255, 240, 245],
+       "lawngreen": [124, 252, 0],
+       "lemonchiffon": [255, 250, 205],
+       "lightblue": [173, 216, 230],
+       "lightcoral": [240, 128, 128],
+       "lightcyan": [224, 255, 255],
+       "lightgoldenrodyellow": [250, 250, 210],
+       "lightgray": [211, 211, 211],
+       "lightgreen": [144, 238, 144],
+       "lightgrey": [211, 211, 211],
+       "lightpink": [255, 182, 193],
+       "lightsalmon": [255, 160, 122],
+       "lightseagreen": [32, 178, 170],
+       "lightskyblue": [135, 206, 250],
+       "lightslategray": [119, 136, 153],
+       "lightslategrey": [119, 136, 153],
+       "lightsteelblue": [176, 196, 222],
+       "lightyellow": [255, 255, 224],
+       "lime": [0, 255, 0],
+       "limegreen": [50, 205, 50],
+       "linen": [250, 240, 230],
+       "magenta": [255, 0, 255],
+       "maroon": [128, 0, 0],
+       "mediumaquamarine": [102, 205, 170],
+       "mediumblue": [0, 0, 205],
+       "mediumorchid": [186, 85, 211],
+       "mediumpurple": [147, 112, 219],
+       "mediumseagreen": [60, 179, 113],
+       "mediumslateblue": [123, 104, 238],
+       "mediumspringgreen": [0, 250, 154],
+       "mediumturquoise": [72, 209, 204],
+       "mediumvioletred": [199, 21, 133],
+       "midnightblue": [25, 25, 112],
+       "mintcream": [245, 255, 250],
+       "mistyrose": [255, 228, 225],
+       "moccasin": [255, 228, 181],
+       "navajowhite": [255, 222, 173],
+       "navy": [0, 0, 128],
+       "oldlace": [253, 245, 230],
+       "olive": [128, 128, 0],
+       "olivedrab": [107, 142, 35],
+       "orange": [255, 165, 0],
+       "orangered": [255, 69, 0],
+       "orchid": [218, 112, 214],
+       "palegoldenrod": [238, 232, 170],
+       "palegreen": [152, 251, 152],
+       "paleturquoise": [175, 238, 238],
+       "palevioletred": [219, 112, 147],
+       "papayawhip": [255, 239, 213],
+       "peachpuff": [255, 218, 185],
+       "peru": [205, 133, 63],
+       "pink": [255, 192, 203],
+       "plum": [221, 160, 221],
+       "powderblue": [176, 224, 230],
+       "purple": [128, 0, 128],
+       "rebeccapurple": [102, 51, 153],
+       "red": [255, 0, 0],
+       "rosybrown": [188, 143, 143],
+       "royalblue": [65, 105, 225],
+       "saddlebrown": [139, 69, 19],
+       "salmon": [250, 128, 114],
+       "sandybrown": [244, 164, 96],
+       "seagreen": [46, 139, 87],
+       "seashell": [255, 245, 238],
+       "sienna": [160, 82, 45],
+       "silver": [192, 192, 192],
+       "skyblue": [135, 206, 235],
+       "slateblue": [106, 90, 205],
+       "slategray": [112, 128, 144],
+       "slategrey": [112, 128, 144],
+       "snow": [255, 250, 250],
+       "springgreen": [0, 255, 127],
+       "steelblue": [70, 130, 180],
+       "tan": [210, 180, 140],
+       "teal": [0, 128, 128],
+       "thistle": [216, 191, 216],
+       "tomato": [255, 99, 71],
+       "turquoise": [64, 224, 208],
+       "violet": [238, 130, 238],
+       "wheat": [245, 222, 179],
+       "white": [255, 255, 255],
+       "whitesmoke": [245, 245, 245],
+       "yellow": [255, 255, 0],
+       "yellowgreen": [154, 205, 50]
+};
+},{}],7:[function(require,module,exports){
+/**
+ * @namespace Chart
+ */
+var Chart = require(28)();
+
+require(26)(Chart);
+require(42)(Chart);
+require(22)(Chart);
+require(31)(Chart);
+require(25)(Chart);
+require(21)(Chart);
+require(23)(Chart);
+require(24)(Chart);
+require(29)(Chart);
+require(33)(Chart);
+require(34)(Chart);
+require(32)(Chart);
+require(35)(Chart);
+require(30)(Chart);
+require(27)(Chart);
+require(36)(Chart);
+
+require(37)(Chart);
+require(38)(Chart);
+require(39)(Chart);
+require(40)(Chart);
+
+require(45)(Chart);
+require(43)(Chart);
+require(44)(Chart);
+require(46)(Chart);
+require(47)(Chart);
+require(48)(Chart);
+
+// Controllers must be loaded after elements
+// See Chart.core.datasetController.dataElementType
+require(15)(Chart);
+require(16)(Chart);
+require(17)(Chart);
+require(18)(Chart);
+require(19)(Chart);
+require(20)(Chart);
+
+require(8)(Chart);
+require(9)(Chart);
+require(10)(Chart);
+require(11)(Chart);
+require(12)(Chart);
+require(13)(Chart);
+require(14)(Chart);
+
+window.Chart = module.exports = Chart;
+
+},{"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16,"17":17,"18":18,"19":19,"20":20,"21":21,"22":22,"23":23,"24":24,"25":25,"26":26,"27":27,"28":28,"29":29,"30":30,"31":31,"32":32,"33":33,"34":34,"35":35,"36":36,"37":37,"38":38,"39":39,"40":40,"42":42,"43":43,"44":44,"45":45,"46":46,"47":47,"48":48,"8":8,"9":9}],8:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       Chart.Bar = function(context, config) {
+               config.type = 'bar';
+
+               return new Chart(context, config);
+       };
+
+};
+
+},{}],9:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       Chart.Bubble = function(context, config) {
+               config.type = 'bubble';
+               return new Chart(context, config);
+       };
+
+};
+
+},{}],10:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       Chart.Doughnut = function(context, config) {
+               config.type = 'doughnut';
+
+               return new Chart(context, config);
+       };
+
+};
+
+},{}],11:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       Chart.Line = function(context, config) {
+               config.type = 'line';
+
+               return new Chart(context, config);
+       };
+
+};
+
+},{}],12:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       Chart.PolarArea = function(context, config) {
+               config.type = 'polarArea';
+
+               return new Chart(context, config);
+       };
+
+};
+
+},{}],13:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       Chart.Radar = function(context, config) {
+               config.type = 'radar';
+
+               return new Chart(context, config);
+       };
+
+};
+
+},{}],14:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       var defaultConfig = {
+               hover: {
+                       mode: 'single'
+               },
+
+               scales: {
+                       xAxes: [{
+                               type: 'linear', // scatter should not use a 
category axis
+                               position: 'bottom',
+                               id: 'x-axis-1' // need an ID so datasets can 
reference the scale
+                       }],
+                       yAxes: [{
+                               type: 'linear',
+                               position: 'left',
+                               id: 'y-axis-1'
+                       }]
+               },
+
+               tooltips: {
+                       callbacks: {
+                               title: function() {
+                                       // Title doesn't make sense for scatter 
since we format the data as a point
+                                       return '';
+                               },
+                               label: function(tooltipItem) {
+                                       return '(' + tooltipItem.xLabel + ', ' 
+ tooltipItem.yLabel + ')';
+                               }
+                       }
+               }
+       };
+
+       // Register the default config for this type
+       Chart.defaults.scatter = defaultConfig;
+
+       // Scatter charts use line controllers
+       Chart.controllers.scatter = Chart.controllers.line;
+
+       Chart.Scatter = function(context, config) {
+               config.type = 'scatter';
+               return new Chart(context, config);
+       };
+
+};
+
+},{}],15:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       var helpers = Chart.helpers;
+
+       Chart.defaults.bar = {
+               hover: {
+                       mode: 'label'
+               },
+
+               scales: {
+                       xAxes: [{
+                               type: 'category',
+
+                               // Specific to Bar Controller
+                               categoryPercentage: 0.8,
+                               barPercentage: 0.9,
+
+                               // grid line settings
+                               gridLines: {
+                                       offsetGridLines: true
+                               }
+                       }],
+                       yAxes: [{
+                               type: 'linear'
+                       }]
+               }
+       };
+
+       Chart.controllers.bar = Chart.DatasetController.extend({
+
+               dataElementType: Chart.elements.Rectangle,
+
+               initialize: function(chart, datasetIndex) {
+                       Chart.DatasetController.prototype.initialize.call(this, 
chart, datasetIndex);
+
+                       var me = this;
+                       var meta = me.getMeta();
+                       var dataset = me.getDataset();
+
+                       meta.stack = dataset.stack;
+                       // Use this to indicate that this is a bar dataset.
+                       meta.bar = true;
+               },
+
+               // Correctly calculate the bar width accounting for stacks and 
the fact that not all bars are visible
+               getStackCount: function() {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var yScale = me.getScaleForId(meta.yAxisID);
+
+                       var stacks = [];
+                       helpers.each(me.chart.data.datasets, function(dataset, 
datasetIndex) {
+                               var dsMeta = 
me.chart.getDatasetMeta(datasetIndex);
+                               if (dsMeta.bar && 
me.chart.isDatasetVisible(datasetIndex) &&
+                                       (yScale.options.stacked === false ||
+                                       (yScale.options.stacked === true && 
stacks.indexOf(dsMeta.stack) === -1) ||
+                                       (yScale.options.stacked === undefined 
&& (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) {
+                                       stacks.push(dsMeta.stack);
+                               }
+                       }, me);
+
+                       return stacks.length;
+               },
+
+               update: function(reset) {
+                       var me = this;
+                       helpers.each(me.getMeta().data, function(rectangle, 
index) {
+                               me.updateElement(rectangle, index, reset);
+                       }, me);
+               },
+
+               updateElement: function(rectangle, index, reset) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var xScale = me.getScaleForId(meta.xAxisID);
+                       var yScale = me.getScaleForId(meta.yAxisID);
+                       var scaleBase = yScale.getBasePixel();
+                       var rectangleElementOptions = 
me.chart.options.elements.rectangle;
+                       var custom = rectangle.custom || {};
+                       var dataset = me.getDataset();
+
+                       rectangle._xScale = xScale;
+                       rectangle._yScale = yScale;
+                       rectangle._datasetIndex = me.index;
+                       rectangle._index = index;
+
+                       var ruler = me.getRuler(index); // The index argument 
for compatible
+                       rectangle._model = {
+                               x: me.calculateBarX(index, me.index, ruler),
+                               y: reset ? scaleBase : me.calculateBarY(index, 
me.index),
+
+                               // Tooltip
+                               label: me.chart.data.labels[index],
+                               datasetLabel: dataset.label,
+
+                               // Appearance
+                               horizontal: false,
+                               base: reset ? scaleBase : 
me.calculateBarBase(me.index, index),
+                               width: me.calculateBarWidth(ruler),
+                               backgroundColor: custom.backgroundColor ? 
custom.backgroundColor : 
helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, 
rectangleElementOptions.backgroundColor),
+                               borderSkipped: custom.borderSkipped ? 
custom.borderSkipped : rectangleElementOptions.borderSkipped,
+                               borderColor: custom.borderColor ? 
custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, 
index, rectangleElementOptions.borderColor),
+                               borderWidth: custom.borderWidth ? 
custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, 
index, rectangleElementOptions.borderWidth)
+                       };
+
+                       rectangle.pivot();
+               },
+
+               calculateBarBase: function(datasetIndex, index) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var yScale = me.getScaleForId(meta.yAxisID);
+                       var base = yScale.getBaseValue();
+                       var original = base;
+
+                       if ((yScale.options.stacked === true) ||
+                               (yScale.options.stacked === undefined && 
meta.stack !== undefined)) {
+                               var chart = me.chart;
+                               var datasets = chart.data.datasets;
+                               var value = 
Number(datasets[datasetIndex].data[index]);
+
+                               for (var i = 0; i < datasetIndex; i++) {
+                                       var currentDs = datasets[i];
+                                       var currentDsMeta = 
chart.getDatasetMeta(i);
+                                       if (currentDsMeta.bar && 
currentDsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i) &&
+                                               meta.stack === 
currentDsMeta.stack) {
+                                               var currentVal = 
Number(currentDs.data[index]);
+                                               base += value < 0 ? 
Math.min(currentVal, original) : Math.max(currentVal, original);
+                                       }
+                               }
+
+                               return yScale.getPixelForValue(base);
+                       }
+
+                       return yScale.getBasePixel();
+               },
+
+               getRuler: function() {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var xScale = me.getScaleForId(meta.xAxisID);
+                       var stackCount = me.getStackCount();
+
+                       var tickWidth = xScale.width / xScale.ticks.length;
+                       var categoryWidth = tickWidth * 
xScale.options.categoryPercentage;
+                       var categorySpacing = (tickWidth - (tickWidth * 
xScale.options.categoryPercentage)) / 2;
+                       var fullBarWidth = categoryWidth / stackCount;
+
+                       var barWidth = fullBarWidth * 
xScale.options.barPercentage;
+                       var barSpacing = fullBarWidth - (fullBarWidth * 
xScale.options.barPercentage);
+
+                       return {
+                               stackCount: stackCount,
+                               tickWidth: tickWidth,
+                               categoryWidth: categoryWidth,
+                               categorySpacing: categorySpacing,
+                               fullBarWidth: fullBarWidth,
+                               barWidth: barWidth,
+                               barSpacing: barSpacing
+                       };
+               },
+
+               calculateBarWidth: function(ruler) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var xScale = me.getScaleForId(meta.xAxisID);
+                       if (xScale.options.barThickness) {
+                               return xScale.options.barThickness;
+                       }
+                       return ruler.barWidth;
+               },
+
+               // Get stack index from the given dataset index accounting for 
stacks and the fact that not all bars are visible
+               getStackIndex: function(datasetIndex) {
+                       var me = this;
+                       var meta = me.chart.getDatasetMeta(datasetIndex);
+                       var yScale = me.getScaleForId(meta.yAxisID);
+                       var dsMeta, j;
+                       var stacks = [meta.stack];
+
+                       for (j = 0; j < datasetIndex; ++j) {
+                               dsMeta = this.chart.getDatasetMeta(j);
+                               if (dsMeta.bar && 
this.chart.isDatasetVisible(j) &&
+                                       (yScale.options.stacked === false ||
+                                       (yScale.options.stacked === true && 
stacks.indexOf(dsMeta.stack) === -1) ||
+                                       (yScale.options.stacked === undefined 
&& (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) {
+                                       stacks.push(dsMeta.stack);
+                               }
+                       }
+
+                       return stacks.length - 1;
+               },
+
+               calculateBarX: function(index, datasetIndex, ruler) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var xScale = me.getScaleForId(meta.xAxisID);
+                       var stackIndex = me.getStackIndex(datasetIndex);
+                       var leftTick = xScale.getPixelForValue(null, index, 
datasetIndex, me.chart.isCombo);
+                       leftTick -= me.chart.isCombo ? (ruler.tickWidth / 2) : 
0;
+
+                       return leftTick +
+                               (ruler.barWidth / 2) +
+                               ruler.categorySpacing +
+                               (ruler.barWidth * stackIndex) +
+                               (ruler.barSpacing / 2) +
+                               (ruler.barSpacing * stackIndex);
+               },
+
+               calculateBarY: function(index, datasetIndex) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var yScale = me.getScaleForId(meta.yAxisID);
+                       var value = Number(me.getDataset().data[index]);
+
+                       if (yScale.options.stacked ||
+                               (yScale.options.stacked === undefined && 
meta.stack !== undefined)) {
+                               var base = yScale.getBaseValue();
+                               var sumPos = base,
+                                       sumNeg = base;
+
+                               for (var i = 0; i < datasetIndex; i++) {
+                                       var ds = me.chart.data.datasets[i];
+                                       var dsMeta = me.chart.getDatasetMeta(i);
+                                       if (dsMeta.bar && dsMeta.yAxisID === 
yScale.id && me.chart.isDatasetVisible(i) &&
+                                               meta.stack === dsMeta.stack) {
+                                               var stackedVal = 
Number(ds.data[index]);
+                                               if (stackedVal < 0) {
+                                                       sumNeg += stackedVal || 
0;
+                                               } else {
+                                                       sumPos += stackedVal || 
0;
+                                               }
+                                       }
+                               }
+
+                               if (value < 0) {
+                                       return yScale.getPixelForValue(sumNeg + 
value);
+                               }
+                               return yScale.getPixelForValue(sumPos + value);
+                       }
+
+                       return yScale.getPixelForValue(value);
+               },
+
+               draw: function(ease) {
+                       var me = this;
+                       var easingDecimal = ease || 1;
+                       var metaData = me.getMeta().data;
+                       var dataset = me.getDataset();
+                       var i, len;
+
+                       Chart.canvasHelpers.clipArea(me.chart.chart.ctx, 
me.chart.chartArea);
+                       for (i = 0, len = metaData.length; i < len; ++i) {
+                               var d = dataset.data[i];
+                               if (d !== null && d !== undefined && !isNaN(d)) 
{
+                                       
metaData[i].transition(easingDecimal).draw();
+                               }
+                       }
+                       Chart.canvasHelpers.unclipArea(me.chart.chart.ctx);
+               },
+
+               setHoverStyle: function(rectangle) {
+                       var dataset = 
this.chart.data.datasets[rectangle._datasetIndex];
+                       var index = rectangle._index;
+
+                       var custom = rectangle.custom || {};
+                       var model = rectangle._model;
+                       model.backgroundColor = custom.hoverBackgroundColor ? 
custom.hoverBackgroundColor : 
helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, 
helpers.getHoverColor(model.backgroundColor));
+                       model.borderColor = custom.hoverBorderColor ? 
custom.hoverBorderColor : 
helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, 
helpers.getHoverColor(model.borderColor));
+                       model.borderWidth = custom.hoverBorderWidth ? 
custom.hoverBorderWidth : 
helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, 
model.borderWidth);
+               },
+
+               removeHoverStyle: function(rectangle) {
+                       var dataset = 
this.chart.data.datasets[rectangle._datasetIndex];
+                       var index = rectangle._index;
+                       var custom = rectangle.custom || {};
+                       var model = rectangle._model;
+                       var rectangleElementOptions = 
this.chart.options.elements.rectangle;
+
+                       model.backgroundColor = custom.backgroundColor ? 
custom.backgroundColor : 
helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, 
rectangleElementOptions.backgroundColor);
+                       model.borderColor = custom.borderColor ? 
custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, 
index, rectangleElementOptions.borderColor);
+                       model.borderWidth = custom.borderWidth ? 
custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, 
index, rectangleElementOptions.borderWidth);
+               }
+
+       });
+
+
+       // including horizontalBar in the bar file, instead of a file of its own
+       // it extends bar (like pie extends doughnut)
+       Chart.defaults.horizontalBar = {
+               hover: {
+                       mode: 'label'
+               },
+
+               scales: {
+                       xAxes: [{
+                               type: 'linear',
+                               position: 'bottom'
+                       }],
+                       yAxes: [{
+                               position: 'left',
+                               type: 'category',
+
+                               // Specific to Horizontal Bar Controller
+                               categoryPercentage: 0.8,
+                               barPercentage: 0.9,
+
+                               // grid line settings
+                               gridLines: {
+                                       offsetGridLines: true
+                               }
+                       }]
+               },
+               elements: {
+                       rectangle: {
+                               borderSkipped: 'left'
+                       }
+               },
+               tooltips: {
+                       callbacks: {
+                               title: function(tooltipItems, data) {
+                                       // Pick first xLabel for now
+                                       var title = '';
+
+                                       if (tooltipItems.length > 0) {
+                                               if (tooltipItems[0].yLabel) {
+                                                       title = 
tooltipItems[0].yLabel;
+                                               } else if (data.labels.length > 
0 && tooltipItems[0].index < data.labels.length) {
+                                                       title = 
data.labels[tooltipItems[0].index];
+                                               }
+                                       }
+
+                                       return title;
+                               },
+                               label: function(tooltipItem, data) {
+                                       var datasetLabel = 
data.datasets[tooltipItem.datasetIndex].label || '';
+                                       return datasetLabel + ': ' + 
tooltipItem.xLabel;
+                               }
+                       }
+               }
+       };
+
+       Chart.controllers.horizontalBar = Chart.controllers.bar.extend({
+
+               // Correctly calculate the bar width accounting for stacks and 
the fact that not all bars are visible
+               getStackCount: function() {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var xScale = me.getScaleForId(meta.xAxisID);
+
+                       var stacks = [];
+                       helpers.each(me.chart.data.datasets, function(dataset, 
datasetIndex) {
+                               var dsMeta = 
me.chart.getDatasetMeta(datasetIndex);
+                               if (dsMeta.bar && 
me.chart.isDatasetVisible(datasetIndex) &&
+                                       (xScale.options.stacked === false ||
+                                       (xScale.options.stacked === true && 
stacks.indexOf(dsMeta.stack) === -1) ||
+                                       (xScale.options.stacked === undefined 
&& (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) {
+                                       stacks.push(dsMeta.stack);
+                               }
+                       }, me);
+
+                       return stacks.length;
+               },
+
+               updateElement: function(rectangle, index, reset) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var xScale = me.getScaleForId(meta.xAxisID);
+                       var yScale = me.getScaleForId(meta.yAxisID);
+                       var scaleBase = xScale.getBasePixel();
+                       var custom = rectangle.custom || {};
+                       var dataset = me.getDataset();
+                       var rectangleElementOptions = 
me.chart.options.elements.rectangle;
+
+                       rectangle._xScale = xScale;
+                       rectangle._yScale = yScale;
+                       rectangle._datasetIndex = me.index;
+                       rectangle._index = index;
+
+                       var ruler = me.getRuler(index); // The index argument 
for compatible
+                       rectangle._model = {
+                               x: reset ? scaleBase : me.calculateBarX(index, 
me.index),
+                               y: me.calculateBarY(index, me.index, ruler),
+
+                               // Tooltip
+                               label: me.chart.data.labels[index],
+                               datasetLabel: dataset.label,
+
+                               // Appearance
+                               horizontal: true,
+                               base: reset ? scaleBase : 
me.calculateBarBase(me.index, index),
+                               height: me.calculateBarHeight(ruler),
+                               backgroundColor: custom.backgroundColor ? 
custom.backgroundColor : 
helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, 
rectangleElementOptions.backgroundColor),
+                               borderSkipped: custom.borderSkipped ? 
custom.borderSkipped : rectangleElementOptions.borderSkipped,
+                               borderColor: custom.borderColor ? 
custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, 
index, rectangleElementOptions.borderColor),
+                               borderWidth: custom.borderWidth ? 
custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, 
index, rectangleElementOptions.borderWidth)
+                       };
+
+                       rectangle.pivot();
+               },
+
+               calculateBarBase: function(datasetIndex, index) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var xScale = me.getScaleForId(meta.xAxisID);
+                       var base = xScale.getBaseValue();
+                       var originalBase = base;
+
+                       if (xScale.options.stacked ||
+                               (xScale.options.stacked === undefined && 
meta.stack !== undefined)) {
+                               var chart = me.chart;
+                               var datasets = chart.data.datasets;
+                               var value = 
Number(datasets[datasetIndex].data[index]);
+
+                               for (var i = 0; i < datasetIndex; i++) {
+                                       var currentDs = datasets[i];
+                                       var currentDsMeta = 
chart.getDatasetMeta(i);
+                                       if (currentDsMeta.bar && 
currentDsMeta.xAxisID === xScale.id && chart.isDatasetVisible(i) &&
+                                               meta.stack === 
currentDsMeta.stack) {
+                                               var currentVal = 
Number(currentDs.data[index]);
+                                               base += value < 0 ? 
Math.min(currentVal, originalBase) : Math.max(currentVal, originalBase);
+                                       }
+                               }
+
+                               return xScale.getPixelForValue(base);
+                       }
+
+                       return xScale.getBasePixel();
+               },
+
+               getRuler: function() {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var yScale = me.getScaleForId(meta.yAxisID);
+                       var stackCount = me.getStackCount();
+
+                       var tickHeight = yScale.height / yScale.ticks.length;
+                       var categoryHeight = tickHeight * 
yScale.options.categoryPercentage;
+                       var categorySpacing = (tickHeight - (tickHeight * 
yScale.options.categoryPercentage)) / 2;
+                       var fullBarHeight = categoryHeight / stackCount;
+
+                       var barHeight = fullBarHeight * 
yScale.options.barPercentage;
+                       var barSpacing = fullBarHeight - (fullBarHeight * 
yScale.options.barPercentage);
+
+                       return {
+                               stackCount: stackCount,
+                               tickHeight: tickHeight,
+                               categoryHeight: categoryHeight,
+                               categorySpacing: categorySpacing,
+                               fullBarHeight: fullBarHeight,
+                               barHeight: barHeight,
+                               barSpacing: barSpacing
+                       };
+               },
+
+               calculateBarHeight: function(ruler) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var yScale = me.getScaleForId(meta.yAxisID);
+                       if (yScale.options.barThickness) {
+                               return yScale.options.barThickness;
+                       }
+                       return ruler.barHeight;
+               },
+
+               // Get stack index from the given dataset index accounting for 
stacks and the fact that not all bars are visible
+               getStackIndex: function(datasetIndex) {
+                       var me = this;
+                       var meta = me.chart.getDatasetMeta(datasetIndex);
+                       var xScale = me.getScaleForId(meta.xAxisID);
+                       var dsMeta, j;
+                       var stacks = [meta.stack];
+
+                       for (j = 0; j < datasetIndex; ++j) {
+                               dsMeta = this.chart.getDatasetMeta(j);
+                               if (dsMeta.bar && 
this.chart.isDatasetVisible(j) &&
+                                       (xScale.options.stacked === false ||
+                                       (xScale.options.stacked === true && 
stacks.indexOf(dsMeta.stack) === -1) ||
+                                       (xScale.options.stacked === undefined 
&& (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) {
+                                       stacks.push(dsMeta.stack);
+                               }
+                       }
+
+                       return stacks.length - 1;
+               },
+
+               calculateBarX: function(index, datasetIndex) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var xScale = me.getScaleForId(meta.xAxisID);
+                       var value = Number(me.getDataset().data[index]);
+
+                       if (xScale.options.stacked ||
+                               (xScale.options.stacked === undefined && 
meta.stack !== undefined)) {
+                               var base = xScale.getBaseValue();
+                               var sumPos = base,
+                                       sumNeg = base;
+
+                               for (var i = 0; i < datasetIndex; i++) {
+                                       var ds = me.chart.data.datasets[i];
+                                       var dsMeta = me.chart.getDatasetMeta(i);
+                                       if (dsMeta.bar && dsMeta.xAxisID === 
xScale.id && me.chart.isDatasetVisible(i) &&
+                                               meta.stack === dsMeta.stack) {
+                                               var stackedVal = 
Number(ds.data[index]);
+                                               if (stackedVal < 0) {
+                                                       sumNeg += stackedVal || 
0;
+                                               } else {
+                                                       sumPos += stackedVal || 
0;
+                                               }
+                                       }
+                               }
+
+                               if (value < 0) {
+                                       return xScale.getPixelForValue(sumNeg + 
value);
+                               }
+                               return xScale.getPixelForValue(sumPos + value);
+                       }
+
+                       return xScale.getPixelForValue(value);
+               },
+
+               calculateBarY: function(index, datasetIndex, ruler) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var yScale = me.getScaleForId(meta.yAxisID);
+                       var stackIndex = me.getStackIndex(datasetIndex);
+                       var topTick = yScale.getPixelForValue(null, index, 
datasetIndex, me.chart.isCombo);
+                       topTick -= me.chart.isCombo ? (ruler.tickHeight / 2) : 
0;
+
+                       return topTick +
+                               (ruler.barHeight / 2) +
+                               ruler.categorySpacing +
+                               (ruler.barHeight * stackIndex) +
+                               (ruler.barSpacing / 2) +
+                               (ruler.barSpacing * stackIndex);
+               }
+       });
+};
+
+},{}],16:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       var helpers = Chart.helpers;
+
+       Chart.defaults.bubble = {
+               hover: {
+                       mode: 'single'
+               },
+
+               scales: {
+                       xAxes: [{
+                               type: 'linear', // bubble should probably use a 
linear scale by default
+                               position: 'bottom',
+                               id: 'x-axis-0' // need an ID so datasets can 
reference the scale
+                       }],
+                       yAxes: [{
+                               type: 'linear',
+                               position: 'left',
+                               id: 'y-axis-0'
+                       }]
+               },
+
+               tooltips: {
+                       callbacks: {
+                               title: function() {
+                                       // Title doesn't make sense for scatter 
since we format the data as a point
+                                       return '';
+                               },
+                               label: function(tooltipItem, data) {
+                                       var datasetLabel = 
data.datasets[tooltipItem.datasetIndex].label || '';
+                                       var dataPoint = 
data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
+                                       return datasetLabel + ': (' + 
tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ', ' + dataPoint.r + ')';
+                               }
+                       }
+               }
+       };
+
+       Chart.controllers.bubble = Chart.DatasetController.extend({
+
+               dataElementType: Chart.elements.Point,
+
+               update: function(reset) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var points = meta.data;
+
+                       // Update Points
+                       helpers.each(points, function(point, index) {
+                               me.updateElement(point, index, reset);
+                       });
+               },
+
+               updateElement: function(point, index, reset) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var xScale = me.getScaleForId(meta.xAxisID);
+                       var yScale = me.getScaleForId(meta.yAxisID);
+
+                       var custom = point.custom || {};
+                       var dataset = me.getDataset();
+                       var data = dataset.data[index];
+                       var pointElementOptions = 
me.chart.options.elements.point;
+                       var dsIndex = me.index;
+
+                       helpers.extend(point, {
+                               // Utility
+                               _xScale: xScale,
+                               _yScale: yScale,
+                               _datasetIndex: dsIndex,
+                               _index: index,
+
+                               // Desired view properties
+                               _model: {
+                                       x: reset ? 
xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 
'object' ? data : NaN, index, dsIndex, me.chart.isCombo),
+                                       y: reset ? yScale.getBasePixel() : 
yScale.getPixelForValue(data, index, dsIndex),
+                                       // Appearance
+                                       radius: reset ? 0 : custom.radius ? 
custom.radius : me.getRadius(data),
+
+                                       // Tooltip
+                                       hitRadius: custom.hitRadius ? 
custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, 
pointElementOptions.hitRadius)
+                               }
+                       });
+
+                       // Trick to reset the styles of the point
+                       
Chart.DatasetController.prototype.removeHoverStyle.call(me, point, 
pointElementOptions);
+
+                       var model = point._model;
+                       model.skip = custom.skip ? custom.skip : 
(isNaN(model.x) || isNaN(model.y));
+
+                       point.pivot();
+               },
+
+               getRadius: function(value) {
+                       return value.r || 
this.chart.options.elements.point.radius;
+               },
+
+               setHoverStyle: function(point) {
+                       var me = this;
+                       
Chart.DatasetController.prototype.setHoverStyle.call(me, point);
+
+                       // Radius
+                       var dataset = 
me.chart.data.datasets[point._datasetIndex];
+                       var index = point._index;
+                       var custom = point.custom || {};
+                       var model = point._model;
+                       model.radius = custom.hoverRadius ? custom.hoverRadius 
: (helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, 
me.chart.options.elements.point.hoverRadius)) + 
me.getRadius(dataset.data[index]);
+               },
+
+               removeHoverStyle: function(point) {
+                       var me = this;
+                       
Chart.DatasetController.prototype.removeHoverStyle.call(me, point, 
me.chart.options.elements.point);
+
+                       var dataVal = 
me.chart.data.datasets[point._datasetIndex].data[point._index];
+                       var custom = point.custom || {};
+                       var model = point._model;
+
+                       model.radius = custom.radius ? custom.radius : 
me.getRadius(dataVal);
+               }
+       });
+};
+
+},{}],17:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       var helpers = Chart.helpers,
+               defaults = Chart.defaults;
+
+       defaults.doughnut = {
+               animation: {
+                       // Boolean - Whether we animate the rotation of the 
Doughnut
+                       animateRotate: true,
+                       // Boolean - Whether we animate scaling the Doughnut 
from the centre
+                       animateScale: false
+               },
+               aspectRatio: 1,
+               hover: {
+                       mode: 'single'
+               },
+               legendCallback: function(chart) {
+                       var text = [];
+                       text.push('<ul class="' + chart.id + '-legend">');
+
+                       var data = chart.data;
+                       var datasets = data.datasets;
+                       var labels = data.labels;
+
+                       if (datasets.length) {
+                               for (var i = 0; i < datasets[0].data.length; 
++i) {
+                                       text.push('<li><span 
style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
+                                       if (labels[i]) {
+                                               text.push(labels[i]);
+                                       }
+                                       text.push('</li>');
+                               }
+                       }
+
+                       text.push('</ul>');
+                       return text.join('');
+               },
+               legend: {
+                       labels: {
+                               generateLabels: function(chart) {
+                                       var data = chart.data;
+                                       if (data.labels.length && 
data.datasets.length) {
+                                               return 
data.labels.map(function(label, i) {
+                                                       var meta = 
chart.getDatasetMeta(0);
+                                                       var ds = 
data.datasets[0];
+                                                       var arc = meta.data[i];
+                                                       var custom = arc && 
arc.custom || {};
+                                                       var 
getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
+                                                       var arcOpts = 
chart.options.elements.arc;
+                                                       var fill = 
custom.backgroundColor ? custom.backgroundColor : 
getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
+                                                       var stroke = 
custom.borderColor ? custom.borderColor : 
getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
+                                                       var bw = 
custom.borderWidth ? custom.borderWidth : 
getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
+
+                                                       return {
+                                                               text: label,
+                                                               fillStyle: fill,
+                                                               strokeStyle: 
stroke,
+                                                               lineWidth: bw,
+                                                               hidden: 
isNaN(ds.data[i]) || meta.data[i].hidden,
+
+                                                               // Extra data 
used for toggling the correct item
+                                                               index: i
+                                                       };
+                                               });
+                                       }
+                                       return [];
+                               }
+                       },
+
+                       onClick: function(e, legendItem) {
+                               var index = legendItem.index;
+                               var chart = this.chart;
+                               var i, ilen, meta;
+
+                               for (i = 0, ilen = (chart.data.datasets || 
[]).length; i < ilen; ++i) {
+                                       meta = chart.getDatasetMeta(i);
+                                       // toggle visibility of index if exists
+                                       if (meta.data[index]) {
+                                               meta.data[index].hidden = 
!meta.data[index].hidden;
+                                       }
+                               }
+
+                               chart.update();
+                       }
+               },
+
+               // The percentage of the chart that we cut out of the middle.
+               cutoutPercentage: 50,
+
+               // The rotation of the chart, where the first data arc begins.
+               rotation: Math.PI * -0.5,
+
+               // The total circumference of the chart.
+               circumference: Math.PI * 2.0,
+
+               // Need to override these to give a nice default
+               tooltips: {
+                       callbacks: {
+                               title: function() {
+                                       return '';
+                               },
+                               label: function(tooltipItem, data) {
+                                       var dataLabel = 
data.labels[tooltipItem.index];
+                                       var value = ': ' + 
data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
+
+                                       if (helpers.isArray(dataLabel)) {
+                                               // show value on first line of 
multiline label
+                                               // need to clone because we are 
changing the value
+                                               dataLabel = dataLabel.slice();
+                                               dataLabel[0] += value;
+                                       } else {
+                                               dataLabel += value;
+                                       }
+
+                                       return dataLabel;
+                               }
+                       }
+               }
+       };
+
+       defaults.pie = helpers.clone(defaults.doughnut);
+       helpers.extend(defaults.pie, {
+               cutoutPercentage: 0
+       });
+
+
+       Chart.controllers.doughnut = Chart.controllers.pie = 
Chart.DatasetController.extend({
+
+               dataElementType: Chart.elements.Arc,
+
+               linkScales: helpers.noop,
+
+               // Get index of the dataset in relation to the visible 
datasets. This allows determining the inner and outer radius correctly
+               getRingIndex: function(datasetIndex) {
+                       var ringIndex = 0;
+
+                       for (var j = 0; j < datasetIndex; ++j) {
+                               if (this.chart.isDatasetVisible(j)) {
+                                       ++ringIndex;
+                               }
+                       }
+
+                       return ringIndex;
+               },
+
+               update: function(reset) {
+                       var me = this;
+                       var chart = me.chart,
+                               chartArea = chart.chartArea,
+                               opts = chart.options,
+                               arcOpts = opts.elements.arc,
+                               availableWidth = chartArea.right - 
chartArea.left - arcOpts.borderWidth,
+                               availableHeight = chartArea.bottom - 
chartArea.top - arcOpts.borderWidth,
+                               minSize = Math.min(availableWidth, 
availableHeight),
+                               offset = {
+                                       x: 0,
+                                       y: 0
+                               },
+                               meta = me.getMeta(),
+                               cutoutPercentage = opts.cutoutPercentage,
+                               circumference = opts.circumference;
+
+                       // If the chart's circumference isn't a full circle, 
calculate minSize as a ratio of the width/height of the arc
+                       if (circumference < Math.PI * 2.0) {
+                               var startAngle = opts.rotation % (Math.PI * 
2.0);
+                               startAngle += Math.PI * 2.0 * (startAngle >= 
Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);
+                               var endAngle = startAngle + circumference;
+                               var start = {x: Math.cos(startAngle), y: 
Math.sin(startAngle)};
+                               var end = {x: Math.cos(endAngle), y: 
Math.sin(endAngle)};
+                               var contains0 = (startAngle <= 0 && 0 <= 
endAngle) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);
+                               var contains90 = (startAngle <= Math.PI * 0.5 
&& Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 
<= endAngle);
+                               var contains180 = (startAngle <= -Math.PI && 
-Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);
+                               var contains270 = (startAngle <= -Math.PI * 0.5 
&& -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 
<= endAngle);
+                               var cutout = cutoutPercentage / 100.0;
+                               var min = {x: contains180 ? -1 : 
Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : 
cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), 
end.y * (end.y < 0 ? 1 : cutout))};
+                               var max = {x: contains0 ? 1 : Math.max(start.x 
* (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 
? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : 
cutout))};
+                               var size = {width: (max.x - min.x) * 0.5, 
height: (max.y - min.y) * 0.5};
+                               minSize = Math.min(availableWidth / size.width, 
availableHeight / size.height);
+                               offset = {x: (max.x + min.x) * -0.5, y: (max.y 
+ min.y) * -0.5};
+                       }
+
+                       chart.borderWidth = me.getMaxBorderWidth(meta.data);
+                       chart.outerRadius = Math.max((minSize - 
chart.borderWidth) / 2, 0);
+                       chart.innerRadius = Math.max(cutoutPercentage ? 
(chart.outerRadius / 100) * (cutoutPercentage) : 0, 0);
+                       chart.radiusLength = (chart.outerRadius - 
chart.innerRadius) / chart.getVisibleDatasetCount();
+                       chart.offsetX = offset.x * chart.outerRadius;
+                       chart.offsetY = offset.y * chart.outerRadius;
+
+                       meta.total = me.calculateTotal();
+
+                       me.outerRadius = chart.outerRadius - 
(chart.radiusLength * me.getRingIndex(me.index));
+                       me.innerRadius = Math.max(me.outerRadius - 
chart.radiusLength, 0);
+
+                       helpers.each(meta.data, function(arc, index) {
+                               me.updateElement(arc, index, reset);
+                       });
+               },
+
+               updateElement: function(arc, index, reset) {
+                       var me = this;
+                       var chart = me.chart,
+                               chartArea = chart.chartArea,
+                               opts = chart.options,
+                               animationOpts = opts.animation,
+                               centerX = (chartArea.left + chartArea.right) / 
2,
+                               centerY = (chartArea.top + chartArea.bottom) / 
2,
+                               startAngle = opts.rotation, // non reset case 
handled later
+                               endAngle = opts.rotation, // non reset case 
handled later
+                               dataset = me.getDataset(),
+                               circumference = reset && 
animationOpts.animateRotate ? 0 : arc.hidden ? 0 : 
me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * 
Math.PI)),
+                               innerRadius = reset && 
animationOpts.animateScale ? 0 : me.innerRadius,
+                               outerRadius = reset && 
animationOpts.animateScale ? 0 : me.outerRadius,
+                               valueAtIndexOrDefault = 
helpers.getValueAtIndexOrDefault;
+
+                       helpers.extend(arc, {
+                               // Utility
+                               _datasetIndex: me.index,
+                               _index: index,
+
+                               // Desired view properties
+                               _model: {
+                                       x: centerX + chart.offsetX,
+                                       y: centerY + chart.offsetY,
+                                       startAngle: startAngle,
+                                       endAngle: endAngle,
+                                       circumference: circumference,
+                                       outerRadius: outerRadius,
+                                       innerRadius: innerRadius,
+                                       label: 
valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index])
+                               }
+                       });
+
+                       var model = arc._model;
+                       // Resets the visual styles
+                       this.removeHoverStyle(arc);
+
+                       // Set correct angles if not resetting
+                       if (!reset || !animationOpts.animateRotate) {
+                               if (index === 0) {
+                                       model.startAngle = opts.rotation;
+                               } else {
+                                       model.startAngle = 
me.getMeta().data[index - 1]._model.endAngle;
+                               }
+
+                               model.endAngle = model.startAngle + 
model.circumference;
+                       }
+
+                       arc.pivot();
+               },
+
+               removeHoverStyle: function(arc) {
+                       
Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, 
this.chart.options.elements.arc);
+               },
+
+               calculateTotal: function() {
+                       var dataset = this.getDataset();
+                       var meta = this.getMeta();
+                       var total = 0;
+                       var value;
+
+                       helpers.each(meta.data, function(element, index) {
+                               value = dataset.data[index];
+                               if (!isNaN(value) && !element.hidden) {
+                                       total += Math.abs(value);
+                               }
+                       });
+
+                       /* if (total === 0) {
+                               total = NaN;
+                       }*/
+
+                       return total;
+               },
+
+               calculateCircumference: function(value) {
+                       var total = this.getMeta().total;
+                       if (total > 0 && !isNaN(value)) {
+                               return (Math.PI * 2.0) * (value / total);
+                       }
+                       return 0;
+               },
+
+               // gets the max border or hover width to properly scale pie 
charts
+               getMaxBorderWidth: function(elements) {
+                       var max = 0,
+                               index = this.index,
+                               length = elements.length,
+                               borderWidth,
+                               hoverWidth;
+
+                       for (var i = 0; i < length; i++) {
+                               borderWidth = elements[i]._model ? 
elements[i]._model.borderWidth : 0;
+                               hoverWidth = elements[i]._chart ? 
elements[i]._chart.config.data.datasets[index].hoverBorderWidth : 0;
+
+                               max = borderWidth > max ? borderWidth : max;
+                               max = hoverWidth > max ? hoverWidth : max;
+                       }
+                       return max;
+               }
+       });
+};
+
+},{}],18:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       var helpers = Chart.helpers;
+
+       Chart.defaults.line = {
+               showLines: true,
+               spanGaps: false,
+
+               hover: {
+                       mode: 'label'
+               },
+
+               scales: {
+                       xAxes: [{
+                               type: 'category',
+                               id: 'x-axis-0'
+                       }],
+                       yAxes: [{
+                               type: 'linear',
+                               id: 'y-axis-0'
+                       }]
+               }
+       };
+
+       function lineEnabled(dataset, options) {
+               return helpers.getValueOrDefault(dataset.showLine, 
options.showLines);
+       }
+
+       Chart.controllers.line = Chart.DatasetController.extend({
+
+               datasetElementType: Chart.elements.Line,
+
+               dataElementType: Chart.elements.Point,
+
+               update: function(reset) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var line = meta.dataset;
+                       var points = meta.data || [];
+                       var options = me.chart.options;
+                       var lineElementOptions = options.elements.line;
+                       var scale = me.getScaleForId(meta.yAxisID);
+                       var i, ilen, custom;
+                       var dataset = me.getDataset();
+                       var showLine = lineEnabled(dataset, options);
+
+                       // Update Line
+                       if (showLine) {
+                               custom = line.custom || {};
+
+                               // Compatibility: If the properties are defined 
with only the old name, use those values
+                               if ((dataset.tension !== undefined) && 
(dataset.lineTension === undefined)) {
+                                       dataset.lineTension = dataset.tension;
+                               }
+
+                               // Utility
+                               line._scale = scale;
+                               line._datasetIndex = me.index;
+                               // Data
+                               line._children = points;
+                               // Model
+                               line._model = {
+                                       // Appearance
+                                       // The default behavior of lines is to 
break at null values, according
+                                       // to 
https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158
+                                       // This option gives lines the ability 
to span gaps
+                                       spanGaps: dataset.spanGaps ? 
dataset.spanGaps : options.spanGaps,
+                                       tension: custom.tension ? 
custom.tension : helpers.getValueOrDefault(dataset.lineTension, 
lineElementOptions.tension),
+                                       backgroundColor: custom.backgroundColor 
? custom.backgroundColor : (dataset.backgroundColor || 
lineElementOptions.backgroundColor),
+                                       borderWidth: custom.borderWidth ? 
custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
+                                       borderColor: custom.borderColor ? 
custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),
+                                       borderCapStyle: custom.borderCapStyle ? 
custom.borderCapStyle : (dataset.borderCapStyle || 
lineElementOptions.borderCapStyle),
+                                       borderDash: custom.borderDash ? 
custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),
+                                       borderDashOffset: 
custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset 
|| lineElementOptions.borderDashOffset),
+                                       borderJoinStyle: custom.borderJoinStyle 
? custom.borderJoinStyle : (dataset.borderJoinStyle || 
lineElementOptions.borderJoinStyle),
+                                       fill: custom.fill ? custom.fill : 
(dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
+                                       steppedLine: custom.steppedLine ? 
custom.steppedLine : helpers.getValueOrDefault(dataset.steppedLine, 
lineElementOptions.stepped),
+                                       cubicInterpolationMode: 
custom.cubicInterpolationMode ? custom.cubicInterpolationMode : 
helpers.getValueOrDefault(dataset.cubicInterpolationMode, 
lineElementOptions.cubicInterpolationMode),
+                                       // Scale
+                                       scaleTop: scale.top,
+                                       scaleBottom: scale.bottom,
+                                       scaleZero: scale.getBasePixel()
+                               };
+
+                               line.pivot();
+                       }
+
+                       // Update Points
+                       for (i=0, ilen=points.length; i<ilen; ++i) {
+                               me.updateElement(points[i], i, reset);
+                       }
+
+                       if (showLine && line._model.tension !== 0) {
+                               me.updateBezierControlPoints();
+                       }
+
+                       // Now pivot the point for animation
+                       for (i=0, ilen=points.length; i<ilen; ++i) {
+                               points[i].pivot();
+                       }
+               },
+
+               getPointBackgroundColor: function(point, index) {
+                       var backgroundColor = 
this.chart.options.elements.point.backgroundColor;
+                       var dataset = this.getDataset();
+                       var custom = point.custom || {};
+
+                       if (custom.backgroundColor) {
+                               backgroundColor = custom.backgroundColor;
+                       } else if (dataset.pointBackgroundColor) {
+                               backgroundColor = 
helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, 
backgroundColor);
+                       } else if (dataset.backgroundColor) {
+                               backgroundColor = dataset.backgroundColor;
+                       }
+
+                       return backgroundColor;
+               },
+
+               getPointBorderColor: function(point, index) {
+                       var borderColor = 
this.chart.options.elements.point.borderColor;
+                       var dataset = this.getDataset();
+                       var custom = point.custom || {};
+
+                       if (custom.borderColor) {
+                               borderColor = custom.borderColor;
+                       } else if (dataset.pointBorderColor) {
+                               borderColor = 
helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, borderColor);
+                       } else if (dataset.borderColor) {
+                               borderColor = dataset.borderColor;
+                       }
+
+                       return borderColor;
+               },
+
+               getPointBorderWidth: function(point, index) {
+                       var borderWidth = 
this.chart.options.elements.point.borderWidth;
+                       var dataset = this.getDataset();
+                       var custom = point.custom || {};
+
+                       if (!isNaN(custom.borderWidth)) {
+                               borderWidth = custom.borderWidth;
+                       } else if (!isNaN(dataset.pointBorderWidth)) {
+                               borderWidth = 
helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth);
+                       } else if (!isNaN(dataset.borderWidth)) {
+                               borderWidth = dataset.borderWidth;
+                       }
+
+                       return borderWidth;
+               },
+
+               updateElement: function(point, index, reset) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var custom = point.custom || {};
+                       var dataset = me.getDataset();
+                       var datasetIndex = me.index;
+                       var value = dataset.data[index];
+                       var yScale = me.getScaleForId(meta.yAxisID);
+                       var xScale = me.getScaleForId(meta.xAxisID);
+                       var pointOptions = me.chart.options.elements.point;
+                       var x, y;
+                       var labels = me.chart.data.labels || [];
+                       var includeOffset = (labels.length === 1 || 
dataset.data.length === 1) || me.chart.isCombo;
+
+                       // Compatibility: If the properties are defined with 
only the old name, use those values
+                       if ((dataset.radius !== undefined) && 
(dataset.pointRadius === undefined)) {
+                               dataset.pointRadius = dataset.radius;
+                       }
+                       if ((dataset.hitRadius !== undefined) && 
(dataset.pointHitRadius === undefined)) {
+                               dataset.pointHitRadius = dataset.hitRadius;
+                       }
+
+                       x = xScale.getPixelForValue(typeof value === 'object' ? 
value : NaN, index, datasetIndex, includeOffset);
+                       y = reset ? yScale.getBasePixel() : 
me.calculatePointY(value, index, datasetIndex);
+
+                       // Utility
+                       point._xScale = xScale;
+                       point._yScale = yScale;
+                       point._datasetIndex = datasetIndex;
+                       point._index = index;
+
+                       // Desired view properties
+                       point._model = {
+                               x: x,
+                               y: y,
+                               skip: custom.skip || isNaN(x) || isNaN(y),
+                               // Appearance
+                               radius: custom.radius || 
helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, 
pointOptions.radius),
+                               pointStyle: custom.pointStyle || 
helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, 
pointOptions.pointStyle),
+                               backgroundColor: 
me.getPointBackgroundColor(point, index),
+                               borderColor: me.getPointBorderColor(point, 
index),
+                               borderWidth: me.getPointBorderWidth(point, 
index),
+                               tension: meta.dataset._model ? 
meta.dataset._model.tension : 0,
+                               steppedLine: meta.dataset._model ? 
meta.dataset._model.steppedLine : false,
+                               // Tooltip
+                               hitRadius: custom.hitRadius || 
helpers.getValueAtIndexOrDefault(dataset.pointHitRadius, index, 
pointOptions.hitRadius)
+                       };
+               },
+
+               calculatePointY: function(value, index, datasetIndex) {
+                       var me = this;
+                       var chart = me.chart;
+                       var meta = me.getMeta();
+                       var yScale = me.getScaleForId(meta.yAxisID);
+                       var sumPos = 0;
+                       var sumNeg = 0;
+                       var i, ds, dsMeta;
+
+                       if (yScale.options.stacked) {
+                               for (i = 0; i < datasetIndex; i++) {
+                                       ds = chart.data.datasets[i];
+                                       dsMeta = chart.getDatasetMeta(i);
+                                       if (dsMeta.type === 'line' && 
dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
+                                               var stackedRightValue = 
Number(yScale.getRightValue(ds.data[index]));
+                                               if (stackedRightValue < 0) {
+                                                       sumNeg += 
stackedRightValue || 0;
+                                               } else {
+                                                       sumPos += 
stackedRightValue || 0;
+                                               }
+                                       }
+                               }
+
+                               var rightValue = 
Number(yScale.getRightValue(value));
+                               if (rightValue < 0) {
+                                       return yScale.getPixelForValue(sumNeg + 
rightValue);
+                               }
+                               return yScale.getPixelForValue(sumPos + 
rightValue);
+                       }
+
+                       return yScale.getPixelForValue(value);
+               },
+
+               updateBezierControlPoints: function() {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var area = me.chart.chartArea;
+                       var points = (meta.data || []);
+                       var i, ilen, point, model, controlPoints;
+
+                       // Only consider points that are drawn in case the 
spanGaps option is used
+                       if (meta.dataset._model.spanGaps) {
+                               points = points.filter(function(pt) {
+                                       return !pt._model.skip;
+                               });
+                       }
+
+                       function capControlPoint(pt, min, max) {
+                               return Math.max(Math.min(pt, max), min);
+                       }
+
+                       if (meta.dataset._model.cubicInterpolationMode === 
'monotone') {
+                               helpers.splineCurveMonotone(points);
+                       } else {
+                               for (i = 0, ilen = points.length; i < ilen; 
++i) {
+                                       point = points[i];
+                                       model = point._model;
+                                       controlPoints = helpers.splineCurve(
+                                               helpers.previousItem(points, 
i)._model,
+                                               model,
+                                               helpers.nextItem(points, 
i)._model,
+                                               meta.dataset._model.tension
+                                       );
+                                       model.controlPointPreviousX = 
controlPoints.previous.x;
+                                       model.controlPointPreviousY = 
controlPoints.previous.y;
+                                       model.controlPointNextX = 
controlPoints.next.x;
+                                       model.controlPointNextY = 
controlPoints.next.y;
+                               }
+                       }
+
+                       if (me.chart.options.elements.line.capBezierPoints) {
+                               for (i = 0, ilen = points.length; i < ilen; 
++i) {
+                                       model = points[i]._model;
+                                       model.controlPointPreviousX = 
capControlPoint(model.controlPointPreviousX, area.left, area.right);
+                                       model.controlPointPreviousY = 
capControlPoint(model.controlPointPreviousY, area.top, area.bottom);
+                                       model.controlPointNextX = 
capControlPoint(model.controlPointNextX, area.left, area.right);
+                                       model.controlPointNextY = 
capControlPoint(model.controlPointNextY, area.top, area.bottom);
+                               }
+                       }
+               },
+
+               draw: function(ease) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var points = meta.data || [];
+                       var easingDecimal = ease || 1;
+                       var i, ilen;
+
+                       // Transition Point Locations
+                       for (i=0, ilen=points.length; i<ilen; ++i) {
+                               points[i].transition(easingDecimal);
+                       }
+
+                       Chart.canvasHelpers.clipArea(me.chart.chart.ctx, 
me.chart.chartArea);
+                       // Transition and Draw the line
+                       if (lineEnabled(me.getDataset(), me.chart.options)) {
+                               meta.dataset.transition(easingDecimal).draw();
+                       }
+                       Chart.canvasHelpers.unclipArea(me.chart.chart.ctx);
+
+                       // Draw the points
+                       for (i=0, ilen=points.length; i<ilen; ++i) {
+                               points[i].draw(me.chart.chartArea);
+                       }
+               },
+
+               setHoverStyle: function(point) {
+                       // Point
+                       var dataset = 
this.chart.data.datasets[point._datasetIndex];
+                       var index = point._index;
+                       var custom = point.custom || {};
+                       var model = point._model;
+
+                       model.radius = custom.hoverRadius || 
helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, 
this.chart.options.elements.point.hoverRadius);
+                       model.backgroundColor = custom.hoverBackgroundColor || 
helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, 
helpers.getHoverColor(model.backgroundColor));
+                       model.borderColor = custom.hoverBorderColor || 
helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, 
helpers.getHoverColor(model.borderColor));
+                       model.borderWidth = custom.hoverBorderWidth || 
helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, 
model.borderWidth);
+               },
+
+               removeHoverStyle: function(point) {
+                       var me = this;
+                       var dataset = 
me.chart.data.datasets[point._datasetIndex];
+                       var index = point._index;
+                       var custom = point.custom || {};
+                       var model = point._model;
+
+                       // Compatibility: If the properties are defined with 
only the old name, use those values
+                       if ((dataset.radius !== undefined) && 
(dataset.pointRadius === undefined)) {
+                               dataset.pointRadius = dataset.radius;
+                       }
+
+                       model.radius = custom.radius || 
helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, 
me.chart.options.elements.point.radius);
+                       model.backgroundColor = 
me.getPointBackgroundColor(point, index);
+                       model.borderColor = me.getPointBorderColor(point, 
index);
+                       model.borderWidth = me.getPointBorderWidth(point, 
index);
+               }
+       });
+};
+
+},{}],19:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       var helpers = Chart.helpers;
+
+       Chart.defaults.polarArea = {
+
+               scale: {
+                       type: 'radialLinear',
+                       lineArc: true, // so that lines are circular
+                       ticks: {
+                               beginAtZero: true
+                       }
+               },
+
+               // Boolean - Whether to animate the rotation of the chart
+               animation: {
+                       animateRotate: true,
+                       animateScale: true
+               },
+
+               startAngle: -0.5 * Math.PI,
+               aspectRatio: 1,
+               legendCallback: function(chart) {
+                       var text = [];
+                       text.push('<ul class="' + chart.id + '-legend">');
+
+                       var data = chart.data;
+                       var datasets = data.datasets;
+                       var labels = data.labels;
+
+                       if (datasets.length) {
+                               for (var i = 0; i < datasets[0].data.length; 
++i) {
+                                       text.push('<li><span 
style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
+                                       if (labels[i]) {
+                                               text.push(labels[i]);
+                                       }
+                                       text.push('</li>');
+                               }
+                       }
+
+                       text.push('</ul>');
+                       return text.join('');
+               },
+               legend: {
+                       labels: {
+                               generateLabels: function(chart) {
+                                       var data = chart.data;
+                                       if (data.labels.length && 
data.datasets.length) {
+                                               return 
data.labels.map(function(label, i) {
+                                                       var meta = 
chart.getDatasetMeta(0);
+                                                       var ds = 
data.datasets[0];
+                                                       var arc = meta.data[i];
+                                                       var custom = arc.custom 
|| {};
+                                                       var 
getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
+                                                       var arcOpts = 
chart.options.elements.arc;
+                                                       var fill = 
custom.backgroundColor ? custom.backgroundColor : 
getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
+                                                       var stroke = 
custom.borderColor ? custom.borderColor : 
getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
+                                                       var bw = 
custom.borderWidth ? custom.borderWidth : 
getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
+
+                                                       return {
+                                                               text: label,
+                                                               fillStyle: fill,
+                                                               strokeStyle: 
stroke,
+                                                               lineWidth: bw,
+                                                               hidden: 
isNaN(ds.data[i]) || meta.data[i].hidden,
+
+                                                               // Extra data 
used for toggling the correct item
+                                                               index: i
+                                                       };
+                                               });
+                                       }
+                                       return [];
+                               }
+                       },
+
+                       onClick: function(e, legendItem) {
+                               var index = legendItem.index;
+                               var chart = this.chart;
+                               var i, ilen, meta;
+
+                               for (i = 0, ilen = (chart.data.datasets || 
[]).length; i < ilen; ++i) {
+                                       meta = chart.getDatasetMeta(i);
+                                       meta.data[index].hidden = 
!meta.data[index].hidden;
+                               }
+
+                               chart.update();
+                       }
+               },
+
+               // Need to override these to give a nice default
+               tooltips: {
+                       callbacks: {
+                               title: function() {
+                                       return '';
+                               },
+                               label: function(tooltipItem, data) {
+                                       return data.labels[tooltipItem.index] + 
': ' + tooltipItem.yLabel;
+                               }
+                       }
+               }
+       };
+
+       Chart.controllers.polarArea = Chart.DatasetController.extend({
+
+               dataElementType: Chart.elements.Arc,
+
+               linkScales: helpers.noop,
+
+               update: function(reset) {
+                       var me = this;
+                       var chart = me.chart;
+                       var chartArea = chart.chartArea;
+                       var meta = me.getMeta();
+                       var opts = chart.options;
+                       var arcOpts = opts.elements.arc;
+                       var minSize = Math.min(chartArea.right - 
chartArea.left, chartArea.bottom - chartArea.top);
+                       chart.outerRadius = Math.max((minSize - 
arcOpts.borderWidth / 2) / 2, 0);
+                       chart.innerRadius = Math.max(opts.cutoutPercentage ? 
(chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);
+                       chart.radiusLength = (chart.outerRadius - 
chart.innerRadius) / chart.getVisibleDatasetCount();
+
+                       me.outerRadius = chart.outerRadius - 
(chart.radiusLength * me.index);
+                       me.innerRadius = me.outerRadius - chart.radiusLength;
+
+                       meta.count = me.countVisibleElements();
+
+                       helpers.each(meta.data, function(arc, index) {
+                               me.updateElement(arc, index, reset);
+                       });
+               },
+
+               updateElement: function(arc, index, reset) {
+                       var me = this;
+                       var chart = me.chart;
+                       var dataset = me.getDataset();
+                       var opts = chart.options;
+                       var animationOpts = opts.animation;
+                       var scale = chart.scale;
+                       var getValueAtIndexOrDefault = 
helpers.getValueAtIndexOrDefault;
+                       var labels = chart.data.labels;
+
+                       var circumference = 
me.calculateCircumference(dataset.data[index]);
+                       var centerX = scale.xCenter;
+                       var centerY = scale.yCenter;
+
+                       // If there is NaN data before us, we need to calculate 
the starting angle correctly.
+                       // We could be way more efficient here, but its 
unlikely that the polar area chart will have a lot of data
+                       var visibleCount = 0;
+                       var meta = me.getMeta();
+                       for (var i = 0; i < index; ++i) {
+                               if (!isNaN(dataset.data[i]) && 
!meta.data[i].hidden) {
+                                       ++visibleCount;
+                               }
+                       }
+
+                       // var negHalfPI = -0.5 * Math.PI;
+                       var datasetStartAngle = opts.startAngle;
+                       var distance = arc.hidden ? 0 : 
scale.getDistanceFromCenterForValue(dataset.data[index]);
+                       var startAngle = datasetStartAngle + (circumference * 
visibleCount);
+                       var endAngle = startAngle + (arc.hidden ? 0 : 
circumference);
+
+                       var resetRadius = animationOpts.animateScale ? 0 : 
scale.getDistanceFromCenterForValue(dataset.data[index]);
+
+                       helpers.extend(arc, {
+                               // Utility
+                               _datasetIndex: me.index,
+                               _index: index,
+                               _scale: scale,
+
+                               // Desired view properties
+                               _model: {
+                                       x: centerX,
+                                       y: centerY,
+                                       innerRadius: 0,
+                                       outerRadius: reset ? resetRadius : 
distance,
+                                       startAngle: reset && 
animationOpts.animateRotate ? datasetStartAngle : startAngle,
+                                       endAngle: reset && 
animationOpts.animateRotate ? datasetStartAngle : endAngle,
+                                       label: getValueAtIndexOrDefault(labels, 
index, labels[index])
+                               }
+                       });
+
+                       // Apply border and fill style
+                       me.removeHoverStyle(arc);
+
+                       arc.pivot();
+               },
+
+               removeHoverStyle: function(arc) {
+                       
Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, 
this.chart.options.elements.arc);
+               },
+
+               countVisibleElements: function() {
+                       var dataset = this.getDataset();
+                       var meta = this.getMeta();
+                       var count = 0;
+
+                       helpers.each(meta.data, function(element, index) {
+                               if (!isNaN(dataset.data[index]) && 
!element.hidden) {
+                                       count++;
+                               }
+                       });
+
+                       return count;
+               },
+
+               calculateCircumference: function(value) {
+                       var count = this.getMeta().count;
+                       if (count > 0 && !isNaN(value)) {
+                               return (2 * Math.PI) / count;
+                       }
+                       return 0;
+               }
+       });
+};
+
+},{}],20:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       var helpers = Chart.helpers;
+
+       Chart.defaults.radar = {
+               aspectRatio: 1,
+               scale: {
+                       type: 'radialLinear'
+               },
+               elements: {
+                       line: {
+                               tension: 0 // no bezier in radar
+                       }
+               }
+       };
+
+       Chart.controllers.radar = Chart.DatasetController.extend({
+
+               datasetElementType: Chart.elements.Line,
+
+               dataElementType: Chart.elements.Point,
+
+               linkScales: helpers.noop,
+
+               update: function(reset) {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var line = meta.dataset;
+                       var points = meta.data;
+                       var custom = line.custom || {};
+                       var dataset = me.getDataset();
+                       var lineElementOptions = me.chart.options.elements.line;
+                       var scale = me.chart.scale;
+
+                       // Compatibility: If the properties are defined with 
only the old name, use those values
+                       if ((dataset.tension !== undefined) && 
(dataset.lineTension === undefined)) {
+                               dataset.lineTension = dataset.tension;
+                       }
+
+                       helpers.extend(meta.dataset, {
+                               // Utility
+                               _datasetIndex: me.index,
+                               // Data
+                               _children: points,
+                               _loop: true,
+                               // Model
+                               _model: {
+                                       // Appearance
+                                       tension: custom.tension ? 
custom.tension : helpers.getValueOrDefault(dataset.lineTension, 
lineElementOptions.tension),
+                                       backgroundColor: custom.backgroundColor 
? custom.backgroundColor : (dataset.backgroundColor || 
lineElementOptions.backgroundColor),
+                                       borderWidth: custom.borderWidth ? 
custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
+                                       borderColor: custom.borderColor ? 
custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),
+                                       fill: custom.fill ? custom.fill : 
(dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
+                                       borderCapStyle: custom.borderCapStyle ? 
custom.borderCapStyle : (dataset.borderCapStyle || 
lineElementOptions.borderCapStyle),
+                                       borderDash: custom.borderDash ? 
custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),
+                                       borderDashOffset: 
custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset 
|| lineElementOptions.borderDashOffset),
+                                       borderJoinStyle: custom.borderJoinStyle 
? custom.borderJoinStyle : (dataset.borderJoinStyle || 
lineElementOptions.borderJoinStyle),
+
+                                       // Scale
+                                       scaleTop: scale.top,
+                                       scaleBottom: scale.bottom,
+                                       scaleZero: scale.getBasePosition()
+                               }
+                       });
+
+                       meta.dataset.pivot();
+
+                       // Update Points
+                       helpers.each(points, function(point, index) {
+                               me.updateElement(point, index, reset);
+                       }, me);
+
+                       // Update bezier control points
+                       me.updateBezierControlPoints();
+               },
+               updateElement: function(point, index, reset) {
+                       var me = this;
+                       var custom = point.custom || {};
+                       var dataset = me.getDataset();
+                       var scale = me.chart.scale;
+                       var pointElementOptions = 
me.chart.options.elements.point;
+                       var pointPosition = 
scale.getPointPositionForValue(index, dataset.data[index]);
+
+                       helpers.extend(point, {
+                               // Utility
+                               _datasetIndex: me.index,
+                               _index: index,
+                               _scale: scale,
+
+                               // Desired view properties
+                               _model: {
+                                       x: reset ? scale.xCenter : 
pointPosition.x, // value not used in dataset scale, but we want a consistent 
API between scales
+                                       y: reset ? scale.yCenter : 
pointPosition.y,
+
+                                       // Appearance
+                                       tension: custom.tension ? 
custom.tension : helpers.getValueOrDefault(dataset.lineTension, 
me.chart.options.elements.line.tension),
+                                       radius: custom.radius ? custom.radius : 
helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, 
pointElementOptions.radius),
+                                       backgroundColor: custom.backgroundColor 
? custom.backgroundColor : 
helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, 
pointElementOptions.backgroundColor),
+                                       borderColor: custom.borderColor ? 
custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, 
index, pointElementOptions.borderColor),
+                                       borderWidth: custom.borderWidth ? 
custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, 
index, pointElementOptions.borderWidth),
+                                       pointStyle: custom.pointStyle ? 
custom.pointStyle : helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, 
pointElementOptions.pointStyle),
+
+                                       // Tooltip
+                                       hitRadius: custom.hitRadius ? 
custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, 
pointElementOptions.hitRadius)
+                               }
+                       });
+
+                       point._model.skip = custom.skip ? custom.skip : 
(isNaN(point._model.x) || isNaN(point._model.y));
+               },
+               updateBezierControlPoints: function() {
+                       var chartArea = this.chart.chartArea;
+                       var meta = this.getMeta();
+
+                       helpers.each(meta.data, function(point, index) {
+                               var model = point._model;
+                               var controlPoints = helpers.splineCurve(
+                                       helpers.previousItem(meta.data, index, 
true)._model,
+                                       model,
+                                       helpers.nextItem(meta.data, index, 
true)._model,
+                                       model.tension
+                               );
+
+                               // Prevent the bezier going outside of the 
bounds of the graph
+                               model.controlPointPreviousX = 
Math.max(Math.min(controlPoints.previous.x, chartArea.right), chartArea.left);
+                               model.controlPointPreviousY = 
Math.max(Math.min(controlPoints.previous.y, chartArea.bottom), chartArea.top);
+
+                               model.controlPointNextX = 
Math.max(Math.min(controlPoints.next.x, chartArea.right), chartArea.left);
+                               model.controlPointNextY = 
Math.max(Math.min(controlPoints.next.y, chartArea.bottom), chartArea.top);
+
+                               // Now pivot the point for animation
+                               point.pivot();
+                       });
+               },
+
+               draw: function(ease) {
+                       var meta = this.getMeta();
+                       var easingDecimal = ease || 1;
+
+                       // Transition Point Locations
+                       helpers.each(meta.data, function(point) {
+                               point.transition(easingDecimal);
+                       });
+
+                       // Transition and Draw the line
+                       meta.dataset.transition(easingDecimal).draw();
+
+                       // Draw the points
+                       helpers.each(meta.data, function(point) {
+                               point.draw();
+                       });
+               },
+
+               setHoverStyle: function(point) {
+                       // Point
+                       var dataset = 
this.chart.data.datasets[point._datasetIndex];
+                       var custom = point.custom || {};
+                       var index = point._index;
+                       var model = point._model;
+
+                       model.radius = custom.hoverRadius ? custom.hoverRadius 
: helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, 
this.chart.options.elements.point.hoverRadius);
+                       model.backgroundColor = custom.hoverBackgroundColor ? 
custom.hoverBackgroundColor : 
helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, 
helpers.getHoverColor(model.backgroundColor));
+                       model.borderColor = custom.hoverBorderColor ? 
custom.hoverBorderColor : 
helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, 
helpers.getHoverColor(model.borderColor));
+                       model.borderWidth = custom.hoverBorderWidth ? 
custom.hoverBorderWidth : 
helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, 
model.borderWidth);
+               },
+
+               removeHoverStyle: function(point) {
+                       var dataset = 
this.chart.data.datasets[point._datasetIndex];
+                       var custom = point.custom || {};
+                       var index = point._index;
+                       var model = point._model;
+                       var pointElementOptions = 
this.chart.options.elements.point;
+
+                       model.radius = custom.radius ? custom.radius : 
helpers.getValueAtIndexOrDefault(dataset.radius, index, 
pointElementOptions.radius);
+                       model.backgroundColor = custom.backgroundColor ? 
custom.backgroundColor : 
helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, 
pointElementOptions.backgroundColor);
+                       model.borderColor = custom.borderColor ? 
custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, 
index, pointElementOptions.borderColor);
+                       model.borderWidth = custom.borderWidth ? 
custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, 
index, pointElementOptions.borderWidth);
+               }
+       });
+};
+
+},{}],21:[function(require,module,exports){
+/* global window: false */
+'use strict';
+
+module.exports = function(Chart) {
+
+       var helpers = Chart.helpers;
+
+       Chart.defaults.global.animation = {
+               duration: 1000,
+               easing: 'easeOutQuart',
+               onProgress: helpers.noop,
+               onComplete: helpers.noop
+       };
+
+       Chart.Animation = Chart.Element.extend({
+               currentStep: null, // the current animation step
+               numSteps: 60, // default number of steps
+               easing: '', // the easing to use for this animation
+               render: null, // render function used by the animation service
+
+               onAnimationProgress: null, // user specified callback to fire 
on each step of the animation
+               onAnimationComplete: null // user specified callback to fire 
when the animation finishes
+       });
+
+       Chart.animationService = {
+               frameDuration: 17,
+               animations: [],
+               dropFrames: 0,
+               request: null,
+
+               /**
+                * @function Chart.animationService.addAnimation
+                * @param chartInstance {ChartController} the chart to animate
+                * @param animationObject {IAnimation} the animation that we 
will animate
+                * @param duration {Number} length of animation in ms
+                * @param lazy {Boolean} if true, the chart is not marked as 
animating to enable more responsive interactions
+                */
+               addAnimation: function(chartInstance, animationObject, 
duration, lazy) {
+                       var me = this;
+
+                       if (!lazy) {
+                               chartInstance.animating = true;
+                       }
+
+                       for (var index = 0; index < me.animations.length; 
++index) {
+                               if (me.animations[index].chartInstance === 
chartInstance) {
+                                       // replacing an in progress animation
+                                       me.animations[index].animationObject = 
animationObject;
+                                       return;
+                               }
+                       }
+
+                       me.animations.push({
+                               chartInstance: chartInstance,
+                               animationObject: animationObject
+                       });
+
+                       // If there are no animations queued, manually 
kickstart a digest, for lack of a better word
+                       if (me.animations.length === 1) {
+                               me.requestAnimationFrame();
+                       }
+               },
+               // Cancel the animation for a given chart instance
+               cancelAnimation: function(chartInstance) {
+                       var index = helpers.findIndex(this.animations, 
function(animationWrapper) {
+                               return animationWrapper.chartInstance === 
chartInstance;
+                       });
+
+                       if (index !== -1) {
+                               this.animations.splice(index, 1);
+                               chartInstance.animating = false;
+                       }
+               },
+               requestAnimationFrame: function() {
+                       var me = this;
+                       if (me.request === null) {
+                               // Skip animation frame requests until the 
active one is executed.
+                               // This can happen when processing mouse 
events, e.g. 'mousemove'
+                               // and 'mouseout' events will trigger multiple 
renders.
+                               me.request = 
helpers.requestAnimFrame.call(window, function() {
+                                       me.request = null;
+                                       me.startDigest();
+                               });
+                       }
+               },
+               startDigest: function() {
+                       var me = this;
+
+                       var startTime = Date.now();
+                       var framesToDrop = 0;
+
+                       if (me.dropFrames > 1) {
+                               framesToDrop = Math.floor(me.dropFrames);
+                               me.dropFrames = me.dropFrames % 1;
+                       }
+
+                       var i = 0;
+                       while (i < me.animations.length) {
+                               if 
(me.animations[i].animationObject.currentStep === null) {
+                                       
me.animations[i].animationObject.currentStep = 0;
+                               }
+
+                               me.animations[i].animationObject.currentStep += 
1 + framesToDrop;
+
+                               if 
(me.animations[i].animationObject.currentStep > 
me.animations[i].animationObject.numSteps) {
+                                       
me.animations[i].animationObject.currentStep = 
me.animations[i].animationObject.numSteps;
+                               }
+
+                               
me.animations[i].animationObject.render(me.animations[i].chartInstance, 
me.animations[i].animationObject);
+                               if 
(me.animations[i].animationObject.onAnimationProgress && 
me.animations[i].animationObject.onAnimationProgress.call) {
+                                       
me.animations[i].animationObject.onAnimationProgress.call(me.animations[i].chartInstance,
 me.animations[i]);
+                               }
+
+                               if 
(me.animations[i].animationObject.currentStep === 
me.animations[i].animationObject.numSteps) {
+                                       if 
(me.animations[i].animationObject.onAnimationComplete && 
me.animations[i].animationObject.onAnimationComplete.call) {
+                                               
me.animations[i].animationObject.onAnimationComplete.call(me.animations[i].chartInstance,
 me.animations[i]);
+                                       }
+
+                                       // executed the last frame. Remove the 
animation.
+                                       
me.animations[i].chartInstance.animating = false;
+
+                                       me.animations.splice(i, 1);
+                               } else {
+                                       ++i;
+                               }
+                       }
+
+                       var endTime = Date.now();
+                       var dropFrames = (endTime - startTime) / 
me.frameDuration;
+
+                       me.dropFrames += dropFrames;
+
+                       // Do we have more stuff to animate?
+                       if (me.animations.length > 0) {
+                               me.requestAnimationFrame();
+                       }
+               }
+       };
+};
+
+},{}],22:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+       // Global Chart canvas helpers object for drawing items to canvas
+       var helpers = Chart.canvasHelpers = {};
+
+       helpers.drawPoint = function(ctx, pointStyle, radius, x, y) {
+               var type, edgeLength, xOffset, yOffset, height, size;
+
+               if (typeof pointStyle === 'object') {
+                       type = pointStyle.toString();
+                       if (type === '[object HTMLImageElement]' || type === 
'[object HTMLCanvasElement]') {
+                               ctx.drawImage(pointStyle, x - pointStyle.width 
/ 2, y - pointStyle.height / 2);
+                               return;
+                       }
+               }
+
+               if (isNaN(radius) || radius <= 0) {
+                       return;
+               }
+
+               switch (pointStyle) {
+               // Default includes circle
+               default:
+                       ctx.beginPath();
+                       ctx.arc(x, y, radius, 0, Math.PI * 2);
+                       ctx.closePath();
+                       ctx.fill();
+                       break;
+               case 'triangle':
+                       ctx.beginPath();
+                       edgeLength = 3 * radius / Math.sqrt(3);
+                       height = edgeLength * Math.sqrt(3) / 2;
+                       ctx.moveTo(x - edgeLength / 2, y + height / 3);
+                       ctx.lineTo(x + edgeLength / 2, y + height / 3);
+                       ctx.lineTo(x, y - 2 * height / 3);
+                       ctx.closePath();
+                       ctx.fill();
+                       break;
+               case 'rect':
+                       size = 1 / Math.SQRT2 * radius;
+                       ctx.beginPath();
+                       ctx.fillRect(x - size, y - size, 2 * size, 2 * size);
+                       ctx.strokeRect(x - size, y - size, 2 * size, 2 * size);
+                       break;
+               case 'rectRounded':
+                       var offset = radius / Math.SQRT2;
+                       var leftX = x - offset;
+                       var topY = y - offset;
+                       var sideSize = Math.SQRT2 * radius;
+                       Chart.helpers.drawRoundedRectangle(ctx, leftX, topY, 
sideSize, sideSize, radius / 2);
+                       ctx.fill();
+                       break;
+               case 'rectRot':
+                       size = 1 / Math.SQRT2 * radius;
+                       ctx.beginPath();
+                       ctx.moveTo(x - size, y);
+                       ctx.lineTo(x, y + size);
+                       ctx.lineTo(x + size, y);
+                       ctx.lineTo(x, y - size);
+                       ctx.closePath();
+                       ctx.fill();
+                       break;
+               case 'cross':
+                       ctx.beginPath();
+                       ctx.moveTo(x, y + radius);
+                       ctx.lineTo(x, y - radius);
+                       ctx.moveTo(x - radius, y);
+                       ctx.lineTo(x + radius, y);
+                       ctx.closePath();
+                       break;
+               case 'crossRot':
+                       ctx.beginPath();
+                       xOffset = Math.cos(Math.PI / 4) * radius;
+                       yOffset = Math.sin(Math.PI / 4) * radius;
+                       ctx.moveTo(x - xOffset, y - yOffset);
+                       ctx.lineTo(x + xOffset, y + yOffset);
+                       ctx.moveTo(x - xOffset, y + yOffset);
+                       ctx.lineTo(x + xOffset, y - yOffset);
+                       ctx.closePath();
+                       break;
+               case 'star':
+                       ctx.beginPath();
+                       ctx.moveTo(x, y + radius);
+                       ctx.lineTo(x, y - radius);
+                       ctx.moveTo(x - radius, y);
+                       ctx.lineTo(x + radius, y);
+                       xOffset = Math.cos(Math.PI / 4) * radius;
+                       yOffset = Math.sin(Math.PI / 4) * radius;
+                       ctx.moveTo(x - xOffset, y - yOffset);
+                       ctx.lineTo(x + xOffset, y + yOffset);
+                       ctx.moveTo(x - xOffset, y + yOffset);
+                       ctx.lineTo(x + xOffset, y - yOffset);
+                       ctx.closePath();
+                       break;
+               case 'line':
+                       ctx.beginPath();
+                       ctx.moveTo(x - radius, y);
+                       ctx.lineTo(x + radius, y);
+                       ctx.closePath();
+                       break;
+               case 'dash':
+                       ctx.beginPath();
+                       ctx.moveTo(x, y);
+                       ctx.lineTo(x + radius, y);
+                       ctx.closePath();
+                       break;
+               }
+
+               ctx.stroke();
+       };
+
+       helpers.clipArea = function(ctx, clipArea) {
+               ctx.save();
+               ctx.beginPath();
+               ctx.rect(clipArea.left, clipArea.top, clipArea.right - 
clipArea.left, clipArea.bottom - clipArea.top);
+               ctx.clip();
+       };
+
+       helpers.unclipArea = function(ctx) {
+               ctx.restore();
+       };
+
+};
+
+},{}],23:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       var helpers = Chart.helpers;
+       var plugins = Chart.plugins;
+       var platform = Chart.platform;
+
+       // Create a dictionary of chart types, to allow for extension of 
existing types
+       Chart.types = {};
+
+       // Store a reference to each instance - allowing us to globally resize 
chart instances on window resize.
+       // Destroy method on the chart will remove the instance of the chart 
from this reference.
+       Chart.instances = {};
+
+       // Controllers available for dataset visualization eg. bar, line, 
slice, etc.
+       Chart.controllers = {};
+
+       /**
+        * Initializes the given config with global and chart default values.
+        */
+       function initConfig(config) {
+               config = config || {};
+
+               // Do NOT use configMerge() for the data object because this 
method merges arrays
+               // and so would change references to labels and datasets, 
preventing data updates.
+               var data = config.data = config.data || {};
+               data.datasets = data.datasets || [];
+               data.labels = data.labels || [];
+
+               config.options = helpers.configMerge(
+                       Chart.defaults.global,
+                       Chart.defaults[config.type],
+                       config.options || {});
+
+               return config;
+       }
+
+       /**
+        * Updates the config of the chart
+        * @param chart {Chart.Controller} chart to update the options for
+        */
+       function updateConfig(chart) {
+               var newOptions = chart.options;
+
+               // Update Scale(s) with options
+               if (newOptions.scale) {
+                       chart.scale.options = newOptions.scale;
+               } else if (newOptions.scales) {
+                       
newOptions.scales.xAxes.concat(newOptions.scales.yAxes).forEach(function(scaleOptions)
 {
+                               chart.scales[scaleOptions.id].options = 
scaleOptions;
+                       });
+               }
+
+               // Tooltip
+               chart.tooltip._options = newOptions.tooltips;
+       }
+
+       /**
+        * @class Chart.Controller
+        * The main controller of a chart.
+        */
+       Chart.Controller = function(item, config, instance) {
+               var me = this;
+
+               config = initConfig(config);
+
+               var context = platform.acquireContext(item, config);
+               var canvas = context && context.canvas;
+               var height = canvas && canvas.height;
+               var width = canvas && canvas.width;
+
+               instance.ctx = context;
+               instance.canvas = canvas;
+               instance.config = config;
+               instance.width = width;
+               instance.height = height;
+               instance.aspectRatio = height? width / height : null;
+
+               me.id = helpers.uid();
+               me.chart = instance;
+               me.config = config;
+               me.options = config.options;
+               me._bufferedRender = false;
+
+               // Add the chart instance to the global namespace
+               Chart.instances[me.id] = me;
+
+               Object.defineProperty(me, 'data', {
+                       get: function() {
+                               return me.config.data;
+                       }
+               });
+
+               if (!context || !canvas) {
+                       // The given item is not a compatible context2d 
element, let's return before finalizing
+                       // the chart initialization but after setting basic 
chart / controller properties that
+                       // can help to figure out that the chart is not valid 
(e.g chart.canvas !== null);
+                       // https://github.com/chartjs/Chart.js/issues/2807
+                       console.error("Failed to create chart: can't acquire 
context from the given item");
+                       return me;
+               }
+
+               me.initialize();
+               me.update();
+
+               return me;
+       };
+
+       helpers.extend(Chart.Controller.prototype, /** @lends 
Chart.Controller.prototype */ {
+               initialize: function() {
+                       var me = this;
+
+                       // Before init plugin notification
+                       plugins.notify(me, 'beforeInit');
+
+                       helpers.retinaScale(me.chart);
+
+                       me.bindEvents();
+
+                       if (me.options.responsive) {
+                               // Initial resize before chart draws (must be 
silent to preserve initial animations).
+                               me.resize(true);
+                       }
+
+                       // Make sure scales have IDs and are built before we 
build any controllers.
+                       me.ensureScalesHaveIDs();
+                       me.buildScales();
+                       me.initToolTip();
+
+                       // After init plugin notification
+                       plugins.notify(me, 'afterInit');
+
+                       return me;
+               },
+
+               clear: function() {
+                       helpers.clear(this.chart);
+                       return this;
+               },
+
+               stop: function() {
+                       // Stops any current animation loop occurring
+                       Chart.animationService.cancelAnimation(this);
+                       return this;
+               },
+
+               resize: function(silent) {
+                       var me = this;
+                       var chart = me.chart;
+                       var options = me.options;
+                       var canvas = chart.canvas;
+                       var aspectRatio = (options.maintainAspectRatio && 
chart.aspectRatio) || null;
+
+                       // the canvas render width and height will be casted to 
integers so make sure that
+                       // the canvas display style uses the same integer 
values to avoid blurring effect.
+                       var newWidth = 
Math.floor(helpers.getMaximumWidth(canvas));
+                       var newHeight = Math.floor(aspectRatio? newWidth / 
aspectRatio : helpers.getMaximumHeight(canvas));
+
+                       if (chart.width === newWidth && chart.height === 
newHeight) {
+                               return;
+                       }
+
+                       canvas.width = chart.width = newWidth;
+                       canvas.height = chart.height = newHeight;
+                       canvas.style.width = newWidth + 'px';
+                       canvas.style.height = newHeight + 'px';
+
+                       helpers.retinaScale(chart);
+
+                       if (!silent) {
+                               // Notify any plugins about the resize
+                               var newSize = {width: newWidth, height: 
newHeight};
+                               plugins.notify(me, 'resize', [newSize]);
+
+                               // Notify of resize
+                               if (me.options.onResize) {
+                                       me.options.onResize(me, newSize);
+                               }
+
+                               me.stop();
+                               
me.update(me.options.responsiveAnimationDuration);
+                       }
+               },
+
+               ensureScalesHaveIDs: function() {
+                       var options = this.options;
+                       var scalesOptions = options.scales || {};
+                       var scaleOptions = options.scale;
+
+                       helpers.each(scalesOptions.xAxes, 
function(xAxisOptions, index) {
+                               xAxisOptions.id = xAxisOptions.id || ('x-axis-' 
+ index);
+                       });
+
+                       helpers.each(scalesOptions.yAxes, 
function(yAxisOptions, index) {
+                               yAxisOptions.id = yAxisOptions.id || ('y-axis-' 
+ index);
+                       });
+
+                       if (scaleOptions) {
+                               scaleOptions.id = scaleOptions.id || 'scale';
+                       }
+               },
+
+               /**
+                * Builds a map of scale ID to scale object for future lookup.
+                */
+               buildScales: function() {
+                       var me = this;
+                       var options = me.options;
+                       var scales = me.scales = {};
+                       var items = [];
+
+                       if (options.scales) {
+                               items = items.concat(
+                                       (options.scales.xAxes || 
[]).map(function(xAxisOptions) {
+                                               return {options: xAxisOptions, 
dtype: 'category'};
+                                       }),
+                                       (options.scales.yAxes || 
[]).map(function(yAxisOptions) {
+                                               return {options: yAxisOptions, 
dtype: 'linear'};
+                                       })
+                               );
+                       }
+
+                       if (options.scale) {
+                               items.push({options: options.scale, dtype: 
'radialLinear', isDefault: true});
+                       }
+
+                       helpers.each(items, function(item) {
+                               var scaleOptions = item.options;
+                               var scaleType = 
helpers.getValueOrDefault(scaleOptions.type, item.dtype);
+                               var scaleClass = 
Chart.scaleService.getScaleConstructor(scaleType);
+                               if (!scaleClass) {
+                                       return;
+                               }
+
+                               var scale = new scaleClass({
+                                       id: scaleOptions.id,
+                                       options: scaleOptions,
+                                       ctx: me.chart.ctx,
+                                       chart: me
+                               });
+
+                               scales[scale.id] = scale;
+
+                               // TODO(SB): I think we should be able to 
remove this custom case (options.scale)
+                               // and consider it as a regular scale part of 
the "scales"" map only! This would
+                               // make the logic easier and remove some 
useless? custom code.
+                               if (item.isDefault) {
+                                       me.scale = scale;
+                               }
+                       });
+
+                       Chart.scaleService.addScalesToLayout(this);
+               },
+
+               buildOrUpdateControllers: function() {
+                       var me = this;
+                       var types = [];
+                       var newControllers = [];
+
+                       helpers.each(me.data.datasets, function(dataset, 
datasetIndex) {
+                               var meta = me.getDatasetMeta(datasetIndex);
+                               if (!meta.type) {
+                                       meta.type = dataset.type || 
me.config.type;
+                               }
+
+                               types.push(meta.type);
+
+                               if (meta.controller) {
+                                       
meta.controller.updateIndex(datasetIndex);
+                               } else {
+                                       meta.controller = new 
Chart.controllers[meta.type](me, datasetIndex);
+                                       newControllers.push(meta.controller);
+                               }
+                       }, me);
+
+                       if (types.length > 1) {
+                               for (var i = 1; i < types.length; i++) {
+                                       if (types[i] !== types[i - 1]) {
+                                               me.isCombo = true;
+                                               break;
+                                       }
+                               }
+                       }
+
+                       return newControllers;
+               },
+
+               /**
+                * Reset the elements of all datasets
+                * @private
+                */
+               resetElements: function() {
+                       var me = this;
+                       helpers.each(me.data.datasets, function(dataset, 
datasetIndex) {
+                               
me.getDatasetMeta(datasetIndex).controller.reset();
+                       }, me);
+               },
+
+               /**
+               * Resets the chart back to it's state before the initial 
animation
+               */
+               reset: function() {
+                       this.resetElements();
+                       this.tooltip.initialize();
+               },
+
+               update: function(animationDuration, lazy) {
+                       var me = this;
+
+                       updateConfig(me);
+
+                       if (plugins.notify(me, 'beforeUpdate') === false) {
+                               return;
+                       }
+
+                       // In case the entire data object changed
+                       me.tooltip._data = me.data;
+
+                       // Make sure dataset controllers are updated and new 
controllers are reset
+                       var newControllers = me.buildOrUpdateControllers();
+
+                       // Make sure all dataset controllers have correct meta 
data counts
+                       helpers.each(me.data.datasets, function(dataset, 
datasetIndex) {
+                               
me.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements();
+                       }, me);
+
+                       me.updateLayout();
+
+                       // Can only reset the new controllers after the scales 
have been updated
+                       helpers.each(newControllers, function(controller) {
+                               controller.reset();
+                       });
+
+                       me.updateDatasets();
+
+                       // Do this before render so that any plugins that need 
final scale updates can use it
+                       plugins.notify(me, 'afterUpdate');
+
+                       if (me._bufferedRender) {
+                               me._bufferedRequest = {
+                                       lazy: lazy,
+                                       duration: animationDuration
+                               };
+                       } else {
+                               me.render(animationDuration, lazy);
+                       }
+               },
+
+               /**
+                * Updates the chart layout unless a plugin returns `false` to 
the `beforeLayout`
+                * hook, in which case, plugins will not be called on 
`afterLayout`.
+                * @private
+                */
+               updateLayout: function() {
+                       var me = this;
+
+                       if (plugins.notify(me, 'beforeLayout') === false) {
+                               return;
+                       }
+
+                       Chart.layoutService.update(this, this.chart.width, 
this.chart.height);
+
+                       /**
+                        * Provided for backward compatibility, use 
`afterLayout` instead.
+                        * @method IPlugin#afterScaleUpdate
+                        * @deprecated since version 2.5.0
+                        * @todo remove at version 3
+                        */
+                       plugins.notify(me, 'afterScaleUpdate');
+                       plugins.notify(me, 'afterLayout');
+               },
+
+               /**
+                * Updates all datasets unless a plugin returns `false` to the 
`beforeDatasetsUpdate`
+                * hook, in which case, plugins will not be called on 
`afterDatasetsUpdate`.
+                * @private
+                */
+               updateDatasets: function() {
+                       var me = this;
+
+                       if (plugins.notify(me, 'beforeDatasetsUpdate') === 
false) {
+                               return;
+                       }
+
+                       for (var i = 0, ilen = me.data.datasets.length; i < 
ilen; ++i) {
+                               me.getDatasetMeta(i).controller.update();
+                       }
+
+                       plugins.notify(me, 'afterDatasetsUpdate');
+               },
+
+               render: function(duration, lazy) {
+                       var me = this;
+
+                       if (plugins.notify(me, 'beforeRender') === false) {
+                               return;
+                       }
+
+                       var animationOptions = me.options.animation;
+                       var onComplete = function() {
+                               plugins.notify(me, 'afterRender');
+                               var callback = animationOptions && 
animationOptions.onComplete;
+                               if (callback && callback.call) {
+                                       callback.call(me);
+                               }
+                       };
+
+                       if (animationOptions && ((typeof duration !== 
'undefined' && duration !== 0) || (typeof duration === 'undefined' && 
animationOptions.duration !== 0))) {
+                               var animation = new Chart.Animation();
+                               animation.numSteps = (duration || 
animationOptions.duration) / 16.66; // 60 fps
+                               animation.easing = animationOptions.easing;
+
+                               // render function
+                               animation.render = function(chartInstance, 
animationObject) {
+                                       var easingFunction = 
helpers.easingEffects[animationObject.easing];
+                                       var stepDecimal = 
animationObject.currentStep / animationObject.numSteps;
+                                       var easeDecimal = 
easingFunction(stepDecimal);
+
+                                       chartInstance.draw(easeDecimal, 
stepDecimal, animationObject.currentStep);
+                               };
+
+                               // user events
+                               animation.onAnimationProgress = 
animationOptions.onProgress;
+                               animation.onAnimationComplete = onComplete;
+
+                               Chart.animationService.addAnimation(me, 
animation, duration, lazy);
+                       } else {
+                               me.draw();
+                               onComplete();
+                       }
+
+                       return me;
+               },
+
+               draw: function(easingValue) {
+                       var me = this;
+
+                       me.clear();
+
+                       if (easingValue === undefined || easingValue === null) {
+                               easingValue = 1;
+                       }
+
+                       if (plugins.notify(me, 'beforeDraw', [easingValue]) === 
false) {
+                               return;
+                       }
+
+                       // Draw all the scales
+                       helpers.each(me.boxes, function(box) {
+                               box.draw(me.chartArea);
+                       }, me);
+
+                       if (me.scale) {
+                               me.scale.draw();
+                       }
+
+                       me.drawDatasets(easingValue);
+
+                       // Finally draw the tooltip
+                       me.tooltip.transition(easingValue).draw();
+
+                       plugins.notify(me, 'afterDraw', [easingValue]);
+               },
+
+               /**
+                * Draws all datasets unless a plugin returns `false` to the 
`beforeDatasetsDraw`
+                * hook, in which case, plugins will not be called on 
`afterDatasetsDraw`.
+                * @private
+                */
+               drawDatasets: function(easingValue) {
+                       var me = this;
+
+                       if (plugins.notify(me, 'beforeDatasetsDraw', 
[easingValue]) === false) {
+                               return;
+                       }
+
+                       // Draw each dataset via its respective controller 
(reversed to support proper line stacking)
+                       helpers.each(me.data.datasets, function(dataset, 
datasetIndex) {
+                               if (me.isDatasetVisible(datasetIndex)) {
+                                       
me.getDatasetMeta(datasetIndex).controller.draw(easingValue);
+                               }
+                       }, me, true);
+
+                       plugins.notify(me, 'afterDatasetsDraw', [easingValue]);
+               },
+
+               // Get the single element that was clicked on
+               // @return : An object containing the dataset index and element 
index of the matching element. Also contains the rectangle that was draw
+               getElementAtEvent: function(e) {
+                       return Chart.Interaction.modes.single(this, e);
+               },
+
+               getElementsAtEvent: function(e) {
+                       return Chart.Interaction.modes.label(this, e, 
{intersect: true});
+               },
+
+               getElementsAtXAxis: function(e) {
+                       return Chart.Interaction.modes['x-axis'](this, e, 
{intersect: true});
+               },
+
+               getElementsAtEventForMode: function(e, mode, options) {
+                       var method = Chart.Interaction.modes[mode];
+                       if (typeof method === 'function') {
+                               return method(this, e, options);
+                       }
+
+                       return [];
+               },
+
+               getDatasetAtEvent: function(e) {
+                       return Chart.Interaction.modes.dataset(this, e, 
{intersect: true});
+               },
+
+               getDatasetMeta: function(datasetIndex) {
+                       var me = this;
+                       var dataset = me.data.datasets[datasetIndex];
+                       if (!dataset._meta) {
+                               dataset._meta = {};
+                       }
+
+                       var meta = dataset._meta[me.id];
+                       if (!meta) {
+                               meta = dataset._meta[me.id] = {
+                                       type: null,
+                                       data: [],
+                                       dataset: null,
+                                       controller: null,
+                                       hidden: null,                   // See 
isDatasetVisible() comment
+                                       xAxisID: null,
+                                       yAxisID: null
+                               };
+                       }
+
+                       return meta;
+               },
+
+               getVisibleDatasetCount: function() {
+                       var count = 0;
+                       for (var i = 0, ilen = this.data.datasets.length; 
i<ilen; ++i) {
+                               if (this.isDatasetVisible(i)) {
+                                       count++;
+                               }
+                       }
+                       return count;
+               },
+
+               isDatasetVisible: function(datasetIndex) {
+                       var meta = this.getDatasetMeta(datasetIndex);
+
+                       // meta.hidden is a per chart dataset hidden flag 
override with 3 states: if true or false,
+                       // the dataset.hidden value is ignored, else if null, 
the dataset hidden state is returned.
+                       return typeof meta.hidden === 'boolean'? !meta.hidden : 
!this.data.datasets[datasetIndex].hidden;
+               },
+
+               generateLegend: function() {
+                       return this.options.legendCallback(this);
+               },
+
+               destroy: function() {
+                       var me = this;
+                       var canvas = me.chart.canvas;
+                       var meta, i, ilen;
+
+                       me.stop();
+
+                       // dataset controllers need to cleanup associated data
+                       for (i = 0, ilen = me.data.datasets.length; i < ilen; 
++i) {
+                               meta = me.getDatasetMeta(i);
+                               if (meta.controller) {
+                                       meta.controller.destroy();
+                                       meta.controller = null;
+                               }
+                       }
+
+                       if (canvas) {
+                               me.unbindEvents();
+                               helpers.clear(me.chart);
+                               platform.releaseContext(me.chart.ctx);
+                               me.chart.canvas = null;
+                               me.chart.ctx = null;
+                       }
+
+                       plugins.notify(me, 'destroy');
+
+                       delete Chart.instances[me.id];
+               },
+
+               toBase64Image: function() {
+                       return 
this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
+               },
+
+               initToolTip: function() {
+                       var me = this;
+                       me.tooltip = new Chart.Tooltip({
+                               _chart: me.chart,
+                               _chartInstance: me,
+                               _data: me.data,
+                               _options: me.options.tooltips
+                       }, me);
+                       me.tooltip.initialize();
+               },
+
+               /**
+                * @private
+                */
+               bindEvents: function() {
+                       var me = this;
+                       var listeners = me._listeners = {};
+                       var listener = function() {
+                               me.eventHandler.apply(me, arguments);
+                       };
+
+                       helpers.each(me.options.events, function(type) {
+                               platform.addEventListener(me, type, listener);
+                               listeners[type] = listener;
+                       });
+
+                       // Responsiveness is currently based on the use of an 
iframe, however this method causes
+                       // performance issues and could be troublesome when 
used with ad blockers. So make sure
+                       // that the user is still able to create a chart 
without iframe when responsive is false.
+                       // See https://github.com/chartjs/Chart.js/issues/2210
+                       if (me.options.responsive) {
+                               listener = function() {
+                                       me.resize();
+                               };
+
+                               platform.addEventListener(me, 'resize', 
listener);
+                               listeners.resize = listener;
+                       }
+               },
+
+               /**
+                * @private
+                */
+               unbindEvents: function() {
+                       var me = this;
+                       var listeners = me._listeners;
+                       if (!listeners) {
+                               return;
+                       }
+
+                       delete me._listeners;
+                       helpers.each(listeners, function(listener, type) {
+                               platform.removeEventListener(me, type, 
listener);
+                       });
+               },
+
+               updateHoverStyle: function(elements, mode, enabled) {
+                       var method = enabled? 'setHoverStyle' : 
'removeHoverStyle';
+                       var element, i, ilen;
+
+                       for (i=0, ilen=elements.length; i<ilen; ++i) {
+                               element = elements[i];
+                               if (element) {
+                                       
this.getDatasetMeta(element._datasetIndex).controller[method](element);
+                               }
+                       }
+               },
+
+               /**
+                * @private
+                */
+               eventHandler: function(e) {
+                       var me = this;
+                       var tooltip = me.tooltip;
+
+                       if (plugins.notify(me, 'beforeEvent', [e]) === false) {
+                               return;
+                       }
+
+                       // Buffer any update calls so that renders do not occur
+                       me._bufferedRender = true;
+                       me._bufferedRequest = null;
+
+                       var changed = me.handleEvent(e);
+                       changed |= tooltip && tooltip.handleEvent(e);
+
+                       plugins.notify(me, 'afterEvent', [e]);
+
+                       var bufferedRequest = me._bufferedRequest;
+                       if (bufferedRequest) {
+                               // If we have an update that was triggered, we 
need to do a normal render
+                               me.render(bufferedRequest.duration, 
bufferedRequest.lazy);
+                       } else if (changed && !me.animating) {
+                               // If entering, leaving, or changing elements, 
animate the change via pivot
+                               me.stop();
+
+                               // We only need to render at this point. 
Updating will cause scales to be
+                               // recomputed generating flicker & using more 
memory than necessary.
+                               me.render(me.options.hover.animationDuration, 
true);
+                       }
+
+                       me._bufferedRender = false;
+                       me._bufferedRequest = null;
+
+                       return me;
+               },
+
+               /**
+                * Handle an event
+                * @private
+                * @param {IEvent} event the event to handle
+                * @return {Boolean} true if the chart needs to re-render
+                */
+               handleEvent: function(e) {
+                       var me = this;
+                       var options = me.options || {};
+                       var hoverOptions = options.hover;
+                       var changed = false;
+
+                       me.lastActive = me.lastActive || [];
+
+                       // Find Active Elements for hover and tooltips
+                       if (e.type === 'mouseout') {
+                               me.active = [];
+                       } else {
+                               me.active = me.getElementsAtEventForMode(e, 
hoverOptions.mode, hoverOptions);
+                       }
+
+                       // On Hover hook
+                       if (hoverOptions.onHover) {
+                               // Need to call with native event here to not 
break backwards compatibility
+                               hoverOptions.onHover.call(me, e.native, 
me.active);
+                       }
+
+                       if (e.type === 'mouseup' || e.type === 'click') {
+                               if (options.onClick) {
+                                       // Use e.native here for backwards 
compatibility
+                                       options.onClick.call(me, e.native, 
me.active);
+                               }
+                       }
+
+                       // Remove styling for last active (even if it may still 
be active)
+                       if (me.lastActive.length) {
+                               me.updateHoverStyle(me.lastActive, 
hoverOptions.mode, false);
+                       }
+
+                       // Built in hover styling
+                       if (me.active.length && hoverOptions.mode) {
+                               me.updateHoverStyle(me.active, 
hoverOptions.mode, true);
+                       }
+
+                       changed = !helpers.arrayEquals(me.active, 
me.lastActive);
+
+                       // Remember Last Actives
+                       me.lastActive = me.active;
+
+                       return changed;
+               }
+       });
+};
+
+},{}],24:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       var helpers = Chart.helpers;
+
+       var arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift'];
+
+       /**
+        * Hooks the array methods that add or remove values ('push', pop', 
'shift', 'splice',
+        * 'unshift') and notify the listener AFTER the array has been altered. 
Listeners are
+        * called on the 'onData*' callbacks (e.g. onDataPush, etc.) with same 
arguments.
+        */
+       function listenArrayEvents(array, listener) {
+               if (array._chartjs) {
+                       array._chartjs.listeners.push(listener);
+                       return;
+               }
+
+               Object.defineProperty(array, '_chartjs', {
+                       configurable: true,
+                       enumerable: false,
+                       value: {
+                               listeners: [listener]
+                       }
+               });
+
+               arrayEvents.forEach(function(key) {
+                       var method = 'onData' + key.charAt(0).toUpperCase() + 
key.slice(1);
+                       var base = array[key];
+
+                       Object.defineProperty(array, key, {
+                               configurable: true,
+                               enumerable: false,
+                               value: function() {
+                                       var args = 
Array.prototype.slice.call(arguments);
+                                       var res = base.apply(this, args);
+
+                                       helpers.each(array._chartjs.listeners, 
function(object) {
+                                               if (typeof object[method] === 
'function') {
+                                                       
object[method].apply(object, args);
+                                               }
+                                       });
+
+                                       return res;
+                               }
+                       });
+               });
+       }
+
+       /**
+        * Removes the given array event listener and cleanup extra attached 
properties (such as
+        * the _chartjs stub and overridden methods) if array doesn't have any 
more listeners.
+        */
+       function unlistenArrayEvents(array, listener) {
+               var stub = array._chartjs;
+               if (!stub) {
+                       return;
+               }
+
+               var listeners = stub.listeners;
+               var index = listeners.indexOf(listener);
+               if (index !== -1) {
+                       listeners.splice(index, 1);
+               }
+
+               if (listeners.length > 0) {
+                       return;
+               }
+
+               arrayEvents.forEach(function(key) {
+                       delete array[key];
+               });
+
+               delete array._chartjs;
+       }
+
+       // Base class for all dataset controllers (line, bar, etc)
+       Chart.DatasetController = function(chart, datasetIndex) {
+               this.initialize(chart, datasetIndex);
+       };
+
+       helpers.extend(Chart.DatasetController.prototype, {
+
+               /**
+                * Element type used to generate a meta dataset (e.g. 
Chart.element.Line).
+                * @type {Chart.core.element}
+                */
+               datasetElementType: null,
+
+               /**
+                * Element type used to generate a meta data (e.g. 
Chart.element.Point).
+                * @type {Chart.core.element}
+                */
+               dataElementType: null,
+
+               initialize: function(chart, datasetIndex) {
+                       var me = this;
+                       me.chart = chart;
+                       me.index = datasetIndex;
+                       me.linkScales();
+                       me.addElements();
+               },
+
+               updateIndex: function(datasetIndex) {
+                       this.index = datasetIndex;
+               },
+
+               linkScales: function() {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var dataset = me.getDataset();
+
+                       if (meta.xAxisID === null) {
+                               meta.xAxisID = dataset.xAxisID || 
me.chart.options.scales.xAxes[0].id;
+                       }
+                       if (meta.yAxisID === null) {
+                               meta.yAxisID = dataset.yAxisID || 
me.chart.options.scales.yAxes[0].id;
+                       }
+               },
+
+               getDataset: function() {
+                       return this.chart.data.datasets[this.index];
+               },
+
+               getMeta: function() {
+                       return this.chart.getDatasetMeta(this.index);
+               },
+
+               getScaleForId: function(scaleID) {
+                       return this.chart.scales[scaleID];
+               },
+
+               reset: function() {
+                       this.update(true);
+               },
+
+               /**
+                * @private
+                */
+               destroy: function() {
+                       if (this._data) {
+                               unlistenArrayEvents(this._data, this);
+                       }
+               },
+
+               createMetaDataset: function() {
+                       var me = this;
+                       var type = me.datasetElementType;
+                       return type && new type({
+                               _chart: me.chart.chart,
+                               _datasetIndex: me.index
+                       });
+               },
+
+               createMetaData: function(index) {
+                       var me = this;
+                       var type = me.dataElementType;
+                       return type && new type({
+                               _chart: me.chart.chart,
+                               _datasetIndex: me.index,
+                               _index: index
+                       });
+               },
+
+               addElements: function() {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var data = me.getDataset().data || [];
+                       var metaData = meta.data;
+                       var i, ilen;
+
+                       for (i=0, ilen=data.length; i<ilen; ++i) {
+                               metaData[i] = metaData[i] || 
me.createMetaData(i);
+                       }
+
+                       meta.dataset = meta.dataset || me.createMetaDataset();
+               },
+
+               addElementAndReset: function(index) {
+                       var element = this.createMetaData(index);
+                       this.getMeta().data.splice(index, 0, element);
+                       this.updateElement(element, index, true);
+               },
+
+               buildOrUpdateElements: function() {
+                       var me = this;
+                       var dataset = me.getDataset();
+                       var data = dataset.data || (dataset.data = []);
+
+                       // In order to correctly handle data addition/deletion 
animation (an thus simulate
+                       // real-time charts), we need to monitor these data 
modifications and synchronize
+                       // the internal meta data accordingly.
+                       if (me._data !== data) {
+                               if (me._data) {
+                                       // This case happens when the user 
replaced the data array instance.
+                                       unlistenArrayEvents(me._data, me);
+                               }
+
+                               listenArrayEvents(data, me);
+                               me._data = data;
+                       }
+
+                       // Re-sync meta data in case the user replaced the data 
array or if we missed
+                       // any updates and so make sure that we handle number 
of datapoints changing.
+                       me.resyncElements();
+               },
+
+               update: helpers.noop,
+
+               draw: function(ease) {
+                       var easingDecimal = ease || 1;
+                       var i, len;
+                       var metaData = this.getMeta().data;
+                       for (i = 0, len = metaData.length; i < len; ++i) {
+                               metaData[i].transition(easingDecimal).draw();
+                       }
+               },
+
+               removeHoverStyle: function(element, elementOpts) {
+                       var dataset = 
this.chart.data.datasets[element._datasetIndex],
+                               index = element._index,
+                               custom = element.custom || {},
+                               valueOrDefault = 
helpers.getValueAtIndexOrDefault,
+                               model = element._model;
+
+                       model.backgroundColor = custom.backgroundColor ? 
custom.backgroundColor : valueOrDefault(dataset.backgroundColor, index, 
elementOpts.backgroundColor);
+                       model.borderColor = custom.borderColor ? 
custom.borderColor : valueOrDefault(dataset.borderColor, index, 
elementOpts.borderColor);
+                       model.borderWidth = custom.borderWidth ? 
custom.borderWidth : valueOrDefault(dataset.borderWidth, index, 
elementOpts.borderWidth);
+               },
+
+               setHoverStyle: function(element) {
+                       var dataset = 
this.chart.data.datasets[element._datasetIndex],
+                               index = element._index,
+                               custom = element.custom || {},
+                               valueOrDefault = 
helpers.getValueAtIndexOrDefault,
+                               getHoverColor = helpers.getHoverColor,
+                               model = element._model;
+
+                       model.backgroundColor = custom.hoverBackgroundColor ? 
custom.hoverBackgroundColor : valueOrDefault(dataset.hoverBackgroundColor, 
index, getHoverColor(model.backgroundColor));
+                       model.borderColor = custom.hoverBorderColor ? 
custom.hoverBorderColor : valueOrDefault(dataset.hoverBorderColor, index, 
getHoverColor(model.borderColor));
+                       model.borderWidth = custom.hoverBorderWidth ? 
custom.hoverBorderWidth : valueOrDefault(dataset.hoverBorderWidth, index, 
model.borderWidth);
+               },
+
+               /**
+                * @private
+                */
+               resyncElements: function() {
+                       var me = this;
+                       var meta = me.getMeta();
+                       var data = me.getDataset().data;
+                       var numMeta = meta.data.length;
+                       var numData = data.length;
+
+                       if (numData < numMeta) {
+                               meta.data.splice(numData, numMeta - numData);
+                       } else if (numData > numMeta) {
+                               me.insertElements(numMeta, numData - numMeta);
+                       }
+               },
+
+               /**
+                * @private
+                */
+               insertElements: function(start, count) {
+                       for (var i=0; i<count; ++i) {
+                               this.addElementAndReset(start + i);
+                       }
+               },
+
+               /**
+                * @private
+                */
+               onDataPush: function() {
+                       this.insertElements(this.getDataset().data.length-1, 
arguments.length);
+               },
+
+               /**
+                * @private
+                */
+               onDataPop: function() {
+                       this.getMeta().data.pop();
+               },
+
+               /**
+                * @private
+                */
+               onDataShift: function() {
+                       this.getMeta().data.shift();
+               },
+
+               /**
+                * @private
+                */
+               onDataSplice: function(start, count) {
+                       this.getMeta().data.splice(start, count);
+                       this.insertElements(start, arguments.length - 2);
+               },
+
+               /**
+                * @private
+                */
+               onDataUnshift: function() {
+                       this.insertElements(0, arguments.length);
+               }
+       });
+
+       Chart.DatasetController.extend = helpers.inherits;
+};
+
+},{}],25:[function(require,module,exports){
+'use strict';
+
+module.exports = function(Chart) {
+
+       var helpers = Chart.helpers;
+
+       Chart.elements = {};
+
+       Chart.Element = function(configuration) {
+               helpers.extend(this, configuration);
+               this.initialize.apply(this, arguments);
+       };
+
+       helpers.extend(Chart.Element.prototype, {
+
+               initialize: function() {
+                       this.hidden = false;
+               },
+
+               pivot: function() {
+                       var me = this;
+                       if (!me._view) {
+                               me._view = helpers.clone(me._model);
+                       }
+                       me._start = helpers.clone(me._view);
+                       return me;
+               },
+
+               transition: function(ease) {
+                       var me = this;
+
+                       if (!me._view) {
+                               me._view = helpers.clone(me._model);
+                       }
+
+                       // No animation -> No Transition
+                       if (ease === 1) {
+                               me._view = me._model;
+                               me._start = null;
+                               return me;
+                       }
+
+                       if (!me._start) {
+                               me.pivot();
+                       }
+
+                       helpers.each(me._model, function(value, key) {
+
+                               if (key[0] === '_') {
+                                       // Only non-underscored properties
+                               // Init if doesn't exist
+                               } else if (!me._view.hasOwnProperty(key)) {
+                                       if (typeof value === 'number' && 
!isNaN(me._view[key])) {
+                                               me._view[key] = value * ease;
+                                       } else {
+                                               me._view[key] = value;
+                                       }
+                               // No unnecessary computations
+                               } else if (value === me._view[key]) {
+                                       // It's the same! Woohoo!
+                               // Color transitions if possible
+                               } else if (typeof value === 'string') {
+                                       try {
+                                               var color = 
helpers.color(me._model[key]).mix(helpers.color(me._start[key]), ease);
+                                               me._view[key] = 
color.rgbString();
+                                       } catch (err) {
+                                               me._view[key] = value;
+                                       }
+                               // Number transitions
+                               } else if (typeof value === 'number') {
+                                       var startVal = me._start[key] !== 
undefined && isNaN(me._start[key]) === false ? me._start[key] : 0;
+                                       me._view[key] = ((me._model[key] - 
startVal) * ease) + startVal;
+                               // Everything else
+                               } else {
+                                       me._view[key] = value;
+                               }
+                       }, me);
+
+                       return me;
+               },
+
+               tooltipPosition: function() {
+                       return {
+                               x: this._model.x,
+                               y: this._model.y
+                       };
+               },
+
+               hasValue: function() {
+                       return helpers.isNumber(this._model.x) && 
helpers.isNumber(this._model.y);
+               }
+       });
+
+       Chart.Element.extend = helpers.inherits;
+
+};
+
+},{}],26:[function(require,module,exports){
+/* global window: false */
+/* global document: false */
+'use strict';
+
+var color = require(3);
+
+module.exports = function(Chart) {
+       // Global Chart helpers object for utility methods and classes
+       var helpers = Chart.helpers = {};
+
+       // -- Basic js utility methods
+       helpers.each = function(loopable, callback, self, reverse) {
+               // Check to see if null or undefined firstly.
+               var i, len;
+               if (helpers.isArray(loopable)) {
+                       len = loopable.length;
+                       if (reverse) {
+                               for (i = len - 1; i >= 0; i--) {
+                                       callback.call(self, loopable[i], i);
+                               }
+                       } else {
+                               for (i = 0; i < len; i++) {
+                                       callback.call(self, loopable[i], i);
+                               }
+                       }
+               } else if (typeof loopable === 'object') {
+                       var keys = Object.keys(loopable);
+                       len = keys.length;
+                       for (i = 0; i < len; i++) {
+                               callback.call(self, loopable[keys[i]], keys[i]);
+                       }
+               }
+       };
+       helpers.clone = function(obj) {
+               var objClone = {};
+               helpers.each(obj, function(value, key) {
+                       if (helpers.isArray(value)) {
+                               objClone[key] = value.slice(0);
+                       } else if (typeof value === 'object' && value !== null) 
{
+                               objClone[key] = helpers.clone(value);
+                       } else {
+                               objClone[key] = value;
+                       }
+               });
+               return objClone;
+       };
+       helpers.extend = function(base) {
+               var setFn = function(value, key) {
+                       base[key] = value;
+               };
+               for (var i = 1, ilen = arguments.length; i < ilen; i++) {
+                       helpers.each(arguments[i], setFn);
+               }
+               return base;
+       };
+       // Need a special merge function to chart configs since they are now 
grouped
+       helpers.configMerge = function(_base) {
+               var base = helpers.clone(_base);
+               helpers.each(Array.prototype.slice.call(arguments, 1), 
function(extension) {
+                       helpers.each(extension, function(value, key) {
+                               var baseHasProperty = base.hasOwnProperty(key);
+                               var baseVal = baseHasProperty ? base[key] : {};
+
+                               if (key === 'scales') {
+                                       // Scale config merging is complex. Add 
our own function here for that
+                                       base[key] = helpers.scaleMerge(baseVal, 
value);
+                               } else if (key === 'scale') {
+                                       // Used in polar area & radar charts 
since there is only one scale
+                                       base[key] = 
helpers.configMerge(baseVal, Chart.scaleService.getScaleDefaults(value.type), 
value);
+                               } else if (baseHasProperty
+                                               && typeof baseVal === 'object'
+                                               && !helpers.isArray(baseVal)
+                                               && baseVal !== null
+                                               && typeof value === 'object'
+                                               && !helpers.isArray(value)) {
+                                       // If we are overwriting an object with 
an object, do a merge of the properties.
+                                       base[key] = 
helpers.configMerge(baseVal, value);
+                               } else {
+                                       // can just overwrite the value in this 
case
+                                       base[key] = value;
+                               }
+                       });
+               });
+
+               return base;
+       };
+       helpers.scaleMerge = function(_base, extension) {
+               var base = helpers.clone(_base);
+
+               helpers.each(extension, function(value, key) {
+                       if (key === 'xAxes' || key === 'yAxes') {
+                               // These properties are arrays of items
+                               if (base.hasOwnProperty(key)) {
+                                       helpers.each(value, function(valueObj, 
index) {
+                                               var axisType = 
helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 
'linear');
+                                               var axisDefaults = 
Chart.scaleService.getScaleDefaults(axisType);
+                                               if (index >= base[key].length 
|| !base[key][index].type) {
+                                                       
base[key].push(helpers.configMerge(axisDefaults, valueObj));
+                                               } else if (valueObj.type && 
valueObj.type !== base[key][index].type) {
+                                                       // Type changed. Bring 
in the new defaults before we bring in valueObj so that valueObj can override 
the correct scale defaults
+                                                       base[key][index] = 
helpers.configMerge(base[key][index], axisDefaults, valueObj);
+                                               } else {
+                                                       // Type is the same
+                                                       base[key][index] = 
helpers.configMerge(base[key][index], valueObj);
+                                               }
+                                       });
+                               } else {
+                                       base[key] = [];
+                                       helpers.each(value, function(valueObj) {
+                                               var axisType = 
helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 
'linear');
+                                               
base[key].push(helpers.configMerge(Chart.scaleService.getScaleDefaults(axisType),
 valueObj));
+                                       });
+                               }
+                       } else if (base.hasOwnProperty(key) && typeof base[key] 
=== 'object' && base[key] !== null && typeof value === 'object') {
+                               // If we are overwriting an object with an 
object, do a merge of the properties.
+                               base[key] = helpers.configMerge(base[key], 
value);
+
+                       } else {
+                               // can just overwrite the value in this case
+                               base[key] = value;
+                       }
+               });
+
+               return base;
+       };
+       helpers.getValueAtIndexOrDefault = function(value, index, defaultValue) 
{
+               if (value === undefined || value === null) {
+                       return defaultValue;
+               }
+
+               if (helpers.isArray(value)) {
+                       return index < value.length ? value[index] : 
defaultValue;
+               }
+
+               return value;
+       };
+       helpers.getValueOrDefault = function(value, defaultValue) {
+               return value === undefined ? defaultValue : value;
+       };
+       helpers.indexOf = Array.prototype.indexOf?
+               function(array, item) {
+                       return array.indexOf(item);
+               }:
+               function(array, item) {
+                       for (var i = 0, ilen = array.length; i < ilen; ++i) {
+                               if (array[i] === item) {
+                                       return i;
+                               }
+                       }
+                       return -1;
+               };
+       helpers.where = function(collection, filterCallback) {
+               if (helpers.isArray(collection) && Array.prototype.filter) {
+                       return collection.filter(filterCallback);
+               }
+               var filtered = [];
+
+               helpers.each(collection, function(item) {
+                       if (filterCallback(item)) {
+                               filtered.push(item);
+                       }
+               });
+
+               return filtered;
+       };
+       helpers.findIndex = Array.prototype.findIndex?
+               function(array, callback, scope) {
+                       return array.findIndex(callback, scope);
+               } :
+               function(array, callback, scope) {
+                       scope = scope === undefined? array : scope;
+                       for (var i = 0, ilen = array.length; i < ilen; ++i) {
+                               if (callback.call(scope, array[i], i, array)) {
+                                       return i;
+                               }
+                       }
+                       return -1;
+               };
+       helpers.findNextWhere = function(arrayToSearch, filterCallback, 
startIndex) {
+               // Default to start of the array
+               if (startIndex === undefined || startIndex === null) {
+                       startIndex = -1;
+               }
+               for (var i = startIndex + 1; i < arrayToSearch.length; i++) {
+                       var currentItem = arrayToSearch[i];
+                       if (filterCallback(currentItem)) {
+                               return currentItem;
+                       }
+               }
+       };
+       helpers.findPreviousWhere = function(arrayToSearch, filterCallback, 
startIndex) {
+               // Default to end of the array
+               if (startIndex === undefined || startIndex === null) {
+                       startIndex = arrayToSearch.length;
+               }
+               for (var i = startIndex - 1; i >= 0; i--) {
+                       var currentItem = arrayToSearch[i];
+                       if (filterCallback(currentItem)) {
+                               return currentItem;
+                       }
+               }
+       };
+       helpers.inherits = function(extensions) {
+               // Basic javascript inheritance based on the model created in 
Backbone.js
+               var me = this;
+               var ChartElement = (extensions && 
extensions.hasOwnProperty('constructor')) ? extensions.constructor : function() 
{
+                       return me.apply(this, arguments);
+               };
+
+               var Surrogate = function() {
+                       this.constructor = ChartElement;
+               };
+               Surrogate.prototype = me.prototype;
+               ChartElement.prototype = new Surrogate();
+
+               ChartElement.extend = helpers.inherits;
+
+               if (extensions) {
+                       helpers.extend(ChartElement.prototype, extensions);
+               }
+
+               ChartElement.__super__ = me.prototype;
+
+               return ChartElement;
+       };
+       helpers.noop = function() {};
+       helpers.uid = (function() {
+               var id = 0;
+               return function() {
+                       return id++;
+               };
+       }());
+       // -- Math methods
+       helpers.isNumber = function(n) {
+               return !isNaN(parseFloat(n)) && isFinite(n);
+       };
+       helpers.almostEquals = function(x, y, epsilon) {
+               return Math.abs(x - y) < epsilon;
+       };
+       helpers.almostWhole = function(x, epsilon) {
+               var rounded = Math.round(x);
+               return (((rounded - epsilon) < x) && ((rounded + epsilon) > x));
+       };
+       helpers.max = function(array) {
+               return array.reduce(function(max, value) {
+                       if (!isNaN(value)) {
+                               return Math.max(max, value);
+                       }
+                       return max;
+               }, Number.NEGATIVE_INFINITY);
+       };
+       helpers.min = function(array) {
+               return array.reduce(function(min, value) {
+                       if (!isNaN(value)) {
+                               return Math.min(min, value);
+                       }
+                       return min;
+               }, Number.POSITIVE_INFINITY);
+       };
+       helpers.sign = Math.sign?
+               function(x) {
+                       return Math.sign(x);
+               } :
+               function(x) {
+                       x = +x; // convert to a number
+                       if (x === 0 || isNaN(x)) {
+                               return x;
+                       }
+                       return x > 0 ? 1 : -1;
+               };
+       helpers.log10 = Math.log10?
+               function(x) {
+                       return Math.log10(x);
+               } :
+               function(x) {
+                       return Math.log(x) / Math.LN10;
+               };
+       helpers.toRadians = function(degrees) {
+               return degrees * (Math.PI / 180);
+       };
+       helpers.toDegrees = function(radians) {
+               return radians * (180 / Math.PI);
+       };
+       // Gets the angle from vertical upright to the point about a centre.
+       helpers.getAngleFromPoint = function(centrePoint, anglePoint) {
+               var distanceFromXCenter = anglePoint.x - centrePoint.x,
+                       distanceFromYCenter = anglePoint.y - centrePoint.y,
+                       radialDistanceFromCenter = 
Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * 
distanceFromYCenter);
+
+               var angle = Math.atan2(distanceFromYCenter, 
distanceFromXCenter);
+
+               if (angle < (-0.5 * Math.PI)) {
+                       angle += 2.0 * Math.PI; // make sure the returned angle 
is in the range of (-PI/2, 3PI/2]
+               }
+
+               return {
+                       angle: angle,
+                       distance: radialDistanceFromCenter
+               };
+       };
+       helpers.distanceBetweenPoints = function(pt1, pt2) {
+               return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - 
pt1.y, 2));
+       };
+       helpers.aliasPixel = function(pixelWidth) {
+               return (pixelWidth % 2 === 0) ? 0 : 0.5;
+       };
+       helpers.splineCurve = function(firstPoint, middlePoint, afterPoint, t) {
+               // Props to Rob Spencer at scaled innovation for his post on 
splining between points
+               // 
http://scaledinnovation.com/analytics/splines/aboutSplines.html
+
+               // This function must also respect "skipped" points
+
+               var previous = firstPoint.skip ? middlePoint : firstPoint,
+                       current = middlePoint,
+                       next = afterPoint.skip ? middlePoint : afterPoint;
+
+               var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + 
Math.pow(current.y - previous.y, 2));
+               var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + 
Math.pow(next.y - current.y, 2));
+
+               var s01 = d01 / (d01 + d12);
+               var s12 = d12 / (d01 + d12);
+
+               // If all points are the same, s01 & s02 will be inf
+               s01 = isNaN(s01) ? 0 : s01;
+               s12 = isNaN(s12) ? 0 : s12;
+
+               var fa = t * s01; // scaling factor for triangle Ta
+               var fb = t * s12;
+
+               return {
+                       previous: {
+                               x: current.x - fa * (next.x - previous.x),
+                               y: current.y - fa * (next.y - previous.y)
+                       },
+                       next: {
+                               x: current.x + fb * (next.x - previous.x),
+                               y: current.y + fb * (next.y - previous.y)
+                       }
+               };
+       };
+       helpers.EPSILON = Number.EPSILON || 1e-14;
+       helpers.splineCurveMonotone = function(points) {
+               // This function calculates Bézier control points in a similar 
way than |splineCurve|,
+               // but preserves monotonicity of the provided data and ensures 
no local extremums are added
+               // between the dataset discrete points due to the interpolation.
+               // See : 
https://en.wikipedia.org/wiki/Monotone_cubic_interpolation
+
+               var pointsWithTangents = (points || []).map(function(point) {
+                       return {
+                               model: point._model,
+                               deltaK: 0,
+                               mK: 0
+                       };
+               });
+
+               // Calculate slopes (deltaK) and initialize tangents (mK)
+               var pointsLen = pointsWithTangents.length;
+               var i, pointBefore, pointCurrent, pointAfter;
+               for (i = 0; i < pointsLen; ++i) {
+                       pointCurrent = pointsWithTangents[i];
+                       if (pointCurrent.model.skip) {
+                               continue;
+                       }
+
+                       pointBefore = i > 0 ? pointsWithTangents[i - 1] : null;
+                       pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 
1] : null;
+                       if (pointAfter && !pointAfter.model.skip) {
+                               var slopeDeltaX = (pointAfter.model.x - 
pointCurrent.model.x);
+
+                               // In the case of two points that appear at the 
same x pixel, slopeDeltaX is 0
+                               pointCurrent.deltaK = slopeDeltaX !== 0 ? 
(pointAfter.model.y - pointCurrent.model.y) / slopeDeltaX : 0;
+                       }
+
+                       if (!pointBefore || pointBefore.model.skip) {
+                               pointCurrent.mK = pointCurrent.deltaK;
+                       } else if (!pointAfter || pointAfter.model.skip) {
+                               pointCurrent.mK = pointBefore.deltaK;
+                       } else if (this.sign(pointBefore.deltaK) !== 
this.sign(pointCurrent.deltaK)) {
+                               pointCurrent.mK = 0;
+                       } else {
+                               pointCurrent.mK = (pointBefore.deltaK + 
pointCurrent.deltaK) / 2;
+                       }
+               }
+
+               // Adjust tangents to ensure monotonic properties
+               var alphaK, betaK, tauK, squaredMagnitude;
+               for (i = 0; i < pointsLen - 1; ++i) {
+                       pointCurrent = pointsWithTangents[i];
+                       pointAfter = pointsWithTangents[i + 1];
+                       if (pointCurrent.model.skip || pointAfter.model.skip) {
+                               continue;
+                       }
+
+                       if (helpers.almostEquals(pointCurrent.deltaK, 0, 
this.EPSILON)) {
+                               pointCurrent.mK = pointAfter.mK = 0;
+                               continue;
+                       }
+
+                       alphaK = pointCurrent.mK / pointCurrent.deltaK;
+                       betaK = pointAfter.mK / pointCurrent.deltaK;
+                       squaredMagnitude = Math.pow(alphaK, 2) + 
Math.pow(betaK, 2);
+                       if (squaredMagnitude <= 9) {
+                               continue;
+                       }
+
+                       tauK = 3 / Math.sqrt(squaredMagnitude);
+                       pointCurrent.mK = alphaK * tauK * pointCurrent.deltaK;
+                       pointAfter.mK = betaK * tauK * pointCurrent.deltaK;
+               }
+
+               // Compute control points
+               var deltaX;
+               for (i = 0; i < pointsLen; ++i) {
+                       pointCurrent = pointsWithTangents[i];
+                       if (pointCurrent.model.skip) {
+                               continue;
+                       }
+
+                       pointBefore = i > 0 ? pointsWithTangents[i - 1] : null;
+                       pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 
1] : null;
+                       if (pointBefore && !pointBefore.model.skip) {
+                               deltaX = (pointCurrent.model.x - 
pointBefore.model.x) / 3;
+                               pointCurrent.model.controlPointPreviousX = 
pointCurrent.model.x - deltaX;
+                               pointCurrent.model.controlPointPreviousY = 
pointCurrent.model.y - deltaX * pointCurrent.mK;
+                       }
+                       if (pointAfter && !pointAfter.model.skip) {
+                               deltaX = (pointAfter.model.x - 
pointCurrent.model.x) / 3;
+                               pointCurrent.model.controlPointNextX = 
pointCurrent.model.x + deltaX;
+                               pointCurrent.model.controlPointNextY = 
pointCurrent.model.y + deltaX * pointCurrent.mK;
+                       }
+               }
+       };
+       helpers.nextItem = function(collection, index, loop) {
+               if (loop) {
+                       return index >= collection.length - 1 ? collection[0] : 
collection[index + 1];
+               }
+               return index >= collection.length - 1 ? 
collection[collection.length - 1] : collection[index + 1];
+       };
+       helpers.previousItem = function(collection, index, loop) {
+               if (loop) {

@@ Diff output truncated at 153600 characters. @@



reply via email to

[Prev in Thread] Current Thread [Next in Thread]