MDL-56013 lib: Upgrade Chart.js to version 2.2.2
authorSimey Lameze <simey@moodle.com>
Tue, 20 Sep 2016 07:51:40 +0000 (15:51 +0800)
committerSimey Lameze <simey@moodle.com>
Wed, 21 Sep 2016 00:25:13 +0000 (08:25 +0800)
lib/amd/build/chartjs-lazy.min.js
lib/amd/src/chartjs-lazy.js
lib/thirdpartylibs.xml

index 0361ea9..62a3d19 100644 (file)
Binary files a/lib/amd/build/chartjs-lazy.min.js and b/lib/amd/build/chartjs-lazy.min.js differ
index f0261ae..033e609 100644 (file)
@@ -1,7 +1,7 @@
 /*!\r
  * Chart.js\r
  * http://chartjs.org/\r
- * Version: 2.1.6\r
+ * Version: 2.2.2\r
  *\r
  * Copyright 2016 Nick Downie\r
  * Released under the MIT license\r
  * - Copy Chart.js to lib/amd/src/chartjs.js.\r
  * - Add these instructions to the file.\r
  * - Add the jshint ignore rules.\r
+ * - Visit lib/tests/other/chartjstestpage.php to see if the library still works after the update.\r
  */\r
 \r
 (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){\r
 \r
 },{}],2:[function(require,module,exports){\r
-/* MIT license */\r
-var colorNames = require(6);\r
-\r
-module.exports = {\r
-   getRgba: getRgba,\r
-   getHsla: getHsla,\r
-   getRgb: getRgb,\r
-   getHsl: getHsl,\r
-   getHwb: getHwb,\r
-   getAlpha: getAlpha,\r
-\r
-   hexString: hexString,\r
-   rgbString: rgbString,\r
-   rgbaString: rgbaString,\r
-   percentString: percentString,\r
-   percentaString: percentaString,\r
-   hslString: hslString,\r
-   hslaString: hslaString,\r
-   hwbString: hwbString,\r
-   keyword: keyword\r
-}\r
-\r
-function getRgba(string) {\r
-   if (!string) {\r
-      return;\r
-   }\r
-   var abbr =  /^#([a-fA-F0-9]{3})$/,\r
-       hex =  /^#([a-fA-F0-9]{6})$/,\r
-       rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,\r
-       per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,\r
-       keyword = /(\w+)/;\r
-\r
-   var rgb = [0, 0, 0],\r
-       a = 1,\r
-       match = string.match(abbr);\r
-   if (match) {\r
-      match = match[1];\r
-      for (var i = 0; i < rgb.length; i++) {\r
-         rgb[i] = parseInt(match[i] + match[i], 16);\r
-      }\r
-   }\r
-   else if (match = string.match(hex)) {\r
-      match = match[1];\r
-      for (var i = 0; i < rgb.length; i++) {\r
-         rgb[i] = parseInt(match.slice(i * 2, i * 2 + 2), 16);\r
-      }\r
-   }\r
-   else if (match = string.match(rgba)) {\r
-      for (var i = 0; i < rgb.length; i++) {\r
-         rgb[i] = parseInt(match[i + 1]);\r
-      }\r
-      a = parseFloat(match[4]);\r
-   }\r
-   else if (match = string.match(per)) {\r
-      for (var i = 0; i < rgb.length; i++) {\r
-         rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55);\r
-      }\r
-      a = parseFloat(match[4]);\r
-   }\r
-   else if (match = string.match(keyword)) {\r
-      if (match[1] == "transparent") {\r
-         return [0, 0, 0, 0];\r
-      }\r
-      rgb = colorNames[match[1]];\r
-      if (!rgb) {\r
-         return;\r
-      }\r
-   }\r
-\r
-   for (var i = 0; i < rgb.length; i++) {\r
-      rgb[i] = scale(rgb[i], 0, 255);\r
-   }\r
-   if (!a && a != 0) {\r
-      a = 1;\r
-   }\r
-   else {\r
-      a = scale(a, 0, 1);\r
-   }\r
-   rgb[3] = a;\r
-   return rgb;\r
-}\r
-\r
-function getHsla(string) {\r
-   if (!string) {\r
-      return;\r
-   }\r
-   var hsl = /^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/;\r
-   var match = string.match(hsl);\r
-   if (match) {\r
-      var alpha = parseFloat(match[4]);\r
-      var h = scale(parseInt(match[1]), 0, 360),\r
-          s = scale(parseFloat(match[2]), 0, 100),\r
-          l = scale(parseFloat(match[3]), 0, 100),\r
-          a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);\r
-      return [h, s, l, a];\r
-   }\r
-}\r
-\r
-function getHwb(string) {\r
-   if (!string) {\r
-      return;\r
-   }\r
-   var hwb = /^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/;\r
-   var match = string.match(hwb);\r
-   if (match) {\r
-    var alpha = parseFloat(match[4]);\r
-      var h = scale(parseInt(match[1]), 0, 360),\r
-          w = scale(parseFloat(match[2]), 0, 100),\r
-          b = scale(parseFloat(match[3]), 0, 100),\r
-          a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);\r
-      return [h, w, b, a];\r
-   }\r
-}\r
-\r
-function getRgb(string) {\r
-   var rgba = getRgba(string);\r
-   return rgba && rgba.slice(0, 3);\r
-}\r
-\r
-function getHsl(string) {\r
-  var hsla = getHsla(string);\r
-  return hsla && hsla.slice(0, 3);\r
-}\r
-\r
-function getAlpha(string) {\r
-   var vals = getRgba(string);\r
-   if (vals) {\r
-      return vals[3];\r
-   }\r
-   else if (vals = getHsla(string)) {\r
-      return vals[3];\r
-   }\r
-   else if (vals = getHwb(string)) {\r
-      return vals[3];\r
-   }\r
-}\r
-\r
-// generators\r
-function hexString(rgb) {\r
-   return "#" + hexDouble(rgb[0]) + hexDouble(rgb[1])\r
-              + hexDouble(rgb[2]);\r
-}\r
-\r
-function rgbString(rgba, alpha) {\r
-   if (alpha < 1 || (rgba[3] && rgba[3] < 1)) {\r
-      return rgbaString(rgba, alpha);\r
-   }\r
-   return "rgb(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ")";\r
-}\r
-\r
-function rgbaString(rgba, alpha) {\r
-   if (alpha === undefined) {\r
-      alpha = (rgba[3] !== undefined ? rgba[3] : 1);\r
-   }\r
-   return "rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2]\r
-           + ", " + alpha + ")";\r
-}\r
-\r
-function percentString(rgba, alpha) {\r
-   if (alpha < 1 || (rgba[3] && rgba[3] < 1)) {\r
-      return percentaString(rgba, alpha);\r
-   }\r
-   var r = Math.round(rgba[0]/255 * 100),\r
-       g = Math.round(rgba[1]/255 * 100),\r
-       b = Math.round(rgba[2]/255 * 100);\r
-\r
-   return "rgb(" + r + "%, " + g + "%, " + b + "%)";\r
-}\r
-\r
-function percentaString(rgba, alpha) {\r
-   var r = Math.round(rgba[0]/255 * 100),\r
-       g = Math.round(rgba[1]/255 * 100),\r
-       b = Math.round(rgba[2]/255 * 100);\r
-   return "rgba(" + r + "%, " + g + "%, " + b + "%, " + (alpha || rgba[3] || 1) + ")";\r
-}\r
-\r
-function hslString(hsla, alpha) {\r
-   if (alpha < 1 || (hsla[3] && hsla[3] < 1)) {\r
-      return hslaString(hsla, alpha);\r
-   }\r
-   return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)";\r
-}\r
-\r
-function hslaString(hsla, alpha) {\r
-   if (alpha === undefined) {\r
-      alpha = (hsla[3] !== undefined ? hsla[3] : 1);\r
-   }\r
-   return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, "\r
-           + alpha + ")";\r
-}\r
-\r
-// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax\r
-// (hwb have alpha optional & 1 is default value)\r
-function hwbString(hwb, alpha) {\r
-   if (alpha === undefined) {\r
-      alpha = (hwb[3] !== undefined ? hwb[3] : 1);\r
-   }\r
-   return "hwb(" + hwb[0] + ", " + hwb[1] + "%, " + hwb[2] + "%"\r
-           + (alpha !== undefined && alpha !== 1 ? ", " + alpha : "") + ")";\r
-}\r
-\r
-function keyword(rgb) {\r
-  return reverseNames[rgb.slice(0, 3)];\r
-}\r
-\r
-// helpers\r
-function scale(num, min, max) {\r
-   return Math.min(Math.max(min, num), max);\r
-}\r
-\r
-function hexDouble(num) {\r
-  var str = num.toString(16).toUpperCase();\r
-  return (str.length < 2) ? "0" + str : str;\r
-}\r
-\r
-\r
-//create a list of reverse color names\r
-var reverseNames = {};\r
-for (var name in colorNames) {\r
-   reverseNames[colorNames[name]] = name;\r
-}\r
-\r
-},{"6":6}],3:[function(require,module,exports){\r
-/* MIT license */\r
-var convert = require(5);\r
-var string = require(2);\r
-\r
-var Color = function (obj) {\r
-       if (obj instanceof Color) {\r
-               return obj;\r
+       /* MIT license */\r
+       var colorNames = require(6);\r
+\r
+       module.exports = {\r
+               getRgba: getRgba,\r
+               getHsla: getHsla,\r
+               getRgb: getRgb,\r
+               getHsl: getHsl,\r
+               getHwb: getHwb,\r
+               getAlpha: getAlpha,\r
+\r
+               hexString: hexString,\r
+               rgbString: rgbString,\r
+               rgbaString: rgbaString,\r
+               percentString: percentString,\r
+               percentaString: percentaString,\r
+               hslString: hslString,\r
+               hslaString: hslaString,\r
+               hwbString: hwbString,\r
+               keyword: keyword\r
        }\r
-       if (!(this instanceof Color)) {\r
-               return new Color(obj);\r
-       }\r
-\r
-       this.values = {\r
-               rgb: [0, 0, 0],\r
-               hsl: [0, 0, 0],\r
-               hsv: [0, 0, 0],\r
-               hwb: [0, 0, 0],\r
-               cmyk: [0, 0, 0, 0],\r
-               alpha: 1\r
-       };\r
 \r
-       // parse Color() argument\r
-       var vals;\r
-       if (typeof obj === 'string') {\r
-               vals = string.getRgba(obj);\r
-               if (vals) {\r
-                       this.setValues('rgb', vals);\r
-               } else if (vals = string.getHsla(obj)) {\r
-                       this.setValues('hsl', vals);\r
-               } else if (vals = string.getHwb(obj)) {\r
-                       this.setValues('hwb', vals);\r
-               } else {\r
-                       throw new Error('Unable to parse color from string "' + obj + '"');\r
+       function getRgba(string) {\r
+               if (!string) {\r
+                       return;\r
                }\r
-       } else if (typeof obj === 'object') {\r
-               vals = obj;\r
-               if (vals.r !== undefined || vals.red !== undefined) {\r
-                       this.setValues('rgb', vals);\r
-               } else if (vals.l !== undefined || vals.lightness !== undefined) {\r
-                       this.setValues('hsl', vals);\r
-               } else if (vals.v !== undefined || vals.value !== undefined) {\r
-                       this.setValues('hsv', vals);\r
-               } else if (vals.w !== undefined || vals.whiteness !== undefined) {\r
-                       this.setValues('hwb', vals);\r
-               } else if (vals.c !== undefined || vals.cyan !== undefined) {\r
-                       this.setValues('cmyk', vals);\r
-               } else {\r
-                       throw new Error('Unable to parse color from object ' + JSON.stringify(obj));\r
+               var abbr =  /^#([a-fA-F0-9]{3})$/,\r
+                       hex =  /^#([a-fA-F0-9]{6})$/,\r
+                       rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,\r
+                       per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,\r
+                       keyword = /(\w+)/;\r
+\r
+               var rgb = [0, 0, 0],\r
+                       a = 1,\r
+                       match = string.match(abbr);\r
+               if (match) {\r
+                       match = match[1];\r
+                       for (var i = 0; i < rgb.length; i++) {\r
+                               rgb[i] = parseInt(match[i] + match[i], 16);\r
+                       }\r
                }\r
-       }\r
-};\r
-\r
-Color.prototype = {\r
-       rgb: function () {\r
-               return this.setSpace('rgb', arguments);\r
-       },\r
-       hsl: function () {\r
-               return this.setSpace('hsl', arguments);\r
-       },\r
-       hsv: function () {\r
-               return this.setSpace('hsv', arguments);\r
-       },\r
-       hwb: function () {\r
-               return this.setSpace('hwb', arguments);\r
-       },\r
-       cmyk: function () {\r
-               return this.setSpace('cmyk', arguments);\r
-       },\r
-\r
-       rgbArray: function () {\r
-               return this.values.rgb;\r
-       },\r
-       hslArray: function () {\r
-               return this.values.hsl;\r
-       },\r
-       hsvArray: function () {\r
-               return this.values.hsv;\r
-       },\r
-       hwbArray: function () {\r
-               var values = this.values;\r
-               if (values.alpha !== 1) {\r
-                       return values.hwb.concat([values.alpha]);\r
+               else if (match = string.match(hex)) {\r
+                       match = match[1];\r
+                       for (var i = 0; i < rgb.length; i++) {\r
+                               rgb[i] = parseInt(match.slice(i * 2, i * 2 + 2), 16);\r
+                       }\r
                }\r
-               return values.hwb;\r
-       },\r
-       cmykArray: function () {\r
-               return this.values.cmyk;\r
-       },\r
-       rgbaArray: function () {\r
-               var values = this.values;\r
-               return values.rgb.concat([values.alpha]);\r
-       },\r
-       hslaArray: function () {\r
-               var values = this.values;\r
-               return values.hsl.concat([values.alpha]);\r
-       },\r
-       alpha: function (val) {\r
-               if (val === undefined) {\r
-                       return this.values.alpha;\r
+               else if (match = string.match(rgba)) {\r
+                       for (var i = 0; i < rgb.length; i++) {\r
+                               rgb[i] = parseInt(match[i + 1]);\r
+                       }\r
+                       a = parseFloat(match[4]);\r
                }\r
-               this.setValues('alpha', val);\r
-               return this;\r
-       },\r
-\r
-       red: function (val) {\r
-               return this.setChannel('rgb', 0, val);\r
-       },\r
-       green: function (val) {\r
-               return this.setChannel('rgb', 1, val);\r
-       },\r
-       blue: function (val) {\r
-               return this.setChannel('rgb', 2, val);\r
-       },\r
-       hue: function (val) {\r
-               if (val) {\r
-                       val %= 360;\r
-                       val = val < 0 ? 360 + val : val;\r
+               else if (match = string.match(per)) {\r
+                       for (var i = 0; i < rgb.length; i++) {\r
+                               rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55);\r
+                       }\r
+                       a = parseFloat(match[4]);\r
+               }\r
+               else if (match = string.match(keyword)) {\r
+                       if (match[1] == "transparent") {\r
+                               return [0, 0, 0, 0];\r
+                       }\r
+                       rgb = colorNames[match[1]];\r
+                       if (!rgb) {\r
+                               return;\r
+                       }\r
                }\r
-               return this.setChannel('hsl', 0, val);\r
-       },\r
-       saturation: function (val) {\r
-               return this.setChannel('hsl', 1, val);\r
-       },\r
-       lightness: function (val) {\r
-               return this.setChannel('hsl', 2, val);\r
-       },\r
-       saturationv: function (val) {\r
-               return this.setChannel('hsv', 1, val);\r
-       },\r
-       whiteness: function (val) {\r
-               return this.setChannel('hwb', 1, val);\r
-       },\r
-       blackness: function (val) {\r
-               return this.setChannel('hwb', 2, val);\r
-       },\r
-       value: function (val) {\r
-               return this.setChannel('hsv', 2, val);\r
-       },\r
-       cyan: function (val) {\r
-               return this.setChannel('cmyk', 0, val);\r
-       },\r
-       magenta: function (val) {\r
-               return this.setChannel('cmyk', 1, val);\r
-       },\r
-       yellow: function (val) {\r
-               return this.setChannel('cmyk', 2, val);\r
-       },\r
-       black: function (val) {\r
-               return this.setChannel('cmyk', 3, val);\r
-       },\r
-\r
-       hexString: function () {\r
-               return string.hexString(this.values.rgb);\r
-       },\r
-       rgbString: function () {\r
-               return string.rgbString(this.values.rgb, this.values.alpha);\r
-       },\r
-       rgbaString: function () {\r
-               return string.rgbaString(this.values.rgb, this.values.alpha);\r
-       },\r
-       percentString: function () {\r
-               return string.percentString(this.values.rgb, this.values.alpha);\r
-       },\r
-       hslString: function () {\r
-               return string.hslString(this.values.hsl, this.values.alpha);\r
-       },\r
-       hslaString: function () {\r
-               return string.hslaString(this.values.hsl, this.values.alpha);\r
-       },\r
-       hwbString: function () {\r
-               return string.hwbString(this.values.hwb, this.values.alpha);\r
-       },\r
-       keyword: function () {\r
-               return string.keyword(this.values.rgb, this.values.alpha);\r
-       },\r
-\r
-       rgbNumber: function () {\r
-               var rgb = this.values.rgb;\r
-               return (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];\r
-       },\r
-\r
-       luminosity: function () {\r
-               // http://www.w3.org/TR/WCAG20/#relativeluminancedef\r
-               var rgb = this.values.rgb;\r
-               var lum = [];\r
+\r
                for (var i = 0; i < rgb.length; i++) {\r
-                       var chan = rgb[i] / 255;\r
-                       lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4);\r
+                       rgb[i] = scale(rgb[i], 0, 255);\r
                }\r
-               return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2];\r
-       },\r
-\r
-       contrast: function (color2) {\r
-               // http://www.w3.org/TR/WCAG20/#contrast-ratiodef\r
-               var lum1 = this.luminosity();\r
-               var lum2 = color2.luminosity();\r
-               if (lum1 > lum2) {\r
-                       return (lum1 + 0.05) / (lum2 + 0.05);\r
+               if (!a && a != 0) {\r
+                       a = 1;\r
                }\r
-               return (lum2 + 0.05) / (lum1 + 0.05);\r
-       },\r
-\r
-       level: function (color2) {\r
-               var contrastRatio = this.contrast(color2);\r
-               if (contrastRatio >= 7.1) {\r
-                       return 'AAA';\r
+               else {\r
+                       a = scale(a, 0, 1);\r
                }\r
+               rgb[3] = a;\r
+               return rgb;\r
+       }\r
 \r
-               return (contrastRatio >= 4.5) ? 'AA' : '';\r
-       },\r
-\r
-       dark: function () {\r
-               // YIQ equation from http://24ways.org/2010/calculating-color-contrast\r
-               var rgb = this.values.rgb;\r
-               var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000;\r
-               return yiq < 128;\r
-       },\r
-\r
-       light: function () {\r
-               return !this.dark();\r
-       },\r
-\r
-       negate: function () {\r
-               var rgb = [];\r
-               for (var i = 0; i < 3; i++) {\r
-                       rgb[i] = 255 - this.values.rgb[i];\r
+       function getHsla(string) {\r
+               if (!string) {\r
+                       return;\r
                }\r
-               this.setValues('rgb', rgb);\r
-               return this;\r
-       },\r
-\r
-       lighten: function (ratio) {\r
-               var hsl = this.values.hsl;\r
-               hsl[2] += hsl[2] * ratio;\r
-               this.setValues('hsl', hsl);\r
-               return this;\r
-       },\r
-\r
-       darken: function (ratio) {\r
-               var hsl = this.values.hsl;\r
-               hsl[2] -= hsl[2] * ratio;\r
-               this.setValues('hsl', hsl);\r
-               return this;\r
-       },\r
-\r
-       saturate: function (ratio) {\r
-               var hsl = this.values.hsl;\r
-               hsl[1] += hsl[1] * ratio;\r
-               this.setValues('hsl', hsl);\r
-               return this;\r
-       },\r
+               var hsl = /^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/;\r
+               var match = string.match(hsl);\r
+               if (match) {\r
+                       var alpha = parseFloat(match[4]);\r
+                       var h = scale(parseInt(match[1]), 0, 360),\r
+                               s = scale(parseFloat(match[2]), 0, 100),\r
+                               l = scale(parseFloat(match[3]), 0, 100),\r
+                               a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);\r
+                       return [h, s, l, a];\r
+               }\r
+       }\r
 \r
-       desaturate: function (ratio) {\r
-               var hsl = this.values.hsl;\r
-               hsl[1] -= hsl[1] * ratio;\r
-               this.setValues('hsl', hsl);\r
-               return this;\r
-       },\r
+       function getHwb(string) {\r
+               if (!string) {\r
+                       return;\r
+               }\r
+               var hwb = /^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/;\r
+               var match = string.match(hwb);\r
+               if (match) {\r
+                       var alpha = parseFloat(match[4]);\r
+                       var h = scale(parseInt(match[1]), 0, 360),\r
+                               w = scale(parseFloat(match[2]), 0, 100),\r
+                               b = scale(parseFloat(match[3]), 0, 100),\r
+                               a = scale(isNaN(alpha) ? 1 : alpha, 0, 1);\r
+                       return [h, w, b, a];\r
+               }\r
+       }\r
 \r
-       whiten: function (ratio) {\r
-               var hwb = this.values.hwb;\r
-               hwb[1] += hwb[1] * ratio;\r
-               this.setValues('hwb', hwb);\r
-               return this;\r
-       },\r
+       function getRgb(string) {\r
+               var rgba = getRgba(string);\r
+               return rgba && rgba.slice(0, 3);\r
+       }\r
 \r
-       blacken: function (ratio) {\r
-               var hwb = this.values.hwb;\r
-               hwb[2] += hwb[2] * ratio;\r
-               this.setValues('hwb', hwb);\r
-               return this;\r
-       },\r
+       function getHsl(string) {\r
+               var hsla = getHsla(string);\r
+               return hsla && hsla.slice(0, 3);\r
+       }\r
 \r
-       greyscale: function () {\r
-               var rgb = this.values.rgb;\r
-               // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale\r
-               var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11;\r
-               this.setValues('rgb', [val, val, val]);\r
-               return this;\r
-       },\r
+       function getAlpha(string) {\r
+               var vals = getRgba(string);\r
+               if (vals) {\r
+                       return vals[3];\r
+               }\r
+               else if (vals = getHsla(string)) {\r
+                       return vals[3];\r
+               }\r
+               else if (vals = getHwb(string)) {\r
+                       return vals[3];\r
+               }\r
+       }\r
 \r
-       clearer: function (ratio) {\r
-               var alpha = this.values.alpha;\r
-               this.setValues('alpha', alpha - (alpha * ratio));\r
-               return this;\r
-       },\r
+// generators\r
+       function hexString(rgb) {\r
+               return "#" + hexDouble(rgb[0]) + hexDouble(rgb[1])\r
+                       + hexDouble(rgb[2]);\r
+       }\r
 \r
-       opaquer: function (ratio) {\r
-               var alpha = this.values.alpha;\r
-               this.setValues('alpha', alpha + (alpha * ratio));\r
-               return this;\r
-       },\r
+       function rgbString(rgba, alpha) {\r
+               if (alpha < 1 || (rgba[3] && rgba[3] < 1)) {\r
+                       return rgbaString(rgba, alpha);\r
+               }\r
+               return "rgb(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ")";\r
+       }\r
 \r
-       rotate: function (degrees) {\r
-               var hsl = this.values.hsl;\r
-               var hue = (hsl[0] + degrees) % 360;\r
-               hsl[0] = hue < 0 ? 360 + hue : hue;\r
-               this.setValues('hsl', hsl);\r
-               return this;\r
-       },\r
+       function rgbaString(rgba, alpha) {\r
+               if (alpha === undefined) {\r
+                       alpha = (rgba[3] !== undefined ? rgba[3] : 1);\r
+               }\r
+               return "rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2]\r
+                       + ", " + alpha + ")";\r
+       }\r
 \r
-       /**\r
-        * Ported from sass implementation in C\r
-        * https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209\r
-        */\r
-       mix: function (mixinColor, weight) {\r
-               var color1 = this;\r
-               var color2 = mixinColor;\r
-               var p = weight === undefined ? 0.5 : weight;\r
-\r
-               var w = 2 * p - 1;\r
-               var a = color1.alpha() - color2.alpha();\r
-\r
-               var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0;\r
-               var w2 = 1 - w1;\r
-\r
-               return this\r
-                       .rgb(\r
-                               w1 * color1.red() + w2 * color2.red(),\r
-                               w1 * color1.green() + w2 * color2.green(),\r
-                               w1 * color1.blue() + w2 * color2.blue()\r
-                       )\r
-                       .alpha(color1.alpha() * p + color2.alpha() * (1 - p));\r
-       },\r
-\r
-       toJSON: function () {\r
-               return this.rgb();\r
-       },\r
-\r
-       clone: function () {\r
-               // NOTE(SB): using node-clone creates a dependency to Buffer when using browserify,\r
-               // making the final build way to big to embed in Chart.js. So let's do it manually,\r
-               // assuming that values to clone are 1 dimension arrays containing only numbers,\r
-               // except 'alpha' which is a number.\r
-               var result = new Color();\r
-               var source = this.values;\r
-               var target = result.values;\r
-               var value, type;\r
-\r
-               for (var prop in source) {\r
-                       if (source.hasOwnProperty(prop)) {\r
-                               value = source[prop];\r
-                               type = ({}).toString.call(value);\r
-                               if (type === '[object Array]') {\r
-                                       target[prop] = value.slice(0);\r
-                               } else if (type === '[object Number]') {\r
-                                       target[prop] = value;\r
-                               } else {\r
-                                       console.error('unexpected color value:', value);\r
-                               }\r
-                       }\r
+       function percentString(rgba, alpha) {\r
+               if (alpha < 1 || (rgba[3] && rgba[3] < 1)) {\r
+                       return percentaString(rgba, alpha);\r
                }\r
+               var r = Math.round(rgba[0]/255 * 100),\r
+                       g = Math.round(rgba[1]/255 * 100),\r
+                       b = Math.round(rgba[2]/255 * 100);\r
 \r
-               return result;\r
-       }\r
-};\r
-\r
-Color.prototype.spaces = {\r
-       rgb: ['red', 'green', 'blue'],\r
-       hsl: ['hue', 'saturation', 'lightness'],\r
-       hsv: ['hue', 'saturation', 'value'],\r
-       hwb: ['hue', 'whiteness', 'blackness'],\r
-       cmyk: ['cyan', 'magenta', 'yellow', 'black']\r
-};\r
-\r
-Color.prototype.maxes = {\r
-       rgb: [255, 255, 255],\r
-       hsl: [360, 100, 100],\r
-       hsv: [360, 100, 100],\r
-       hwb: [360, 100, 100],\r
-       cmyk: [100, 100, 100, 100]\r
-};\r
-\r
-Color.prototype.getValues = function (space) {\r
-       var values = this.values;\r
-       var vals = {};\r
-\r
-       for (var i = 0; i < space.length; i++) {\r
-               vals[space.charAt(i)] = values[space][i];\r
+               return "rgb(" + r + "%, " + g + "%, " + b + "%)";\r
        }\r
 \r
-       if (values.alpha !== 1) {\r
-               vals.a = values.alpha;\r
+       function percentaString(rgba, alpha) {\r
+               var r = Math.round(rgba[0]/255 * 100),\r
+                       g = Math.round(rgba[1]/255 * 100),\r
+                       b = Math.round(rgba[2]/255 * 100);\r
+               return "rgba(" + r + "%, " + g + "%, " + b + "%, " + (alpha || rgba[3] || 1) + ")";\r
        }\r
 \r
-       // {r: 255, g: 255, b: 255, a: 0.4}\r
-       return vals;\r
-};\r
-\r
-Color.prototype.setValues = function (space, vals) {\r
-       var values = this.values;\r
-       var spaces = this.spaces;\r
-       var maxes = this.maxes;\r
-       var alpha = 1;\r
-       var i;\r
-\r
-       if (space === 'alpha') {\r
-               alpha = vals;\r
-       } else if (vals.length) {\r
-               // [10, 10, 10]\r
-               values[space] = vals.slice(0, space.length);\r
-               alpha = vals[space.length];\r
-       } else if (vals[space.charAt(0)] !== undefined) {\r
-               // {r: 10, g: 10, b: 10}\r
-               for (i = 0; i < space.length; i++) {\r
-                       values[space][i] = vals[space.charAt(i)];\r
+       function hslString(hsla, alpha) {\r
+               if (alpha < 1 || (hsla[3] && hsla[3] < 1)) {\r
+                       return hslaString(hsla, alpha);\r
                }\r
+               return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)";\r
+       }\r
 \r
-               alpha = vals.a;\r
-       } else if (vals[spaces[space][0]] !== undefined) {\r
-               // {red: 10, green: 10, blue: 10}\r
-               var chans = spaces[space];\r
+       function hslaString(hsla, alpha) {\r
+               if (alpha === undefined) {\r
+                       alpha = (hsla[3] !== undefined ? hsla[3] : 1);\r
+               }\r
+               return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, "\r
+                       + alpha + ")";\r
+       }\r
 \r
-               for (i = 0; i < space.length; i++) {\r
-                       values[space][i] = vals[chans[i]];\r
+// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax\r
+// (hwb have alpha optional & 1 is default value)\r
+       function hwbString(hwb, alpha) {\r
+               if (alpha === undefined) {\r
+                       alpha = (hwb[3] !== undefined ? hwb[3] : 1);\r
                }\r
+               return "hwb(" + hwb[0] + ", " + hwb[1] + "%, " + hwb[2] + "%"\r
+                       + (alpha !== undefined && alpha !== 1 ? ", " + alpha : "") + ")";\r
+       }\r
 \r
-               alpha = vals.alpha;\r
+       function keyword(rgb) {\r
+               return reverseNames[rgb.slice(0, 3)];\r
        }\r
 \r
-       values.alpha = Math.max(0, Math.min(1, (alpha === undefined ? values.alpha : alpha)));\r
+// helpers\r
+       function scale(num, min, max) {\r
+               return Math.min(Math.max(min, num), max);\r
+       }\r
 \r
-       if (space === 'alpha') {\r
-               return false;\r
+       function hexDouble(num) {\r
+               var str = num.toString(16).toUpperCase();\r
+               return (str.length < 2) ? "0" + str : str;\r
        }\r
 \r
-       var capped;\r
 \r
-       // cap values of the space prior converting all values\r
-       for (i = 0; i < space.length; i++) {\r
-               capped = Math.max(0, Math.min(maxes[space][i], values[space][i]));\r
-               values[space][i] = Math.round(capped);\r
+//create a list of reverse color names\r
+       var reverseNames = {};\r
+       for (var name in colorNames) {\r
+               reverseNames[colorNames[name]] = name;\r
        }\r
 \r
-       // convert to all the other color spaces\r
-       for (var sname in spaces) {\r
-               if (sname !== space) {\r
-                       values[sname] = convert[space][sname](values[space]);\r
+},{"6":6}],3:[function(require,module,exports){\r
+       /* MIT license */\r
+       var convert = require(5);\r
+       var string = require(2);\r
+\r
+       var Color = function (obj) {\r
+               if (obj instanceof Color) {\r
+                       return obj;\r
+               }\r
+               if (!(this instanceof Color)) {\r
+                       return new Color(obj);\r
                }\r
-       }\r
 \r
-       return true;\r
-};\r
+               this.values = {\r
+                       rgb: [0, 0, 0],\r
+                       hsl: [0, 0, 0],\r
+                       hsv: [0, 0, 0],\r
+                       hwb: [0, 0, 0],\r
+                       cmyk: [0, 0, 0, 0],\r
+                       alpha: 1\r
+               };\r
 \r
-Color.prototype.setSpace = function (space, args) {\r
-       var vals = args[0];\r
+               // parse Color() argument\r
+               var vals;\r
+               if (typeof obj === 'string') {\r
+                       vals = string.getRgba(obj);\r
+                       if (vals) {\r
+                               this.setValues('rgb', vals);\r
+                       } else if (vals = string.getHsla(obj)) {\r
+                               this.setValues('hsl', vals);\r
+                       } else if (vals = string.getHwb(obj)) {\r
+                               this.setValues('hwb', vals);\r
+                       } else {\r
+                               throw new Error('Unable to parse color from string "' + obj + '"');\r
+                       }\r
+               } else if (typeof obj === 'object') {\r
+                       vals = obj;\r
+                       if (vals.r !== undefined || vals.red !== undefined) {\r
+                               this.setValues('rgb', vals);\r
+                       } else if (vals.l !== undefined || vals.lightness !== undefined) {\r
+                               this.setValues('hsl', vals);\r
+                       } else if (vals.v !== undefined || vals.value !== undefined) {\r
+                               this.setValues('hsv', vals);\r
+                       } else if (vals.w !== undefined || vals.whiteness !== undefined) {\r
+                               this.setValues('hwb', vals);\r
+                       } else if (vals.c !== undefined || vals.cyan !== undefined) {\r
+                               this.setValues('cmyk', vals);\r
+                       } else {\r
+                               throw new Error('Unable to parse color from object ' + JSON.stringify(obj));\r
+                       }\r
+               }\r
+       };\r
 \r
-       if (vals === undefined) {\r
-               // color.rgb()\r
-               return this.getValues(space);\r
-       }\r
+       Color.prototype = {\r
+               rgb: function () {\r
+                       return this.setSpace('rgb', arguments);\r
+               },\r
+               hsl: function () {\r
+                       return this.setSpace('hsl', arguments);\r
+               },\r
+               hsv: function () {\r
+                       return this.setSpace('hsv', arguments);\r
+               },\r
+               hwb: function () {\r
+                       return this.setSpace('hwb', arguments);\r
+               },\r
+               cmyk: function () {\r
+                       return this.setSpace('cmyk', arguments);\r
+               },\r
 \r
-       // color.rgb(10, 10, 10)\r
-       if (typeof vals === 'number') {\r
-               vals = Array.prototype.slice.call(args);\r
-       }\r
+               rgbArray: function () {\r
+                       return this.values.rgb;\r
+               },\r
+               hslArray: function () {\r
+                       return this.values.hsl;\r
+               },\r
+               hsvArray: function () {\r
+                       return this.values.hsv;\r
+               },\r
+               hwbArray: function () {\r
+                       var values = this.values;\r
+                       if (values.alpha !== 1) {\r
+                               return values.hwb.concat([values.alpha]);\r
+                       }\r
+                       return values.hwb;\r
+               },\r
+               cmykArray: function () {\r
+                       return this.values.cmyk;\r
+               },\r
+               rgbaArray: function () {\r
+                       var values = this.values;\r
+                       return values.rgb.concat([values.alpha]);\r
+               },\r
+               hslaArray: function () {\r
+                       var values = this.values;\r
+                       return values.hsl.concat([values.alpha]);\r
+               },\r
+               alpha: function (val) {\r
+                       if (val === undefined) {\r
+                               return this.values.alpha;\r
+                       }\r
+                       this.setValues('alpha', val);\r
+                       return this;\r
+               },\r
 \r
-       this.setValues(space, vals);\r
-       return this;\r
-};\r
-\r
-Color.prototype.setChannel = function (space, index, val) {\r
-       var svalues = this.values[space];\r
-       if (val === undefined) {\r
-               // color.red()\r
-               return svalues[index];\r
-       } else if (val === svalues[index]) {\r
-               // color.red(color.red())\r
-               return this;\r
-       }\r
+               red: function (val) {\r
+                       return this.setChannel('rgb', 0, val);\r
+               },\r
+               green: function (val) {\r
+                       return this.setChannel('rgb', 1, val);\r
+               },\r
+               blue: function (val) {\r
+                       return this.setChannel('rgb', 2, val);\r
+               },\r
+               hue: function (val) {\r
+                       if (val) {\r
+                               val %= 360;\r
+                               val = val < 0 ? 360 + val : val;\r
+                       }\r
+                       return this.setChannel('hsl', 0, val);\r
+               },\r
+               saturation: function (val) {\r
+                       return this.setChannel('hsl', 1, val);\r
+               },\r
+               lightness: function (val) {\r
+                       return this.setChannel('hsl', 2, val);\r
+               },\r
+               saturationv: function (val) {\r
+                       return this.setChannel('hsv', 1, val);\r
+               },\r
+               whiteness: function (val) {\r
+                       return this.setChannel('hwb', 1, val);\r
+               },\r
+               blackness: function (val) {\r
+                       return this.setChannel('hwb', 2, val);\r
+               },\r
+               value: function (val) {\r
+                       return this.setChannel('hsv', 2, val);\r
+               },\r
+               cyan: function (val) {\r
+                       return this.setChannel('cmyk', 0, val);\r
+               },\r
+               magenta: function (val) {\r
+                       return this.setChannel('cmyk', 1, val);\r
+               },\r
+               yellow: function (val) {\r
+                       return this.setChannel('cmyk', 2, val);\r
+               },\r
+               black: function (val) {\r
+                       return this.setChannel('cmyk', 3, val);\r
+               },\r
 \r
-       // color.red(100)\r
-       svalues[index] = val;\r
-       this.setValues(space, svalues);\r
+               hexString: function () {\r
+                       return string.hexString(this.values.rgb);\r
+               },\r
+               rgbString: function () {\r
+                       return string.rgbString(this.values.rgb, this.values.alpha);\r
+               },\r
+               rgbaString: function () {\r
+                       return string.rgbaString(this.values.rgb, this.values.alpha);\r
+               },\r
+               percentString: function () {\r
+                       return string.percentString(this.values.rgb, this.values.alpha);\r
+               },\r
+               hslString: function () {\r
+                       return string.hslString(this.values.hsl, this.values.alpha);\r
+               },\r
+               hslaString: function () {\r
+                       return string.hslaString(this.values.hsl, this.values.alpha);\r
+               },\r
+               hwbString: function () {\r
+                       return string.hwbString(this.values.hwb, this.values.alpha);\r
+               },\r
+               keyword: function () {\r
+                       return string.keyword(this.values.rgb, this.values.alpha);\r
+               },\r
 \r
-       return this;\r
-};\r
+               rgbNumber: function () {\r
+                       var rgb = this.values.rgb;\r
+                       return (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];\r
+               },\r
 \r
-if (typeof window !== 'undefined') {\r
-       window.Color = Color;\r
-}\r
+               luminosity: function () {\r
+                       // http://www.w3.org/TR/WCAG20/#relativeluminancedef\r
+                       var rgb = this.values.rgb;\r
+                       var lum = [];\r
+                       for (var i = 0; i < rgb.length; i++) {\r
+                               var chan = rgb[i] / 255;\r
+                               lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4);\r
+                       }\r
+                       return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2];\r
+               },\r
 \r
-module.exports = Color;\r
+               contrast: function (color2) {\r
+                       // http://www.w3.org/TR/WCAG20/#contrast-ratiodef\r
+                       var lum1 = this.luminosity();\r
+                       var lum2 = color2.luminosity();\r
+                       if (lum1 > lum2) {\r
+                               return (lum1 + 0.05) / (lum2 + 0.05);\r
+                       }\r
+                       return (lum2 + 0.05) / (lum1 + 0.05);\r
+               },\r
 \r
-},{"2":2,"5":5}],4:[function(require,module,exports){\r
-/* MIT license */\r
-\r
-module.exports = {\r
-  rgb2hsl: rgb2hsl,\r
-  rgb2hsv: rgb2hsv,\r
-  rgb2hwb: rgb2hwb,\r
-  rgb2cmyk: rgb2cmyk,\r
-  rgb2keyword: rgb2keyword,\r
-  rgb2xyz: rgb2xyz,\r
-  rgb2lab: rgb2lab,\r
-  rgb2lch: rgb2lch,\r
-\r
-  hsl2rgb: hsl2rgb,\r
-  hsl2hsv: hsl2hsv,\r
-  hsl2hwb: hsl2hwb,\r
-  hsl2cmyk: hsl2cmyk,\r
-  hsl2keyword: hsl2keyword,\r
-\r
-  hsv2rgb: hsv2rgb,\r
-  hsv2hsl: hsv2hsl,\r
-  hsv2hwb: hsv2hwb,\r
-  hsv2cmyk: hsv2cmyk,\r
-  hsv2keyword: hsv2keyword,\r
-\r
-  hwb2rgb: hwb2rgb,\r
-  hwb2hsl: hwb2hsl,\r
-  hwb2hsv: hwb2hsv,\r
-  hwb2cmyk: hwb2cmyk,\r
-  hwb2keyword: hwb2keyword,\r
-\r
-  cmyk2rgb: cmyk2rgb,\r
-  cmyk2hsl: cmyk2hsl,\r
-  cmyk2hsv: cmyk2hsv,\r
-  cmyk2hwb: cmyk2hwb,\r
-  cmyk2keyword: cmyk2keyword,\r
-\r
-  keyword2rgb: keyword2rgb,\r
-  keyword2hsl: keyword2hsl,\r
-  keyword2hsv: keyword2hsv,\r
-  keyword2hwb: keyword2hwb,\r
-  keyword2cmyk: keyword2cmyk,\r
-  keyword2lab: keyword2lab,\r
-  keyword2xyz: keyword2xyz,\r
-\r
-  xyz2rgb: xyz2rgb,\r
-  xyz2lab: xyz2lab,\r
-  xyz2lch: xyz2lch,\r
-\r
-  lab2xyz: lab2xyz,\r
-  lab2rgb: lab2rgb,\r
-  lab2lch: lab2lch,\r
-\r
-  lch2lab: lch2lab,\r
-  lch2xyz: lch2xyz,\r
-  lch2rgb: lch2rgb\r
-}\r
-\r
-\r
-function rgb2hsl(rgb) {\r
-  var r = rgb[0]/255,\r
-      g = rgb[1]/255,\r
-      b = rgb[2]/255,\r
-      min = Math.min(r, g, b),\r
-      max = Math.max(r, g, b),\r
-      delta = max - min,\r
-      h, s, l;\r
-\r
-  if (max == min)\r
-    h = 0;\r
-  else if (r == max)\r
-    h = (g - b) / delta;\r
-  else if (g == max)\r
-    h = 2 + (b - r) / delta;\r
-  else if (b == max)\r
-    h = 4 + (r - g)/ delta;\r
-\r
-  h = Math.min(h * 60, 360);\r
-\r
-  if (h < 0)\r
-    h += 360;\r
-\r
-  l = (min + max) / 2;\r
-\r
-  if (max == min)\r
-    s = 0;\r
-  else if (l <= 0.5)\r
-    s = delta / (max + min);\r
-  else\r
-    s = delta / (2 - max - min);\r
-\r
-  return [h, s * 100, l * 100];\r
-}\r
-\r
-function rgb2hsv(rgb) {\r
-  var r = rgb[0],\r
-      g = rgb[1],\r
-      b = rgb[2],\r
-      min = Math.min(r, g, b),\r
-      max = Math.max(r, g, b),\r
-      delta = max - min,\r
-      h, s, v;\r
-\r
-  if (max == 0)\r
-    s = 0;\r
-  else\r
-    s = (delta/max * 1000)/10;\r
-\r
-  if (max == min)\r
-    h = 0;\r
-  else if (r == max)\r
-    h = (g - b) / delta;\r
-  else if (g == max)\r
-    h = 2 + (b - r) / delta;\r
-  else if (b == max)\r
-    h = 4 + (r - g) / delta;\r
-\r
-  h = Math.min(h * 60, 360);\r
-\r
-  if (h < 0)\r
-    h += 360;\r
-\r
-  v = ((max / 255) * 1000) / 10;\r
-\r
-  return [h, s, v];\r
-}\r
-\r
-function rgb2hwb(rgb) {\r
-  var r = rgb[0],\r
-      g = rgb[1],\r
-      b = rgb[2],\r
-      h = rgb2hsl(rgb)[0],\r
-      w = 1/255 * Math.min(r, Math.min(g, b)),\r
-      b = 1 - 1/255 * Math.max(r, Math.max(g, b));\r
-\r
-  return [h, w * 100, b * 100];\r
-}\r
-\r
-function rgb2cmyk(rgb) {\r
-  var r = rgb[0] / 255,\r
-      g = rgb[1] / 255,\r
-      b = rgb[2] / 255,\r
-      c, m, y, k;\r
-\r
-  k = Math.min(1 - r, 1 - g, 1 - b);\r
-  c = (1 - r - k) / (1 - k) || 0;\r
-  m = (1 - g - k) / (1 - k) || 0;\r
-  y = (1 - b - k) / (1 - k) || 0;\r
-  return [c * 100, m * 100, y * 100, k * 100];\r
-}\r
-\r
-function rgb2keyword(rgb) {\r
-  return reverseKeywords[JSON.stringify(rgb)];\r
-}\r
-\r
-function rgb2xyz(rgb) {\r
-  var r = rgb[0] / 255,\r
-      g = rgb[1] / 255,\r
-      b = rgb[2] / 255;\r
-\r
-  // assume sRGB\r
-  r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92);\r
-  g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92);\r
-  b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92);\r
-\r
-  var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);\r
-  var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);\r
-  var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);\r
-\r
-  return [x * 100, y *100, z * 100];\r
-}\r
-\r
-function rgb2lab(rgb) {\r
-  var xyz = rgb2xyz(rgb),\r
-        x = xyz[0],\r
-        y = xyz[1],\r
-        z = xyz[2],\r
-        l, a, b;\r
-\r
-  x /= 95.047;\r
-  y /= 100;\r
-  z /= 108.883;\r
-\r
-  x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);\r
-  y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);\r
-  z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);\r
-\r
-  l = (116 * y) - 16;\r
-  a = 500 * (x - y);\r
-  b = 200 * (y - z);\r
-\r
-  return [l, a, b];\r
-}\r
-\r
-function rgb2lch(args) {\r
-  return lab2lch(rgb2lab(args));\r
-}\r
-\r
-function hsl2rgb(hsl) {\r
-  var h = hsl[0] / 360,\r
-      s = hsl[1] / 100,\r
-      l = hsl[2] / 100,\r
-      t1, t2, t3, rgb, val;\r
-\r
-  if (s == 0) {\r
-    val = l * 255;\r
-    return [val, val, val];\r
-  }\r
-\r
-  if (l < 0.5)\r
-    t2 = l * (1 + s);\r
-  else\r
-    t2 = l + s - l * s;\r
-  t1 = 2 * l - t2;\r
-\r
-  rgb = [0, 0, 0];\r
-  for (var i = 0; i < 3; i++) {\r
-    t3 = h + 1 / 3 * - (i - 1);\r
-    t3 < 0 && t3++;\r
-    t3 > 1 && t3--;\r
-\r
-    if (6 * t3 < 1)\r
-      val = t1 + (t2 - t1) * 6 * t3;\r
-    else if (2 * t3 < 1)\r
-      val = t2;\r
-    else if (3 * t3 < 2)\r
-      val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;\r
-    else\r
-      val = t1;\r
-\r
-    rgb[i] = val * 255;\r
-  }\r
-\r
-  return rgb;\r
-}\r
-\r
-function hsl2hsv(hsl) {\r
-  var h = hsl[0],\r
-      s = hsl[1] / 100,\r
-      l = hsl[2] / 100,\r
-      sv, v;\r
-\r
-  if(l === 0) {\r
-      // no need to do calc on black\r
-      // also avoids divide by 0 error\r
-      return [0, 0, 0];\r
-  }\r
-\r
-  l *= 2;\r
-  s *= (l <= 1) ? l : 2 - l;\r
-  v = (l + s) / 2;\r
-  sv = (2 * s) / (l + s);\r
-  return [h, sv * 100, v * 100];\r
-}\r
-\r
-function hsl2hwb(args) {\r
-  return rgb2hwb(hsl2rgb(args));\r
-}\r
-\r
-function hsl2cmyk(args) {\r
-  return rgb2cmyk(hsl2rgb(args));\r
-}\r
-\r
-function hsl2keyword(args) {\r
-  return rgb2keyword(hsl2rgb(args));\r
-}\r
-\r
-\r
-function hsv2rgb(hsv) {\r
-  var h = hsv[0] / 60,\r
-      s = hsv[1] / 100,\r
-      v = hsv[2] / 100,\r
-      hi = Math.floor(h) % 6;\r
-\r
-  var f = h - Math.floor(h),\r
-      p = 255 * v * (1 - s),\r
-      q = 255 * v * (1 - (s * f)),\r
-      t = 255 * v * (1 - (s * (1 - f))),\r
-      v = 255 * v;\r
-\r
-  switch(hi) {\r
-    case 0:\r
-      return [v, t, p];\r
-    case 1:\r
-      return [q, v, p];\r
-    case 2:\r
-      return [p, v, t];\r
-    case 3:\r
-      return [p, q, v];\r
-    case 4:\r
-      return [t, p, v];\r
-    case 5:\r
-      return [v, p, q];\r
-  }\r
-}\r
-\r
-function hsv2hsl(hsv) {\r
-  var h = hsv[0],\r
-      s = hsv[1] / 100,\r
-      v = hsv[2] / 100,\r
-      sl, l;\r
-\r
-  l = (2 - s) * v;\r
-  sl = s * v;\r
-  sl /= (l <= 1) ? l : 2 - l;\r
-  sl = sl || 0;\r
-  l /= 2;\r
-  return [h, sl * 100, l * 100];\r
-}\r
-\r
-function hsv2hwb(args) {\r
-  return rgb2hwb(hsv2rgb(args))\r
-}\r
-\r
-function hsv2cmyk(args) {\r
-  return rgb2cmyk(hsv2rgb(args));\r
-}\r
-\r
-function hsv2keyword(args) {\r
-  return rgb2keyword(hsv2rgb(args));\r
-}\r
+               level: function (color2) {\r
+                       var contrastRatio = this.contrast(color2);\r
+                       if (contrastRatio >= 7.1) {\r
+                               return 'AAA';\r
+                       }\r
 \r
-// http://dev.w3.org/csswg/css-color/#hwb-to-rgb\r
-function hwb2rgb(hwb) {\r
-  var h = hwb[0] / 360,\r
-      wh = hwb[1] / 100,\r
-      bl = hwb[2] / 100,\r
-      ratio = wh + bl,\r
-      i, v, f, n;\r
-\r
-  // wh + bl cant be > 1\r
-  if (ratio > 1) {\r
-    wh /= ratio;\r
-    bl /= ratio;\r
-  }\r
-\r
-  i = Math.floor(6 * h);\r
-  v = 1 - bl;\r
-  f = 6 * h - i;\r
-  if ((i & 0x01) != 0) {\r
-    f = 1 - f;\r
-  }\r
-  n = wh + f * (v - wh);  // linear interpolation\r
-\r
-  switch (i) {\r
-    default:\r
-    case 6:\r
-    case 0: r = v; g = n; b = wh; break;\r
-    case 1: r = n; g = v; b = wh; break;\r
-    case 2: r = wh; g = v; b = n; break;\r
-    case 3: r = wh; g = n; b = v; break;\r
-    case 4: r = n; g = wh; b = v; break;\r
-    case 5: r = v; g = wh; b = n; break;\r
-  }\r
-\r
-  return [r * 255, g * 255, b * 255];\r
-}\r
-\r
-function hwb2hsl(args) {\r
-  return rgb2hsl(hwb2rgb(args));\r
-}\r
-\r
-function hwb2hsv(args) {\r
-  return rgb2hsv(hwb2rgb(args));\r
-}\r
-\r
-function hwb2cmyk(args) {\r
-  return rgb2cmyk(hwb2rgb(args));\r
-}\r
-\r
-function hwb2keyword(args) {\r
-  return rgb2keyword(hwb2rgb(args));\r
-}\r
-\r
-function cmyk2rgb(cmyk) {\r
-  var c = cmyk[0] / 100,\r
-      m = cmyk[1] / 100,\r
-      y = cmyk[2] / 100,\r
-      k = cmyk[3] / 100,\r
-      r, g, b;\r
-\r
-  r = 1 - Math.min(1, c * (1 - k) + k);\r
-  g = 1 - Math.min(1, m * (1 - k) + k);\r
-  b = 1 - Math.min(1, y * (1 - k) + k);\r
-  return [r * 255, g * 255, b * 255];\r
-}\r
-\r
-function cmyk2hsl(args) {\r
-  return rgb2hsl(cmyk2rgb(args));\r
-}\r
-\r
-function cmyk2hsv(args) {\r
-  return rgb2hsv(cmyk2rgb(args));\r
-}\r
-\r
-function cmyk2hwb(args) {\r
-  return rgb2hwb(cmyk2rgb(args));\r
-}\r
-\r
-function cmyk2keyword(args) {\r
-  return rgb2keyword(cmyk2rgb(args));\r
-}\r
-\r
-\r
-function xyz2rgb(xyz) {\r
-  var x = xyz[0] / 100,\r
-      y = xyz[1] / 100,\r
-      z = xyz[2] / 100,\r
-      r, g, b;\r
-\r
-  r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);\r
-  g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);\r
-  b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);\r
-\r
-  // assume sRGB\r
-  r = r > 0.0031308 ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055)\r
-    : r = (r * 12.92);\r
-\r
-  g = g > 0.0031308 ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055)\r
-    : g = (g * 12.92);\r
-\r
-  b = b > 0.0031308 ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055)\r
-    : b = (b * 12.92);\r
-\r
-  r = Math.min(Math.max(0, r), 1);\r
-  g = Math.min(Math.max(0, g), 1);\r
-  b = Math.min(Math.max(0, b), 1);\r
-\r
-  return [r * 255, g * 255, b * 255];\r
-}\r
-\r
-function xyz2lab(xyz) {\r
-  var x = xyz[0],\r
-      y = xyz[1],\r
-      z = xyz[2],\r
-      l, a, b;\r
-\r
-  x /= 95.047;\r
-  y /= 100;\r
-  z /= 108.883;\r
-\r
-  x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);\r
-  y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);\r
-  z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);\r
-\r
-  l = (116 * y) - 16;\r
-  a = 500 * (x - y);\r
-  b = 200 * (y - z);\r
-\r
-  return [l, a, b];\r
-}\r
-\r
-function xyz2lch(args) {\r
-  return lab2lch(xyz2lab(args));\r
-}\r
-\r
-function lab2xyz(lab) {\r
-  var l = lab[0],\r
-      a = lab[1],\r
-      b = lab[2],\r
-      x, y, z, y2;\r
-\r
-  if (l <= 8) {\r
-    y = (l * 100) / 903.3;\r
-    y2 = (7.787 * (y / 100)) + (16 / 116);\r
-  } else {\r
-    y = 100 * Math.pow((l + 16) / 116, 3);\r
-    y2 = Math.pow(y / 100, 1/3);\r
-  }\r
-\r
-  x = x / 95.047 <= 0.008856 ? x = (95.047 * ((a / 500) + y2 - (16 / 116))) / 7.787 : 95.047 * Math.pow((a / 500) + y2, 3);\r
-\r
-  z = z / 108.883 <= 0.008859 ? z = (108.883 * (y2 - (b / 200) - (16 / 116))) / 7.787 : 108.883 * Math.pow(y2 - (b / 200), 3);\r
-\r
-  return [x, y, z];\r
-}\r
-\r
-function lab2lch(lab) {\r
-  var l = lab[0],\r
-      a = lab[1],\r
-      b = lab[2],\r
-      hr, h, c;\r
-\r
-  hr = Math.atan2(b, a);\r
-  h = hr * 360 / 2 / Math.PI;\r
-  if (h < 0) {\r
-    h += 360;\r
-  }\r
-  c = Math.sqrt(a * a + b * b);\r
-  return [l, c, h];\r
-}\r
-\r
-function lab2rgb(args) {\r
-  return xyz2rgb(lab2xyz(args));\r
-}\r
-\r
-function lch2lab(lch) {\r
-  var l = lch[0],\r
-      c = lch[1],\r
-      h = lch[2],\r
-      a, b, hr;\r
-\r
-  hr = h / 360 * 2 * Math.PI;\r
-  a = c * Math.cos(hr);\r
-  b = c * Math.sin(hr);\r
-  return [l, a, b];\r
-}\r
-\r
-function lch2xyz(args) {\r
-  return lab2xyz(lch2lab(args));\r
-}\r
-\r
-function lch2rgb(args) {\r
-  return lab2rgb(lch2lab(args));\r
-}\r
-\r
-function keyword2rgb(keyword) {\r
-  return cssKeywords[keyword];\r
-}\r
-\r
-function keyword2hsl(args) {\r
-  return rgb2hsl(keyword2rgb(args));\r
-}\r
-\r
-function keyword2hsv(args) {\r
-  return rgb2hsv(keyword2rgb(args));\r
-}\r
-\r
-function keyword2hwb(args) {\r
-  return rgb2hwb(keyword2rgb(args));\r
-}\r
-\r
-function keyword2cmyk(args) {\r
-  return rgb2cmyk(keyword2rgb(args));\r
-}\r
-\r
-function keyword2lab(args) {\r
-  return rgb2lab(keyword2rgb(args));\r
-}\r
-\r
-function keyword2xyz(args) {\r
-  return rgb2xyz(keyword2rgb(args));\r
-}\r
-\r
-var cssKeywords = {\r
-  aliceblue:  [240,248,255],\r
-  antiquewhite: [250,235,215],\r
-  aqua: [0,255,255],\r
-  aquamarine: [127,255,212],\r
-  azure:  [240,255,255],\r
-  beige:  [245,245,220],\r
-  bisque: [255,228,196],\r
-  black:  [0,0,0],\r
-  blanchedalmond: [255,235,205],\r
-  blue: [0,0,255],\r
-  blueviolet: [138,43,226],\r
-  brown:  [165,42,42],\r
-  burlywood:  [222,184,135],\r
-  cadetblue:  [95,158,160],\r
-  chartreuse: [127,255,0],\r
-  chocolate:  [210,105,30],\r
-  coral:  [255,127,80],\r
-  cornflowerblue: [100,149,237],\r
-  cornsilk: [255,248,220],\r
-  crimson:  [220,20,60],\r
-  cyan: [0,255,255],\r
-  darkblue: [0,0,139],\r
-  darkcyan: [0,139,139],\r
-  darkgoldenrod:  [184,134,11],\r
-  darkgray: [169,169,169],\r
-  darkgreen:  [0,100,0],\r
-  darkgrey: [169,169,169],\r
-  darkkhaki:  [189,183,107],\r
-  darkmagenta:  [139,0,139],\r
-  darkolivegreen: [85,107,47],\r
-  darkorange: [255,140,0],\r
-  darkorchid: [153,50,204],\r
-  darkred:  [139,0,0],\r
-  darksalmon: [233,150,122],\r
-  darkseagreen: [143,188,143],\r
-  darkslateblue:  [72,61,139],\r
-  darkslategray:  [47,79,79],\r
-  darkslategrey:  [47,79,79],\r
-  darkturquoise:  [0,206,209],\r
-  darkviolet: [148,0,211],\r
-  deeppink: [255,20,147],\r
-  deepskyblue:  [0,191,255],\r
-  dimgray:  [105,105,105],\r
-  dimgrey:  [105,105,105],\r
-  dodgerblue: [30,144,255],\r
-  firebrick:  [178,34,34],\r
-  floralwhite:  [255,250,240],\r
-  forestgreen:  [34,139,34],\r
-  fuchsia:  [255,0,255],\r
-  gainsboro:  [220,220,220],\r
-  ghostwhite: [248,248,255],\r
-  gold: [255,215,0],\r
-  goldenrod:  [218,165,32],\r
-  gray: [128,128,128],\r
-  green:  [0,128,0],\r
-  greenyellow:  [173,255,47],\r
-  grey: [128,128,128],\r
-  honeydew: [240,255,240],\r
-  hotpink:  [255,105,180],\r
-  indianred:  [205,92,92],\r
-  indigo: [75,0,130],\r
-  ivory:  [255,255,240],\r
-  khaki:  [240,230,140],\r
-  lavender: [230,230,250],\r
-  lavenderblush:  [255,240,245],\r
-  lawngreen:  [124,252,0],\r
-  lemonchiffon: [255,250,205],\r
-  lightblue:  [173,216,230],\r
-  lightcoral: [240,128,128],\r
-  lightcyan:  [224,255,255],\r
-  lightgoldenrodyellow: [250,250,210],\r
-  lightgray:  [211,211,211],\r
-  lightgreen: [144,238,144],\r
-  lightgrey:  [211,211,211],\r
-  lightpink:  [255,182,193],\r
-  lightsalmon:  [255,160,122],\r
-  lightseagreen:  [32,178,170],\r
-  lightskyblue: [135,206,250],\r
-  lightslategray: [119,136,153],\r
-  lightslategrey: [119,136,153],\r
-  lightsteelblue: [176,196,222],\r
-  lightyellow:  [255,255,224],\r
-  lime: [0,255,0],\r
-  limegreen:  [50,205,50],\r
-  linen:  [250,240,230],\r
-  magenta:  [255,0,255],\r
-  maroon: [128,0,0],\r
-  mediumaquamarine: [102,205,170],\r
-  mediumblue: [0,0,205],\r
-  mediumorchid: [186,85,211],\r
-  mediumpurple: [147,112,219],\r
-  mediumseagreen: [60,179,113],\r
-  mediumslateblue:  [123,104,238],\r
-  mediumspringgreen:  [0,250,154],\r
-  mediumturquoise:  [72,209,204],\r
-  mediumvioletred:  [199,21,133],\r
-  midnightblue: [25,25,112],\r
-  mintcream:  [245,255,250],\r
-  mistyrose:  [255,228,225],\r
-  moccasin: [255,228,181],\r
-  navajowhite:  [255,222,173],\r
-  navy: [0,0,128],\r
-  oldlace:  [253,245,230],\r
-  olive:  [128,128,0],\r
-  olivedrab:  [107,142,35],\r
-  orange: [255,165,0],\r
-  orangered:  [255,69,0],\r
-  orchid: [218,112,214],\r
-  palegoldenrod:  [238,232,170],\r
-  palegreen:  [152,251,152],\r
-  paleturquoise:  [175,238,238],\r
-  palevioletred:  [219,112,147],\r
-  papayawhip: [255,239,213],\r
-  peachpuff:  [255,218,185],\r
-  peru: [205,133,63],\r
-  pink: [255,192,203],\r
-  plum: [221,160,221],\r
-  powderblue: [176,224,230],\r
-  purple: [128,0,128],\r
-  rebeccapurple: [102, 51, 153],\r
-  red:  [255,0,0],\r
-  rosybrown:  [188,143,143],\r
-  royalblue:  [65,105,225],\r
-  saddlebrown:  [139,69,19],\r
-  salmon: [250,128,114],\r
-  sandybrown: [244,164,96],\r
-  seagreen: [46,139,87],\r
-  seashell: [255,245,238],\r
-  sienna: [160,82,45],\r
-  silver: [192,192,192],\r
-  skyblue:  [135,206,235],\r
-  slateblue:  [106,90,205],\r
-  slategray:  [112,128,144],\r
-  slategrey:  [112,128,144],\r
-  snow: [255,250,250],\r
-  springgreen:  [0,255,127],\r
-  steelblue:  [70,130,180],\r
-  tan:  [210,180,140],\r
-  teal: [0,128,128],\r
-  thistle:  [216,191,216],\r
-  tomato: [255,99,71],\r
-  turquoise:  [64,224,208],\r
-  violet: [238,130,238],\r
-  wheat:  [245,222,179],\r
-  white:  [255,255,255],\r
-  whitesmoke: [245,245,245],\r
-  yellow: [255,255,0],\r
-  yellowgreen:  [154,205,50]\r
-};\r
-\r
-var reverseKeywords = {};\r
-for (var key in cssKeywords) {\r
-  reverseKeywords[JSON.stringify(cssKeywords[key])] = key;\r
-}\r
+                       return (contrastRatio >= 4.5) ? 'AA' : '';\r
+               },\r
 \r
-},{}],5:[function(require,module,exports){\r
-var conversions = require(4);\r
-\r
-var convert = function() {\r
-   return new Converter();\r
-}\r
-\r
-for (var func in conversions) {\r
-  // export Raw versions\r
-  convert[func + "Raw"] =  (function(func) {\r
-    // accept array or plain args\r
-    return function(arg) {\r
-      if (typeof arg == "number")\r
-        arg = Array.prototype.slice.call(arguments);\r
-      return conversions[func](arg);\r
-    }\r
-  })(func);\r
-\r
-  var pair = /(\w+)2(\w+)/.exec(func),\r
-      from = pair[1],\r
-      to = pair[2];\r
-\r
-  // export rgb2hsl and ["rgb"]["hsl"]\r
-  convert[from] = convert[from] || {};\r
-\r
-  convert[from][to] = convert[func] = (function(func) { \r
-    return function(arg) {\r
-      if (typeof arg == "number")\r
-        arg = Array.prototype.slice.call(arguments);\r
-      \r
-      var val = conversions[func](arg);\r
-      if (typeof val == "string" || val === undefined)\r
-        return val; // keyword\r
-\r
-      for (var i = 0; i < val.length; i++)\r
-        val[i] = Math.round(val[i]);\r
-      return val;\r
-    }\r
-  })(func);\r
-}\r
-\r
-\r
-/* Converter does lazy conversion and caching */\r
-var Converter = function() {\r
-   this.convs = {};\r
-};\r
-\r
-/* Either get the values for a space or\r
-  set the values for a space, depending on args */\r
-Converter.prototype.routeSpace = function(space, args) {\r
-   var values = args[0];\r
-   if (values === undefined) {\r
-      // color.rgb()\r
-      return this.getValues(space);\r
-   }\r
-   // color.rgb(10, 10, 10)\r
-   if (typeof values == "number") {\r
-      values = Array.prototype.slice.call(args);        \r
-   }\r
-\r
-   return this.setValues(space, values);\r
-};\r
-  \r
-/* Set the values for a space, invalidating cache */\r
-Converter.prototype.setValues = function(space, values) {\r
-   this.space = space;\r
-   this.convs = {};\r
-   this.convs[space] = values;\r
-   return this;\r
-};\r
-\r
-/* Get the values for a space. If there's already\r
-  a conversion for the space, fetch it, otherwise\r
-  compute it */\r
-Converter.prototype.getValues = function(space) {\r
-   var vals = this.convs[space];\r
-   if (!vals) {\r
-      var fspace = this.space,\r
-          from = this.convs[fspace];\r
-      vals = convert[fspace][space](from);\r
-\r
-      this.convs[space] = vals;\r
-   }\r
-  return vals;\r
-};\r
-\r
-["rgb", "hsl", "hsv", "cmyk", "keyword"].forEach(function(space) {\r
-   Converter.prototype[space] = function(vals) {\r
-      return this.routeSpace(space, arguments);\r
-   }\r
-});\r
-\r
-module.exports = convert;\r
-},{"4":4}],6:[function(require,module,exports){\r
-module.exports = {\r
-       "aliceblue": [240, 248, 255],\r
-       "antiquewhite": [250, 235, 215],\r
-       "aqua": [0, 255, 255],\r
-       "aquamarine": [127, 255, 212],\r
-       "azure": [240, 255, 255],\r
-       "beige": [245, 245, 220],\r
-       "bisque": [255, 228, 196],\r
-       "black": [0, 0, 0],\r
-       "blanchedalmond": [255, 235, 205],\r
-       "blue": [0, 0, 255],\r
-       "blueviolet": [138, 43, 226],\r
-       "brown": [165, 42, 42],\r
-       "burlywood": [222, 184, 135],\r
-       "cadetblue": [95, 158, 160],\r
-       "chartreuse": [127, 255, 0],\r
-       "chocolate": [210, 105, 30],\r
-       "coral": [255, 127, 80],\r
-       "cornflowerblue": [100, 149, 237],\r
-       "cornsilk": [255, 248, 220],\r
-       "crimson": [220, 20, 60],\r
-       "cyan": [0, 255, 255],\r
-       "darkblue": [0, 0, 139],\r
-       "darkcyan": [0, 139, 139],\r
-       "darkgoldenrod": [184, 134, 11],\r
-       "darkgray": [169, 169, 169],\r
-       "darkgreen": [0, 100, 0],\r
-       "darkgrey": [169, 169, 169],\r
-       "darkkhaki": [189, 183, 107],\r
-       "darkmagenta": [139, 0, 139],\r
-       "darkolivegreen": [85, 107, 47],\r
-       "darkorange": [255, 140, 0],\r
-       "darkorchid": [153, 50, 204],\r
-       "darkred": [139, 0, 0],\r
-       "darksalmon": [233, 150, 122],\r
-       "darkseagreen": [143, 188, 143],\r
-       "darkslateblue": [72, 61, 139],\r
-       "darkslategray": [47, 79, 79],\r
-       "darkslategrey": [47, 79, 79],\r
-       "darkturquoise": [0, 206, 209],\r
-       "darkviolet": [148, 0, 211],\r
-       "deeppink": [255, 20, 147],\r
-       "deepskyblue": [0, 191, 255],\r
-       "dimgray": [105, 105, 105],\r
-       "dimgrey": [105, 105, 105],\r
-       "dodgerblue": [30, 144, 255],\r
-       "firebrick": [178, 34, 34],\r
-       "floralwhite": [255, 250, 240],\r
-       "forestgreen": [34, 139, 34],\r
-       "fuchsia": [255, 0, 255],\r
-       "gainsboro": [220, 220, 220],\r
-       "ghostwhite": [248, 248, 255],\r
-       "gold": [255, 215, 0],\r
-       "goldenrod": [218, 165, 32],\r
-       "gray": [128, 128, 128],\r
-       "green": [0, 128, 0],\r
-       "greenyellow": [173, 255, 47],\r
-       "grey": [128, 128, 128],\r
-       "honeydew": [240, 255, 240],\r
-       "hotpink": [255, 105, 180],\r
-       "indianred": [205, 92, 92],\r
-       "indigo": [75, 0, 130],\r
-       "ivory": [255, 255, 240],\r
-       "khaki": [240, 230, 140],\r
-       "lavender": [230, 230, 250],\r
-       "lavenderblush": [255, 240, 245],\r
-       "lawngreen": [124, 252, 0],\r
-       "lemonchiffon": [255, 250, 205],\r
-       "lightblue": [173, 216, 230],\r
-       "lightcoral": [240, 128, 128],\r
-       "lightcyan": [224, 255, 255],\r
-       "lightgoldenrodyellow": [250, 250, 210],\r
-       "lightgray": [211, 211, 211],\r
-       "lightgreen": [144, 238, 144],\r
-       "lightgrey": [211, 211, 211],\r
-       "lightpink": [255, 182, 193],\r
-       "lightsalmon": [255, 160, 122],\r
-       "lightseagreen": [32, 178, 170],\r
-       "lightskyblue": [135, 206, 250],\r
-       "lightslategray": [119, 136, 153],\r
-       "lightslategrey": [119, 136, 153],\r
-       "lightsteelblue": [176, 196, 222],\r
-       "lightyellow": [255, 255, 224],\r
-       "lime": [0, 255, 0],\r
-       "limegreen": [50, 205, 50],\r
-       "linen": [250, 240, 230],\r
-       "magenta": [255, 0, 255],\r
-       "maroon": [128, 0, 0],\r
-       "mediumaquamarine": [102, 205, 170],\r
-       "mediumblue": [0, 0, 205],\r
-       "mediumorchid": [186, 85, 211],\r
-       "mediumpurple": [147, 112, 219],\r
-       "mediumseagreen": [60, 179, 113],\r
-       "mediumslateblue": [123, 104, 238],\r
-       "mediumspringgreen": [0, 250, 154],\r
-       "mediumturquoise": [72, 209, 204],\r
-       "mediumvioletred": [199, 21, 133],\r
-       "midnightblue": [25, 25, 112],\r
-       "mintcream": [245, 255, 250],\r
-       "mistyrose": [255, 228, 225],\r
-       "moccasin": [255, 228, 181],\r
-       "navajowhite": [255, 222, 173],\r
-       "navy": [0, 0, 128],\r
-       "oldlace": [253, 245, 230],\r
-       "olive": [128, 128, 0],\r
-       "olivedrab": [107, 142, 35],\r
-       "orange": [255, 165, 0],\r
-       "orangered": [255, 69, 0],\r
-       "orchid": [218, 112, 214],\r
-       "palegoldenrod": [238, 232, 170],\r
-       "palegreen": [152, 251, 152],\r
-       "paleturquoise": [175, 238, 238],\r
-       "palevioletred": [219, 112, 147],\r
-       "papayawhip": [255, 239, 213],\r
-       "peachpuff": [255, 218, 185],\r
-       "peru": [205, 133, 63],\r
-       "pink": [255, 192, 203],\r
-       "plum": [221, 160, 221],\r
-       "powderblue": [176, 224, 230],\r
-       "purple": [128, 0, 128],\r
-       "rebeccapurple": [102, 51, 153],\r
-       "red": [255, 0, 0],\r
-       "rosybrown": [188, 143, 143],\r
-       "royalblue": [65, 105, 225],\r
-       "saddlebrown": [139, 69, 19],\r
-       "salmon": [250, 128, 114],\r
-       "sandybrown": [244, 164, 96],\r
-       "seagreen": [46, 139, 87],\r
-       "seashell": [255, 245, 238],\r
-       "sienna": [160, 82, 45],\r
-       "silver": [192, 192, 192],\r
-       "skyblue": [135, 206, 235],\r
-       "slateblue": [106, 90, 205],\r
-       "slategray": [112, 128, 144],\r
-       "slategrey": [112, 128, 144],\r
-       "snow": [255, 250, 250],\r
-       "springgreen": [0, 255, 127],\r
-       "steelblue": [70, 130, 180],\r
-       "tan": [210, 180, 140],\r
-       "teal": [0, 128, 128],\r
-       "thistle": [216, 191, 216],\r
-       "tomato": [255, 99, 71],\r
-       "turquoise": [64, 224, 208],\r
-       "violet": [238, 130, 238],\r
-       "wheat": [245, 222, 179],\r
-       "white": [255, 255, 255],\r
-       "whitesmoke": [245, 245, 245],\r
-       "yellow": [255, 255, 0],\r
-       "yellowgreen": [154, 205, 50]\r
-};\r
-},{}],7:[function(require,module,exports){\r
-/**\r
- * @namespace Chart\r
- */\r
-var Chart = require(26)();\r
-\r
-require(25)(Chart);\r
-require(24)(Chart);\r
-require(21)(Chart);\r
-require(22)(Chart);\r
-require(23)(Chart);\r
-require(27)(Chart);\r
-require(31)(Chart);\r
-require(29)(Chart);\r
-require(30)(Chart);\r
-require(32)(Chart);\r
-require(28)(Chart);\r
-require(33)(Chart);\r
-\r
-require(34)(Chart);\r
-require(35)(Chart);\r
-require(36)(Chart);\r
-require(37)(Chart);\r
-\r
-require(40)(Chart);\r
-require(38)(Chart);\r
-require(39)(Chart);\r
-require(41)(Chart);\r
-require(42)(Chart);\r
-require(43)(Chart);\r
+               dark: function () {\r
+                       // YIQ equation from http://24ways.org/2010/calculating-color-contrast\r
+                       var rgb = this.values.rgb;\r
+                       var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000;\r
+                       return yiq < 128;\r
+               },\r
 \r
-// Controllers must be loaded after elements\r
-// See Chart.core.datasetController.dataElementType\r
-require(15)(Chart);\r
-require(16)(Chart);\r
-require(17)(Chart);\r
-require(18)(Chart);\r
-require(19)(Chart);\r
-require(20)(Chart);\r
+               light: function () {\r
+                       return !this.dark();\r
+               },\r
 \r
-require(8)(Chart);\r
-require(9)(Chart);\r
-require(10)(Chart);\r
-require(11)(Chart);\r
-require(12)(Chart);\r
-require(13)(Chart);\r
-require(14)(Chart);\r
+               negate: function () {\r
+                       var rgb = [];\r
+                       for (var i = 0; i < 3; i++) {\r
+                               rgb[i] = 255 - this.values.rgb[i];\r
+                       }\r
+                       this.setValues('rgb', rgb);\r
+                       return this;\r
+               },\r
 \r
-window.Chart = module.exports = Chart;\r
+               lighten: function (ratio) {\r
+                       var hsl = this.values.hsl;\r
+                       hsl[2] += hsl[2] * ratio;\r
+                       this.setValues('hsl', hsl);\r
+                       return this;\r
+               },\r
 \r
-},{"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,"41":41,"42":42,"43":43,"8":8,"9":9}],8:[function(require,module,exports){\r
-"use strict";\r
+               darken: function (ratio) {\r
+                       var hsl = this.values.hsl;\r
+                       hsl[2] -= hsl[2] * ratio;\r
+                       this.setValues('hsl', hsl);\r
+                       return this;\r
+               },\r
 \r
-module.exports = function(Chart) {\r
+               saturate: function (ratio) {\r
+                       var hsl = this.values.hsl;\r
+                       hsl[1] += hsl[1] * ratio;\r
+                       this.setValues('hsl', hsl);\r
+                       return this;\r
+               },\r
 \r
-       Chart.Bar = function(context, config) {\r
-               config.type = 'bar';\r
+               desaturate: function (ratio) {\r
+                       var hsl = this.values.hsl;\r
+                       hsl[1] -= hsl[1] * ratio;\r
+                       this.setValues('hsl', hsl);\r
+                       return this;\r
+               },\r
 \r
-               return new Chart(context, config);\r
-       };\r
+               whiten: function (ratio) {\r
+                       var hwb = this.values.hwb;\r
+                       hwb[1] += hwb[1] * ratio;\r
+                       this.setValues('hwb', hwb);\r
+                       return this;\r
+               },\r
 \r
-};\r
-},{}],9:[function(require,module,exports){\r
-"use strict";\r
+               blacken: function (ratio) {\r
+                       var hwb = this.values.hwb;\r
+                       hwb[2] += hwb[2] * ratio;\r
+                       this.setValues('hwb', hwb);\r
+                       return this;\r
+               },\r
 \r
-module.exports = function(Chart) {\r
+               greyscale: function () {\r
+                       var rgb = this.values.rgb;\r
+                       // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale\r
+                       var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11;\r
+                       this.setValues('rgb', [val, val, val]);\r
+                       return this;\r
+               },\r
 \r
-       Chart.Bubble = function(context, config) {\r
-               config.type = 'bubble';\r
-               return new Chart(context, config);\r
-       };\r
+               clearer: function (ratio) {\r
+                       var alpha = this.values.alpha;\r
+                       this.setValues('alpha', alpha - (alpha * ratio));\r
+                       return this;\r
+               },\r
 \r
-};\r
-},{}],10:[function(require,module,exports){\r
-"use strict";\r
+               opaquer: function (ratio) {\r
+                       var alpha = this.values.alpha;\r
+                       this.setValues('alpha', alpha + (alpha * ratio));\r
+                       return this;\r
+               },\r
 \r
-module.exports = function(Chart) {\r
+               rotate: function (degrees) {\r
+                       var hsl = this.values.hsl;\r
+                       var hue = (hsl[0] + degrees) % 360;\r
+                       hsl[0] = hue < 0 ? 360 + hue : hue;\r
+                       this.setValues('hsl', hsl);\r
+                       return this;\r
+               },\r
 \r
-       Chart.Doughnut = function(context, config) {\r
-               config.type = 'doughnut';\r
+               /**\r
+                * Ported from sass implementation in C\r
+                * https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209\r
+                */\r
+               mix: function (mixinColor, weight) {\r
+                       var color1 = this;\r
+                       var color2 = mixinColor;\r
+                       var p = weight === undefined ? 0.5 : weight;\r
+\r
+                       var w = 2 * p - 1;\r
+                       var a = color1.alpha() - color2.alpha();\r
+\r
+                       var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0;\r
+                       var w2 = 1 - w1;\r
+\r
+                       return this\r
+                               .rgb(\r
+                                       w1 * color1.red() + w2 * color2.red(),\r
+                                       w1 * color1.green() + w2 * color2.green(),\r
+                                       w1 * color1.blue() + w2 * color2.blue()\r
+                               )\r
+                               .alpha(color1.alpha() * p + color2.alpha() * (1 - p));\r
+               },\r
+\r
+               toJSON: function () {\r
+                       return this.rgb();\r
+               },\r
+\r
+               clone: function () {\r
+                       // NOTE(SB): using node-clone creates a dependency to Buffer when using browserify,\r
+                       // making the final build way to big to embed in Chart.js. So let's do it manually,\r
+                       // assuming that values to clone are 1 dimension arrays containing only numbers,\r
+                       // except 'alpha' which is a number.\r
+                       var result = new Color();\r
+                       var source = this.values;\r
+                       var target = result.values;\r
+                       var value, type;\r
+\r
+                       for (var prop in source) {\r
+                               if (source.hasOwnProperty(prop)) {\r
+                                       value = source[prop];\r
+                                       type = ({}).toString.call(value);\r
+                                       if (type === '[object Array]') {\r
+                                               target[prop] = value.slice(0);\r
+                                       } else if (type === '[object Number]') {\r
+                                               target[prop] = value;\r
+                                       } else {\r
+                                               console.error('unexpected color value:', value);\r
+                                       }\r
+                               }\r
+                       }\r
 \r
-               return new Chart(context, config);\r
+                       return result;\r
+               }\r
        };\r
 \r
-};\r
-},{}],11:[function(require,module,exports){\r
-"use strict";\r
-\r
-module.exports = function(Chart) {\r
-\r
-       Chart.Line = function(context, config) {\r
-               config.type = 'line';\r
+       Color.prototype.spaces = {\r
+               rgb: ['red', 'green', 'blue'],\r
+               hsl: ['hue', 'saturation', 'lightness'],\r
+               hsv: ['hue', 'saturation', 'value'],\r
+               hwb: ['hue', 'whiteness', 'blackness'],\r
+               cmyk: ['cyan', 'magenta', 'yellow', 'black']\r
+       };\r
 \r
-               return new Chart(context, config);\r
+       Color.prototype.maxes = {\r
+               rgb: [255, 255, 255],\r
+               hsl: [360, 100, 100],\r
+               hsv: [360, 100, 100],\r
+               hwb: [360, 100, 100],\r
+               cmyk: [100, 100, 100, 100]\r
        };\r
 \r
-};\r
-},{}],12:[function(require,module,exports){\r
-"use strict";\r
+       Color.prototype.getValues = function (space) {\r
+               var values = this.values;\r
+               var vals = {};\r
 \r
-module.exports = function(Chart) {\r
+               for (var i = 0; i < space.length; i++) {\r
+                       vals[space.charAt(i)] = values[space][i];\r
+               }\r
 \r
-       Chart.PolarArea = function(context, config) {\r
-               config.type = 'polarArea';\r
+               if (values.alpha !== 1) {\r
+                       vals.a = values.alpha;\r
+               }\r
 \r
-               return new Chart(context, config);\r
+               // {r: 255, g: 255, b: 255, a: 0.4}\r
+               return vals;\r
        };\r
 \r
-};\r
-},{}],13:[function(require,module,exports){\r
-"use strict";\r
+       Color.prototype.setValues = function (space, vals) {\r
+               var values = this.values;\r
+               var spaces = this.spaces;\r
+               var maxes = this.maxes;\r
+               var alpha = 1;\r
+               var i;\r
 \r
-module.exports = function(Chart) {\r
-       \r
-       Chart.Radar = function(context, config) {\r
-               config.options = Chart.helpers.configMerge({ aspectRatio: 1 }, config.options);\r
-               config.type = 'radar';\r
+               if (space === 'alpha') {\r
+                       alpha = vals;\r
+               } else if (vals.length) {\r
+                       // [10, 10, 10]\r
+                       values[space] = vals.slice(0, space.length);\r
+                       alpha = vals[space.length];\r
+               } else if (vals[space.charAt(0)] !== undefined) {\r
+                       // {r: 10, g: 10, b: 10}\r
+                       for (i = 0; i < space.length; i++) {\r
+                               values[space][i] = vals[space.charAt(i)];\r
+                       }\r
 \r
-               return new Chart(context, config);\r
-       };\r
+                       alpha = vals.a;\r
+               } else if (vals[spaces[space][0]] !== undefined) {\r
+                       // {red: 10, green: 10, blue: 10}\r
+                       var chans = spaces[space];\r
 \r
-};\r
+                       for (i = 0; i < space.length; i++) {\r
+                               values[space][i] = vals[chans[i]];\r
+                       }\r
 \r
-},{}],14:[function(require,module,exports){\r
-"use strict";\r
+                       alpha = vals.alpha;\r
+               }\r
 \r
-module.exports = function(Chart) {\r
+               values.alpha = Math.max(0, Math.min(1, (alpha === undefined ? values.alpha : alpha)));\r
 \r
-       var defaultConfig = {\r
-               hover: {\r
-                       mode: 'single'\r
-               },\r
+               if (space === 'alpha') {\r
+                       return false;\r
+               }\r
 \r
-               scales: {\r
-                       xAxes: [{\r
-                               type: "linear", // scatter should not use a category axis\r
-                               position: "bottom",\r
-                               id: "x-axis-1" // need an ID so datasets can reference the scale\r
-                       }],\r
-                       yAxes: [{\r
-                               type: "linear",\r
-                               position: "left",\r
-                               id: "y-axis-1"\r
-                       }]\r
-               },\r
+               var capped;\r
 \r
-               tooltips: {\r
-                       callbacks: {\r
-                               title: function(tooltipItems, data) {\r
-                                       // Title doesn't make sense for scatter since we format the data as a point\r
-                                       return '';\r
-                               },\r
-                               label: function(tooltipItem, data) {\r
-                                       return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';\r
-                               }\r
+               // cap values of the space prior converting all values\r
+               for (i = 0; i < space.length; i++) {\r
+                       capped = Math.max(0, Math.min(maxes[space][i], values[space][i]));\r
+                       values[space][i] = Math.round(capped);\r
+               }\r
+\r
+               // convert to all the other color spaces\r
+               for (var sname in spaces) {\r
+                       if (sname !== space) {\r
+                               values[sname] = convert[space][sname](values[space]);\r
                        }\r
                }\r
+\r
+               return true;\r
        };\r
 \r
-       // Register the default config for this type\r
-       Chart.defaults.scatter = defaultConfig;\r
+       Color.prototype.setSpace = function (space, args) {\r
+               var vals = args[0];\r
+\r
+               if (vals === undefined) {\r
+                       // color.rgb()\r
+                       return this.getValues(space);\r
+               }\r
 \r
-       // Scatter charts use line controllers\r
-       Chart.controllers.scatter = Chart.controllers.line;\r
+               // color.rgb(10, 10, 10)\r
+               if (typeof vals === 'number') {\r
+                       vals = Array.prototype.slice.call(args);\r
+               }\r
 \r
-       Chart.Scatter = function(context, config) {\r
-               config.type = 'scatter';\r
-               return new Chart(context, config);\r
+               this.setValues(space, vals);\r
+               return this;\r
        };\r
 \r
-};\r
-},{}],15:[function(require,module,exports){\r
-"use strict";\r
+       Color.prototype.setChannel = function (space, index, val) {\r
+               var svalues = this.values[space];\r
+               if (val === undefined) {\r
+                       // color.red()\r
+                       return svalues[index];\r
+               } else if (val === svalues[index]) {\r
+                       // color.red(color.red())\r
+                       return this;\r
+               }\r
 \r
-module.exports = function(Chart) {\r
+               // color.red(100)\r
+               svalues[index] = val;\r
+               this.setValues(space, svalues);\r
 \r
-       var helpers = Chart.helpers;\r
+               return this;\r
+       };\r
 \r
-       Chart.defaults.bar = {\r
-               hover: {\r
-                       mode: "label"\r
-               },\r
+       if (typeof window !== 'undefined') {\r
+               window.Color = Color;\r
+       }\r
 \r
-               scales: {\r
-                       xAxes: [{\r
-                               type: "category",\r
+       module.exports = Color;\r
 \r
-                               // Specific to Bar Controller\r
-                               categoryPercentage: 0.8,\r
-                               barPercentage: 0.9,\r
+},{"2":2,"5":5}],4:[function(require,module,exports){\r
+       /* MIT license */\r
+\r
+       module.exports = {\r
+               rgb2hsl: rgb2hsl,\r
+               rgb2hsv: rgb2hsv,\r
+               rgb2hwb: rgb2hwb,\r
+               rgb2cmyk: rgb2cmyk,\r
+               rgb2keyword: rgb2keyword,\r
+               rgb2xyz: rgb2xyz,\r
+               rgb2lab: rgb2lab,\r
+               rgb2lch: rgb2lch,\r
+\r
+               hsl2rgb: hsl2rgb,\r
+               hsl2hsv: hsl2hsv,\r
+               hsl2hwb: hsl2hwb,\r
+               hsl2cmyk: hsl2cmyk,\r
+               hsl2keyword: hsl2keyword,\r
+\r
+               hsv2rgb: hsv2rgb,\r
+               hsv2hsl: hsv2hsl,\r
+               hsv2hwb: hsv2hwb,\r
+               hsv2cmyk: hsv2cmyk,\r
+               hsv2keyword: hsv2keyword,\r
+\r
+               hwb2rgb: hwb2rgb,\r
+               hwb2hsl: hwb2hsl,\r
+               hwb2hsv: hwb2hsv,\r
+               hwb2cmyk: hwb2cmyk,\r
+               hwb2keyword: hwb2keyword,\r
+\r
+               cmyk2rgb: cmyk2rgb,\r
+               cmyk2hsl: cmyk2hsl,\r
+               cmyk2hsv: cmyk2hsv,\r
+               cmyk2hwb: cmyk2hwb,\r
+               cmyk2keyword: cmyk2keyword,\r
+\r
+               keyword2rgb: keyword2rgb,\r
+               keyword2hsl: keyword2hsl,\r
+               keyword2hsv: keyword2hsv,\r
+               keyword2hwb: keyword2hwb,\r
+               keyword2cmyk: keyword2cmyk,\r
+               keyword2lab: keyword2lab,\r
+               keyword2xyz: keyword2xyz,\r
+\r
+               xyz2rgb: xyz2rgb,\r
+               xyz2lab: xyz2lab,\r
+               xyz2lch: xyz2lch,\r
+\r
+               lab2xyz: lab2xyz,\r
+               lab2rgb: lab2rgb,\r
+               lab2lch: lab2lch,\r
+\r
+               lch2lab: lch2lab,\r
+               lch2xyz: lch2xyz,\r
+               lch2rgb: lch2rgb\r
+       }\r
 \r
-                               // grid line settings\r
-                               gridLines: {\r
-                                       offsetGridLines: true\r
-                               }\r
-                       }],\r
-                       yAxes: [{\r
-                               type: "linear"\r
-                       }]\r
-               }\r
-       };\r
 \r
-       Chart.controllers.bar = Chart.DatasetController.extend({\r
+       function rgb2hsl(rgb) {\r
+               var r = rgb[0]/255,\r
+                       g = rgb[1]/255,\r
+                       b = rgb[2]/255,\r
+                       min = Math.min(r, g, b),\r
+                       max = Math.max(r, g, b),\r
+                       delta = max - min,\r
+                       h, s, l;\r
 \r
-               dataElementType: Chart.elements.Rectangle,\r
+               if (max == min)\r
+                       h = 0;\r
+               else if (r == max)\r
+                       h = (g - b) / delta;\r
+               else if (g == max)\r
+                       h = 2 + (b - r) / delta;\r
+               else if (b == max)\r
+                       h = 4 + (r - g)/ delta;\r
 \r
-               initialize: function(chart, datasetIndex) {\r
-                       Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex);\r
+               h = Math.min(h * 60, 360);\r
 \r
-                       // Use this to indicate that this is a bar dataset.\r
-                       this.getMeta().bar = true;\r
-               },\r
+               if (h < 0)\r
+                       h += 360;\r
 \r
-               // Get the number of datasets that display bars. We use this to correctly calculate the bar width\r
-               getBarCount: function getBarCount() {\r
-                       var me = this;\r
-                       var barCount = 0;\r
-                       helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) {\r
-                               var meta = me.chart.getDatasetMeta(datasetIndex);\r
-                               if (meta.bar && me.chart.isDatasetVisible(datasetIndex)) {\r
-                                       ++barCount;\r
-                               }\r
-                       }, me);\r
-                       return barCount;\r
-               },\r
+               l = (min + max) / 2;\r
 \r
-               update: function update(reset) {\r
-                       var me = this;\r
-                       helpers.each(me.getMeta().data, function(rectangle, index) {\r
-                               me.updateElement(rectangle, index, reset);\r
-                       }, me);\r
-               },\r
+               if (max == min)\r
+                       s = 0;\r
+               else if (l <= 0.5)\r
+                       s = delta / (max + min);\r
+               else\r
+                       s = delta / (2 - max - min);\r
 \r
-               updateElement: function updateElement(rectangle, index, reset) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var xScale = me.getScaleForId(meta.xAxisID);\r
-                       var yScale = me.getScaleForId(meta.yAxisID);\r
-                       var scaleBase = yScale.getBasePixel();\r
-                       var rectangleElementOptions = me.chart.options.elements.rectangle;\r
-                       var custom = rectangle.custom || {};\r
-                       var dataset = me.getDataset();\r
-\r
-                       helpers.extend(rectangle, {\r
-                               // Utility\r
-                               _xScale: xScale,\r
-                               _yScale: yScale,\r
-                               _datasetIndex: me.index,\r
-                               _index: index,\r
+               return [h, s * 100, l * 100];\r
+       }\r
 \r
-                               // Desired view properties\r
-                               _model: {\r
-                                       x: me.calculateBarX(index, me.index),\r
-                                       y: reset ? scaleBase : me.calculateBarY(index, me.index),\r
+       function rgb2hsv(rgb) {\r
+               var r = rgb[0],\r
+                       g = rgb[1],\r
+                       b = rgb[2],\r
+                       min = Math.min(r, g, b),\r
+                       max = Math.max(r, g, b),\r
+                       delta = max - min,\r
+                       h, s, v;\r
+\r
+               if (max == 0)\r
+                       s = 0;\r
+               else\r
+                       s = (delta/max * 1000)/10;\r
+\r
+               if (max == min)\r
+                       h = 0;\r
+               else if (r == max)\r
+                       h = (g - b) / delta;\r
+               else if (g == max)\r
+                       h = 2 + (b - r) / delta;\r
+               else if (b == max)\r
+                       h = 4 + (r - g) / delta;\r
+\r
+               h = Math.min(h * 60, 360);\r
+\r
+               if (h < 0)\r
+                       h += 360;\r
+\r
+               v = ((max / 255) * 1000) / 10;\r
+\r
+               return [h, s, v];\r
+       }\r
 \r
-                                       // Tooltip\r
-                                       label: me.chart.data.labels[index],\r
-                                       datasetLabel: dataset.label,\r
+       function rgb2hwb(rgb) {\r
+               var r = rgb[0],\r
+                       g = rgb[1],\r
+                       b = rgb[2],\r
+                       h = rgb2hsl(rgb)[0],\r
+                       w = 1/255 * Math.min(r, Math.min(g, b)),\r
+                       b = 1 - 1/255 * Math.max(r, Math.max(g, b));\r
 \r
-                                       // Appearance\r
-                                       base: reset ? scaleBase : me.calculateBarBase(me.index, index),\r
-                                       width: me.calculateBarWidth(index),\r
-                                       backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),\r
-                                       borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,\r
-                                       borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),\r
-                                       borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)\r
-                               }\r
-                       });\r
-                       rectangle.pivot();\r
-               },\r
+               return [h, w * 100, b * 100];\r
+       }\r
 \r
-               calculateBarBase: function(datasetIndex, index) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var yScale = me.getScaleForId(meta.yAxisID);\r
-                       var base = 0;\r
+       function rgb2cmyk(rgb) {\r
+               var r = rgb[0] / 255,\r
+                       g = rgb[1] / 255,\r
+                       b = rgb[2] / 255,\r
+                       c, m, y, k;\r
+\r
+               k = Math.min(1 - r, 1 - g, 1 - b);\r
+               c = (1 - r - k) / (1 - k) || 0;\r
+               m = (1 - g - k) / (1 - k) || 0;\r
+               y = (1 - b - k) / (1 - k) || 0;\r
+               return [c * 100, m * 100, y * 100, k * 100];\r
+       }\r
 \r
-                       if (yScale.options.stacked) {\r
-                               var chart = me.chart;\r
-                               var datasets = chart.data.datasets;\r
-                               var value = datasets[datasetIndex].data[index];\r
+       function rgb2keyword(rgb) {\r
+               return reverseKeywords[JSON.stringify(rgb)];\r
+       }\r
 \r
-                               if (value < 0) {\r
-                                       for (var i = 0; i < datasetIndex; i++) {\r
-                                               var negDS = datasets[i];\r
-                                               var negDSMeta = chart.getDatasetMeta(i);\r
-                                               if (negDSMeta.bar && negDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {\r
-                                                       base += negDS.data[index] < 0 ? negDS.data[index] : 0;\r
-                                               }\r
-                                       }\r
-                               } else {\r
-                                       for (var j = 0; j < datasetIndex; j++) {\r
-                                               var posDS = datasets[j];\r
-                                               var posDSMeta = chart.getDatasetMeta(j);\r
-                                               if (posDSMeta.bar && posDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(j)) {\r
-                                                       base += posDS.data[index] > 0 ? posDS.data[index] : 0;\r
-                                               }\r
-                                       }\r
-                               }\r
+       function rgb2xyz(rgb) {\r
+               var r = rgb[0] / 255,\r
+                       g = rgb[1] / 255,\r
+                       b = rgb[2] / 255;\r
 \r
-                               return yScale.getPixelForValue(base);\r
-                       }\r
+               // assume sRGB\r
+               r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92);\r
+               g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92);\r
+               b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92);\r
 \r
-                       return yScale.getBasePixel();\r
-               },\r
+               var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);\r
+               var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);\r
+               var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);\r
 \r
-               getRuler: function(index) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var xScale = me.getScaleForId(meta.xAxisID);\r
-                       var datasetCount = me.getBarCount();\r
+               return [x * 100, y *100, z * 100];\r
+       }\r
 \r
-                       var tickWidth;\r
+       function rgb2lab(rgb) {\r
+               var xyz = rgb2xyz(rgb),\r
+                       x = xyz[0],\r
+                       y = xyz[1],\r
+                       z = xyz[2],\r
+                       l, a, b;\r
 \r
-                       if (xScale.options.type === 'category') {\r
-                               tickWidth = xScale.getPixelForTick(index + 1) - xScale.getPixelForTick(index);\r
-                       } else {\r
-                               // Average width\r
-                               tickWidth = xScale.width / xScale.ticks.length;\r
-                       }\r
-                       var categoryWidth = tickWidth * xScale.options.categoryPercentage;\r
-                       var categorySpacing = (tickWidth - (tickWidth * xScale.options.categoryPercentage)) / 2;\r
-                       var fullBarWidth = categoryWidth / datasetCount;\r
+               x /= 95.047;\r
+               y /= 100;\r
+               z /= 108.883;\r
 \r
-                       if (xScale.ticks.length !== me.chart.data.labels.length) {\r
-                           var perc = xScale.ticks.length / me.chart.data.labels.length;\r
-                           fullBarWidth = fullBarWidth * perc;\r
-                       }\r
+               x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);\r
+               y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);\r
+               z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);\r
 \r
-                       var barWidth = fullBarWidth * xScale.options.barPercentage;\r
-                       var barSpacing = fullBarWidth - (fullBarWidth * xScale.options.barPercentage);\r
+               l = (116 * y) - 16;\r
+               a = 500 * (x - y);\r
+               b = 200 * (y - z);\r
 \r
-                       return {\r
-                               datasetCount: datasetCount,\r
-                               tickWidth: tickWidth,\r
-                               categoryWidth: categoryWidth,\r
-                               categorySpacing: categorySpacing,\r
-                               fullBarWidth: fullBarWidth,\r
-                               barWidth: barWidth,\r
-                               barSpacing: barSpacing\r
-                       };\r
-               },\r
+               return [l, a, b];\r
+       }\r
 \r
-               calculateBarWidth: function(index) {\r
-                       var xScale = this.getScaleForId(this.getMeta().xAxisID);\r
-                       var ruler = this.getRuler(index);\r
-                       return xScale.options.stacked ? ruler.categoryWidth : ruler.barWidth;\r
-               },\r
+       function rgb2lch(args) {\r
+               return lab2lch(rgb2lab(args));\r
+       }\r
 \r
-               // Get bar index from the given dataset index accounting for the fact that not all bars are visible\r
-               getBarIndex: function(datasetIndex) {\r
-                       var barIndex = 0;\r
-                       var meta, j;\r
+       function hsl2rgb(hsl) {\r
+               var h = hsl[0] / 360,\r
+                       s = hsl[1] / 100,\r
+                       l = hsl[2] / 100,\r
+                       t1, t2, t3, rgb, val;\r
 \r
-                       for (j = 0; j < datasetIndex; ++j) {\r
-                               meta = this.chart.getDatasetMeta(j);\r
-                               if (meta.bar && this.chart.isDatasetVisible(j)) {\r
-                                       ++barIndex;\r
-                               }\r
-                       }\r
+               if (s == 0) {\r
+                       val = l * 255;\r
+                       return [val, val, val];\r
+               }\r
 \r
-                       return barIndex;\r
-               },\r
+               if (l < 0.5)\r
+                       t2 = l * (1 + s);\r
+               else\r
+                       t2 = l + s - l * s;\r
+               t1 = 2 * l - t2;\r
 \r
-               calculateBarX: function(index, datasetIndex) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var xScale = me.getScaleForId(meta.xAxisID);\r
-                       var barIndex = me.getBarIndex(datasetIndex);\r
+               rgb = [0, 0, 0];\r
+               for (var i = 0; i < 3; i++) {\r
+                       t3 = h + 1 / 3 * - (i - 1);\r
+                       t3 < 0 && t3++;\r
+                       t3 > 1 && t3--;\r
+\r
+                       if (6 * t3 < 1)\r
+                               val = t1 + (t2 - t1) * 6 * t3;\r
+                       else if (2 * t3 < 1)\r
+                               val = t2;\r
+                       else if (3 * t3 < 2)\r
+                               val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;\r
+                       else\r
+                               val = t1;\r
+\r
+                       rgb[i] = val * 255;\r
+               }\r
 \r
-                       var ruler = me.getRuler(index);\r
-                       var leftTick = xScale.getPixelForValue(null, index, datasetIndex, me.chart.isCombo);\r
-                       leftTick -= me.chart.isCombo ? (ruler.tickWidth / 2) : 0;\r
+               return rgb;\r
+       }\r
 \r
-                       if (xScale.options.stacked) {\r
-                               return leftTick + (ruler.categoryWidth / 2) + ruler.categorySpacing;\r
-                       }\r
+       function hsl2hsv(hsl) {\r
+               var h = hsl[0],\r
+                       s = hsl[1] / 100,\r
+                       l = hsl[2] / 100,\r
+                       sv, v;\r
 \r
-                       return leftTick +\r
-                               (ruler.barWidth / 2) +\r
-                               ruler.categorySpacing +\r
-                               (ruler.barWidth * barIndex) +\r
-                               (ruler.barSpacing / 2) +\r
-                               (ruler.barSpacing * barIndex);\r
-               },\r
+               if(l === 0) {\r
+                       // no need to do calc on black\r
+                       // also avoids divide by 0 error\r
+                       return [0, 0, 0];\r
+               }\r
 \r
-               calculateBarY: function(index, datasetIndex) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var yScale = me.getScaleForId(meta.yAxisID);\r
-                       var value = me.getDataset().data[index];\r
+               l *= 2;\r
+               s *= (l <= 1) ? l : 2 - l;\r
+               v = (l + s) / 2;\r
+               sv = (2 * s) / (l + s);\r
+               return [h, sv * 100, v * 100];\r
+       }\r
 \r
-                       if (yScale.options.stacked) {\r
+       function hsl2hwb(args) {\r
+               return rgb2hwb(hsl2rgb(args));\r
+       }\r
 \r
-                               var sumPos = 0,\r
-                                       sumNeg = 0;\r
+       function hsl2cmyk(args) {\r
+               return rgb2cmyk(hsl2rgb(args));\r
+       }\r
 \r
-                               for (var i = 0; i < datasetIndex; i++) {\r
-                                       var ds = me.chart.data.datasets[i];\r
-                                       var dsMeta = me.chart.getDatasetMeta(i);\r
-                                       if (dsMeta.bar && dsMeta.yAxisID === yScale.id && me.chart.isDatasetVisible(i)) {\r
-                                               if (ds.data[index] < 0) {\r
-                                                       sumNeg += ds.data[index] || 0;\r
-                                               } else {\r
-                                                       sumPos += ds.data[index] || 0;\r
-                                               }\r
-                                       }\r
-                               }\r
+       function hsl2keyword(args) {\r
+               return rgb2keyword(hsl2rgb(args));\r
+       }\r
 \r
-                               if (value < 0) {\r
-                                       return yScale.getPixelForValue(sumNeg + value);\r
-                               } else {\r
-                                       return yScale.getPixelForValue(sumPos + value);\r
-                               }\r
-                       }\r
 \r
-                       return yScale.getPixelForValue(value);\r
-               },\r
+       function hsv2rgb(hsv) {\r
+               var h = hsv[0] / 60,\r
+                       s = hsv[1] / 100,\r
+                       v = hsv[2] / 100,\r
+                       hi = Math.floor(h) % 6;\r
+\r
+               var f = h - Math.floor(h),\r
+                       p = 255 * v * (1 - s),\r
+                       q = 255 * v * (1 - (s * f)),\r
+                       t = 255 * v * (1 - (s * (1 - f))),\r
+                       v = 255 * v;\r
+\r
+               switch(hi) {\r
+                       case 0:\r
+                               return [v, t, p];\r
+                       case 1:\r
+                               return [q, v, p];\r
+                       case 2:\r
+                               return [p, v, t];\r
+                       case 3:\r
+                               return [p, q, v];\r
+                       case 4:\r
+                               return [t, p, v];\r
+                       case 5:\r
+                               return [v, p, q];\r
+               }\r
+       }\r
 \r
-               draw: function(ease) {\r
-                       var me = this;\r
-                       var easingDecimal = ease || 1;\r
-                       helpers.each(me.getMeta().data, function(rectangle, index) {\r
-                               var d = me.getDataset().data[index];\r
-                               if (d !== null && d !== undefined && !isNaN(d)) {\r
-                                       rectangle.transition(easingDecimal).draw();\r
-                               }\r
-                       }, me);\r
-               },\r
+       function hsv2hsl(hsv) {\r
+               var h = hsv[0],\r
+                       s = hsv[1] / 100,\r
+                       v = hsv[2] / 100,\r
+                       sl, l;\r
+\r
+               l = (2 - s) * v;\r
+               sl = s * v;\r
+               sl /= (l <= 1) ? l : 2 - l;\r
+               sl = sl || 0;\r
+               l /= 2;\r
+               return [h, sl * 100, l * 100];\r
+       }\r
 \r
-               setHoverStyle: function(rectangle) {\r
-                       var dataset = this.chart.data.datasets[rectangle._datasetIndex];\r
-                       var index = rectangle._index;\r
+       function hsv2hwb(args) {\r
+               return rgb2hwb(hsv2rgb(args))\r
+       }\r
 \r
-                       var custom = rectangle.custom || {};\r
-                       var model = rectangle._model;\r
-                       model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));\r
-                       model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));\r
-                       model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);\r
-               },\r
+       function hsv2cmyk(args) {\r
+               return rgb2cmyk(hsv2rgb(args));\r
+       }\r
 \r
-               removeHoverStyle: function(rectangle) {\r
-                       var dataset = this.chart.data.datasets[rectangle._datasetIndex];\r
-                       var index = rectangle._index;\r
-                       var custom = rectangle.custom || {};\r
-                       var model = rectangle._model;\r
-                       var rectangleElementOptions = this.chart.options.elements.rectangle;\r
+       function hsv2keyword(args) {\r
+               return rgb2keyword(hsv2rgb(args));\r
+       }\r
 \r
-                       model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor);\r
-                       model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor);\r
-                       model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth);\r
+// http://dev.w3.org/csswg/css-color/#hwb-to-rgb\r
+       function hwb2rgb(hwb) {\r
+               var h = hwb[0] / 360,\r
+                       wh = hwb[1] / 100,\r
+                       bl = hwb[2] / 100,\r
+                       ratio = wh + bl,\r
+                       i, v, f, n;\r
+\r
+               // wh + bl cant be > 1\r
+               if (ratio > 1) {\r
+                       wh /= ratio;\r
+                       bl /= ratio;\r
                }\r
 \r
-       });\r
+               i = Math.floor(6 * h);\r
+               v = 1 - bl;\r
+               f = 6 * h - i;\r
+               if ((i & 0x01) != 0) {\r
+                       f = 1 - f;\r
+               }\r
+               n = wh + f * (v - wh);  // linear interpolation\r
 \r
+               switch (i) {\r
+                       default:\r
+                       case 6:\r
+                       case 0: r = v; g = n; b = wh; break;\r
+                       case 1: r = n; g = v; b = wh; break;\r
+                       case 2: r = wh; g = v; b = n; break;\r
+                       case 3: r = wh; g = n; b = v; break;\r
+                       case 4: r = n; g = wh; b = v; break;\r
+                       case 5: r = v; g = wh; b = n; break;\r
+               }\r
 \r
-       // including horizontalBar in the bar file, instead of a file of its own\r
-       // it extends bar (like pie extends doughnut)\r
-       Chart.defaults.horizontalBar = {\r
-               hover: {\r
-                       mode: "label"\r
-               },\r
+               return [r * 255, g * 255, b * 255];\r
+       }\r
 \r
-               scales: {\r
-                       xAxes: [{\r
-                               type: "linear",\r
-                               position: "bottom"\r
-                       }],\r
-                       yAxes: [{\r
-                               position: "left",\r
-                               type: "category",\r
+       function hwb2hsl(args) {\r
+               return rgb2hsl(hwb2rgb(args));\r
+       }\r
 \r
-                               // Specific to Horizontal Bar Controller\r
-                               categoryPercentage: 0.8,\r
-                               barPercentage: 0.9,\r
+       function hwb2hsv(args) {\r
+               return rgb2hsv(hwb2rgb(args));\r
+       }\r
 \r
-                               // grid line settings\r
-                               gridLines: {\r
-                                       offsetGridLines: true\r
-                               }\r
-                       }]\r
-               },\r
-               elements: {\r
-                       rectangle: {\r
-                               borderSkipped: 'left'\r
-                       }\r
-               },\r
-               tooltips: {\r
-                       callbacks: {\r
-                               title: function(tooltipItems, data) {\r
-                                       // Pick first xLabel for now\r
-                                       var title = '';\r
+       function hwb2cmyk(args) {\r
+               return rgb2cmyk(hwb2rgb(args));\r
+       }\r
 \r
-                                       if (tooltipItems.length > 0) {\r
-                                               if (tooltipItems[0].yLabel) {\r
-                                                       title = tooltipItems[0].yLabel;\r
-                                               } else if (data.labels.length > 0 && tooltipItems[0].index < data.labels.length) {\r
-                                                       title = data.labels[tooltipItems[0].index];\r
-                                               }\r
-                                       }\r
+       function hwb2keyword(args) {\r
+               return rgb2keyword(hwb2rgb(args));\r
+       }\r
 \r
-                                       return title;\r
-                               },\r
-                               label: function(tooltipItem, data) {\r
-                                       var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';\r
-                               return datasetLabel + ': ' + tooltipItem.xLabel;\r
-                               }\r
-                       }\r
-               }\r
-       };\r
+       function cmyk2rgb(cmyk) {\r
+               var c = cmyk[0] / 100,\r
+                       m = cmyk[1] / 100,\r
+                       y = cmyk[2] / 100,\r
+                       k = cmyk[3] / 100,\r
+                       r, g, b;\r
+\r
+               r = 1 - Math.min(1, c * (1 - k) + k);\r
+               g = 1 - Math.min(1, m * (1 - k) + k);\r
+               b = 1 - Math.min(1, y * (1 - k) + k);\r
+               return [r * 255, g * 255, b * 255];\r
+       }\r
 \r
-       Chart.controllers.horizontalBar = Chart.controllers.bar.extend({\r
-               updateElement: function updateElement(rectangle, index, reset, numBars) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var xScale = me.getScaleForId(meta.xAxisID);\r
-                       var yScale = me.getScaleForId(meta.yAxisID);\r
-                       var scaleBase = xScale.getBasePixel();\r
-                       var custom = rectangle.custom || {};\r
-                       var dataset = me.getDataset();\r
-                       var rectangleElementOptions = me.chart.options.elements.rectangle;\r
-\r
-                       helpers.extend(rectangle, {\r
-                               // Utility\r
-                               _xScale: xScale,\r
-                               _yScale: yScale,\r
-                               _datasetIndex: me.index,\r
-                               _index: index,\r
+       function cmyk2hsl(args) {\r
+               return rgb2hsl(cmyk2rgb(args));\r
+       }\r
 \r
-                               // Desired view properties\r
-                               _model: {\r
-                                       x: reset ? scaleBase : me.calculateBarX(index, me.index),\r
-                                       y: me.calculateBarY(index, me.index),\r
+       function cmyk2hsv(args) {\r
+               return rgb2hsv(cmyk2rgb(args));\r
+       }\r
 \r
-                                       // Tooltip\r
-                                       label: me.chart.data.labels[index],\r
-                                       datasetLabel: dataset.label,\r
+       function cmyk2hwb(args) {\r
+               return rgb2hwb(cmyk2rgb(args));\r
+       }\r
 \r
-                                       // Appearance\r
-                                       base: reset ? scaleBase : me.calculateBarBase(me.index, index),\r
-                                       height: me.calculateBarHeight(index),\r
-                                       backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),\r
-                                       borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,\r
-                                       borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),\r
-                                       borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)\r
-                               },\r
+       function cmyk2keyword(args) {\r
+               return rgb2keyword(cmyk2rgb(args));\r
+       }\r
 \r
-                               draw: function () {\r
-                                       var ctx = this._chart.ctx;\r
-                                       var vm = this._view;\r
 \r
-                                       var halfHeight = vm.height / 2,\r
-                                               topY = vm.y - halfHeight,\r
-                                               bottomY = vm.y + halfHeight,\r
-                                               right = vm.base - (vm.base - vm.x),\r
-                                               halfStroke = vm.borderWidth / 2;\r
+       function xyz2rgb(xyz) {\r
+               var x = xyz[0] / 100,\r
+                       y = xyz[1] / 100,\r
+                       z = xyz[2] / 100,\r
+                       r, g, b;\r
 \r
-                                       // Canvas doesn't allow us to stroke inside the width so we can\r
-                                       // adjust the sizes to fit if we're setting a stroke on the line\r
-                                       if (vm.borderWidth) {\r
-                                               topY += halfStroke;\r
-                                               bottomY -= halfStroke;\r
-                                               right += halfStroke;\r
-                                       }\r
+               r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);\r
+               g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);\r
+               b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);\r
 \r
-                                       ctx.beginPath();\r
+               // assume sRGB\r
+               r = r > 0.0031308 ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055)\r
+                       : r = (r * 12.92);\r
 \r
-                                       ctx.fillStyle = vm.backgroundColor;\r
-                                       ctx.strokeStyle = vm.borderColor;\r
-                                       ctx.lineWidth = vm.borderWidth;\r
+               g = g > 0.0031308 ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055)\r
+                       : g = (g * 12.92);\r
 \r
-                                       // Corner points, from bottom-left to bottom-right clockwise\r
-                                       // | 1 2 |\r
-                                       // | 0 3 |\r
-                                       var corners = [\r
-                                               [vm.base, bottomY],\r
-                                               [vm.base, topY],\r
-                                               [right, topY],\r
-                                               [right, bottomY]\r
-                                       ];\r
+               b = b > 0.0031308 ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055)\r
+                       : b = (b * 12.92);\r
 \r
-                                       // Find first (starting) corner with fallback to 'bottom'\r
-                                       var borders = ['bottom', 'left', 'top', 'right'];\r
-                                       var startCorner = borders.indexOf(vm.borderSkipped, 0);\r
-                                       if (startCorner === -1)\r
-                                               startCorner = 0;\r
+               r = Math.min(Math.max(0, r), 1);\r
+               g = Math.min(Math.max(0, g), 1);\r
+               b = Math.min(Math.max(0, b), 1);\r
 \r
-                                       function cornerAt(index) {\r
-                                               return corners[(startCorner + index) % 4];\r
-                                       }\r
+               return [r * 255, g * 255, b * 255];\r
+       }\r
 \r
-                                       // Draw rectangle from 'startCorner'\r
-                                       ctx.moveTo.apply(ctx, cornerAt(0));\r
-                                       for (var i = 1; i < 4; i++)\r
-                                               ctx.lineTo.apply(ctx, cornerAt(i));\r
+       function xyz2lab(xyz) {\r
+               var x = xyz[0],\r
+                       y = xyz[1],\r
+                       z = xyz[2],\r
+                       l, a, b;\r
 \r
-                                       ctx.fill();\r
-                                       if (vm.borderWidth) {\r
-                                               ctx.stroke();\r
-                                       }\r
-                               },\r
+               x /= 95.047;\r
+               y /= 100;\r
+               z /= 108.883;\r
 \r
-                               inRange: function (mouseX, mouseY) {\r
-                                       var vm = this._view;\r
-                                       var inRange = false;\r
+               x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);\r
+               y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);\r
+               z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);\r
 \r
-                                       if (vm) {\r
-                                               if (vm.x < vm.base) {\r
-                                                       inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.x && mouseX <= vm.base);\r
-                                               } else {\r
-                                                       inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.base && mouseX <= vm.x);\r
-                                               }\r
-                                       }\r
+               l = (116 * y) - 16;\r
+               a = 500 * (x - y);\r
+               b = 200 * (y - z);\r
 \r
-                                       return inRange;\r
-                               }\r
-                       });\r
+               return [l, a, b];\r
+       }\r
 \r
-                       rectangle.pivot();\r
-               },\r
+       function xyz2lch(args) {\r
+               return lab2lch(xyz2lab(args));\r
+       }\r
 \r
-               calculateBarBase: function (datasetIndex, index) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var xScale = me.getScaleForId(meta.xAxisID);\r
-                       var base = 0;\r
+       function lab2xyz(lab) {\r
+               var l = lab[0],\r
+                       a = lab[1],\r
+                       b = lab[2],\r
+                       x, y, z, y2;\r
 \r
-                       if (xScale.options.stacked) {\r
+               if (l <= 8) {\r
+                       y = (l * 100) / 903.3;\r
+                       y2 = (7.787 * (y / 100)) + (16 / 116);\r
+               } else {\r
+                       y = 100 * Math.pow((l + 16) / 116, 3);\r
+                       y2 = Math.pow(y / 100, 1/3);\r
+               }\r
 \r
-                               var value = me.chart.data.datasets[datasetIndex].data[index];\r
+               x = x / 95.047 <= 0.008856 ? x = (95.047 * ((a / 500) + y2 - (16 / 116))) / 7.787 : 95.047 * Math.pow((a / 500) + y2, 3);\r
 \r
-                               if (value < 0) {\r
-                                       for (var i = 0; i < datasetIndex; i++) {\r
-                                               var negDS = me.chart.data.datasets[i];\r
-                                               var negDSMeta = me.chart.getDatasetMeta(i);\r
-                                               if (negDSMeta.bar && negDSMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(i)) {\r
-                                                       base += negDS.data[index] < 0 ? negDS.data[index] : 0;\r
-                                               }\r
-                                       }\r
-                               } else {\r
-                                       for (var j = 0; j < datasetIndex; j++) {\r
-                                               var posDS = me.chart.data.datasets[j];\r
-                                               var posDSMeta = me.chart.getDatasetMeta(j);\r
-                                               if (posDSMeta.bar && posDSMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(j)) {\r
-                                                       base += posDS.data[index] > 0 ? posDS.data[index] : 0;\r
-                                               }\r
-                                       }\r
-                               }\r
+               z = z / 108.883 <= 0.008859 ? z = (108.883 * (y2 - (b / 200) - (16 / 116))) / 7.787 : 108.883 * Math.pow(y2 - (b / 200), 3);\r
 \r
-                               return xScale.getPixelForValue(base);\r
-                       }\r
+               return [x, y, z];\r
+       }\r
 \r
-                       return xScale.getBasePixel();\r
-               },\r
+       function lab2lch(lab) {\r
+               var l = lab[0],\r
+                       a = lab[1],\r
+                       b = lab[2],\r
+                       hr, h, c;\r
 \r
-               getRuler: function (index) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var yScale = me.getScaleForId(meta.yAxisID);\r
-                       var datasetCount = me.getBarCount();\r
+               hr = Math.atan2(b, a);\r
+               h = hr * 360 / 2 / Math.PI;\r
+               if (h < 0) {\r
+                       h += 360;\r
+               }\r
+               c = Math.sqrt(a * a + b * b);\r
+               return [l, c, h];\r
+       }\r
 \r
-                       var tickHeight;\r
-                       if (yScale.options.type === 'category') {\r
-                               tickHeight = yScale.getPixelForTick(index + 1) - yScale.getPixelForTick(index);\r
-                       } else {\r
-                               // Average width\r
-                               tickHeight = yScale.width / yScale.ticks.length;\r
-                       }\r
-                       var categoryHeight = tickHeight * yScale.options.categoryPercentage;\r
-                       var categorySpacing = (tickHeight - (tickHeight * yScale.options.categoryPercentage)) / 2;\r
-                       var fullBarHeight = categoryHeight / datasetCount;\r
+       function lab2rgb(args) {\r
+               return xyz2rgb(lab2xyz(args));\r
+       }\r
 \r
-                       if (yScale.ticks.length !== me.chart.data.labels.length) {\r
-                               var perc = yScale.ticks.length / me.chart.data.labels.length;\r
-                               fullBarHeight = fullBarHeight * perc;\r
-                       }\r
+       function lch2lab(lch) {\r
+               var l = lch[0],\r
+                       c = lch[1],\r
+                       h = lch[2],\r
+                       a, b, hr;\r
 \r
-                       var barHeight = fullBarHeight * yScale.options.barPercentage;\r
-                       var barSpacing = fullBarHeight - (fullBarHeight * yScale.options.barPercentage);\r
+               hr = h / 360 * 2 * Math.PI;\r
+               a = c * Math.cos(hr);\r
+               b = c * Math.sin(hr);\r
+               return [l, a, b];\r
+       }\r
 \r
-                       return {\r
-                               datasetCount: datasetCount,\r
-                               tickHeight: tickHeight,\r
-                               categoryHeight: categoryHeight,\r
-                               categorySpacing: categorySpacing,\r
-                               fullBarHeight: fullBarHeight,\r
-                               barHeight: barHeight,\r
-                               barSpacing: barSpacing,\r
-                       };\r
-               },\r
+       function lch2xyz(args) {\r
+               return lab2xyz(lch2lab(args));\r
+       }\r
 \r
-               calculateBarHeight: function (index) {\r
-                       var me = this;\r
-                       var yScale = me.getScaleForId(me.getMeta().yAxisID);\r
-                       var ruler = me.getRuler(index);\r
-                       return yScale.options.stacked ? ruler.categoryHeight : ruler.barHeight;\r
-               },\r
+       function lch2rgb(args) {\r
+               return lab2rgb(lch2lab(args));\r
+       }\r
 \r
-               calculateBarX: function (index, datasetIndex) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var xScale = me.getScaleForId(meta.xAxisID);\r
-                       var value = me.getDataset().data[index];\r
+       function keyword2rgb(keyword) {\r
+               return cssKeywords[keyword];\r
+       }\r
 \r
-                       if (xScale.options.stacked) {\r
+       function keyword2hsl(args) {\r
+               return rgb2hsl(keyword2rgb(args));\r
+       }\r
 \r
-                               var sumPos = 0,\r
-                                       sumNeg = 0;\r
+       function keyword2hsv(args) {\r
+               return rgb2hsv(keyword2rgb(args));\r
+       }\r
 \r
-                               for (var i = 0; i < datasetIndex; i++) {\r
-                                       var ds = me.chart.data.datasets[i];\r
-                                       var dsMeta = me.chart.getDatasetMeta(i);\r
-                                       if (dsMeta.bar && dsMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(i)) {\r
-                                               if (ds.data[index] < 0) {\r
-                                                       sumNeg += ds.data[index] || 0;\r
-                                               } else {\r
-                                                       sumPos += ds.data[index] || 0;\r
-                                               }\r
-                                       }\r
-                               }\r
+       function keyword2hwb(args) {\r
+               return rgb2hwb(keyword2rgb(args));\r
+       }\r
 \r
-                               if (value < 0) {\r
-                                       return xScale.getPixelForValue(sumNeg + value);\r
-                               } else {\r
-                                       return xScale.getPixelForValue(sumPos + value);\r
-                               }\r
-                       }\r
+       function keyword2cmyk(args) {\r
+               return rgb2cmyk(keyword2rgb(args));\r
+       }\r
 \r
-                       return xScale.getPixelForValue(value);\r
-               },\r
+       function keyword2lab(args) {\r
+               return rgb2lab(keyword2rgb(args));\r
+       }\r
 \r
-               calculateBarY: function (index, datasetIndex) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var yScale = me.getScaleForId(meta.yAxisID);\r
-                       var barIndex = me.getBarIndex(datasetIndex);\r
+       function keyword2xyz(args) {\r
+               return rgb2xyz(keyword2rgb(args));\r
+       }\r
 \r
-                       var ruler = me.getRuler(index);\r
-                       var topTick = yScale.getPixelForValue(null, index, datasetIndex, me.chart.isCombo);\r
-                       topTick -= me.chart.isCombo ? (ruler.tickHeight / 2) : 0;\r
+       var cssKeywords = {\r
+               aliceblue:  [240,248,255],\r
+               antiquewhite: [250,235,215],\r
+               aqua: [0,255,255],\r
+               aquamarine: [127,255,212],\r
+               azure:  [240,255,255],\r
+               beige:  [245,245,220],\r
+               bisque: [255,228,196],\r
+               black:  [0,0,0],\r
+               blanchedalmond: [255,235,205],\r
+               blue: [0,0,255],\r
+               blueviolet: [138,43,226],\r
+               brown:  [165,42,42],\r
+               burlywood:  [222,184,135],\r
+               cadetblue:  [95,158,160],\r
+               chartreuse: [127,255,0],\r
+               chocolate:  [210,105,30],\r
+               coral:  [255,127,80],\r
+               cornflowerblue: [100,149,237],\r
+               cornsilk: [255,248,220],\r
+               crimson:  [220,20,60],\r
+               cyan: [0,255,255],\r
+               darkblue: [0,0,139],\r
+               darkcyan: [0,139,139],\r
+               darkgoldenrod:  [184,134,11],\r
+               darkgray: [169,169,169],\r
+               darkgreen:  [0,100,0],\r
+               darkgrey: [169,169,169],\r
+               darkkhaki:  [189,183,107],\r
+               darkmagenta:  [139,0,139],\r
+               darkolivegreen: [85,107,47],\r
+               darkorange: [255,140,0],\r
+               darkorchid: [153,50,204],\r
+               darkred:  [139,0,0],\r
+               darksalmon: [233,150,122],\r
+               darkseagreen: [143,188,143],\r
+               darkslateblue:  [72,61,139],\r
+               darkslategray:  [47,79,79],\r
+               darkslategrey:  [47,79,79],\r
+               darkturquoise:  [0,206,209],\r
+               darkviolet: [148,0,211],\r
+               deeppink: [255,20,147],\r
+               deepskyblue:  [0,191,255],\r
+               dimgray:  [105,105,105],\r
+               dimgrey:  [105,105,105],\r
+               dodgerblue: [30,144,255],\r
+               firebrick:  [178,34,34],\r
+               floralwhite:  [255,250,240],\r
+               forestgreen:  [34,139,34],\r
+               fuchsia:  [255,0,255],\r
+               gainsboro:  [220,220,220],\r
+               ghostwhite: [248,248,255],\r
+               gold: [255,215,0],\r
+               goldenrod:  [218,165,32],\r
+               gray: [128,128,128],\r
+               green:  [0,128,0],\r
+               greenyellow:  [173,255,47],\r
+               grey: [128,128,128],\r
+               honeydew: [240,255,240],\r
+               hotpink:  [255,105,180],\r
+               indianred:  [205,92,92],\r
+               indigo: [75,0,130],\r
+               ivory:  [255,255,240],\r
+               khaki:  [240,230,140],\r
+               lavender: [230,230,250],\r
+               lavenderblush:  [255,240,245],\r
+               lawngreen:  [124,252,0],\r
+               lemonchiffon: [255,250,205],\r
+               lightblue:  [173,216,230],\r
+               lightcoral: [240,128,128],\r
+               lightcyan:  [224,255,255],\r
+               lightgoldenrodyellow: [250,250,210],\r
+               lightgray:  [211,211,211],\r
+               lightgreen: [144,238,144],\r
+               lightgrey:  [211,211,211],\r
+               lightpink:  [255,182,193],\r
+               lightsalmon:  [255,160,122],\r
+               lightseagreen:  [32,178,170],\r
+               lightskyblue: [135,206,250],\r
+               lightslategray: [119,136,153],\r
+               lightslategrey: [119,136,153],\r
+               lightsteelblue: [176,196,222],\r
+               lightyellow:  [255,255,224],\r
+               lime: [0,255,0],\r
+               limegreen:  [50,205,50],\r
+               linen:  [250,240,230],\r
+               magenta:  [255,0,255],\r
+               maroon: [128,0,0],\r
+               mediumaquamarine: [102,205,170],\r
+               mediumblue: [0,0,205],\r
+               mediumorchid: [186,85,211],\r
+               mediumpurple: [147,112,219],\r
+               mediumseagreen: [60,179,113],\r
+               mediumslateblue:  [123,104,238],\r
+               mediumspringgreen:  [0,250,154],\r
+               mediumturquoise:  [72,209,204],\r
+               mediumvioletred:  [199,21,133],\r
+               midnightblue: [25,25,112],\r
+               mintcream:  [245,255,250],\r
+               mistyrose:  [255,228,225],\r
+               moccasin: [255,228,181],\r
+               navajowhite:  [255,222,173],\r
+               navy: [0,0,128],\r
+               oldlace:  [253,245,230],\r
+               olive:  [128,128,0],\r
+               olivedrab:  [107,142,35],\r
+               orange: [255,165,0],\r
+               orangered:  [255,69,0],\r
+               orchid: [218,112,214],\r
+               palegoldenrod:  [238,232,170],\r
+               palegreen:  [152,251,152],\r
+               paleturquoise:  [175,238,238],\r
+               palevioletred:  [219,112,147],\r
+               papayawhip: [255,239,213],\r
+               peachpuff:  [255,218,185],\r
+               peru: [205,133,63],\r
+               pink: [255,192,203],\r
+               plum: [221,160,221],\r
+               powderblue: [176,224,230],\r
+               purple: [128,0,128],\r
+               rebeccapurple: [102, 51, 153],\r
+               red:  [255,0,0],\r
+               rosybrown:  [188,143,143],\r
+               royalblue:  [65,105,225],\r
+               saddlebrown:  [139,69,19],\r
+               salmon: [250,128,114],\r
+               sandybrown: [244,164,96],\r
+               seagreen: [46,139,87],\r
+               seashell: [255,245,238],\r
+               sienna: [160,82,45],\r
+               silver: [192,192,192],\r
+               skyblue:  [135,206,235],\r
+               slateblue:  [106,90,205],\r
+               slategray:  [112,128,144],\r
+               slategrey:  [112,128,144],\r
+               snow: [255,250,250],\r
+               springgreen:  [0,255,127],\r
+               steelblue:  [70,130,180],\r
+               tan:  [210,180,140],\r
+               teal: [0,128,128],\r
+               thistle:  [216,191,216],\r
+               tomato: [255,99,71],\r
+               turquoise:  [64,224,208],\r
+               violet: [238,130,238],\r
+               wheat:  [245,222,179],\r
+               white:  [255,255,255],\r
+               whitesmoke: [245,245,245],\r
+               yellow: [255,255,0],\r
+               yellowgreen:  [154,205,50]\r
+       };\r
 \r
-                       if (yScale.options.stacked) {\r
-                               return topTick + (ruler.categoryHeight / 2) + ruler.categorySpacing;\r
-                       }\r
+       var reverseKeywords = {};\r
+       for (var key in cssKeywords) {\r
+               reverseKeywords[JSON.stringify(cssKeywords[key])] = key;\r
+       }\r
 \r
-                       return topTick +\r
-                               (ruler.barHeight / 2) +\r
-                               ruler.categorySpacing +\r
-                               (ruler.barHeight * barIndex) +\r
-                               (ruler.barSpacing / 2) +\r
-                               (ruler.barSpacing * barIndex);\r
-               }\r
-       });\r
-};\r
+},{}],5:[function(require,module,exports){\r
+       var conversions = require(4);\r
 \r
-},{}],16:[function(require,module,exports){\r
-"use strict";\r
+       var convert = function() {\r
+               return new Converter();\r
+       }\r
 \r
-module.exports = function(Chart) {\r
+       for (var func in conversions) {\r
+               // export Raw versions\r
+               convert[func + "Raw"] =  (function(func) {\r
+                       // accept array or plain args\r
+                       return function(arg) {\r
+                               if (typeof arg == "number")\r
+                                       arg = Array.prototype.slice.call(arguments);\r
+                               return conversions[func](arg);\r
+                       }\r
+               })(func);\r
 \r
-       var helpers = Chart.helpers;\r
+               var pair = /(\w+)2(\w+)/.exec(func),\r
+                       from = pair[1],\r
+                       to = pair[2];\r
 \r
-       Chart.defaults.bubble = {\r
-               hover: {\r
-                       mode: "single"\r
-               },\r
+               // export rgb2hsl and ["rgb"]["hsl"]\r
+               convert[from] = convert[from] || {};\r
 \r
-               scales: {\r
-                       xAxes: [{\r
-                               type: "linear", // bubble should probably use a linear scale by default\r
-                               position: "bottom",\r
-                               id: "x-axis-0" // need an ID so datasets can reference the scale\r
-                       }],\r
-                       yAxes: [{\r
-                               type: "linear",\r
-                               position: "left",\r
-                               id: "y-axis-0"\r
-                       }]\r
-               },\r
+               convert[from][to] = convert[func] = (function(func) {\r
+                       return function(arg) {\r
+                               if (typeof arg == "number")\r
+                                       arg = Array.prototype.slice.call(arguments);\r
 \r
-               tooltips: {\r
-                       callbacks: {\r
-                               title: function(tooltipItems, data) {\r
-                                       // Title doesn't make sense for scatter since we format the data as a point\r
-                                       return '';\r
-                               },\r
-                               label: function(tooltipItem, data) {\r
-                                       var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';\r
-                                       var dataPoint = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\r
-                                       return datasetLabel + ': (' + dataPoint.x + ', ' + dataPoint.y + ', ' + dataPoint.r + ')';\r
-                               }\r
+                               var val = conversions[func](arg);\r
+                               if (typeof val == "string" || val === undefined)\r
+                                       return val; // keyword\r
+\r
+                               for (var i = 0; i < val.length; i++)\r
+                                       val[i] = Math.round(val[i]);\r
+                               return val;\r
                        }\r
-               }\r
+               })(func);\r
+       }\r
+\r
+\r
+       /* Converter does lazy conversion and caching */\r
+       var Converter = function() {\r
+               this.convs = {};\r
        };\r
 \r
-       Chart.controllers.bubble = Chart.DatasetController.extend({\r
+       /* Either get the values for a space or\r
+        set the values for a space, depending on args */\r
+       Converter.prototype.routeSpace = function(space, args) {\r
+               var values = args[0];\r
+               if (values === undefined) {\r
+                       // color.rgb()\r
+                       return this.getValues(space);\r
+               }\r
+               // color.rgb(10, 10, 10)\r
+               if (typeof values == "number") {\r
+                       values = Array.prototype.slice.call(args);\r
+               }\r
 \r
-               dataElementType: Chart.elements.Point,\r
+               return this.setValues(space, values);\r
+       };\r
 \r
-               update: function update(reset) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var points = meta.data;\r
+       /* Set the values for a space, invalidating cache */\r
+       Converter.prototype.setValues = function(space, values) {\r
+               this.space = space;\r
+               this.convs = {};\r
+               this.convs[space] = values;\r
+               return this;\r
+       };\r
 \r
-                       // Update Points\r
-                       helpers.each(points, function(point, index) {\r
-                               me.updateElement(point, index, reset);\r
-                       });\r
-               },\r
+       /* Get the values for a space. If there's already\r
+        a conversion for the space, fetch it, otherwise\r
+        compute it */\r
+       Converter.prototype.getValues = function(space) {\r
+               var vals = this.convs[space];\r
+               if (!vals) {\r
+                       var fspace = this.space,\r
+                               from = this.convs[fspace];\r
+                       vals = convert[fspace][space](from);\r
+\r
+                       this.convs[space] = vals;\r
+               }\r
+               return vals;\r
+       };\r
 \r
-               updateElement: function(point, index, reset) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var xScale = me.getScaleForId(meta.xAxisID);\r
-                       var yScale = me.getScaleForId(meta.yAxisID);\r
+       ["rgb", "hsl", "hsv", "cmyk", "keyword"].forEach(function(space) {\r
+               Converter.prototype[space] = function(vals) {\r
+                       return this.routeSpace(space, arguments);\r
+               }\r
+       });\r
 \r
-                       var custom = point.custom || {};\r
-                       var dataset = me.getDataset();\r
-                       var data = dataset.data[index];\r
-                       var pointElementOptions = me.chart.options.elements.point;\r
-                       var dsIndex = me.index;\r
+       module.exports = convert;\r
+},{"4":4}],6:[function(require,module,exports){\r
+       module.exports = {\r
+               "aliceblue": [240, 248, 255],\r
+               "antiquewhite": [250, 235, 215],\r
+               "aqua": [0, 255, 255],\r
+               "aquamarine": [127, 255, 212],\r
+               "azure": [240, 255, 255],\r
+               "beige": [245, 245, 220],\r
+               "bisque": [255, 228, 196],\r
+               "black": [0, 0, 0],\r
+               "blanchedalmond": [255, 235, 205],\r
+               "blue": [0, 0, 255],\r
+               "blueviolet": [138, 43, 226],\r
+               "brown": [165, 42, 42],\r
+               "burlywood": [222, 184, 135],\r
+               "cadetblue": [95, 158, 160],\r
+               "chartreuse": [127, 255, 0],\r
+               "chocolate": [210, 105, 30],\r
+               "coral": [255, 127, 80],\r
+               "cornflowerblue": [100, 149, 237],\r
+               "cornsilk": [255, 248, 220],\r
+               "crimson": [220, 20, 60],\r
+               "cyan": [0, 255, 255],\r
+               "darkblue": [0, 0, 139],\r
+               "darkcyan": [0, 139, 139],\r
+               "darkgoldenrod": [184, 134, 11],\r
+               "darkgray": [169, 169, 169],\r
+               "darkgreen": [0, 100, 0],\r
+               "darkgrey": [169, 169, 169],\r
+               "darkkhaki": [189, 183, 107],\r
+               "darkmagenta": [139, 0, 139],\r
+               "darkolivegreen": [85, 107, 47],\r
+               "darkorange": [255, 140, 0],\r
+               "darkorchid": [153, 50, 204],\r
+               "darkred": [139, 0, 0],\r
+               "darksalmon": [233, 150, 122],\r
+               "darkseagreen": [143, 188, 143],\r
+               "darkslateblue": [72, 61, 139],\r
+               "darkslategray": [47, 79, 79],\r
+               "darkslategrey": [47, 79, 79],\r
+               "darkturquoise": [0, 206, 209],\r
+               "darkviolet": [148, 0, 211],\r
+               "deeppink": [255, 20, 147],\r
+               "deepskyblue": [0, 191, 255],\r
+               "dimgray": [105, 105, 105],\r
+               "dimgrey": [105, 105, 105],\r
+               "dodgerblue": [30, 144, 255],\r
+               "firebrick": [178, 34, 34],\r
+               "floralwhite": [255, 250, 240],\r
+               "forestgreen": [34, 139, 34],\r
+               "fuchsia": [255, 0, 255],\r
+               "gainsboro": [220, 220, 220],\r
+               "ghostwhite": [248, 248, 255],\r
+               "gold": [255, 215, 0],\r
+               "goldenrod": [218, 165, 32],\r
+               "gray": [128, 128, 128],\r
+               "green": [0, 128, 0],\r
+               "greenyellow": [173, 255, 47],\r
+               "grey": [128, 128, 128],\r
+               "honeydew": [240, 255, 240],\r
+               "hotpink": [255, 105, 180],\r
+               "indianred": [205, 92, 92],\r
+               "indigo": [75, 0, 130],\r
+               "ivory": [255, 255, 240],\r
+               "khaki": [240, 230, 140],\r
+               "lavender": [230, 230, 250],\r
+               "lavenderblush": [255, 240, 245],\r
+               "lawngreen": [124, 252, 0],\r
+               "lemonchiffon": [255, 250, 205],\r
+               "lightblue": [173, 216, 230],\r
+               "lightcoral": [240, 128, 128],\r
+               "lightcyan": [224, 255, 255],\r
+               "lightgoldenrodyellow": [250, 250, 210],\r
+               "lightgray": [211, 211, 211],\r
+               "lightgreen": [144, 238, 144],\r
+               "lightgrey": [211, 211, 211],\r
+               "lightpink": [255, 182, 193],\r
+               "lightsalmon": [255, 160, 122],\r
+               "lightseagreen": [32, 178, 170],\r
+               "lightskyblue": [135, 206, 250],\r
+               "lightslategray": [119, 136, 153],\r
+               "lightslategrey": [119, 136, 153],\r
+               "lightsteelblue": [176, 196, 222],\r
+               "lightyellow": [255, 255, 224],\r
+               "lime": [0, 255, 0],\r
+               "limegreen": [50, 205, 50],\r
+               "linen": [250, 240, 230],\r
+               "magenta": [255, 0, 255],\r
+               "maroon": [128, 0, 0],\r
+               "mediumaquamarine": [102, 205, 170],\r
+               "mediumblue": [0, 0, 205],\r
+               "mediumorchid": [186, 85, 211],\r
+               "mediumpurple": [147, 112, 219],\r
+               "mediumseagreen": [60, 179, 113],\r
+               "mediumslateblue": [123, 104, 238],\r
+               "mediumspringgreen": [0, 250, 154],\r
+               "mediumturquoise": [72, 209, 204],\r
+               "mediumvioletred": [199, 21, 133],\r
+               "midnightblue": [25, 25, 112],\r
+               "mintcream": [245, 255, 250],\r
+               "mistyrose": [255, 228, 225],\r
+               "moccasin": [255, 228, 181],\r
+               "navajowhite": [255, 222, 173],\r
+               "navy": [0, 0, 128],\r
+               "oldlace": [253, 245, 230],\r
+               "olive": [128, 128, 0],\r
+               "olivedrab": [107, 142, 35],\r
+               "orange": [255, 165, 0],\r
+               "orangered": [255, 69, 0],\r
+               "orchid": [218, 112, 214],\r
+               "palegoldenrod": [238, 232, 170],\r
+               "palegreen": [152, 251, 152],\r
+               "paleturquoise": [175, 238, 238],\r
+               "palevioletred": [219, 112, 147],\r
+               "papayawhip": [255, 239, 213],\r
+               "peachpuff": [255, 218, 185],\r
+               "peru": [205, 133, 63],\r
+               "pink": [255, 192, 203],\r
+               "plum": [221, 160, 221],\r
+               "powderblue": [176, 224, 230],\r
+               "purple": [128, 0, 128],\r
+               "rebeccapurple": [102, 51, 153],\r
+               "red": [255, 0, 0],\r
+               "rosybrown": [188, 143, 143],\r
+               "royalblue": [65, 105, 225],\r
+               "saddlebrown": [139, 69, 19],\r
+               "salmon": [250, 128, 114],\r
+               "sandybrown": [244, 164, 96],\r
+               "seagreen": [46, 139, 87],\r
+               "seashell": [255, 245, 238],\r
+               "sienna": [160, 82, 45],\r
+               "silver": [192, 192, 192],\r
+               "skyblue": [135, 206, 235],\r
+               "slateblue": [106, 90, 205],\r
+               "slategray": [112, 128, 144],\r
+               "slategrey": [112, 128, 144],\r
+               "snow": [255, 250, 250],\r
+               "springgreen": [0, 255, 127],\r
+               "steelblue": [70, 130, 180],\r
+               "tan": [210, 180, 140],\r
+               "teal": [0, 128, 128],\r
+               "thistle": [216, 191, 216],\r
+               "tomato": [255, 99, 71],\r
+               "turquoise": [64, 224, 208],\r
+               "violet": [238, 130, 238],\r
+               "wheat": [245, 222, 179],\r
+               "white": [255, 255, 255],\r
+               "whitesmoke": [245, 245, 245],\r
+               "yellow": [255, 255, 0],\r
+               "yellowgreen": [154, 205, 50]\r
+       };\r
+},{}],7:[function(require,module,exports){\r
+       /**\r
+        * @namespace Chart\r
+        */\r
+       var Chart = require(27)();\r
+\r
+       require(26)(Chart);\r
+       require(22)(Chart);\r
+       require(25)(Chart);\r
+       require(21)(Chart);\r
+       require(23)(Chart);\r
+       require(24)(Chart);\r
+       require(28)(Chart);\r
+       require(32)(Chart);\r
+       require(30)(Chart);\r
+       require(31)(Chart);\r
+       require(33)(Chart);\r
+       require(29)(Chart);\r
+       require(34)(Chart);\r
+\r
+       require(35)(Chart);\r
+       require(36)(Chart);\r
+       require(37)(Chart);\r
+       require(38)(Chart);\r
+\r
+       require(41)(Chart);\r
+       require(39)(Chart);\r
+       require(40)(Chart);\r
+       require(42)(Chart);\r
+       require(43)(Chart);\r
+       require(44)(Chart);\r
 \r
-                       helpers.extend(point, {\r
-                               // Utility\r
-                               _xScale: xScale,\r
-                               _yScale: yScale,\r
-                               _datasetIndex: dsIndex,\r
-                               _index: index,\r
+// Controllers must be loaded after elements\r
+// See Chart.core.datasetController.dataElementType\r
+       require(15)(Chart);\r
+       require(16)(Chart);\r
+       require(17)(Chart);\r
+       require(18)(Chart);\r
+       require(19)(Chart);\r
+       require(20)(Chart);\r
 \r
-                               // Desired view properties\r
-                               _model: {\r
-                                       x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(data, index, dsIndex, me.chart.isCombo),\r
-                                       y: reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex),\r
-                                       // Appearance\r
-                                       radius: reset ? 0 : custom.radius ? custom.radius : me.getRadius(data),\r
+       require(8)(Chart);\r
+       require(9)(Chart);\r
+       require(10)(Chart);\r
+       require(11)(Chart);\r
+       require(12)(Chart);\r
+       require(13)(Chart);\r
+       require(14)(Chart);\r
 \r
-                                       // Tooltip\r
-                                       hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)\r
-                               }\r
-                       });\r
+       window.Chart = module.exports = Chart;\r
 \r
-                       // Trick to reset the styles of the point\r
-                       Chart.DatasetController.prototype.removeHoverStyle.call(me, point, pointElementOptions);\r
+},{"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,"41":41,"42":42,"43":43,"44":44,"8":8,"9":9}],8:[function(require,module,exports){\r
+       "use strict";\r
 \r
-                       var model = point._model;\r
-                       model.skip = custom.skip ? custom.skip : (isNaN(model.x) || isNaN(model.y));\r
+       module.exports = function(Chart) {\r
 \r
-                       point.pivot();\r
-               },\r
+               Chart.Bar = function(context, config) {\r
+                       config.type = 'bar';\r
 \r
-               getRadius: function(value) {\r
-                       return value.r || this.chart.options.elements.point.radius;\r
-               },\r
+                       return new Chart(context, config);\r
+               };\r
 \r
-               setHoverStyle: function(point) {\r
-                       var me = this;\r
-                       Chart.DatasetController.prototype.setHoverStyle.call(me, point);\r
-\r
-                       // Radius\r
-                       var dataset = me.chart.data.datasets[point._datasetIndex];\r
-                       var index = point._index;\r
-                       var custom = point.custom || {};\r
-                       var model = point._model;\r
-                       model.radius = custom.hoverRadius ? custom.hoverRadius : (helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, me.chart.options.elements.point.hoverRadius)) + me.getRadius(dataset.data[index]);\r
-               },\r
+       };\r
+},{}],9:[function(require,module,exports){\r
+       "use strict";\r
 \r
-               removeHoverStyle: function(point) {\r
-                       var me = this;\r
-                       Chart.DatasetController.prototype.removeHoverStyle.call(me, point, me.chart.options.elements.point);\r
+       module.exports = function(Chart) {\r
 \r
-                       var dataVal = me.chart.data.datasets[point._datasetIndex].data[point._index];\r
-                       var custom = point.custom || {};\r
-                       var model = point._model;\r
+               Chart.Bubble = function(context, config) {\r
+                       config.type = 'bubble';\r
+                       return new Chart(context, config);\r
+               };\r
 \r
-                       model.radius = custom.radius ? custom.radius : me.getRadius(dataVal);\r
-               }\r
-       });\r
-};\r
+       };\r
+},{}],10:[function(require,module,exports){\r
+       "use strict";\r
 \r
-},{}],17:[function(require,module,exports){\r
-"use strict";\r
+       module.exports = function(Chart) {\r
 \r
-module.exports = function(Chart) {\r
+               Chart.Doughnut = function(context, config) {\r
+                       config.type = 'doughnut';\r
 \r
-       var helpers = Chart.helpers,\r
-               defaults = Chart.defaults;\r
+                       return new Chart(context, config);\r
+               };\r
 \r
-       defaults.doughnut = {\r
-               animation: {\r
-                       //Boolean - Whether we animate the rotation of the Doughnut\r
-                       animateRotate: true,\r
-                       //Boolean - Whether we animate scaling the Doughnut from the centre\r
-                       animateScale: false\r
-               },\r
-               aspectRatio: 1,\r
-               hover: {\r
-                       mode: 'single'\r
-               },\r
-               legendCallback: function(chart) {\r
-                       var text = [];\r
-                       text.push('<ul class="' + chart.id + '-legend">');\r
+       };\r
+},{}],11:[function(require,module,exports){\r
+       "use strict";\r
 \r
-                       var data = chart.data;\r
-                       var datasets = data.datasets;\r
-                       var labels = data.labels;\r
+       module.exports = function(Chart) {\r
 \r
-                       if (datasets.length) {\r
-                               for (var i = 0; i < datasets[0].data.length; ++i) {\r
-                                       text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');\r
-                                       if (labels[i]) {\r
-                                               text.push(labels[i]);\r
-                                       }\r
-                                       text.push('</li>');\r
-                               }\r
-                       }\r
+               Chart.Line = function(context, config) {\r
+                       config.type = 'line';\r
 \r
-                       text.push('</ul>');\r
-                       return text.join("");\r
-               },\r
-               legend: {\r
-                       labels: {\r
-                               generateLabels: function(chart) {\r
-                                       var data = chart.data;\r
-                                       if (data.labels.length && data.datasets.length) {\r
-                                               return data.labels.map(function(label, i) {\r
-                                                       var meta = chart.getDatasetMeta(0);\r
-                                                       var ds = data.datasets[0];\r
-                                                       var arc = meta.data[i];\r
-                                                       var custom = arc.custom || {};\r
-                                                       var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\r
-                                                       var arcOpts = chart.options.elements.arc;\r
-                                                       var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);\r
-                                                       var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);\r
-                                                       var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);\r
-\r
-                                                       return {\r
-                                                               text: label,\r
-                                                               fillStyle: fill,\r
-                                                               strokeStyle: stroke,\r
-                                                               lineWidth: bw,\r
-                                                               hidden: isNaN(ds.data[i]) || meta.data[i].hidden,\r
-\r
-                                                               // Extra data used for toggling the correct item\r
-                                                               index: i\r
-                                                       };\r
-                                               });\r
-                                       } else {\r
-                                               return [];\r
-                                       }\r
-                               }\r
-                       },\r
+                       return new Chart(context, config);\r
+               };\r
 \r
-                       onClick: function(e, legendItem) {\r
-                               var index = legendItem.index;\r
-                               var chart = this.chart;\r
-                               var i, ilen, meta;\r
+       };\r
+},{}],12:[function(require,module,exports){\r
+       "use strict";\r
 \r
-                               for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {\r
-                                       meta = chart.getDatasetMeta(i);\r
-                                       meta.data[index].hidden = !meta.data[index].hidden;\r
-                               }\r
+       module.exports = function(Chart) {\r
 \r
-                               chart.update();\r
-                       }\r
-               },\r
+               Chart.PolarArea = function(context, config) {\r
+                       config.type = 'polarArea';\r
 \r
-               //The percentage of the chart that we cut out of the middle.\r
-               cutoutPercentage: 50,\r
+                       return new Chart(context, config);\r
+               };\r
 \r
-               //The rotation of the chart, where the first data arc begins.\r
-               rotation: Math.PI * -0.5,\r
+       };\r
+},{}],13:[function(require,module,exports){\r
+       "use strict";\r
 \r
-               //The total circumference of the chart.\r
-               circumference: Math.PI * 2.0,\r
+       module.exports = function(Chart) {\r
 \r
-               // Need to override these to give a nice default\r
-               tooltips: {\r
-                       callbacks: {\r
-                               title: function() {\r
-                                       return '';\r
-                               },\r
-                               label: function(tooltipItem, data) {\r
-                                       return data.labels[tooltipItem.index] + ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\r
-                               }\r
-                       }\r
-               }\r
-       };\r
+               Chart.Radar = function(context, config) {\r
+                       config.options = Chart.helpers.configMerge({ aspectRatio: 1 }, config.options);\r
+                       config.type = 'radar';\r
 \r
-       defaults.pie = helpers.clone(defaults.doughnut);\r
-       helpers.extend(defaults.pie, {\r
-               cutoutPercentage: 0\r
-       });\r
+                       return new Chart(context, config);\r
+               };\r
 \r
+       };\r
 \r
-       Chart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({\r
+},{}],14:[function(require,module,exports){\r
+       "use strict";\r
 \r
-               dataElementType: Chart.elements.Arc,\r
+       module.exports = function(Chart) {\r
 \r
-               linkScales: helpers.noop,\r
+               var defaultConfig = {\r
+                       hover: {\r
+                               mode: 'single'\r
+                       },\r
 \r
-               // Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly\r
-               getRingIndex: function getRingIndex(datasetIndex) {\r
-                       var ringIndex = 0;\r
+                       scales: {\r
+                               xAxes: [{\r
+                                       type: "linear", // scatter should not use a category axis\r
+                                       position: "bottom",\r
+                                       id: "x-axis-1" // need an ID so datasets can reference the scale\r
+                               }],\r
+                               yAxes: [{\r
+                                       type: "linear",\r
+                                       position: "left",\r
+                                       id: "y-axis-1"\r
+                               }]\r
+                       },\r
 \r
-                       for (var j = 0; j < datasetIndex; ++j) {\r
-                               if (this.chart.isDatasetVisible(j)) {\r
-                                       ++ringIndex;\r
+                       tooltips: {\r
+                               callbacks: {\r
+                                       title: function() {\r
+                                               // Title doesn't make sense for scatter since we format the data as a point\r
+                                               return '';\r
+                                       },\r
+                                       label: function(tooltipItem) {\r
+                                               return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';\r
+                                       }\r
                                }\r
                        }\r
+               };\r
 \r
-                       return ringIndex;\r
-               },\r
-\r
-               update: function update(reset) {\r
-                       var me = this;\r
-                       var chart = me.chart,\r
-                               chartArea = chart.chartArea,\r
-                               opts = chart.options,\r
-                               arcOpts = opts.elements.arc,\r
-                               availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth,\r
-                               availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth,\r
-                               minSize = Math.min(availableWidth, availableHeight),\r
-                               offset = {\r
-                                       x: 0,\r
-                                       y: 0\r
-                               },\r
-                               meta = me.getMeta(),\r
-                               cutoutPercentage = opts.cutoutPercentage,\r
-                               circumference = opts.circumference;\r
-\r
-                       // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc\r
-                       if (circumference < Math.PI * 2.0) {\r
-                               var startAngle = opts.rotation % (Math.PI * 2.0);\r
-                               startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);\r
-                               var endAngle = startAngle + circumference;\r
-                               var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)};\r
-                               var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)};\r
-                               var contains0 = (startAngle <= 0 && 0 <= endAngle) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);\r
-                               var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle);\r
-                               var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);\r
-                               var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle);\r
-                               var cutout = cutoutPercentage / 100.0;\r
-                               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))};\r
-                               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))};\r
-                               var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5};\r
-                               minSize = Math.min(availableWidth / size.width, availableHeight / size.height);\r
-                               offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};\r
-                       }\r
+               // Register the default config for this type\r
+               Chart.defaults.scatter = defaultConfig;\r
 \r
-                       chart.outerRadius = Math.max(minSize / 2, 0);\r
-                       chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 1, 0);\r
-                       chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();\r
-                       chart.offsetX = offset.x * chart.outerRadius;\r
-                       chart.offsetY = offset.y * chart.outerRadius;\r
+               // Scatter charts use line controllers\r
+               Chart.controllers.scatter = Chart.controllers.line;\r
 \r
-                       meta.total = me.calculateTotal();\r
+               Chart.Scatter = function(context, config) {\r
+                       config.type = 'scatter';\r
+                       return new Chart(context, config);\r
+               };\r
 \r
-                       me.outerRadius = chart.outerRadius - (chart.radiusLength * me.getRingIndex(me.index));\r
-                       me.innerRadius = me.outerRadius - chart.radiusLength;\r
+       };\r
+},{}],15:[function(require,module,exports){\r
+       "use strict";\r
 \r
-                       helpers.each(meta.data, function(arc, index) {\r
-                               me.updateElement(arc, index, reset);\r
-                       });\r
-               },\r
+       module.exports = function(Chart) {\r
 \r
-               updateElement: function(arc, index, reset) {\r
-                       var me = this;\r
-                       var chart = me.chart,\r
-                               chartArea = chart.chartArea,\r
-                               opts = chart.options,\r
-                               animationOpts = opts.animation,\r
-                               arcOpts = opts.elements.arc,\r
-                               centerX = (chartArea.left + chartArea.right) / 2,\r
-                               centerY = (chartArea.top + chartArea.bottom) / 2,\r
-                               startAngle = opts.rotation, // non reset case handled later\r
-                               endAngle = opts.rotation, // non reset case handled later\r
-                               dataset = me.getDataset(),\r
-                               circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI)),\r
-                               innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius,\r
-                               outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius,\r
-                               custom = arc.custom || {},\r
-                               valueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\r
-\r
-                       helpers.extend(arc, {\r
-                               // Utility\r
-                               _datasetIndex: me.index,\r
-                               _index: index,\r
+               var helpers = Chart.helpers;\r
 \r
-                               // Desired view properties\r
-                               _model: {\r
-                                       x: centerX + chart.offsetX,\r
-                                       y: centerY + chart.offsetY,\r
-                                       startAngle: startAngle,\r
-                                       endAngle: endAngle,\r
-                                       circumference: circumference,\r
-                                       outerRadius: outerRadius,\r
-                                       innerRadius: innerRadius,\r
-                                       label: valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index])\r
-                               }\r
-                       });\r
+               Chart.defaults.bar = {\r
+                       hover: {\r
+                               mode: "label"\r
+                       },\r
 \r
-                       var model = arc._model;\r
-                       // Resets the visual styles\r
-                       this.removeHoverStyle(arc);\r
+                       scales: {\r
+                               xAxes: [{\r
+                                       type: "category",\r
 \r
-                       // Set correct angles if not resetting\r
-                       if (!reset || !animationOpts.animateRotate) {\r
-                               if (index === 0) {\r
-                                       model.startAngle = opts.rotation;\r
-                               } else {\r
-                                       model.startAngle = me.getMeta().data[index - 1]._model.endAngle;\r
-                               }\r
+                                       // Specific to Bar Controller\r
+                                       categoryPercentage: 0.8,\r
+                                       barPercentage: 0.9,\r
 \r
-                               model.endAngle = model.startAngle + model.circumference;\r
+                                       // grid line settings\r
+                                       gridLines: {\r
+                                               offsetGridLines: true\r
+                                       }\r
+                               }],\r
+                               yAxes: [{\r
+                                       type: "linear"\r
+                               }]\r
                        }\r
+               };\r
 \r
-                       arc.pivot();\r
-               },\r
+               Chart.controllers.bar = Chart.DatasetController.extend({\r
 \r
-               removeHoverStyle: function(arc) {\r
-                       Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);\r
-               },\r
+                       dataElementType: Chart.elements.Rectangle,\r
 \r
-               calculateTotal: function() {\r
-                       var dataset = this.getDataset();\r
-                       var meta = this.getMeta();\r
-                       var total = 0;\r
-                       var value;\r
+                       initialize: function(chart, datasetIndex) {\r
+                               Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex);\r
 \r
-                       helpers.each(meta.data, function(element, index) {\r
-                               value = dataset.data[index];\r
-                               if (!isNaN(value) && !element.hidden) {\r
-                                       total += Math.abs(value);\r
-                               }\r
-                       });\r
+                               // Use this to indicate that this is a bar dataset.\r
+                               this.getMeta().bar = true;\r
+                       },\r
 \r
-                       return total;\r
-               },\r
+                       // Get the number of datasets that display bars. We use this to correctly calculate the bar width\r
+                       getBarCount: function() {\r
+                               var me = this;\r
+                               var barCount = 0;\r
+                               helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) {\r
+                                       var meta = me.chart.getDatasetMeta(datasetIndex);\r
+                                       if (meta.bar && me.chart.isDatasetVisible(datasetIndex)) {\r
+                                               ++barCount;\r
+                                       }\r
+                               }, me);\r
+                               return barCount;\r
+                       },\r
 \r
-               calculateCircumference: function(value) {\r
-                       var total = this.getMeta().total;\r
-                       if (total > 0 && !isNaN(value)) {\r
-                               return (Math.PI * 2.0) * (value / total);\r
-                       } else {\r
-                               return 0;\r
-                       }\r
-               }\r
-       });\r
-};\r
+                       update: function(reset) {\r
+                               var me = this;\r
+                               helpers.each(me.getMeta().data, function(rectangle, index) {\r
+                                       me.updateElement(rectangle, index, reset);\r
+                               }, me);\r
+                       },\r
 \r
-},{}],18:[function(require,module,exports){\r
-"use strict";\r
+                       updateElement: function(rectangle, index, reset) {\r
+                               var me = this;\r
+                               var meta = me.getMeta();\r
+                               var xScale = me.getScaleForId(meta.xAxisID);\r
+                               var yScale = me.getScaleForId(meta.yAxisID);\r
+                               var scaleBase = yScale.getBasePixel();\r
+                               var rectangleElementOptions = me.chart.options.elements.rectangle;\r
+                               var custom = rectangle.custom || {};\r
+                               var dataset = me.getDataset();\r
+\r
+                               helpers.extend(rectangle, {\r
+                                       // Utility\r
+                                       _xScale: xScale,\r
+                                       _yScale: yScale,\r
+                                       _datasetIndex: me.index,\r
+                                       _index: index,\r
+\r
+                                       // Desired view properties\r
+                                       _model: {\r
+                                               x: me.calculateBarX(index, me.index),\r
+                                               y: reset ? scaleBase : me.calculateBarY(index, me.index),\r
+\r
+                                               // Tooltip\r
+                                               label: me.chart.data.labels[index],\r
+                                               datasetLabel: dataset.label,\r
+\r
+                                               // Appearance\r
+                                               base: reset ? scaleBase : me.calculateBarBase(me.index, index),\r
+                                               width: me.calculateBarWidth(index),\r
+                                               backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),\r
+                                               borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,\r
+                                               borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),\r
+                                               borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)\r
+                                       }\r
+                               });\r
+                               rectangle.pivot();\r
+                       },\r
 \r
-module.exports = function(Chart) {\r
+                       calculateBarBase: function(datasetIndex, index) {\r
+                               var me = this;\r
+                               var meta = me.getMeta();\r
+                               var yScale = me.getScaleForId(meta.yAxisID);\r
+                               var base = 0;\r
 \r
-       var helpers = Chart.helpers;\r
+                               if (yScale.options.stacked) {\r
+                                       var chart = me.chart;\r
+                                       var datasets = chart.data.datasets;\r
+                                       var value = Number(datasets[datasetIndex].data[index]);\r
 \r
-       Chart.defaults.line = {\r
-               showLines: true,\r
+                                       for (var i = 0; i < datasetIndex; i++) {\r
+                                               var currentDs = datasets[i];\r
+                                               var currentDsMeta = chart.getDatasetMeta(i);\r
+                                               if (currentDsMeta.bar && currentDsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {\r
+                                                       var currentVal = Number(currentDs.data[index]);\r
+                                                       base += value < 0 ? Math.min(currentVal, 0) : Math.max(currentVal, 0);\r
+                                               }\r
+                                       }\r
 \r
-               hover: {\r
-                       mode: "label"\r
-               },\r
+                                       return yScale.getPixelForValue(base);\r
+                               }\r
 \r
-               scales: {\r
-                       xAxes: [{\r
-                               type: "category",\r
-                               id: 'x-axis-0'\r
-                       }],\r
-                       yAxes: [{\r
-                               type: "linear",\r
-                               id: 'y-axis-0'\r
-                       }]\r
-               }\r
-       };\r
+                               return yScale.getBasePixel();\r
+                       },\r
 \r
-       function lineEnabled(dataset, options) {\r
-               return helpers.getValueOrDefault(dataset.showLine, options.showLines);\r
-       }\r
+                       getRuler: function(index) {\r
+                               var me = this;\r
+                               var meta = me.getMeta();\r
+                               var xScale = me.getScaleForId(meta.xAxisID);\r
+                               var datasetCount = me.getBarCount();\r
 \r
-       Chart.controllers.line = Chart.DatasetController.extend({\r
+                               var tickWidth;\r
 \r
-               datasetElementType: Chart.elements.Line,\r
+                               if (xScale.options.type === 'category') {\r
+                                       tickWidth = xScale.getPixelForTick(index + 1) - xScale.getPixelForTick(index);\r
+                               } else {\r
+                                       // Average width\r
+                                       tickWidth = xScale.width / xScale.ticks.length;\r
+                               }\r
+                               var categoryWidth = tickWidth * xScale.options.categoryPercentage;\r
+                               var categorySpacing = (tickWidth - (tickWidth * xScale.options.categoryPercentage)) / 2;\r
+                               var fullBarWidth = categoryWidth / datasetCount;\r
 \r
-               dataElementType: Chart.elements.Point,\r
+                               if (xScale.ticks.length !== me.chart.data.labels.length) {\r
+                                       var perc = xScale.ticks.length / me.chart.data.labels.length;\r
+                                       fullBarWidth = fullBarWidth * perc;\r
+                               }\r
 \r
-               addElementAndReset: function(index) {\r
-                       var me = this;\r
-                       var options = me.chart.options;\r
-                       var meta = me.getMeta();\r
+                               var barWidth = fullBarWidth * xScale.options.barPercentage;\r
+                               var barSpacing = fullBarWidth - (fullBarWidth * xScale.options.barPercentage);\r
 \r
-                       Chart.DatasetController.prototype.addElementAndReset.call(me, index);\r
+                               return {\r
+                                       datasetCount: datasetCount,\r
+                                       tickWidth: tickWidth,\r
+                                       categoryWidth: categoryWidth,\r
+                                       categorySpacing: categorySpacing,\r
+                                       fullBarWidth: fullBarWidth,\r
+                                       barWidth: barWidth,\r
+                                       barSpacing: barSpacing\r
+                               };\r
+                       },\r
 \r
-                       // Make sure bezier control points are updated\r
-                       if (lineEnabled(me.getDataset(), options) && meta.dataset._model.tension !== 0) {\r
-                               me.updateBezierControlPoints();\r
-                       }\r
-               },\r
+                       calculateBarWidth: function(index) {\r
+                               var xScale = this.getScaleForId(this.getMeta().xAxisID);\r
+                               if (xScale.options.barThickness) {\r
+                                       return xScale.options.barThickness;\r
+                               }\r
+                               var ruler = this.getRuler(index);\r
+                               return xScale.options.stacked ? ruler.categoryWidth : ruler.barWidth;\r
+                       },\r
 \r
-               update: function update(reset) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var line = meta.dataset;\r
-                       var points = meta.data || [];\r
-                       var options = me.chart.options;\r
-                       var lineElementOptions = options.elements.line;\r
-                       var scale = me.getScaleForId(meta.yAxisID);\r
-                       var i, ilen, custom;\r
-                       var dataset = me.getDataset();\r
-                       var showLine = lineEnabled(dataset, options);\r
-\r
-                       // Update Line\r
-                       if (showLine) {\r
-                               custom = line.custom || {};\r
+                       // Get bar index from the given dataset index accounting for the fact that not all bars are visible\r
+                       getBarIndex: function(datasetIndex) {\r
+                               var barIndex = 0;\r
+                               var meta, j;\r
 \r
-                               // Compatibility: If the properties are defined with only the old name, use those values\r
-                               if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {\r
-                                       dataset.lineTension = dataset.tension;\r
+                               for (j = 0; j < datasetIndex; ++j) {\r
+                                       meta = this.chart.getDatasetMeta(j);\r
+                                       if (meta.bar && this.chart.isDatasetVisible(j)) {\r
+                                               ++barIndex;\r
+                                       }\r
                                }\r
 \r
-                               // Utility\r
-                               line._scale = scale;\r
-                               line._datasetIndex = me.index;\r
-                               // Data\r
-                               line._children = points;\r
-                               // Model\r
-                               line._model = {\r
-                                       // Appearance\r
-                                       // The default behavior of lines is to break at null values, according\r
-                                       // to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158\r
-                                       // This option gives linse the ability to span gaps\r
-                                       spanGaps: dataset.spanGaps ? dataset.spanGaps : false,\r
-                                       tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),\r
-                                       backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),\r
-                                       borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),\r
-                                       borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),\r
-                                       borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),\r
-                                       borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),\r
-                                       borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),\r
-                                       borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),\r
-                                       fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),\r
-                                       // Scale\r
-                                       scaleTop: scale.top,\r
-                                       scaleBottom: scale.bottom,\r
-                                       scaleZero: scale.getBasePixel()\r
-                               };\r
+                               return barIndex;\r
+                       },\r
 \r
-                               line.pivot();\r
-                       }\r
+                       calculateBarX: function(index, datasetIndex) {\r
+                               var me = this;\r
+                               var meta = me.getMeta();\r
+                               var xScale = me.getScaleForId(meta.xAxisID);\r
+                               var barIndex = me.getBarIndex(datasetIndex);\r
 \r
-                       // Update Points\r
-                       for (i=0, ilen=points.length; i<ilen; ++i) {\r
-                               me.updateElement(points[i], i, reset);\r
-                       }\r
+                               var ruler = me.getRuler(index);\r
+                               var leftTick = xScale.getPixelForValue(null, index, datasetIndex, me.chart.isCombo);\r
+                               leftTick -= me.chart.isCombo ? (ruler.tickWidth / 2) : 0;\r
 \r
-                       if (showLine && line._model.tension !== 0) {\r
-                               me.updateBezierControlPoints();\r
-                       }\r
+                               if (xScale.options.stacked) {\r
+                                       return leftTick + (ruler.categoryWidth / 2) + ruler.categorySpacing;\r
+                               }\r
 \r
-                       // Now pivot the point for animation\r
-                       for (i=0, ilen=points.length; i<ilen; ++i) {\r
-                               points[i].pivot();\r
-                       }\r
-               },\r
+                               return leftTick +\r
+                                       (ruler.barWidth / 2) +\r
+                                       ruler.categorySpacing +\r
+                                       (ruler.barWidth * barIndex) +\r
+                                       (ruler.barSpacing / 2) +\r
+                                       (ruler.barSpacing * barIndex);\r
+                       },\r
 \r
-               getPointBackgroundColor: function(point, index) {\r
-                       var backgroundColor = this.chart.options.elements.point.backgroundColor;\r
-                       var dataset = this.getDataset();\r
-                       var custom = point.custom || {};\r
-\r
-                       if (custom.backgroundColor) {\r
-                               backgroundColor = custom.backgroundColor;\r
-                       } else if (dataset.pointBackgroundColor) {\r
-                               backgroundColor = helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, backgroundColor);\r
-                       } else if (dataset.backgroundColor) {\r
-                               backgroundColor = dataset.backgroundColor;\r
-                       }\r
+                       calculateBarY: function(index, datasetIndex) {\r
+                               var me = this;\r
+                               var meta = me.getMeta();\r
+                               var yScale = me.getScaleForId(meta.yAxisID);\r
+                               var value = Number(me.getDataset().data[index]);\r
 \r
-                       return backgroundColor;\r
-               },\r
+                               if (yScale.options.stacked) {\r
 \r
-               getPointBorderColor: function(point, index) {\r
-                       var borderColor = this.chart.options.elements.point.borderColor;\r
-                       var dataset = this.getDataset();\r
-                       var custom = point.custom || {};\r
-\r
-                       if (custom.borderColor) {\r
-                               borderColor = custom.borderColor;\r
-                       } else if (dataset.pointBorderColor) {\r
-                               borderColor = helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, borderColor);\r
-                       } else if (dataset.borderColor) {\r
-                               borderColor = dataset.borderColor;\r
-                       }\r
+                                       var sumPos = 0,\r
+                                               sumNeg = 0;\r
 \r
-                       return borderColor;\r
-               },\r
+                                       for (var i = 0; i < datasetIndex; i++) {\r
+                                               var ds = me.chart.data.datasets[i];\r
+                                               var dsMeta = me.chart.getDatasetMeta(i);\r
+                                               if (dsMeta.bar && dsMeta.yAxisID === yScale.id && me.chart.isDatasetVisible(i)) {\r
+                                                       var stackedVal = Number(ds.data[index]);\r
+                                                       if (stackedVal < 0) {\r
+                                                               sumNeg += stackedVal || 0;\r
+                                                       } else {\r
+                                                               sumPos += stackedVal || 0;\r
+                                                       }\r
+                                               }\r
+                                       }\r
 \r
-               getPointBorderWidth: function(point, index) {\r
-                       var borderWidth = this.chart.options.elements.point.borderWidth;\r
-                       var dataset = this.getDataset();\r
-                       var custom = point.custom || {};\r
-\r
-                       if (custom.borderWidth) {\r
-                               borderWidth = custom.borderWidth;\r
-                       } else if (dataset.pointBorderWidth) {\r
-                               borderWidth = helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth);\r
-                       } else if (dataset.borderWidth) {\r
-                               borderWidth = dataset.borderWidth;\r
-                       }\r
+                                       if (value < 0) {\r
+                                               return yScale.getPixelForValue(sumNeg + value);\r
+                                       } else {\r
+                                               return yScale.getPixelForValue(sumPos + value);\r
+                                       }\r
+                               }\r
 \r
-                       return borderWidth;\r
-               },\r
+                               return yScale.getPixelForValue(value);\r
+                       },\r
 \r
-               updateElement: function(point, index, reset) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var custom = point.custom || {};\r
-                       var dataset = me.getDataset();\r
-                       var datasetIndex = me.index;\r
-                       var value = dataset.data[index];\r
-                       var yScale = me.getScaleForId(meta.yAxisID);\r
-                       var xScale = me.getScaleForId(meta.xAxisID);\r
-                       var pointOptions = me.chart.options.elements.point;\r
-                       var x, y;\r
-\r
-                       // Compatibility: If the properties are defined with only the old name, use those values\r
-                       if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {\r
-                               dataset.pointRadius = dataset.radius;\r
-                       }\r
-                       if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) {\r
-                               dataset.pointHitRadius = dataset.hitRadius;\r
-                       }\r
+                       draw: function(ease) {\r
+                               var me = this;\r
+                               var easingDecimal = ease || 1;\r
+                               helpers.each(me.getMeta().data, function(rectangle, index) {\r
+                                       var d = me.getDataset().data[index];\r
+                                       if (d !== null && d !== undefined && !isNaN(d)) {\r
+                                               rectangle.transition(easingDecimal).draw();\r
+                                       }\r
+                               }, me);\r
+                       },\r
 \r
-                       x = xScale.getPixelForValue(value, index, datasetIndex, me.chart.isCombo);\r
-                       y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex, me.chart.isCombo);\r
-\r
-                       // Utility\r
-                       point._xScale = xScale;\r
-                       point._yScale = yScale;\r
-                       point._datasetIndex = datasetIndex;\r
-                       point._index = index;\r
-\r
-                       // Desired view properties\r
-                       point._model = {\r
-                               x: x,\r
-                               y: y,\r
-                               skip: custom.skip || isNaN(x) || isNaN(y),\r
-                               // Appearance\r
-                               radius: custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointOptions.radius),\r
-                               pointStyle: custom.pointStyle || helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointOptions.pointStyle),\r
-                               backgroundColor: me.getPointBackgroundColor(point, index),\r
-                               borderColor: me.getPointBorderColor(point, index),\r
-                               borderWidth: me.getPointBorderWidth(point, index),\r
-                               tension: meta.dataset._model ? meta.dataset._model.tension : 0,\r
-                               // Tooltip\r
-                               hitRadius: custom.hitRadius || helpers.getValueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius)\r
-                       };\r
-               },\r
+                       setHoverStyle: function(rectangle) {\r
+                               var dataset = this.chart.data.datasets[rectangle._datasetIndex];\r
+                               var index = rectangle._index;\r
 \r
-               calculatePointY: function(value, index, datasetIndex, isCombo) {\r
-                       var me = this;\r
-                       var chart = me.chart;\r
-                       var meta = me.getMeta();\r
-                       var yScale = me.getScaleForId(meta.yAxisID);\r
-                       var sumPos = 0;\r
-                       var sumNeg = 0;\r
-                       var i, ds, dsMeta;\r
-\r
-                       if (yScale.options.stacked) {\r
-                               for (i = 0; i < datasetIndex; i++) {\r
-                                       ds = chart.data.datasets[i];\r
-                                       dsMeta = chart.getDatasetMeta(i);\r
-                                       if (dsMeta.type === 'line' && chart.isDatasetVisible(i)) {\r
-                                               if (ds.data[index] < 0) {\r
-                                                       sumNeg += ds.data[index] || 0;\r
-                                               } else {\r
-                                                       sumPos += ds.data[index] || 0;\r
-                                               }\r
-                                       }\r
-                               }\r
+                               var custom = rectangle.custom || {};\r
+                               var model = rectangle._model;\r
+                               model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));\r
+                               model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));\r
+                               model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);\r
+                       },\r
 \r
-                               if (value < 0) {\r
-                                       return yScale.getPixelForValue(sumNeg + value);\r
-                               } else {\r
-                                       return yScale.getPixelForValue(sumPos + value);\r
-                               }\r
+                       removeHoverStyle: function(rectangle) {\r
+                               var dataset = this.chart.data.datasets[rectangle._datasetIndex];\r
+                               var index = rectangle._index;\r
+                               var custom = rectangle.custom || {};\r
+                               var model = rectangle._model;\r
+                               var rectangleElementOptions = this.chart.options.elements.rectangle;\r
+\r
+                               model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor);\r
+                               model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor);\r
+                               model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth);\r
                        }\r
 \r
-                       return yScale.getPixelForValue(value);\r
-               },\r
+               });\r
 \r
-               updateBezierControlPoints: function() {\r
-                       var meta = this.getMeta();\r
-                       var area = this.chart.chartArea;\r
-                       var points = meta.data || [];\r
-                       var i, ilen, point, model, controlPoints;\r
-\r
-                       for (i=0, ilen=points.length; i<ilen; ++i) {\r
-                               point = points[i];\r
-                               model = point._model;\r
-                               controlPoints = helpers.splineCurve(\r
-                                       helpers.previousItem(points, i)._model,\r
-                                       model,\r
-                                       helpers.nextItem(points, i)._model,\r
-                                       meta.dataset._model.tension\r
-                               );\r
-\r
-                               model.controlPointPreviousX = controlPoints.previous.x;\r
-                               model.controlPointPreviousY = controlPoints.previous.y;\r
-                               model.controlPointNextX = controlPoints.next.x;\r
-                               model.controlPointNextY = controlPoints.next.y;\r
-                       }\r
-               },\r
 \r
-               draw: function(ease) {\r
-                       var me = this;\r
-                       var meta = me.getMeta();\r
-                       var points = meta.data || [];\r
-                       var easingDecimal = ease || 1;\r
-                       var i, ilen;\r
-\r
-                       // Transition Point Locations\r
-                       for (i=0, ilen=points.length; i<ilen; ++i) {\r
-                               points[i].transition(easingDecimal);\r
-                       }\r
+               // including horizontalBar in the bar file, instead of a file of its own\r
+               // it extends bar (like pie extends doughnut)\r
+               Chart.defaults.horizontalBar = {\r
+                       hover: {\r
+                               mode: "label"\r
+                       },\r
 \r
-                       // Transition and Draw the line\r
-                       if (lineEnabled(me.getDataset(), me.chart.options)) {\r
-                               meta.dataset.transition(easingDecimal).draw();\r
-                       }\r
+                       scales: {\r
+                               xAxes: [{\r
+                                       type: "linear",\r
+                                       position: "bottom"\r
+                               }],\r
+                               yAxes: [{\r
+                                       position: "left",\r
+                                       type: "category",\r
+\r
+                                       // Specific to Horizontal Bar Controller\r
+                                       categoryPercentage: 0.8,\r
+                                       barPercentage: 0.9,\r
+\r
+                                       // grid line settings\r
+                                       gridLines: {\r
+                                               offsetGridLines: true\r
+                                       }\r
+                               }]\r
+                       },\r
+                       elements: {\r
+                               rectangle: {\r
+                                       borderSkipped: 'left'\r
+                               }\r
+                       },\r
+                       tooltips: {\r
+                               callbacks: {\r
+                                       title: function(tooltipItems, data) {\r
+                                               // Pick first xLabel for now\r
+                                               var title = '';\r
+\r
+                                               if (tooltipItems.length > 0) {\r
+                                                       if (tooltipItems[0].yLabel) {\r
+                                                               title = tooltipItems[0].yLabel;\r
+                                                       } else if (data.labels.length > 0 && tooltipItems[0].index < data.labels.length) {\r
+                                                               title = data.labels[tooltipItems[0].index];\r
+                                                       }\r
+                                               }\r
 \r
-                       // Draw the points\r
-                       for (i=0, ilen=points.length; i<ilen; ++i) {\r
-                               points[i].draw();\r
+                                               return title;\r
+                                       },\r
+                                       label: function(tooltipItem, data) {\r
+                                               var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';\r
+                                               return datasetLabel + ': ' + tooltipItem.xLabel;\r
+                                       }\r
+                               }\r
                        }\r
-               },\r
+               };\r
 \r
-               setHoverStyle: function(point) {\r
-                       // Point\r
-                       var dataset = this.chart.data.datasets[point._datasetIndex];\r
-                       var index = point._index;\r
-                       var custom = point.custom || {};\r
-                       var model = point._model;\r
-\r
-                       model.radius = custom.hoverRadius || helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);\r
-                       model.backgroundColor = custom.hoverBackgroundColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));\r
-                       model.borderColor = custom.hoverBorderColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));\r
-                       model.borderWidth = custom.hoverBorderWidth || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);\r
-               },\r
+               Chart.controllers.horizontalBar = Chart.controllers.bar.extend({\r
+                       updateElement: function(rectangle, index, reset) {\r
+                               var me = this;\r
+                               var meta = me.getMeta();\r
+                               var xScale = me.getScaleForId(meta.xAxisID);\r
+                               var yScale = me.getScaleForId(meta.yAxisID);\r
+                               var scaleBase = xScale.getBasePixel();\r
+                               var custom = rectangle.custom || {};\r
+                               var dataset = me.getDataset();\r
+                               var rectangleElementOptions = me.chart.options.elements.rectangle;\r
+\r
+                               helpers.extend(rectangle, {\r
+                                       // Utility\r
+                                       _xScale: xScale,\r
+                                       _yScale: yScale,\r
+                                       _datasetIndex: me.index,\r
+                                       _index: index,\r
+\r
+                                       // Desired view properties\r
+                                       _model: {\r
+                                               x: reset ? scaleBase : me.calculateBarX(index, me.index),\r
+                                               y: me.calculateBarY(index, me.index),\r
+\r
+                                               // Tooltip\r
+                                               label: me.chart.data.labels[index],\r
+                                               datasetLabel: dataset.label,\r
+\r
+                                               // Appearance\r
+                                               base: reset ? scaleBase : me.calculateBarBase(me.index, index),\r
+                                               height: me.calculateBarHeight(index),\r
+                                               backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),\r
+                                               borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,\r
+                                               borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),\r
+                                               borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)\r
+                                       },\r
+\r
+                                       draw: function () {\r
+                                               var ctx = this._chart.ctx;\r
+                                               var vm = this._view;\r
+\r
+                                               var halfHeight = vm.height / 2,\r
+                                                       topY = vm.y - halfHeight,\r
+                                                       bottomY = vm.y + halfHeight,\r
+                                                       right = vm.base - (vm.base - vm.x),\r
+                                                       halfStroke = vm.borderWidth / 2;\r
+\r
+                                               // Canvas doesn't allow us to stroke inside the width so we can\r
+                                               // adjust the sizes to fit if we're setting a stroke on the line\r
+                                               if (vm.borderWidth) {\r
+                                                       topY += halfStroke;\r
+                                                       bottomY -= halfStroke;\r
+                                                       right += halfStroke;\r
+                                               }\r
 \r
-               removeHoverStyle: function(point) {\r
-                       var me = this;\r
-                       var dataset = me.chart.data.datasets[point._datasetIndex];\r
-                       var index = point._index;\r
-                       var custom = point.custom || {};\r
-                       var model = point._model;\r
-\r
-                       // Compatibility: If the properties are defined with only the old name, use those values\r
-                       if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {\r
-                               dataset.pointRadius = dataset.radius;\r
-                       }\r
+                                               ctx.beginPath();\r
 \r
-                       model.radius = custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, me.chart.options.elements.point.radius);\r
-                       model.backgroundColor = me.getPointBackgroundColor(point, index);\r
-                       model.borderColor = me.getPointBorderColor(point, index);\r
-                       model.borderWidth = me.getPointBorderWidth(point, index);\r
-               }\r
-       });\r
-};\r
+                                               ctx.fillStyle = vm.backgroundColor;\r
+                                               ctx.strokeStyle = vm.borderColor;\r
+                                               ctx.lineWidth = vm.borderWidth;\r
+\r
+                                               // Corner points, from bottom-left to bottom-right clockwise\r
+                                               // | 1 2 |\r
+                                               // | 0 3 |\r
+                                               var corners = [\r
+                                                       [vm.base, bottomY],\r
+                                                       [vm.base, topY],\r
+                                                       [right, topY],\r
+                                                       [right, bottomY]\r
+                                               ];\r
+\r
+                                               // Find first (starting) corner with fallback to 'bottom'\r
+                                               var borders = ['bottom', 'left', 'top', 'right'];\r
+                                               var startCorner = borders.indexOf(vm.borderSkipped, 0);\r
+                                               if (startCorner === -1)\r
+                                                       startCorner = 0;\r
+\r
+                                               function cornerAt(index) {\r
+                                                       return corners[(startCorner + index) % 4];\r
+                                               }\r
 \r
-},{}],19:[function(require,module,exports){\r
-"use strict";\r
+                                               // Draw rectangle from 'startCorner'\r
+                                               ctx.moveTo.apply(ctx, cornerAt(0));\r
+                                               for (var i = 1; i < 4; i++)\r
+                                                       ctx.lineTo.apply(ctx, cornerAt(i));\r
 \r
-module.exports = function(Chart) {\r
+                                               ctx.fill();\r
+                                               if (vm.borderWidth) {\r
+                                                       ctx.stroke();\r
+                                               }\r
+                                       },\r
 \r
-       var helpers = Chart.helpers;\r
+                                       inRange: function (mouseX, mouseY) {\r
+                                               var vm = this._view;\r
+                                               var inRange = false;\r
 \r
-       Chart.defaults.polarArea = {\r
+                                               if (vm) {\r
+                                                       if (vm.x < vm.base) {\r
+                                                               inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.x && mouseX <= vm.base);\r
+                                                       } else {\r
+                                                               inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.base && mouseX <= vm.x);\r
+                                                       }\r
+                                               }\r
 \r
-               scale: {\r
-                       type: "radialLinear",\r
-                       lineArc: true // so that lines are circular\r
-               },\r
+                                               return inRange;\r
+                                       }\r
+                               });\r
 \r
-               //Boolean - Whether to animate the rotation of the chart\r
-               animation: {\r
-                       animateRotate: true,\r
-                       animateScale: true\r
-               },\r
+                               rectangle.pivot();\r
+                       },\r
 \r
-               aspectRatio: 1,\r
-               legendCallback: function(chart) {\r
-                       var text = [];\r
-                       text.push('<ul class="' + chart.id + '-legend">');\r
+                       calculateBarBase: function (datasetIndex, index) {\r
+                               var me = this;\r
+                               var meta = me.getMeta();\r
+                               var xScale = me.getScaleForId(meta.xAxisID);\r
+                               var base = 0;\r
 \r
-                       var data = chart.data;\r
-                       var datasets = data.datasets;\r
-                       var labels = data.labels;\r
+                               if (xScale.options.stacked) {\r
+                                       var chart = me.chart;\r
+                                       var datasets = chart.data.datasets;\r
+                                       var value = Number(datasets[datasetIndex].data[index]);\r
 \r
-                       if (datasets.length) {\r
-                               for (var i = 0; i < datasets[0].data.length; ++i) {\r
-                                       text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '">');\r
-                                       if (labels[i]) {\r
-                                               text.push(labels[i]);\r
+                                       for (var i = 0; i < datasetIndex; i++) {\r
+                                               var currentDs = datasets[i];\r
+                                               var currentDsMeta = chart.getDatasetMeta(i);\r
+                                               if (currentDsMeta.bar && currentDsMeta.xAxisID === xScale.id && chart.isDatasetVisible(i)) {\r
+                                                       var currentVal = Number(currentDs.data[index]);\r
+                                                       base += value < 0 ? Math.min(currentVal, 0) : Math.max(currentVal, 0);\r
+                                               }\r
                                        }\r
-                                       text.push('</span></li>');\r
-                               }\r
-                       }\r
 \r
-                       text.push('</ul>');\r
-                       return text.join("");\r
-               },\r
-               legend: {\r
-                       labels: {\r
-                               generateLabels: function(chart) {\r
-                                       var data = chart.data;\r
-                                       if (data.labels.length && data.datasets.length) {\r
-                                               return data.labels.map(function(label, i) {\r
-                                                       var meta = chart.getDatasetMeta(0);\r
-                                                       var ds = data.datasets[0];\r
-                                                       var arc = meta.data[i];\r
-                                                       var custom = arc.custom || {};\r
-                                                       var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\r
-                                                       var arcOpts = chart.options.elements.arc;\r
-                                                       var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);\r
-                                                       var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);\r
-                                                       var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);\r
-\r
-                                                       return {\r
-                                                               text: label,\r
-                                                               fillStyle: fill,\r
-                                                               strokeStyle: stroke,\r
-                                                               lineWidth: bw,\r
-                                                               hidden: isNaN(ds.data[i]) || meta.data[i].hidden,\r
-\r
-                                                               // Extra data used for toggling the correct item\r
-                                                               index: i\r
-                                                       };\r
-                                               });\r
-                                       } else {\r
-                                               return [];\r
-                                       }\r
+                                       return xScale.getPixelForValue(base);\r
                                }\r
+\r
+                               return xScale.getBasePixel();\r
                        },\r
 \r
-                       onClick: function(e, legendItem) {\r
-                               var index = legendItem.index;\r
-                               var chart = this.chart;\r
-                               var i, ilen, meta;\r
+                       getRuler: function (index) {\r
+                               var me = this;\r
+                               var meta = me.getMeta();\r
+                               var yScale = me.getScaleForId(meta.yAxisID);\r
+                               var datasetCount = me.getBarCount();\r
 \r
-                               for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {\r
-                                       meta = chart.getDatasetMeta(i);\r
-                                       meta.data[index].hidden = !meta.data[index].hidden;\r
+                               var tickHeight;\r
+                               if (yScale.options.type === 'category') {\r
+                                       tickHeight = yScale.getPixelForTick(index + 1) - yScale.getPixelForTick(index);\r
+                               } else {\r
+                                       // Average width\r
+                                       tickHeight = yScale.width / yScale.ticks.length;\r
                                }\r
+                               var categoryHeight = tickHeight * yScale.options.categoryPercentage;\r
+                               var categorySpacing = (tickHeight - (tickHeight * yScale.options.categoryPercentage)) / 2;\r
+                               var fullBarHeight = categoryHeight / datasetCount;\r
 \r
-                               chart.update();\r
-                       }\r
-               },\r
+                               if (yScale.ticks.length !== me.chart.data.labels.length) {\r
+                                       var perc = yScale.ticks.length / me.chart.data.labels.length;\r
+                                       fullBarHeight = fullBarHeight * perc;\r
+                               }\r
 \r
-               // Need to override these to give a nice default\r
-               tooltips: {\r
-                       callbacks: {\r
-                               title: function() {\r
-                                       return '';\r
-                               },\r
-                               label: function(tooltipItem, data) {\r
-                                       return data.labels[tooltipItem.index] + ': ' + tooltipItem.yLabel;\r
+                               var barHeight = fullBarHeight * yScale.options.barPercentage;\r
+                               var barSpacing = fullBarHeight - (fullBarHeight * yScale.options.barPercentage);\r
+\r
+                               return {\r
+                                       datasetCount: datasetCount,\r
+                                       tickHeight: tickHeight,\r
+                                       categoryHeight: categoryHeight,\r
+                                       categorySpacing: categorySpacing,\r
+                                       fullBarHeight: fullBarHeight,\r
+                                       barHeight: barHeight,\r
+                                       barSpacing: barSpacing\r
+                               };\r
+                       },\r
+\r
+                       calculateBarHeight: function (index) {\r
+                               var me = this;\r
+                               var yScale = me.getScaleForId(me.getMeta().yAxisID);\r
+                               if (yScale.options.barThickness) {\r
+                                       return yScale.options.barThickness;\r
                                }\r
-                       }\r
-               }\r
-       };\r
+                               var ruler = me.getRuler(index);\r
+                               return yScale.options.stacked ? ruler.categoryHeight : ruler.barHeight;\r
+                       },\r
 \r
-       Chart.controllers.polarArea = Chart.DatasetController.extend({\r
+                       calculateBarX: function (index, datasetIndex) {\r
+                               var me = this;\r
+                               var meta = me.getMeta();\r
+                               var xScale = me.getScaleForId(meta.xAxisID);\r
+                               var value = Number(me.getDataset().data[index]);\r
 \r
-               dataElementType: Chart.elements.Arc,\r
+                               if (xScale.options.stacked) {\r
 \r
-               linkScales: helpers.noop,\r
+                                       var sumPos = 0,\r
+                                               sumNeg = 0;\r
 \r
-               update: function update(reset) {\r
-                       var me = this;\r
-                       var chart = me.chart;\r
-                       var chartArea = chart.chartArea;\r
-                       var meta = me.getMeta();\r
-                       var opts = chart.options;\r
-                       var arcOpts = opts.elements.arc;\r
-                       var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);\r
-                       chart.outerRadius = Math.max((minSize - arcOpts.borderWidth / 2) / 2, 0);\r
-                       chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);\r
-                       chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();\r
-\r
-                       me.outerRadius = chart.outerRadius - (chart.radiusLength * me.index);\r
-                       me.innerRadius = me.outerRadius - chart.radiusLength;\r
-\r
-                       meta.count = me.countVisibleElements();\r
-\r
-                       helpers.each(meta.data, function(arc, index) {\r
-                               me.updateElement(arc, index, reset);\r
-                       });\r
-               },\r
+                                       for (var i = 0; i < datasetIndex; i++) {\r
+                                               var ds = me.chart.data.datasets[i];\r
+                                               var dsMeta = me.chart.getDatasetMeta(i);\r
+                                               if (dsMeta.bar && dsMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(i)) {\r
+                                                       var stackedVal = Number(ds.data[index]);\r
+                                                       if (stackedVal < 0) {\r
+                                                               sumNeg += stackedVal || 0;\r
+                                                       } else {\r
+                                                               sumPos += stackedVal || 0;\r
+                                                       }\r
+                                               }\r
+                                       }\r
 \r
-               updateElement: function(arc, index, reset) {\r
-                       var me = this;\r
-                       var chart = me.chart;\r
-                       var chartArea = chart.chartArea;\r
-                       var dataset = me.getDataset();\r
-                       var opts = chart.options;\r
-                       var animationOpts = opts.animation;\r
-                       var arcOpts = opts.elements.arc;\r
-                       var custom = arc.custom || {};\r
-                       var scale = chart.scale;\r
-                       var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\r
-                       var labels = chart.data.labels;\r
-\r
-                       var circumference = me.calculateCircumference(dataset.data[index]);\r
-                       var centerX = (chartArea.left + chartArea.right) / 2;\r
-                       var centerY = (chartArea.top + chartArea.bottom) / 2;\r
-\r
-                       // If there is NaN data before us, we need to calculate the starting angle correctly.\r
-                       // We could be way more efficient here, but its unlikely that the polar&