Merge "Delete old unused Polymer versions."
diff --git a/polymer_0.5.0/bower.json b/polymer_0.5.0/bower.json
deleted file mode 100644
index 6c2af27..0000000
--- a/polymer_0.5.0/bower.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "name": "chrome-infra",
-  "dependencies": {
-    "app-router": "~0.6.2",
-    "chai": "chai#~1.9.1",
-    "chartnewjs": "*",
-    "core-elements": "Polymer/core-elements#~0.5.0",
-    "dygraph": "http://dygraphs.com/1.0.1/dygraph-combined.js",
-    "gif.js": "~0.1.6",
-    "paper-elements": "Polymer/paper-elements#~0.5.0",
-    "polymer": "Polymer/polymer#~0.5.0",
-    "sugar": "sugar#~1.4.1"
-  }
-}
diff --git a/polymer_0.5.0/bower_components/app-router/.bower.json b/polymer_0.5.0/bower_components/app-router/.bower.json
deleted file mode 100644
index 271dc5d..0000000
--- a/polymer_0.5.0/bower_components/app-router/.bower.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
-  "name": "app-router",
-  "version": "0.6.2",
-  "authors": [
-    "Erik Ringsmuth <erik.ringsmuth@gmail.com>"
-  ],
-  "description": "Router for Web Components.",
-  "keywords": [
-    "web-components",
-    "router",
-    "polymer",
-    "x-tag"
-  ],
-  "main": "index.html",
-  "license": "MIT",
-  "homepage": "https://github.com/erikringsmuth/app-router",
-  "ignore": [
-    "**/.*",
-    "bower_components",
-    "node_modules",
-    "tests",
-    "tmp",
-    "gulpfile.js",
-    "package.json"
-  ],
-  "devDependencies": {
-    "platform": "Polymer/platform-dev#~0.3.5",
-    "polymer": "Polymer/polymer-dev#~0.3.5"
-  },
-  "_release": "0.6.2",
-  "_resolution": {
-    "type": "version",
-    "tag": "v0.6.2",
-    "commit": "eee41ff18b42c7b3836553308c922ddb3857eeaf"
-  },
-  "_source": "git://github.com/erikringsmuth/app-router.git",
-  "_target": "~0.6.2",
-  "_originalSource": "app-router"
-}
\ No newline at end of file
diff --git a/polymer_0.5.0/bower_components/app-router/LICENSE.md b/polymer_0.5.0/bower_components/app-router/LICENSE.md
deleted file mode 100644
index c22844b..0000000
--- a/polymer_0.5.0/bower_components/app-router/LICENSE.md
+++ /dev/null
@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 Erik Ringsmuth
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/polymer_0.5.0/bower_components/app-router/README.md b/polymer_0.5.0/bower_components/app-router/README.md
deleted file mode 100644
index bb020ff..0000000
--- a/polymer_0.5.0/bower_components/app-router/README.md
+++ /dev/null
@@ -1,189 +0,0 @@
-## Router for Web Components
-> Works with [Polymer](http://www.polymer-project.org/), [X-Tag](http://www.x-tags.org/), and natively with the [platform](https://github.com/Polymer/platform) polyfill.
-
-> [erikringsmuth.github.io/app-router](http://erikringsmuth.github.io/app-router)
-
-Lazy-loads content. Binds path variables and query parameters to the page element's attributes. Supports multiple layouts. Works with `hashchange` and HTML5 `pushState`. One set of routes will match regular paths `/`, hash paths `#/`, and hashbang paths `#!/`.
-
-[Download](https://github.com/erikringsmuth/app-router/archive/master.zip) or run `bower install app-router --save`.
-
-## Configuration
-
-```html
-<!doctype html>
-<html>
-  <head>
-    <title>App Router</title>
-    <link rel="import" href="/bower_components/app-router/app-router.html">
-  </head>
-  <body>
-    <app-router>
-      <!-- matches an exact path -->
-      <app-route path="/home" import="/pages/home-page.html"></app-route>
-
-      <!-- matches using a wildcard -->
-      <app-route path="/customer/*" import="/pages/customer-page.html"></app-route>
-
-      <!-- matches using a path variable -->
-      <app-route path="/order/:id" import="/pages/order-page.html"></app-route>
-
-      <!-- matches a pattern like '/word/number' -->
-      <app-route path="/^\/\w+\/\d+$/i" regex import="/pages/regex-page.html"></app-route>
-
-      <!-- matches everything else -->
-      <app-route path="*" import="/pages/not-found-page.html"></app-route>
-    </app-router>
-  </body>
-</html>
-```
-
-Changing the URL will find the first `app-route` that matches, load the element or template, and replace the current view.
-
-## Data Binding
-Path variables and query parameters automatically attach to the element's attributes.
-
-``` html
-<!-- url -->
-http://www.example.com/order/123?sort=ascending
-
-<!-- route -->
-<app-route path="/order/:id" import="/pages/order-page.html"></app-route>
-
-<!-- will bind 123 to the page's `id` attribute and "ascending" to the `sort` attribute -->
-<order-page id="123" sort="ascending"></order-page>
-```
-
-See it in action [here](http://erikringsmuth.github.io/app-router/#/databinding/1337?queryParam1=Routing%20with%20Web%20Components!).
-
-## Multiple Layouts
-Each page chooses which layout to use. This allows multiple layouts in the same app. Use `<content>` tag insertion points to insert the page into the layout. This is similar to nested routes but completely decouples the page layout from the router.
-
-This is a simple example showing a page and it's layout.
-
-#### home-page.html
-
-```html
-<link rel="import" href="/layouts/simple-layout.html">
-<polymer-element name="home-page" noscript>
-  <template>
-    <simple-layout>
-      <div class="title">Home</div>
-      <p>The home page!</p>
-    </simple-layout>
-  </template>
-</polymer-element>
-```
-
-#### simple-layout.html
-
-```html
-<polymer-element name="simple-layout" noscript>
-  <template>
-    <core-toolbar>
-      <content select=".title"><!-- content with class 'title' --></content>
-    </core-toolbar>
-    <content><!-- all other content --></content>
-  </template>
-</polymer-element>
-```
-
-## &lt;app-route&gt; options
-
-#### import a custom element
-Lazy-load a custom element.
-
-```html
-<app-route path="/customer/:customerId" import="/pages/customer-page.html"></app-route>
-```
-
-When you navigate to `/customer/123` the router will load `/pages/customer-page.html`, replace the active view with a new `customer-page` element, and bind any attributes `element.setAttribute('customerId', 123)`.
-
-You can manually set the element's name with the `element` attribute if it's different from the file name. This is useful when bundling (vulcanizing) custom elements.
-
-```html
-<app-route path="/customer/:customerId" import="/pages/page-bundle.html" element="customer-page"></app-route>
-```
-
-#### pre-loaded custom element
-You can route to a pre-loaded custom element. In this case, load the element normally in the `<head>` and include the `element="element-name"` attribute on the route. This is how you'd bundle and pre-load custom elements.
-
-```html
-<head>
-  <link rel="import" href="/pages/page-bundle.html">
-</head>
-<app-router>
-  <app-route path="/customer/:customerId" element="customer-page"></app-route>
-</app-router>
-```
-
-#### import template
-You can use a `<template>` instead of a custom element. This doesn't have data binding and is lighter-weight than a custom element. Just include the `template` attribute.
-
-```html
-<app-route path="/example" import="/pages/template-page.html" template></app-route>
-```
-
-#### inline template
-Finally, you can in-line a `<template>` like this.
-
-```html
-<app-route path="/example" template>
-  <template>
-    <p>Inline template FTW!</p>
-  </template>
-</app-route>
-```
-
-#### regular expressions
-Include the `regex` attribute to match on a regular expression. The format is the same as a JavaScript regular expression.
-```html
-<!-- matches a pattern like '/word/number' -->
-<app-route path="/^\/\w+\/\d+$/i" regex import="/pages/regex-page.html"></app-route>
-```
-Note: The regular expression must start with a `/` and end with a `/` optionally followed by `i`. Options global `g`, multiline `m`, and sticky `y` aren't valid when matching paths.
-
-## &lt;app-router&gt; options
-
-#### Trailing Slashes
-By default `/home` and `/home/` are treated as separate routes. You can configure the router to ignore trailing slashes with `trailingSlash="ignore"`.
-```html
-<app-router trailingSlash="ignore">
-  <!-- matches '/home' and '/home/' -->
-  <app-route path="/home" import="/pages/home-page.html"></app-route>
-</app-router>
-```
-
-## Navigation
-There are three ways change the active route. `hashchange`, `pushState()`, and a full page load.
-
-#### hashchange
-If you're using `hashchange` you don't need to do anything. Clicking a link `<a href="/#/new/page">New Page</a>` will fire a `hashchange` event and tell the router to load the new route. You don't need to handle the event in your code.
-
-#### pushState
-If you're using HTML5 `pushState` you need one extra step. The `pushState()` method was not meant to change the page, it was only meant to push state into history. This is an "undo" feature for single page applications. To use `pushState()` to navigate to another route you need to call it like this.
-
-```js
-history.pushState(stateObj, title, '/new/page'); // push a new URL into the history stack
-history.go(0); // go to the current state in the history stack, this fires a popstate event
-```
-
-#### Full page load
-Clicking a link `<a href="/new/page">New Page</a>` without a hash path will do a full page load. You need to make sure your server will return `index.html` when looking up the resource at `/new/page`. The simplest set up is to always return `index.html` and let the `app-router` handle the routing including a not found page.
-
-## Demo Site & Example Setup
-Check out the `app-router` in action at [erikringsmuth.github.io/app-router](http://erikringsmuth.github.io/app-router).
-
-You can download an example setup here https://github.com/erikringsmuth/app-router-examples to get running locally.
-
-## Build, Test, and Debug [![Build Status](https://travis-ci.org/erikringsmuth/app-router.png?branch=master)](https://travis-ci.org/erikringsmuth/app-router)
-Source files are under the `src` folder. The build process writes to the root directory. The easiest way to debug is to include the source script rather than the minified HTML import.
-```html
-<script src="/bower_components/app-router/src/app-router.js"></script>
-```
-
-To build:
-- Run `bower install` and `npm install` to install dev dependencies
-- Lint, build, and minify code changes with `gulp` (watch with `gulp watch`)
-- Start a static content server to run tests (node `http-server` or `python -m SimpleHTTPServer`)
-- Run unit tests in the browser (PhantomJS doesn't support Web Components) [http://localhost:8080/tests/SpecRunner.html](http://localhost:8080/tests/SpecRunner.html)
-- Manually run functional tests in the browser [http://localhost:8080/tests/functional-test-site/](http://localhost:8080/tests/functional-test-site/)
diff --git a/polymer_0.5.0/bower_components/app-router/app-router.csp.html b/polymer_0.5.0/bower_components/app-router/app-router.csp.html
deleted file mode 100644
index a4a7256..0000000
--- a/polymer_0.5.0/bower_components/app-router/app-router.csp.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!-- Copyright (C) 2014 Erik Ringsmuth - MIT license -->
-<script src="app-router.js"></script>
diff --git a/polymer_0.5.0/bower_components/app-router/app-router.html b/polymer_0.5.0/bower_components/app-router/app-router.html
deleted file mode 100644
index cad35df..0000000
--- a/polymer_0.5.0/bower_components/app-router/app-router.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!-- Copyright (C) 2014 Erik Ringsmuth - MIT license -->
-<script type="text/javascript">
-!function(t,e){function i(t,i,r){var n=e.createEvent("CustomEvent");return n.initCustomEvent(t,!1,!0,i),r.dispatchEvent(n)}e.registerElement("app-route",{prototype:Object.create(HTMLElement.prototype)}),e.registerElement("active-route",{prototype:Object.create(HTMLElement.prototype)});var r=Object.create(HTMLElement.prototype),n={},a="ActiveXObject"in t;r.attachedCallback=function(){"manual"!==this.getAttribute("init")&&this.init()},r.init=function(){this.isInitialized||(this.isInitialized=!0,this.activeRoute=e.createElement("app-route"),this.stateChangeHandler=this.go.bind(this),t.addEventListener("popstate",this.stateChangeHandler,!1),a&&t.addEventListener("hashchange",this.stateChangeHandler,!1),this.activeRouteContent=e.createElement("active-route"),this.appendChild(this.activeRouteContent),this.hasAttribute("shadow")&&(this.activeRouteContent=this.activeRouteContent.createShadowRoot()),this.go())},r.detachedCallback=function(){t.removeEventListener("popstate",this.stateChangeHandler,!1),a&&t.removeEventListener("hashchange",this.stateChangeHandler,!1)},r.go=function(){var e=this.parseUrlPath(t.location.href),r={path:e};if(i("state-change",r,this)){for(var n=this.querySelectorAll("app-route"),a=0;a<n.length;a++)if(this.testRoute(n[a].getAttribute("path"),e,this.getAttribute("trailingSlash"),n[a].hasAttribute("regex")))return void this.activateRoute(n[a],e);i("not-found",r,this)}},r.activateRoute=function(t,e){var r={path:e,route:t,oldRoute:this.activeRoute};if(i("activate-route-start",r,this)&&i("activate-route-start",r,t)){this.activeRoute.removeAttribute("active"),t.setAttribute("active","active"),this.activeRoute=t;var n=t.getAttribute("import"),a=t.getAttribute("path"),s=t.hasAttribute("regex"),o=t.getAttribute("element"),c=t.hasAttribute("template"),l=!c;l&&n?this.importAndActivateCustomElement(n,o,a,e,s,r):l&&!n&&o?this.activateCustomElement(o,a,e,s,r):c&&n?this.importAndActivateTemplate(n,t,r):c&&!n&&this.activateTemplate(t,r)}},r.importAndActivateCustomElement=function(t,i,r,a,s,o){if(!n.hasOwnProperty(t)){n[t]=!0;var c=e.createElement("link");c.setAttribute("rel","import"),c.setAttribute("href",t),e.head.appendChild(c)}this.activateCustomElement(i||t.split("/").slice(-1)[0].replace(".html",""),r,a,s,o)},r.activateCustomElement=function(i,r,n,a,s){var o=e.createElement(i),c=this.routeArguments(r,n,t.location.href,a);for(var l in c)c.hasOwnProperty(l)&&(o[l]=c[l]);this.activeElement(o,s)},r.importAndActivateTemplate=function(t,i,r){if(n.hasOwnProperty(t)){var a=e.querySelector('link[href="'+t+'"]');a.import?this.activeElement(e.importNode(a.import.querySelector("template").content,!0),r):a.onload=function(){i.hasAttribute("active")&&this.activeElement(e.importNode(a.import.querySelector("template").content,!0),r)}.bind(this)}else{n[t]=!0;var s=e.createElement("link");s.setAttribute("rel","import"),s.setAttribute("href",t),s.onload=function(){i.hasAttribute("active")&&this.activeElement(e.importNode(s.import.querySelector("template").content,!0),r)}.bind(this),e.head.appendChild(s)}},r.activateTemplate=function(t,i){var r=e.importNode(t.querySelector("template").content,!0);this.activeElement(r,i)},r.activeElement=function(t,e){for(;this.activeRouteContent.firstChild;)this.activeRouteContent.removeChild(this.activeRouteContent.firstChild);this.activeRouteContent.appendChild(t),i("activate-route-end",e,this),i("activate-route-end",e,e.route)},r.parseUrlPath=function(t){var e=t.split("/"),i="/"+e.splice(3,e.length-3).join("/"),r=i.split(/[\?#]/)[0],n=i.indexOf("#");if(-1!==n){var a=i.substring(n).split("?")[0];"#/"===a.substring(0,2)?r=a.substring(1):"#!/"===a.substring(0,3)&&(r=a.substring(2))}return r},r.testRoute=function(t,e,i,r){if("ignore"===i&&("/"===e.slice(-1)&&(e=e.slice(0,-1)),"/"!==t.slice(-1)||r||(t=t.slice(0,-1))),r){if("/"!==t.charAt(0))return!1;t=t.slice(1);var n="";if("/"===t.slice(-1))t=t.slice(0,-1);else{if("/i"!==t.slice(-2))return!1;t=t.slice(0,-2),n="i"}return new RegExp(t,n).test(e)}if(t===e||"*"===t)return!0;if(-1===t.indexOf("*")&&-1===t.indexOf(":"))return!1;var a=e.split("/"),s=t.split("/");if(a.length!==s.length)return!1;for(var o=0;o<s.length;o++){var c=s[o];if(c!==a[o]&&"*"!==c&&":"!==c.charAt(0))return!1}return!0},r.routeArguments=function(t,e,i,r){var n={},a=e.split("/");if(!r)for(var s=t.split("/"),o=0;o<s.length;o++){var c=s[o];":"===c.charAt(0)&&(n[c.substring(1)]=a[o])}var l=i.indexOf("?"),h="";if(-1!==l){h=i.substring(l);var u=h.indexOf("#");-1!==u&&(h=h.substring(0,u))}var v=i.indexOf("#/"),p=i.indexOf("#!/");if(-1!==v||-1!==p){var m="";m=i.substring(-1!==v?v:p),l=m.indexOf("?"),-1!==l&&(h=m.substring(l))}var d=h.substring(1).split("&");1===d.length&&""===d[0]&&(d=[]);for(var f=0;f<d.length;f++){var g=d[f],b=g.split("=");n[b[0]]=b.splice(1,b.length-1).join("=")}for(var A in n){var E=n[A];n[A]="true"===E?!0:"false"===E?!1:isNaN(E)||""===E?decodeURIComponent(E):+E}return n},e.registerElement("app-router",{prototype:r})}(window,document);
-</script>
diff --git a/polymer_0.5.0/bower_components/app-router/app-router.js b/polymer_0.5.0/bower_components/app-router/app-router.js
deleted file mode 100644
index 2a1f413..0000000
--- a/polymer_0.5.0/bower_components/app-router/app-router.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(t,e){function i(t,i,r){var n=e.createEvent("CustomEvent");return n.initCustomEvent(t,!1,!0,i),r.dispatchEvent(n)}e.registerElement("app-route",{prototype:Object.create(HTMLElement.prototype)}),e.registerElement("active-route",{prototype:Object.create(HTMLElement.prototype)});var r=Object.create(HTMLElement.prototype),n={},a="ActiveXObject"in t;r.attachedCallback=function(){"manual"!==this.getAttribute("init")&&this.init()},r.init=function(){this.isInitialized||(this.isInitialized=!0,this.activeRoute=e.createElement("app-route"),this.stateChangeHandler=this.go.bind(this),t.addEventListener("popstate",this.stateChangeHandler,!1),a&&t.addEventListener("hashchange",this.stateChangeHandler,!1),this.activeRouteContent=e.createElement("active-route"),this.appendChild(this.activeRouteContent),this.hasAttribute("shadow")&&(this.activeRouteContent=this.activeRouteContent.createShadowRoot()),this.go())},r.detachedCallback=function(){t.removeEventListener("popstate",this.stateChangeHandler,!1),a&&t.removeEventListener("hashchange",this.stateChangeHandler,!1)},r.go=function(){var e=this.parseUrlPath(t.location.href),r={path:e};if(i("state-change",r,this)){for(var n=this.querySelectorAll("app-route"),a=0;a<n.length;a++)if(this.testRoute(n[a].getAttribute("path"),e,this.getAttribute("trailingSlash"),n[a].hasAttribute("regex")))return void this.activateRoute(n[a],e);i("not-found",r,this)}},r.activateRoute=function(t,e){var r={path:e,route:t,oldRoute:this.activeRoute};if(i("activate-route-start",r,this)&&i("activate-route-start",r,t)){this.activeRoute.removeAttribute("active"),t.setAttribute("active","active"),this.activeRoute=t;var n=t.getAttribute("import"),a=t.getAttribute("path"),s=t.hasAttribute("regex"),o=t.getAttribute("element"),c=t.hasAttribute("template"),l=!c;l&&n?this.importAndActivateCustomElement(n,o,a,e,s,r):l&&!n&&o?this.activateCustomElement(o,a,e,s,r):c&&n?this.importAndActivateTemplate(n,t,r):c&&!n&&this.activateTemplate(t,r)}},r.importAndActivateCustomElement=function(t,i,r,a,s,o){if(!n.hasOwnProperty(t)){n[t]=!0;var c=e.createElement("link");c.setAttribute("rel","import"),c.setAttribute("href",t),e.head.appendChild(c)}this.activateCustomElement(i||t.split("/").slice(-1)[0].replace(".html",""),r,a,s,o)},r.activateCustomElement=function(i,r,n,a,s){var o=e.createElement(i),c=this.routeArguments(r,n,t.location.href,a);for(var l in c)c.hasOwnProperty(l)&&(o[l]=c[l]);this.activeElement(o,s)},r.importAndActivateTemplate=function(t,i,r){if(n.hasOwnProperty(t)){var a=e.querySelector('link[href="'+t+'"]');a.import?this.activeElement(e.importNode(a.import.querySelector("template").content,!0),r):a.onload=function(){i.hasAttribute("active")&&this.activeElement(e.importNode(a.import.querySelector("template").content,!0),r)}.bind(this)}else{n[t]=!0;var s=e.createElement("link");s.setAttribute("rel","import"),s.setAttribute("href",t),s.onload=function(){i.hasAttribute("active")&&this.activeElement(e.importNode(s.import.querySelector("template").content,!0),r)}.bind(this),e.head.appendChild(s)}},r.activateTemplate=function(t,i){var r=e.importNode(t.querySelector("template").content,!0);this.activeElement(r,i)},r.activeElement=function(t,e){for(;this.activeRouteContent.firstChild;)this.activeRouteContent.removeChild(this.activeRouteContent.firstChild);this.activeRouteContent.appendChild(t),i("activate-route-end",e,this),i("activate-route-end",e,e.route)},r.parseUrlPath=function(t){var e=t.split("/"),i="/"+e.splice(3,e.length-3).join("/"),r=i.split(/[\?#]/)[0],n=i.indexOf("#");if(-1!==n){var a=i.substring(n).split("?")[0];"#/"===a.substring(0,2)?r=a.substring(1):"#!/"===a.substring(0,3)&&(r=a.substring(2))}return r},r.testRoute=function(t,e,i,r){if("ignore"===i&&("/"===e.slice(-1)&&(e=e.slice(0,-1)),"/"!==t.slice(-1)||r||(t=t.slice(0,-1))),r){if("/"!==t.charAt(0))return!1;t=t.slice(1);var n="";if("/"===t.slice(-1))t=t.slice(0,-1);else{if("/i"!==t.slice(-2))return!1;t=t.slice(0,-2),n="i"}return new RegExp(t,n).test(e)}if(t===e||"*"===t)return!0;if(-1===t.indexOf("*")&&-1===t.indexOf(":"))return!1;var a=e.split("/"),s=t.split("/");if(a.length!==s.length)return!1;for(var o=0;o<s.length;o++){var c=s[o];if(c!==a[o]&&"*"!==c&&":"!==c.charAt(0))return!1}return!0},r.routeArguments=function(t,e,i,r){var n={},a=e.split("/");if(!r)for(var s=t.split("/"),o=0;o<s.length;o++){var c=s[o];":"===c.charAt(0)&&(n[c.substring(1)]=a[o])}var l=i.indexOf("?"),h="";if(-1!==l){h=i.substring(l);var u=h.indexOf("#");-1!==u&&(h=h.substring(0,u))}var v=i.indexOf("#/"),p=i.indexOf("#!/");if(-1!==v||-1!==p){var m="";m=i.substring(-1!==v?v:p),l=m.indexOf("?"),-1!==l&&(h=m.substring(l))}var d=h.substring(1).split("&");1===d.length&&""===d[0]&&(d=[]);for(var f=0;f<d.length;f++){var g=d[f],b=g.split("=");n[b[0]]=b.splice(1,b.length-1).join("=")}for(var A in n){var E=n[A];n[A]="true"===E?!0:"false"===E?!1:isNaN(E)||""===E?decodeURIComponent(E):+E}return n},e.registerElement("app-router",{prototype:r})}(window,document);
\ No newline at end of file
diff --git a/polymer_0.5.0/bower_components/app-router/bower.json b/polymer_0.5.0/bower_components/app-router/bower.json
deleted file mode 100644
index 2b766ee..0000000
--- a/polymer_0.5.0/bower_components/app-router/bower.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-  "name": "app-router",
-  "version": "0.6.2",
-  "authors": [
-    "Erik Ringsmuth <erik.ringsmuth@gmail.com>"
-  ],
-  "description": "Router for Web Components.",
-  "keywords": [
-    "web-components",
-    "router",
-    "polymer",
-    "x-tag"
-  ],
-  "main": "index.html",
-  "license": "MIT",
-  "homepage": "https://github.com/erikringsmuth/app-router",
-  "ignore": [
-    "**/.*",
-    "bower_components",
-    "node_modules",
-    "tests",
-    "tmp",
-    "gulpfile.js",
-    "package.json"
-  ],
-  "devDependencies": {
-    "platform": "Polymer/platform-dev#~0.3.5",
-    "polymer": "Polymer/polymer-dev#~0.3.5"
-  }
-}
diff --git a/polymer_0.5.0/bower_components/app-router/preview.png b/polymer_0.5.0/bower_components/app-router/preview.png
deleted file mode 100644
index d18770f..0000000
--- a/polymer_0.5.0/bower_components/app-router/preview.png
+++ /dev/null
Binary files differ
diff --git a/polymer_0.5.0/bower_components/app-router/src/app-router.html b/polymer_0.5.0/bower_components/app-router/src/app-router.html
deleted file mode 100644
index 8911ba8..0000000
--- a/polymer_0.5.0/bower_components/app-router/src/app-router.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<!-- Copyright (C) 2014 Erik Ringsmuth - MIT license -->
-<script type="text/javascript" src="app-router.js"></script>
diff --git a/polymer_0.5.0/bower_components/app-router/src/app-router.js b/polymer_0.5.0/bower_components/app-router/src/app-router.js
deleted file mode 100644
index 912ba1c..0000000
--- a/polymer_0.5.0/bower_components/app-router/src/app-router.js
+++ /dev/null
@@ -1,406 +0,0 @@
-(function(window, document) {
-  // <app-route path="/path" [import="/page/cust-el.html"] [element="cust-el"] [template]></app-route>
-  document.registerElement('app-route', {
-    prototype: Object.create(HTMLElement.prototype)
-  });
-
-  // <active-route></active-route> holds the active route's content when `shadow` is not enabled
-  document.registerElement('active-route', {
-    prototype: Object.create(HTMLElement.prototype)
-  });
-
-  // <app-router [shadow] [trailingSlash="strict|ignore"] [init="auto|manual"]></app-router>
-  var router = Object.create(HTMLElement.prototype);
-
-  var importedURIs = {};
-  var isIE = 'ActiveXObject' in window;
-
-  // fire(type, detail, node) - Fire a new CustomEvent(type, detail) on the node
-  //
-  // listen with document.querySelector('app-router').addEventListener(type, function(event) {
-  //   event.detail, event.preventDefault()
-  // })
-  function fire(type, detail, node) {
-    // create a CustomEvent the old way for IE9/10 support
-    var event = document.createEvent('CustomEvent');
-
-    // initCustomEvent(type, bubbles, cancelable, detail)
-    event.initCustomEvent(type, false, true, detail);
-
-    // returns false when event.preventDefault() is called, true otherwise
-    return node.dispatchEvent(event);
-  }
-
-  // Initial set up when attached
-  router.attachedCallback = function() {
-    if(this.getAttribute('init') !== 'manual') {
-      this.init();
-    }
-  };
-
-  // Initialize the router
-  router.init = function() {
-    if (this.isInitialized) {
-      return;
-    }
-    this.isInitialized = true;
-    this.activeRoute = document.createElement('app-route');
-
-    // Listen for URL change events.
-    this.stateChangeHandler = this.go.bind(this);
-    window.addEventListener('popstate', this.stateChangeHandler, false);
-    if (isIE) {
-      // IE is truly special! A hashchange is supposed to trigger a popstate, making popstate the only
-      // even you should need to listen to. Not the case in IE! Make another event listener for it!
-      window.addEventListener('hashchange', this.stateChangeHandler, false);
-    }
-
-    // set up an <active-route> element for the active route's content
-    this.activeRouteContent = document.createElement('active-route');
-    this.appendChild(this.activeRouteContent);
-    if (this.hasAttribute('shadow')) {
-      this.activeRouteContent = this.activeRouteContent.createShadowRoot();
-    }
-
-    // load the web component for the active route
-    this.go();
-  };
-
-  // clean up global event listeners
-  router.detachedCallback = function() {
-    window.removeEventListener('popstate', this.stateChangeHandler, false);
-    if (isIE) {
-      window.removeEventListener('hashchange', this.stateChangeHandler, false);
-    }
-  };
-
-  // go() - Find the first <app-route> that matches the current URL and change the active route
-  router.go = function() {
-    var urlPath = this.parseUrlPath(window.location.href);
-    var eventDetail = {
-      path: urlPath
-    };
-    if (!fire('state-change', eventDetail, this)) {
-      return;
-    }
-    var routes = this.querySelectorAll('app-route');
-    for (var i = 0; i < routes.length; i++) {
-      if (this.testRoute(routes[i].getAttribute('path'), urlPath, this.getAttribute('trailingSlash'), routes[i].hasAttribute('regex'))) {
-        this.activateRoute(routes[i], urlPath);
-        return;
-      }
-    }
-    fire('not-found', eventDetail, this);
-  };
-
-  // activateRoute(route, urlPath) - Activate the route
-  router.activateRoute = function(route, urlPath) {
-    var eventDetail = {
-      path: urlPath,
-      route: route,
-      oldRoute: this.activeRoute
-    };
-    if (!fire('activate-route-start', eventDetail, this)) {
-      return;
-    }
-    if (!fire('activate-route-start', eventDetail, route)) {
-      return;
-    }
-    
-    this.activeRoute.removeAttribute('active');
-    route.setAttribute('active', 'active');
-    this.activeRoute = route;
-
-    var importUri = route.getAttribute('import');
-    var routePath = route.getAttribute('path');
-    var isRegExp = route.hasAttribute('regex');
-    var elementName = route.getAttribute('element');
-    var isTemplate = route.hasAttribute('template');
-    var isElement = !isTemplate;
-
-    // import custom element
-    if (isElement && importUri) {
-      this.importAndActivateCustomElement(importUri, elementName, routePath, urlPath, isRegExp, eventDetail);
-    }
-    // pre-loaded custom element
-    else if (isElement && !importUri && elementName) {
-      this.activateCustomElement(elementName, routePath, urlPath, isRegExp, eventDetail);
-    }
-    // import template
-    else if (isTemplate && importUri) {
-      this.importAndActivateTemplate(importUri, route, eventDetail);
-    }
-    // pre-loaded template
-    else if (isTemplate && !importUri) {
-      this.activateTemplate(route, eventDetail);
-    }
-  };
-
-  // importAndActivateCustomElement(importUri, elementName, routePath, urlPath, isRegExp, eventDetail) - Import the custom element then replace the active route
-  // with a new instance of the custom element
-  router.importAndActivateCustomElement = function(importUri, elementName, routePath, urlPath, isRegExp, eventDetail) {
-    if (!importedURIs.hasOwnProperty(importUri)) {
-      importedURIs[importUri] = true;
-      var elementLink = document.createElement('link');
-      elementLink.setAttribute('rel', 'import');
-      elementLink.setAttribute('href', importUri);
-      document.head.appendChild(elementLink);
-    }
-    this.activateCustomElement(elementName || importUri.split('/').slice(-1)[0].replace('.html', ''), routePath, urlPath, isRegExp, eventDetail);
-  };
-
-  // activateCustomElement(elementName, routePath, urlPath, isRegExp, eventDetail) - Replace the active route with a new instance of the custom element
-  router.activateCustomElement = function(elementName, routePath, urlPath, isRegExp, eventDetail) {
-    var resourceEl = document.createElement(elementName);
-    var routeArgs = this.routeArguments(routePath, urlPath, window.location.href, isRegExp);
-    for (var arg in routeArgs) {
-      if (routeArgs.hasOwnProperty(arg)) {
-        resourceEl[arg] = routeArgs[arg];
-      }
-    }
-    this.activeElement(resourceEl, eventDetail);
-  };
-
-  // importAndActivateTemplate(importUri, route, eventDetail) - Import the template then replace the active route with a clone of the template's content
-  router.importAndActivateTemplate = function(importUri, route, eventDetail) {
-    if (importedURIs.hasOwnProperty(importUri)) {
-      // previously imported. this is an async operation and may not be complete yet.
-      var previousLink = document.querySelector('link[href="' + importUri + '"]');
-      if (previousLink.import) {
-        // the import is complete
-        this.activeElement(document.importNode(previousLink.import.querySelector('template').content, true), eventDetail);
-      } else {
-        // wait for `onload`
-        previousLink.onload = function() {
-          if (route.hasAttribute('active')) {
-            this.activeElement(document.importNode(previousLink.import.querySelector('template').content, true), eventDetail);
-          }
-        }.bind(this);
-      }
-    } else {
-      // template hasn't been loaded yet
-      importedURIs[importUri] = true;
-      var templateLink = document.createElement('link');
-      templateLink.setAttribute('rel', 'import');
-      templateLink.setAttribute('href', importUri);
-      templateLink.onload = function() {
-        if (route.hasAttribute('active')) {
-          this.activeElement(document.importNode(templateLink.import.querySelector('template').content, true), eventDetail);
-        }
-      }.bind(this);
-      document.head.appendChild(templateLink);
-    }
-  };
-
-  // activateTemplate(route, eventDetail) - Replace the active route with a clone of the template's content
-  router.activateTemplate = function(route, eventDetail) {
-    var clone = document.importNode(route.querySelector('template').content, true);
-    this.activeElement(clone, eventDetail);
-  };
-
-  // activeElement(element, eventDetail) - Replace the active route's content with the new element
-  router.activeElement = function(element, eventDetail) {
-    while (this.activeRouteContent.firstChild) {
-      this.activeRouteContent.removeChild(this.activeRouteContent.firstChild);
-    }
-    this.activeRouteContent.appendChild(element);
-    fire('activate-route-end', eventDetail, this);
-    fire('activate-route-end', eventDetail, eventDetail.route);
-  };
-
-  // urlPath(url) - Parses the url to get the path
-  //
-  // This will return the hash path if it exists or return the real path if no hash path exists.
-  //
-  // Example URL = 'http://domain.com/other/path?queryParam3=false#/example/path?queryParam1=true&queryParam2=example%20string'
-  // path = '/example/path'
-  //
-  // Note: The URL must contain the protocol like 'http(s)://'
-  router.parseUrlPath = function(url) {
-    // The relative URI is everything after the third slash including the third slash
-    // Example relativeUri = '/other/path?queryParam3=false#/example/path?queryParam1=true&queryParam2=example%20string'
-    var splitUrl = url.split('/');
-    var relativeUri = '/' + splitUrl.splice(3, splitUrl.length - 3).join('/');
-
-    // The path is everything in the relative URI up to the first ? or #
-    // Example path = '/other/path'
-    var path = relativeUri.split(/[\?#]/)[0];
-
-    // The hash is everything from the first # up to the the search starting with ? if it exists
-    // Example hash = '#/example/path'
-    var hashIndex = relativeUri.indexOf('#');
-    if (hashIndex !== -1) {
-      var hash = relativeUri.substring(hashIndex).split('?')[0];
-      if (hash.substring(0, 2) === '#/') {
-        // Hash path
-        path = hash.substring(1);
-      } else if (hash.substring(0, 3) === '#!/') {
-        // Hashbang path
-        path = hash.substring(2);
-      }
-    }
-
-    return path;
-  };
-
-  // router.testRoute(routePath, urlPath, trailingSlashOption, isRegExp) - Test if the route's path matches the URL's path
-  //
-  // Example routePath: '/example/*'
-  // Example urlPath = '/example/path'
-  router.testRoute = function(routePath, urlPath, trailingSlashOption, isRegExp) {
-    // This algorithm tries to fail or succeed as quickly as possible for the most common cases.
-
-    // handle trailing slashes (options: strict (default), ignore)
-    if (trailingSlashOption === 'ignore') {
-      // remove trailing / from the route path and URL path
-      if(urlPath.slice(-1) === '/') {
-        urlPath = urlPath.slice(0, -1);
-      }
-      if(routePath.slice(-1) === '/' && !isRegExp) {
-        routePath = routePath.slice(0, -1);
-      }
-    }
-
-    if (isRegExp) {
-      // parse HTML attribute path="/^\/\w+\/\d+$/i" to a regular expression `new RegExp('^\/\w+\/\d+$', 'i')`
-      // note that 'i' is the only valid option. global 'g', multiline 'm', and sticky 'y' won't be valid matchers for a path.
-      if (routePath.charAt(0) !== '/') {
-        // must start with a slash
-        return false;
-      }
-      routePath = routePath.slice(1);
-      var options = '';
-      if (routePath.slice(-1) === '/') {
-        routePath = routePath.slice(0, -1);
-      }
-      else if (routePath.slice(-2) === '/i') {
-        routePath = routePath.slice(0, -2);
-        options = 'i';
-      }
-      else {
-        // must end with a slash followed by zero or more options
-        return false;
-      }
-      return new RegExp(routePath, options).test(urlPath);
-    }
-
-    // If the urlPath is an exact match or '*' then the route is a match
-    if (routePath === urlPath || routePath === '*') {
-      return true;
-    }
-
-    // Look for wildcards
-    if (routePath.indexOf('*') === -1 && routePath.indexOf(':') === -1) {
-      // No wildcards and we already made sure it wasn't an exact match so the test fails
-      return false;
-    }
-
-    // Example urlPathSegments = ['', example', 'path']
-    var urlPathSegments = urlPath.split('/');
-
-    // Example routePathSegments = ['', 'example', '*']
-    var routePathSegments = routePath.split('/');
-
-    // There must be the same number of path segments or it isn't a match
-    if (urlPathSegments.length !== routePathSegments.length) {
-      return false;
-    }
-
-    // Check equality of each path segment
-    for (var i = 0; i < routePathSegments.length; i++) {
-      // The path segments must be equal, be a wildcard segment '*', or be a path parameter like ':id'
-      var routeSegment = routePathSegments[i];
-      if (routeSegment !== urlPathSegments[i] && routeSegment !== '*' && routeSegment.charAt(0) !== ':') {
-        // The path segment wasn't the same string and it wasn't a wildcard or parameter
-        return false;
-      }
-    }
-
-    // Nothing failed. The route matches the URL.
-    return true;
-  };
-
-  // router.routeArguments(routePath, urlPath, url, isRegExp) - Gets the path variables and query parameter values from the URL
-  router.routeArguments = function routeArguments(routePath, urlPath, url, isRegExp) {
-    var args = {};
-
-    // Example urlPathSegments = ['', example', 'path']
-    var urlPathSegments = urlPath.split('/');
-
-    if (!isRegExp) {
-      // Example routePathSegments = ['', 'example', '*']
-      var routePathSegments = routePath.split('/');
-
-      // Get path variables
-      // urlPath '/customer/123'
-      // routePath '/customer/:id'
-      // parses id = '123'
-      for (var index = 0; index < routePathSegments.length; index++) {
-        var routeSegment = routePathSegments[index];
-        if (routeSegment.charAt(0) === ':') {
-          args[routeSegment.substring(1)] = urlPathSegments[index];
-        }
-      }
-    }
-
-    // Get the query parameter values
-    // The search is the query parameters including the leading '?'
-    var searchIndex = url.indexOf('?');
-    var search = '';
-    if (searchIndex !== -1) {
-      search = url.substring(searchIndex);
-      var hashIndex = search.indexOf('#');
-      if (hashIndex !== -1) {
-        search = search.substring(0, hashIndex);
-      }
-    }
-    // If it's a hash URL we need to get the search from the hash
-    var hashPathIndex = url.indexOf('#/');
-    var hashBangPathIndex = url.indexOf('#!/');
-    if (hashPathIndex !== -1 || hashBangPathIndex !== -1) {
-      var hash = '';
-      if (hashPathIndex !== -1) {
-        hash = url.substring(hashPathIndex);
-      } else {
-        hash = url.substring(hashBangPathIndex);
-      }
-      searchIndex = hash.indexOf('?');
-      if (searchIndex !== -1) {
-        search = hash.substring(searchIndex);
-      }
-    }
-
-    var queryParameters = search.substring(1).split('&');
-    // split() on an empty string has a strange behavior of returning [''] instead of []
-    if (queryParameters.length === 1 && queryParameters[0] === '') {
-      queryParameters = [];
-    }
-    for (var i = 0; i < queryParameters.length; i++) {
-      var queryParameter = queryParameters[i];
-      var queryParameterParts = queryParameter.split('=');
-      args[queryParameterParts[0]] = queryParameterParts.splice(1, queryParameterParts.length - 1).join('=');
-    }
-
-    // Parse the arguments into unescaped strings, numbers, or booleans
-    for (var arg in args) {
-      var value = args[arg];
-      if (value === 'true') {
-        args[arg] = true;
-      } else if (value === 'false') {
-        args[arg] = false;
-      } else if (!isNaN(value) && value !== '') {
-        // numeric
-        args[arg] = +value;
-      } else {
-        // string
-        args[arg] = decodeURIComponent(value);
-      }
-    }
-
-    return args;
-  };
-
-  document.registerElement('app-router', {
-    prototype: router
-  });
-})(window, document);
diff --git a/polymer_0.5.0/bower_components/chai/.bower.json b/polymer_0.5.0/bower_components/chai/.bower.json
deleted file mode 100644
index 9337551..0000000
--- a/polymer_0.5.0/bower_components/chai/.bower.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
-  "name": "chai",
-  "version": "1.9.2",
-  "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic.",
-  "license": "MIT",
-  "keywords": [
-    "test",
-    "assertion",
-    "assert",
-    "testing",
-    "chai"
-  ],
-  "main": "chai.js",
-  "ignore": [
-    "build",
-    "components",
-    "lib",
-    "node_modules",
-    "support",
-    "test",
-    "index.js",
-    "Makefile",
-    ".*"
-  ],
-  "dependencies": {},
-  "devDependencies": {},
-  "homepage": "https://github.com/chaijs/chai",
-  "_release": "1.9.2",
-  "_resolution": {
-    "type": "version",
-    "tag": "1.9.2",
-    "commit": "73b4559e5ef336cf4292dfdb9ea4eb62b6bfadae"
-  },
-  "_source": "git://github.com/chaijs/chai.git",
-  "_target": "~1.9.1",
-  "_originalSource": "chai"
-}
\ No newline at end of file
diff --git a/polymer_0.5.0/bower_components/chai/CONTRIBUTING.md b/polymer_0.5.0/bower_components/chai/CONTRIBUTING.md
deleted file mode 100644
index cf6c5dc..0000000
--- a/polymer_0.5.0/bower_components/chai/CONTRIBUTING.md
+++ /dev/null
@@ -1,173 +0,0 @@
-# Chai Contribution Guidelines
-
-We like to encourage you to contribute to the Chai.js repository. This should be as easy as possible for you but there are a few things to consider when contributing. The following guidelines for contribution should be followed if you want to submit a pull request or open an issue.
-
-Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue or assessing patches and features.
-
-#### Table of Contents
-
-- [TLDR;](#tldr)
-- [Contributing](#contributing)
-  - [Bug Reports](#bugs)
-  - [Feature Requests](#features)
-  - [Pull Requests](#pull-requests)
-- [Support](#support)
-  - [Resources](#resources)
-  - [Core Contributors](#contributors)
-
-<a name="tldr"></a>
-## TLDR;
-
-- Creating an Issue or Pull Request requires a [GitHub](http://github.com) account.
-- Issue reports should be **clear**, **concise** and **reproducible**. Check to see if your issue has already been resolved in the [master]() branch or already reported in Chai's [GitHub Issue Tracker](https://github.com/chaijs/chai/issues).
-- Pull Requests must adhere to strict [coding style guidelines](https://github.com/chaijs/chai/wiki/Chai-Coding-Style-Guide).
-- In general, avoid submitting PRs for new Assertions without asking core contributors first. More than likely it would be better implemented as a plugin.
-- Additional support is available via the [Google Group](http://groups.google.com/group/chaijs) or on irc.freenode.net#chaijs.
-- **IMPORTANT**: By submitting a patch, you agree to allow the project owner to license your work under the same license as that used by the project.
-
-
-
-<a name="contributing"></a>
-## Contributing
-
-The issue tracker is the preferred channel for [bug reports](#bugs),
-[feature requests](#features) and [submitting pull
-requests](#pull-requests), but please respect the following restrictions:
-
-* Please **do not** use the issue tracker for personal support requests (use
-  [Google Group](https://groups.google.com/forum/#!forum/chaijs) or IRC).
-* Please **do not** derail or troll issues. Keep the discussion on topic and
-  respect the opinions of others
-
-<a name="bugs"></a>
-### Bug Reports
-
-A bug is a **demonstrable problem** that is caused by the code in the repository.
-
-Guidelines for bug reports:
-
-1. **Use the GitHub issue search** &mdash; check if the issue has already been reported.
-2. **Check if the issue has been fixed** &mdash; try to reproduce it using the latest `master` or development branch in the repository.
-3. **Isolate the problem** &mdash; create a test case to demonstrate your issue. Provide either a repo, gist, or code sample to demonstrate you problem.
-
-A good bug report shouldn't leave others needing to chase you up for more information. Please try to be as detailed as possible in your report. What is your environment? What steps will reproduce the issue? What browser(s) and/or Node.js versions experience the problem? What would you expect to be the outcome? All these details will help people to fix any potential bugs.
-
-Example:
-
-> Short and descriptive example bug report title
->
-> A summary of the issue and the browser/OS environment in which it occurs. If suitable, include the steps required to reproduce the bug.
->
-> 1. This is the first step
-> 2. This is the second step
-> 3. Further steps, etc.
->
-> `<url>` - a link to the reduced test case OR
-> ```js
-> expect(a).to.equal('a');
-> // code sample
-> ```
->
-> Any other information you want to share that is relevant to the issue being reported. This might include the lines of code that you have identified as causing the bug, and potential solutions (and your opinions on their merits).
-
-<a name="features"></a>
-### Feature Requests
-
-Feature requests are welcome. But take a moment to find out whether your idea fits with the scope and aims of the project. It's up to *you* to make a strong case to convince the project's developers of the merits of this feature. Please provide as much detail and context as possible.
-
-Furthermore, since Chai.js has a [robust plugin API](http://chaijs.com/guide/plugins/), we encourage you to publish **new Assertions** as plugins. If your feature is an enhancement to an **existing Assertion**, please propose your changes as an issue prior to opening a pull request. If the core Chai.js contributors feel your plugin would be better suited as a core assertion, they will invite you to open a PR in [chaijs/chai](https://github.com/chaijs/chai).
-
-<a name="pull-requests"></a>
-### Pull Requests
-
-- PRs for new core-assertions are advised against.
-- PRs for core-assertion bug fixes are always welcome.
-- PRs for enhancing the interfaces are always welcome.
-- PRs that increase test coverage are always welcome.
-- PRs are scrutinized for coding-style.
-
-Good pull requests - patches, improvements, new features - are a fantastic help. They should remain focused in scope and avoid containing unrelated commits.
-
-**Please ask first** before embarking on any significant pull request (e.g. implementing features, refactoring code), otherwise you risk spending a lot of time working on something that the project's developers might not want to merge into the project.
-
-Please adhere to the coding conventions used throughout a project (indentation, accurate comments, etc.) and any other requirements (such as test coverage). Please review the [Chai.js Coding Style Guide](https://github.com/chaijs/chai/wiki/Chai-Coding-Style-Guide).
-
-Follow this process if you'd like your work considered for inclusion in the project:
-
-1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork, and configure the remotes:
-
-```bash
-# Clone your fork of the repo into the current directory
-git clone https://github.com/<your-username>/<repo-name>
-# Navigate to the newly cloned directory
-cd <repo-name>
-# Assign the original repo to a remote called "upstream"
-git remote add upstream https://github.com/<upstream-owner>/<repo-name>
-```
-
-2. If you cloned a while ago, get the latest changes from upstream:
-
-```bash
-git checkout <dev-branch>
-git pull upstream <dev-branch>
-```
-
-3. Create a new topic branch (off the main project development branch) to contain your feature, change, or fix:
-
-```bash
-git checkout -b <topic-branch-name>
-```
-
-4. Commit your changes in logical chunks. Use Git's [interactive rebase](https://help.github.com/articles/interactive-rebase) feature to tidy up your commits before making them public.
-
-5. Locally merge (or rebase) the upstream development branch into your topic branch:
-
-```bash
-git pull [--rebase] upstream <dev-branch>
-```
-
-6. Push your topic branch up to your fork:
-
-```bash
-git push origin <topic-branch-name>
-```
-
-7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) with a clear title and description.
-
-**IMPORTANT**: By submitting a patch, you agree to allow the project owner to license your work under the same license as that used by the project.
-
-<a name="support"></a>
-## Support
-
-<a name="resources"></a>
-### Resources
-
-For most of the documentation you are going to want to visit [ChaiJS.com](http://chaijs.com).
-
-- [Getting Started Guide](http://chaijs.com/guide/)
-- [API Reference](http://chaijs.com/api/)
-- [Plugins](http://chaijs.com/plugins/)
-
-Alternatively, the [wiki](https://github.com/chaijs/chai/wiki) might be what you are looking for.
-
-- [Chai Coding Style Guide](https://github.com/chaijs/chai/wiki/Chai-Coding-Style-Guide)
-- [Third-party Resources](https://github.com/chaijs/chai/wiki/Third-Party-Resources)
-
-Or finally, you may find a core-contributor or like-minded developer in any of our support channels.
-
-- IRC: irc.freenode.org #chaijs
-- [Mailing List / Google Group](https://groups.google.com/forum/#!forum/chaijs)
-
-<a name="contributors"></a>
-### Core Contributors
-
-Feel free to reach out to any of the core-contributors with you questions or concerns. We will do our best to respond in a timely manner.
-
-- Jake Luer
-  - GH: [@logicalparadox](https://github.com/logicalparadox)
-  - TW: [@jakeluer](http://twitter.com/jakeluer)
-  - IRC: logicalparadox
-- Veselin Todorov
-  - GH: [@vesln](https://github.com/vesln/)
-  - TW: [@vesln](http://twitter.com/vesln)
-  - IRC: vesln
diff --git a/polymer_0.5.0/bower_components/chai/History.md b/polymer_0.5.0/bower_components/chai/History.md
deleted file mode 100644
index 9d406f6..0000000
--- a/polymer_0.5.0/bower_components/chai/History.md
+++ /dev/null
@@ -1,917 +0,0 @@
-
-1.9.2 / 2014-09-29 
-==================
-
- * Merge pull request #268 from charlierudolph/cr-lazyMessages
- * Merge pull request #269 from charlierudolph/cr-codeCleanup
- * Merge pull request #277 from charlierudolph/fix-doc
- * Merge pull request #279 from mohayonao/fix-closeTo
- * Merge pull request #292 from boneskull/mocha
- * resolves #255: upgrade mocha
- * Merge pull request #289 from charlierudolph/cr-dryUpCode
- * Dry up code
- * Merge pull request #275 from DrRataplan/master
- * assert: .closeTo() verify value's type before assertion
- * Rewrite pretty-printing HTML elements to prevent throwing internal errors Fixes errors occuring when using a non-native DOM implementation
- * Fix assert documentation
- * Remove unused argument
- * Allow messages to be functions
- * Merge pull request #267 from shinnn/master
- * Use SVG badge
- * Merge pull request #264 from cjthompson/keys_diff
- * Show diff for keys assertion
-
-1.9.1 / 2014-03-19 
-==================
-
-  * deps update
-  * util: [getActual] select actual logic now allows undefined for actual. Closes #183
-  * docs: [config] make public, express param type
-  * Merge pull request #251 from romario333/threshold3
-  * Fix issue #166 - configurable threshold in objDisplay.
-  * Move configuration options to config.js.
-  * Merge pull request #233 from Empeeric/master
-  * Merge pull request #244 from leider/fix_for_contains
-  * Merge pull request #247 from didoarellano/typo-fixes
-  * Fix typos
-  * Merge pull request #245 from lfac-pt/patch-1
-  * Update `exports.version` to 1.9.0
-  * aborting loop on finding
-  * declaring variable only once
-  * additional test finds incomplete implementation
-  * simplified code
-  * fixing #239 (without changing chai.js)
-  * ssfi as it should be
-  * Merge pull request #228 from duncanbeevers/deep_members
-  * Deep equality check for collection membership
-
-1.9.0 / 2014-01-29 
-==================
-
-  * docs: add contributing.md #238
-  * assert: .throws() returns thrown error. Closes #185
-  * Merge pull request #232 from laconbass/assert-throws
-  * assert: .fail() parameter mismatch. Closes #206
-  * Merge branch 'karma-fixes'
-  * Add karma phantomjs launcher
-  * Use latest karma and sauce launcher
-  * Karma tweaks
-  * Merge pull request #230 from jkroso/include
-  * Merge pull request #237 from chaijs/coverage
-  * Add coverage to npmignore
-  * Remove lib-cov from test-travisci dependents
-  * Remove the not longer needed lcov reporter
-  * Test coverage with istanbul
-  * Remove jscoverage
-  * Remove coveralls
-  * Merge pull request #226 from duncanbeevers/add_has
-  * Avoid error instantiation if possible on assert.throws
-  * Merge pull request #231 from duncanbeevers/update_copyright_year
-  * Update Copyright notices to 2014
-  * handle negation correctly
-  * add failing test case
-  * support `{a:1,b:2}.should.include({a:1})`
-  * Merge pull request #224 from vbardales/master
-  * Add `has` to language chains
-  * Merge pull request #219 from demands/overwrite_chainable
-  * return error on throw method to chain on error properties, possibly different from message
-  * util: store chainable behavior in a __methods object on ctx
-  * util: code style fix
-  * util: add overwriteChainableMethod utility (for #215)
-  * Merge pull request #217 from demands/test_cleanup
-  * test: make it possible to run utilities tests with --watch
-  * makefile: change location of karma-runner bin script
-  * Merge pull request #202 from andreineculau/patch-2
-  * test: add tests for throwing custom errors
-  * Merge pull request #201 from andreineculau/patch-1
-  * test: updated for the new assertion errors
-  * core: improve message for assertion errors (throw assertion)
-
-1.8.1 / 2013-10-10 
-==================
-
- * pkg: update deep-eql version
-
-1.8.0 / 2013-09-18 
-==================
-
- * test: [sauce] add a few more browsers
- * Merge branch 'refactor/deep-equal'
- * util: remove embedded deep equal utility
- * util: replace embedded deep equal with external module
- * Merge branch 'feature/karma'
- * docs: add sauce badge to readme [ci skip]
- * test: [sauce] use karma@canary to prevent timeouts
- * travis: only run on node 0.10
- * test: [karma] use karma phantomjs runner
- * Merge pull request #181 from tricknotes/fix-highlight
- * Fix highlight for example code
-
-1.7.2 / 2013-06-27 
-==================
-
-  * coverage: add coveralls badge
-  * test: [coveralls] add coveralls api integration. testing travis-ci integration
-  * Merge branch 'master' of github.com:chaijs/chai
-  * Merge branch 'feature/bower'
-  * Merge pull request #180 from tricknotes/modify-method-title
-  * Merge pull request #179 from tricknotes/highlight-code-example
-  * Modify method title to include argument name
-  * Fix to highlight code example
-  * bower: granular ignores
-
-1.7.1 / 2013-06-24 
-==================
-
-  * Merge branch 'feature/bower'. #175
-  * bower: add json file
-  * build: browser
-
-1.7.0 / 2013-06-17 
-==================
-
-  * error: remove internal assertion error constructor
-  * core: [assertion-error] replace internal assertion error with dep
-  * deps: add chaijs/assertion-error@1.0.0
-  * docs: fix typo in source file. #174
-  * Merge pull request #174 from piecioshka/master
-  * typo
-  * Merge branch 'master' of github.com:chaijs/chai
-  * pkg: lock mocha/mocha-phantomjs versions (for now)
-  * Merge pull request #173 from chaijs/inspect-fix
-  * Fix `utils.inspect` with custom object-returning inspect()s.
-  * Merge pull request #171 from Bartvds/master
-  * replaced tabs with 2 spaces
-  * added assert.notOk()
-  * Merge pull request #169 from katsgeorgeek/topics/master
-  * Fix comparison objects.
-
-1.6.1 / 2013-06-05 
-==================
-
-  * Merge pull request #168 from katsgeorgeek/topics/master
-  * Add test for different RegExp flags.
-  * Add test for regexp comparison.
-  * Downgrade mocha version for fix running Phantom tests.
-  * Fix comparison equality of two regexps.
-  * Merge pull request #161 from brandonpayton/master
-  * Fix documented name for assert interfaces isDefined method
-
-1.6.0 / 2013-04-29 
-==================
-
-  * build: browser
-  * assert: [(not)include] throw on incompatible haystack. Closes #142
-  * assert: [notInclude] add assert.notInclude. Closes #158
-  * browser build
-  * makefile: force browser build on browser-test
-  * makefile: use component for browser build
-  * core: [assertions] remove extraneous comments
-  * Merge branch 'master' of github.com:chaijs/chai
-  * test: [assert] deep equal ordering
-  * Merge pull request #153 from NickHeiner/array-assertions
-  * giving members a no-flag assertion
-  * Code review comments - changing syntax
-  * Code review comments
-  * Adding members and memberEquals assertions for checking for subsets and set equality. Implements chaijs/chai#148.
-  * Merge pull request #140 from RubenVerborgh/function-prototype
-  * Restore the `call` and `apply` methods of Function when adding a chainable method.
-  * readme: 2013
-  * notes: migration notes for deep equal changes
-  * test: for ever err() there must be a passing version
-
-1.5.0 / 2013-02-03 
-==================
-
-  * docs: add Release Notes for non-gitlog summary of changes.
-  * lib: update copyright to 2013
-  * Merge branch 'refactor/travis'
-  * makefile: remove test-component for full test run
-  * pkg: script test now runs make test so travis will test browser
-  * browser: build
-  * tests: refactor some tests to support new objDisplay output
-  * test: [bootstrap] normalize boostrap across all test scenarios
-  * assertions: refactor some assertions to use objDisplay instead of inspect
-  * util: [objDisplay] normalize output of functions
-  * makefile: refactor for full build scenarios
-  * component: fix build bug where missing util:type file
-  * assertions: [throw] code cleanup
-  * Merge branch 'refactor/typeDetection'
-  * browser: build
-  * makefile: chai.js is .PHONY so it builds every time
-  * test: [expect] add arguments type detection test
-  * core/assertions: [type] (a/an) refactor to use type detection utility
-  * util: add cross-browser type detection utility
-  * Merge branch 'feature/component'
-  * browser: build
-  * component: add component.json file
-  * makefile: refactor for fine grain control of testing scenarios
-  * test: add mochaPhantomJS support and component test file
-  * deps: add component and mocha-phantomjs for browser testing
-  * ignore: update ignore files for component support
-  * travis: run for all branches
-  * Merge branch 'feature/showDiff'
-  * test: [Assertion] configruable showDiff flag. Closes #132
-  * lib: [Assertion] add configurable showDiff flag. #132
-  * Merge branch 'feature/saucelabs'
-  * Merge branch 'master' into feature/saucelabs
-  * browser: build
-  * support: add mocha cloud runner, client, and html test page
-  * test: [saucelabs] add auth placeholder
-  * deps: add mocha-cloud
-  * Merge pull request #136 from whatthejeff/message_fix
-  * Merge pull request #138 from timnew/master
-  * Fix issue #137, test message existence by using message!=null rather than using message
-  * Fixed backwards negation messages.
-  * Merge pull request #133 from RubenVerborgh/throw
-  * Functions throwing strings can reliably be tested.
-  * Merge pull request #131 from RubenVerborgh/proto
-  * Cache whether __proto__ is supported.
-  * Use __proto__ if available.
-  * Determine the property names to exclude beforehand.
-  * Merge pull request #126 from RubenVerborgh/eqls
-  * Add alias eqls for eql.
-  * Use inherited enumerable properties in deep equality comparison.
-  * Show inherited properties when inspecting an object.
-  * Add new getProperties and getEnumerableProperties utils.
-  * showDiff: force true for equal and eql
-
-1.4.2 / 2012-12-21 
-==================
-
-  * browser build: (object diff support when used with mocha) #106
-  * test: [display] array test for mocha object diff
-  * browser: no longer need different AssertionError constructor
-
-1.4.1 / 2012-12-21 
-==================
-
-  * showDiff: force diff for equal and eql. #106
-  * test: [expect] type null. #122
-  * Merge pull request #115 from eshao/fix-assert-Throw
-  * FIX: assert.Throw checks error type/message
-  * TST: assert.Throw should check error type/message
-
-1.4.0 / 2012-11-29 
-==================
-
-  * pre-release browser build
-  * clean up index.js to not check for cov, revert package.json to use index.js
-  * convert tests to use new bootstrap
-  * refactor testing bootstrap
-  * use spaces (not tabs). Clean up #114
-  * Merge pull request #114 from trantorLiu/master
-  * Add most() (alias: lte) and least() (alias: gte) to the API with new chainers "at" and "of".
-  * Change `main` to ./lib/chai. Fixes #28.
-  * Merge pull request #104 from connec/deep_equals_circular_references_
-  * Merge pull request #109 from nnarhinen/patch-1
-  * Check for 'actual' type
-  * Added support for circular references when checking deep (in)equality.
-
-1.3.0 / 2012-10-01 
-==================
-
-  * browser build w/ folio >= 0.3.4. Closes #99
-  * add back buffer test for deep equal
-  * do not write flags to assertion.prototype
-  * remove buffer test from expect
-  * browser build
-  * improve documentation of custom error messages
-  * Merge branch 'master' of git://github.com/Liffft/chai into Liffft-master
-  * browser build
-  * improved buffer deep equal checking
-  * mocha is npm test command
-  * Cleaning up the js style…
-  * expect tests now include message pass-through
-  * packaging up browser-side changes…
-  * Increasing Throws error message verbosity
-  * Should syntax: piping message through
-  * Make globalShould test work in browser too.
-  * Add a setter for `Object.prototype.should`. Closes #86.
-
-1.2.0 / 2012-08-07 
-==================
-
-  * Merge branch 'feature/errmsg'
-  * browser build
-  * comment updates for utilities
-  * tweak objDislay to only kick in if object inspection is too long
-  * Merge branch 'master' into feature/errmsg
-  * add display sample for error message refactor
-  * first draft of error message refactor. #93
-  * add `closeTo` assertion to `assert` interface. Closes #89.
-  * update folio build for better require.js handling. Closes #85
-  * Merge pull request #92 from paulmillr/topics/add-dom-checks
-  * Add check for DOM objects.
-  * browser build
-  * Merge branch 'master' of github.com:chaijs/chai
-  * bug - getActual not defaulting to assertion subject
-  * Merge pull request #88 from pwnall/master
-  * Don't inspect() assertion arguments if the assertion passes.
-
-1.1.1 / 2012-07-09 
-==================
-
-  * improve commonjs support on browser build
-  * Merge pull request #83 from tkazec/equals
-  * Document .equals
-  * Add .equals as an alias of .equal
-  * remove unused browser prefix/suffix
-  * Merge branch 'feature/folio-build'
-  * browser build
-  * using folio to compile
-  * clean up makefile
-  * early folio 0.3.x support
-
-1.1.0 / 2012-06-26 
-==================
-
-  * browser build
-  * Disable "Assertion.includeStack is false" test in IE.
-  * Use `utils.getName` for all function inspections.
-  * Merge pull request #80 from kilianc/closeTo
-  * fixes #79
-  * browser build
-  * expand  docs to indicate change of subject for chaining. Closes #78
-  * add `that` chain noop
-  * Merge branch 'bug/74'
-  * comments on how to property use `length` as chain. Closes #74
-  * tests for length as chainable property. #74
-  * add support for `length` as chainable prop/method.
-  * Merge branch 'bug/77'
-  * tests for getPathValue when working with nested arrays. Closes #77
-  * add getPathValue support for nested arrays
-  * browser build
-  * fix bug for missing browser utils
-  * compile tool aware of new folder layout
-  * Merge branch 'refactor/1dot1'
-  * move core assertions to own file and refactor all using utils
-  * rearrange folder structure
-
-1.0.4 / 2012-06-03 
-==================
-
-  * Merge pull request #68 from fizker/itself
-  * Added itself chain.
-  * simplify error inspections for cross browser compatibility
-  * fix safari `addChainableMethod` errors. Closes #69
-
-1.0.3 / 2012-05-27 
-==================
-
-  * Point Travis badge to the right place.
-  * Make error message for eql/deep.equal more clear.
-  * Fix .not.deep.equal.
-  * contributors list
-
-1.0.2 / 2012-05-26 
-==================
-
-  * Merge pull request #67 from chaijs/chaining-and-flags
-  * Browser build.
-  * Use `addChainableMethod` to get away from `__proto__` manipulation.
-  * New `addChainableMethod` utility.
-  * Replace `getAllFlags` with `transferFlags` utility.
-  * browser build
-  * test - get all flags
-  * utility - get all flags
-  * Add .mailmap to .npmignore.
-  * Add a .mailmap file to fix my name in shortlogs.
-
-1.0.1 / 2012-05-18 
-==================
-
-  * browser build
-  * Fixing "an" vs. "a" grammar in type assertions.
-  * Uniformize `assert` interface inline docs.
-  * Don't use `instanceof` for `assert.isArray`.
-  * Add `deep` flag for equality and property value.
-  * Merge pull request #64 from chaijs/assertion-docs
-  * Uniformize assertion inline docs.
-  * Add npm-debug.log to .gitignore.
-  * no reserved words as actuals. #62
-
-1.0.0 / 2012-05-15 
-==================
-
-  * readme cleanup
-  * browser build
-  * utility comments
-  * removed docs
-  * update to package.json
-  * docs build
-  * comments / docs updates
-  * plugins app cleanup
-  * Merge pull request #61 from joliss/doc
-  * Fix and improve documentation of assert.equal and friends
-  * browser build
-  * doc checkpoint - texture
-  * Update chai-jquery link
-  * Use defined return value of Assertion extension functions
-  * Update utility docs
-
-1.0.0-rc3 / 2012-05-09 
-==================
-
-  * Merge branch 'feature/rc3'
-  * docs update
-  * browser build
-  * assert test conformity for minor refactor api
-  * assert minor refactor
-  * update util tests for new add/overwrite prop/method format
-  * added chai.Assertion.add/overwrite prop/method for plugin toolbox
-  * add/overwrite prop/method don't make assumptions about context
-  * doc test suite
-  * docs don't need coverage
-  * refactor all simple chains into one forEach loop, for clean documentation
-  * updated npm ignore
-  * remove old docs
-  * docs checkpoint - guide styled
-  * Merge pull request #59 from joliss/doc
-  * Document how to run the test suite
-  * don't need to rebuild docs to view
-  * dep update
-  * docs checkpoint - api section
-  * comment updates for docs
-  * new doc site checkpoint - plugin directory!
-  * Merge pull request #57 from kossnocorp/patch-1
-  * Fix typo: devDependancies → devDependencies
-  * Using message flag in `getMessage` util instead of old `msg` property.
-  * Adding self to package.json contributors.
-  * `getMessage` shouldn't choke on null/omitted messages.
-  * `return this` not necessary in example.
-  * `return this` not necessary in example.
-  * Sinon–Chai has a dash
-  * updated plugins list for docs
-
-1.0.0-rc2 / 2012-05-06 
-==================
-
-  * Merge branch 'feature/test-cov'
-  * browser build
-  * missing assert tests for ownProperty
-  * appropriate assert equivalent for expect.to.have.property(key, val)
-  * reset AssertionError to include full stack
-  * test for plugin utilities
-  * overwrite Property and Method now ensure chain
-  * version notes in readme
-
-1.0.0-rc1 / 2012-05-04 
-==================
-
-  * browser build (rc1)
-  * assert match/notMatch tests
-  * assert interface - notMatch, ownProperty, notOwnProperty, ownPropertyVal, ownPropertyNotVal
-  * cleaner should interface export.
-  * added chai.Assertion.prototype._obj (getter) for quick access to object flag
-  * moved almostEqual / almostDeepEqual to stats plugin
-  * added mocha.opts
-  * Add test for `utils.addMethod`
-  * Fix a typo
-  * Add test for `utils.overwriteMethod`
-  * Fix a typo
-  * Browser build
-  * Add undefined assertion
-  * Add null assertion
-  * Fix an issue with `mocha --watch`
-  * travis no longer tests on node 0.4.x
-  * removing unnecissary carbon dep
-  * Merge branch 'feature/plugins-app'
-  * docs build
-  * templates for docs express app for plugin directory
-  * express app for plugin and static serving
-  * added web server deps
-  * Merge pull request #54 from josher19/master
-  * Remove old test.assert code
-  * Use util.inspect instead of inspect for deepAlmostEqual and almostEqual
-  * browser build
-  * Added almostEqual and deepAlmostEqual to assert test suite.
-  * bug - context determinants for utils
-  * dec=0 means rounding, so assert.deepAlmostEqual({pi: 3.1416}, {pi: 3}, 0) is true
-  * wrong travis link
-  * readme updates for version information
-  * travis tests 0.5.x branch as well
-  * [bug] util `addProperty` not correctly exporting
-  * read me version notes
-  * browser build 1.0.0alpha1
-  * not using reserved words in internal assertions. #52
-  * version tick
-  * clean up redundant tests
-  * Merge branch 'refs/heads/0.6.x'
-  * update version tag in package 1.0.0alpha1
-  * browser build
-  * added utility tests to browser specs
-  * beginning utility testing
-  * updated utility comments
-  * utility - overwriteMethod
-  * utility - overwriteProperty
-  * utility - addMethod
-  * utility - addProperty
-  * missing ;
-  * contributors list update
-  * Merge branch 'refs/heads/0.6.x-docs' into 0.6.x
-  * Added guide link to docs. WIP
-  * Include/contain are now both properties and methods
-  * Add an alias annotation
-  * Remove usless function wrapper
-  * Fix a typo
-  * A/an are now both properties and methods
-  * [docs] new site homepage layout / color checkpoint
-  * Ignore IE-specific error properties.
-  * Fixing order of error message test.
-  * New cross-browser `getName` util.
-  * Fixing up `AssertionError` inheritance.
-  * backup docs
-  * Add doctypes
-  * [bug] was still using `constructor.name` in `throw` assertion
-  * [bug] flag Object.create(null) instead of new Object
-  * [test] browser build
-  * [refactor] all usage of Assertion.prototype.assert now uses template tags and flags
-  * [refactor] remove Assertion.prototype.inspect for testable object inspection
-  * [refactor] object to test is now stored in flag, with ssfi and custom message
-  * [bug] flag util - don't return on `set`
-  * [docs] comments for getMessage utility
-  * [feature] getMessage
-  * [feature] testing utilities
-  * [refactor] flag doesn't require `call`
-  * Make order of source files well-defined
-  * Added support for throw(errorInstance).
-  * Use a foolproof method of grabbing an error's name.
-  * Removed constructor.name check from throw.
-  * disabled stackTrack configuration tests until api is stable again
-  * first version of line displayed error for node js (unstable)
-  * refactor core Assertion to use flag utility for negation
-  * added flag utility
-  * tests for assert interface negatives. Closed #42
-  * added assertion negatives that were missing. #42
-  * Support for expected and actual parameters in assert-style error object
-  * chai as promised - readme
-  * Added assert.fail. Closes #40
-  * better error message for assert.operator. Closes #39
-  * [refactor] Assertion#property to use getPathValue property
-  * added getPathValue utility helper
-  * removed todo about browser build
-  * version notes
-  * version bumb 0.6.0
-  * browser build
-  * [refactor] browser compile function to replace with `require('./error')' with 'require('./browser/error')'
-  * [feature] browser uses different error.js
-  * [refactor] error without chai.fail
-  * Assertion & interfaces use new utils helper export
-  * [refactor] primary export for new plugin util usage
-  * added util index.js helper
-  * added 2012 to copyright headers
-  * Added DeepEqual assertions
-
-0.5.3 / 2012-04-21 
-==================
-
-  * Merge branch 'refs/heads/jgonera-oldbrowsers'
-  * browser build
-  * fixed reserved names for old browsers in interface/assert
-  * fixed reserved names for old browsers in interface/should
-  * fixed: chai.js no longer contains fail()
-  * fixed reserved names for old browsers in Assertion
-  * Merge pull request #49 from joliss/build-order
-  * Make order of source files well-defined
-  * Merge pull request #43 from zzen/patch-1
-  * Support for expected and actual parameters in assert-style error object
-  * chai as promised - readme
-
-0.5.2 / 2012-03-21 
-==================
-
-  * browser build
-  * Merge branch 'feature/assert-fail'
-  * Added assert.fail. Closes #40
-  * Merge branch 'bug/operator-msg'
-  * better error message for assert.operator. Closes #39
-  * version notes
-
-0.5.1 / 2012-03-14 
-==================
-
-  * chai.fail no longer exists
-  * Merge branch 'feature/assertdefined'
-  * Added asset#isDefined. Closes #37.
-  * dev docs update for Assertion#assert
-
-0.5.0 / 2012-03-07 
-==================
-
-  * [bug] on inspect of reg on n 0.4.12
-  * Merge branch 'bug/33-throws'
-  * Merge pull request #35 from logicalparadox/empty-object
-  * browser build
-  * updated #throw docs
-  * Assertion#throw `should` tests updated
-  * Assertion#throw `expect` tests
-  * Should interface supports multiple throw parameters
-  * Update Assertion#throw to support strings and type checks.
-  * Add more tests for `empty` in `should`.
-  * Add more tests for `empty` in `expect`.
-  * Merge branch 'master' into empty-object
-  * don't switch act/exp
-  * Merge pull request #34 from logicalparadox/assert-operator
-  * Update the compiled verison.
-  * Add `assert.operator`.
-  * Notes on messages. #22
-  * browser build
-  * have been test
-  * below tests
-  * Merge branch 'feature/actexp'
-  * browser build
-  * remove unnecessary fail export
-  * full support for actual/expected where relevant
-  * Assertion.assert support expected value
-  * clean up error
-  * Update the compiled version.
-  * Add object & sane arguments support to `Assertion#empty`.
-
-0.4.2 / 2012-02-28 
-==================
-
-  * fix for `process` not available in browser when used via browserify. Closes #28
-  * Merge pull request #31 from joliss/doc
-  * Document that "should" works in browsers other than IE
-  * Merge pull request #30 from logicalparadox/assert-tests
-  * Update the browser version of chai.
-  * Update `assert.doesNotThrow` test in order to check the use case when type is a string.
-  * Add test for `assert.ifError`.
-  * Falsey -> falsy.
-  * Full coverage for `assert.throws` and `assert.doesNotThrow`.
-  * Add test for `assert.doesNotThrow`.
-  * Add test for `assert.throws`.
-  * Add test for `assert.length`.
-  * Add test for `assert.include`.
-  * Add test for `assert.isBoolean`.
-  * Fix the implementation of `assert.isNumber`.
-  * Add test for `assert.isNumber`.
-  * Add test for `assert.isString`.
-  * Add test for `assert.isArray`.
-  * Add test for `assert.isUndefined`.
-  * Add test for `assert.isNotNull`.
-  * Fix `assert.isNotNull` implementation.
-  * Fix `assert.isNull` implementation.
-  * Add test for `assert.isNull`.
-  * Add test for `assert.notDeepEqual`.
-  * Add test for `assert.deepEqual`.
-  * Add test for `assert.notStrictEqual`.
-  * Add test for `assert.strictEqual`.
-  * Add test for `assert.notEqual`.
-
-0.4.1 / 2012-02-26 
-==================
-
-  * Merge pull request #27 from logicalparadox/type-fix
-  * Update the browser version.
-  * Add should tests for type checks.
-  * Add function type check test.
-  * Add more type checks tests.
-  * Add test for `new Number` type check.
-  * Fix type of actual checks.
-
-0.4.0 / 2012-02-25 
-==================
-
-  * docs and readme for upcoming 0.4.0
-  * docs generated
-  * putting coverage and tests for docs in docs/out/support
-  * make docs
-  * makefile copy necessary resources for tests in docs
-  * rename configuration test
-  * Merge pull request #21 from logicalparadox/close-to
-  * Update the browser version.
-  * Update `closeTo()` docs.
-  * Add `Assertion.closeTo()` method.
-  * Add `.closeTo()` should test.
-  * Add `.closeTo()` expect test.
-  * Merge pull request #20 from logicalparadox/satisfy
-  * Update the browser version.
-  * `..` -> `()` in `.satisfy()` should test.
-  * Update example for `.satisfy()`.
-  * Update the compiled browser version.
-  * Add `Assertion.satisfy()` method.
-  * Add `.satisfy()` should test.
-  * Add `.satisfy()` expect test.
-  * Merge pull request #19 from logicalparadox/respond-to
-  * Update the compiled browser version.
-  * Add `respondTo` Assertion.
-  * Add `respondTo` should test.
-  * Add `respondTo` expect test.
-  * Merge branch 'feature/coverage'
-  * mocha coverage support
-  * doc contributors
-  * README contributors
-
-0.3.4 / 2012-02-23 
-==================
-
-  * inline comment typos for #15
-  * Merge branch 'refs/heads/jeffbski-configErrorStackCompat'
-  * includeStack documentation for all interfaces
-  * suite name more generic
-  * Update test to be compatible with browsers that do not support err.stack
-  * udpated compiled chai.js and added to browser tests
-  * Allow inclusion of stack trace for Assert error messages to be configurable
-  * docs sharing buttons
-  * sinon-chai link
-  * doc updates
-  * read me updates include plugins
-
-0.3.3 / 2012-02-12 
-==================
-
-  * Merge pull request #14 from jfirebaugh/configurable_properties
-  * Make Assertion.prototype properties configurable
-
-0.3.2 / 2012-02-10 
-==================
-
-  * codex version
-  * docs
-  * docs cleanup
-
-0.3.1 / 2012-02-07 
-==================
-
-  * node 0.4.x compat
-
-0.3.0 / 2012-02-07 
-==================
-
-  * Merge branch 'feature/03x'
-  * browser build
-  * remove html/json/headers testign
-  * regex error.message testing
-  * tests for using plugins
-  * Merge pull request #11 from domenic/master
-  * Make `chai.use` a no-op if the function has already been used.
-
-0.2.4 / 2012-02-02 
-==================
-
-  * added in past tense switch for `been`
-
-0.2.3 / 2012-02-01 
-==================
-
-  * try that again
-
-0.2.2 / 2012-02-01 
-==================
-
-  * added `been` (past of `be`) alias
-
-0.2.1 / 2012-01-29 
-==================
-
-  * added Throw, with a capital T, as an alias to `throw` (#7)
-
-0.2.0 / 2012-01-26 
-==================
-
-  * update gitignore for vim *.swp
-  * Merge branch 'feature/plugins'
-  * browser build
-  * interfaces now work with use
-  * simple .use function. See #9.
-  * readme notice on browser compat
-
-0.1.7 / 2012-01-25 
-==================
-
-  * added assert tests to browser test runner
-  * browser update
-  * `should` interface patch for primitives support in FF
-  * fix isObject() Thanks @milewise
-  * travis only on branch `master`
-  * add instanceof alias `instanceOf`. #6
-  * some tests for assert module
-
-0.1.6 / 2012-01-02
-==================
-
-  * commenting for assert interface
-  * updated codex dep
-
-0.1.5 / 2012-01-02
-==================
-
-  * browser tests pass
-  * type in should.not.equal
-  * test for should (not) exist
-  * added should.exist and should.not.exist
-  * browser uses tdd
-  * convert tests to tdd
-
-0.1.4 / 2011-12-26
-==================
-
-  * browser lib update for new assert interface compatiblitiy
-  * inspect typos
-  * added strict equal + negatives and ifError
-  * interface assert had doesNotThrow
-  * added should tests to browser
-  * new expect empty tests
-  * should test browser compat
-  * Fix typo for instanceof docs. Closes #3 [ci skip]
-
-0.1.3 / 2011-12-18
-==================
-
-  * much cleaner reporting string on error.
-
-0.1.2 / 2011-12-18
-==================
-
-  * [docs] for upcoming 0.1.2
-  * browser version built with pre/suffix … all tests passing
-  * make / compile now use prefix/suffix correctly
-  * code clean
-  * prefix/suffix to wrap browser output to prevent conflicts with other `require` methods.
-  * Merge branch 'feature/should4xcompatibility'
-  * compile for browser tests.. all pass
-  * added header/status/html/json
-  * throw tests
-  * should.throw & should.not.throw shortcuts
-  * improved `throw` type detection and messaging
-  * contain is now `include` … keys modifier is now `contain`
-  * removed object() test
-  * removed #respondTo
-  * Merge branch 'bug/2'
-  * replaced __defineGetter__ with defineProperty for all uses
-  * [docs] change mp tracking code
-  * docs site updated with assert (TDD) interface
-  * updated doc comments for assert interface
-
-0.1.1 / 2011-12-16
-==================
-
-  * docs ready for upcoming 0.1.1
-  * readme image fixed [ci skip]
-  * more readme tweaks [ci skip]
-  * réadmet image fixed [ci skip]
-  * documentation
-  * codex locked in version 0.0.5
-  * more comments to assertions for docs
-  * assertions fully commented, browser library updated
-  * adding codex as doc dependancy
-  * prepping for docs
-  * assertion component completely commented for documentation
-  * added exist test
-  * var expect outside of browser if check
-  * added keywords to package.json
-
-0.1.0 / 2011-12-15
-==================
-
-  * failing on purpose successful .. back to normal
-  * testing travis failure
-  * assert#arguments getter
-  * readme typo
-  * updated README
-  * added travis and npmignore
-  * copyright notices … think i got them all
-  * moved expect interface to own file for consistency
-  * assert ui deepEqual
-  * browser tests expect (all working)
-  * browser version built
-  * chai.fail (should ui)
-  * expect tests browser compatible
-  * tests for should and expect (all pass)
-  * moved fail to primary export
-  * should compatibility testing
-  * within, greaterThan, object, keys,
-  * Aliases
-  * Assertion#property now correctly works with negate and undefined values
-  * error message language matches should
-  * Assertion#respondTo
-  * Assertion now uses inspect util
-  * git ignore node modules
-  * should is exported
-  * AssertionError __proto__ from Error.prototype
-  * add should interface for should.js compatibility
-  * moved eql to until folder and added inspect from (joyent/node)
-  * added mocha for testing
-  * browser build for current api
-  * multiple .property assertions
-  * added deep equal from node
-
-0.0.2 / 2011-12-07
-==================
-
-  * cleaner output on error
-  * improved exists detection
-  * package remnant artifact
-  * empty deep equal
-  * test browser build
-  * assertion cleanup
-  * client compile script
-  * makefile
-  * most of the basic assertions
-  * allow no parameters to assertion error
-  * name change
-  * assertion error instance
-  * main exports: assert() & expect()
-  * initialize
diff --git a/polymer_0.5.0/bower_components/chai/README.md b/polymer_0.5.0/bower_components/chai/README.md
deleted file mode 100644
index 4d00737..0000000
--- a/polymer_0.5.0/bower_components/chai/README.md
+++ /dev/null
@@ -1,99 +0,0 @@
-[![Chai Documentation](http://chaijs.com/public/img/chai-logo.png)](http://chaijs.com)
-
-Chai is a BDD / TDD assertion library for [node](http://nodejs.org) and the browser that
-can be delightfully paired with any javascript testing framework.
-
-For more information or to download plugins, view the [documentation](http://chaijs.com).
-
-[![Build Status](https://travis-ci.org/chaijs/chai.svg?branch=master)](https://travis-ci.org/chaijs/chai)
-
-[![Selenium Test Status](https://saucelabs.com/browser-matrix/chaijs.svg)](https://saucelabs.com/u/chaijs)
-
-### Plugins
-
-Chai offers a robust Plugin architecture for extending Chai's assertions and interfaces.
-
-- Need a plugin? View the [official plugin list](http://chaijs.com/plugins).
-- Have a plugin and want it listed? Open a Pull Request at [chaijs/chai-docs:plugin.js](https://github.com/chaijs/chai-docs/blob/master/plugins.js#L1-L12). 
-- Want to build a plugin? Read the [plugin api documentation](http://chaijs.com/guide/plugins/).
-
-### Related Projects
-
-- [chaijs / assertion-error](https://github.com/chaijs/assertion-error): Custom `Error` constructor thrown upon an assertion failing.
-- [chaijs / deep-eql](https://github.com/chaijs/deep-eql): Improved deep equality testing for Node.js and the browser.
-
-### Contributors
-
-     project  : chai
-     repo age : 2 years, 3 months ago
-     commits  : 756
-     active   : 170 days
-     files    : 57
-     authors  :
-       540  Jake Luer               71.4%
-        79  Veselin Todorov         10.4%
-        43  Domenic Denicola        5.7%
-         6  Ruben Verborgh          0.8%
-         5  George Kats             0.7%
-         5  Jo Liss                 0.7%
-         5  Juliusz Gonera          0.7%
-         5  Scott Nonnenberg        0.7%
-         5  leider                  0.7%
-         4  John Firebaugh          0.5%
-         4  Max Edmands             0.5%
-         4  Nick Heiner             0.5%
-         4  josher19                0.5%
-         3  Andrei Neculau          0.4%
-         3  Duncan Beevers          0.4%
-         3  Jake Rosoman            0.4%
-         3  Jeff Barczewski         0.4%
-         3  Ryunosuke SATO          0.4%
-         3  Veselin                 0.4%
-         2  Bartvds                 0.3%
-         2  Edwin Shao              0.3%
-         2  Jakub NešetÅ™il          0.3%
-         2  Roman Masek             0.3%
-         2  Teddy Cross             0.3%
-         1  Anand Patil             0.1%
-         1  Benjamin Horsleben      0.1%
-         1  Brandon Payton          0.1%
-         1  Chris Connelly          0.1%
-         1  Chun-Yi                 0.1%
-         1  DD                      0.1%
-         1  Dido Arellano           0.1%
-         1  Jeff Welch              0.1%
-         1  Kilian Ciuffolo         0.1%
-         1  Luís Cardoso            0.1%
-         1  Niklas Närhinen         0.1%
-         1  Paul Miller             0.1%
-         1  Refael Ackermann        0.1%
-         1  Sasha Koss              0.1%
-         1  Victor Costan           0.1%
-         1  Vinay Pulim             0.1%
-         1  Virginie BARDALES       0.1%
-         1  laconbass               0.1%
-         1  piecioshka              0.1%
-
-## License
-
-(The MIT License)
-
-Copyright (c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/polymer_0.5.0/bower_components/chai/ReleaseNotes.md b/polymer_0.5.0/bower_components/chai/ReleaseNotes.md
deleted file mode 100644
index f945e03..0000000
--- a/polymer_0.5.0/bower_components/chai/ReleaseNotes.md
+++ /dev/null
@@ -1,507 +0,0 @@
-# Release Notes
-
-## 1.9.2 / 2014-09-29 
-
-The following changes are required if you are upgrading from the previous version:
-
-- **Users:**
-  - No changes required
-- **Plugin Developers:** 
-  - No changes required
-- **Core Contributors:** 
-  - Refresh `node_modules` folder for updated dependencies. 
-
-### Community Contributions
-
-- [#264](https://github.com/chaijs/chai/pull/264) Show diff for keys assertions [@cjthompson](https://github.com/cjthompson)
-- [#267](https://github.com/chaijs/chai/pull/267) Use SVG badges [@shinnn](https://github.com/shinnn)
-- [#268](https://github.com/chaijs/chai/pull/268) Allow messages to be functions (sinon-compat) [@charlierudolph](https://github.com/charlierudolph)
-- [#269](https://github.com/chaijs/chai/pull/269) Remove unused argument for #lengthOf [@charlierudolph](https://github.com/charlierudolph)
-- [#275](https://github.com/chaijs/chai/pull/275) Rewrite pretty-printing HTML elements to prevent throwing internal errors [@DrRataplan](https://github.com/DrRataplan)
-- [#277](https://github.com/chaijs/chai/pull/277) Fix assert documentation for #sameMembers [@charlierudolph](https://github.com/charlierudolph)
-- [#279](https://github.com/chaijs/chai/pull/279) closeTo should check value's type before assertion [@mohayonao](https://github.com/mohayonao)
-- [#289](https://github.com/chaijs/chai/pull/289) satisfy is called twice [@charlierudolph](https://github.com/charlierudolph)
-- [#292](https://github.com/chaijs/chai/pull/292) resolve conflicts with node-webkit and global usage [@boneskull](https://github.com/boneskull)
-
-Thank you to all who took time to contribute!
-
-## 1.9.1 / 2014-03-19 
-
-The following changes are required if you are upgrading from the previous version:
-
-- **Users:**
-  - Migrate configuration options to new interface. (see notes)
-- **Plugin Developers:** 
-  - No changes required
-- **Core Contributors:** 
-  - Refresh `node_modules` folder for updated dependencies. 
-
-### Configuration
-
-There have been requests for changes and additions to the configuration mechanisms
-and their impact in the Chai architecture. As such, we have decoupled the 
-configuration from the `Assertion` constructor. This not only allows for centralized
-configuration, but will allow us to shift the responsibility from the `Assertion` 
-constructor to the `assert` interface in future releases.
-
-These changes have been implemented in a non-breaking way, but a depretiation
-warning will be presented to users until they migrate. The old config method will 
-be removed in either `v1.11.0` or `v2.0.0`, whichever comes first.
-
-#### Quick Migration
-
-```js
-// change this:
-chai.Assertion.includeStack = true;
-chai.Assertion.showDiff = false;
-
-// ... to this:
-chai.config.includeStack = true;
-chai.config.showDiff = false;
-```
-
-#### All Config Options
-
-##### config.includeStack
-
-- **@param** _{Boolean}_
-- **@default** `false`
-
-User configurable property, influences whether stack trace is included in 
-Assertion error message. Default of `false` suppresses stack trace in the error 
-message.
-
-##### config.showDiff
-
-- **@param** _{Boolean}_
-- **@default** `true`
-
-User configurable property, influences whether or not the `showDiff` flag 
-should be included in the thrown AssertionErrors. `false` will always be `false`; 
-`true` will be true when the assertion has requested a diff be shown.
-
-##### config.truncateThreshold **(NEW)**
-
-- **@param** _{Number}_
-- **@default** `40`
-
-User configurable property, sets length threshold for actual and expected values 
-in assertion errors. If this threshold is exceeded, the value is truncated.
-
-Set it to zero if you want to disable truncating altogether.
-
-```js
-chai.config.truncateThreshold = 0; // disable truncating
-```
-
-### Community Contributions
-
-- [#228](https://github.com/chaijs/chai/pull/228) Deep equality check for memebers. [@duncanbeevers](https://github.com/duncanbeevers)
-- [#247](https://github.com/chaijs/chai/pull/247) Proofreading. [@didorellano](https://github.com/didoarellano)
-- [#244](https://github.com/chaijs/chai/pull/244) Fix `contain`/`include` 1.9.0 regression. [@leider](https://github.com/leider)
-- [#233](https://github.com/chaijs/chai/pull/233) Improvements to `ssfi` for `assert` interface. [@refack](https://github.com/refack)
-- [#251](https://github.com/chaijs/chai/pull/251) New config option: object display threshold. [@romario333](https://github.com/romario333)
-
-Thank you to all who took time to contribute!
-
-### Other Bug Fixes
-
-- [#183](https://github.com/chaijs/chai/issues/183) Allow `undefined` for actual. (internal api)
-- Update Karam(+plugins)/Istanbul to most recent versions.
-
-## 1.9.0 / 2014-01-29 
-
-The following changes are required if you are upgrading from the previous version:
-
-- **Users:**
-  - No changes required
-- **Plugin Developers:** 
-  - Review [#219](https://github.com/chaijs/chai/pull/219).
-- **Core Contributors:** 
-  - Refresh `node_modules` folder for updated dependencies. 
-
-### Community Contributions
-
-- [#202](https://github.com/chaijs/chai/pull/201) Improve error message for .throw(). [@andreineculau](https://github.com/andreineculau)
-- [#217](https://github.com/chaijs/chai/pull/217) Chai tests can be run with `--watch`. [@demands](https://github.com/demands)
-- [#219](https://github.com/chaijs/chai/pull/219) Add overwriteChainableMethod utility. [@demands](https://github.com/demands)
-- [#224](https://github.com/chaijs/chai/pull/224) Return error on throw method to chain on error properties. [@vbardales](https://github.com/vbardales)
-- [#226](https://github.com/chaijs/chai/pull/226) Add `has` to language chains. [@duncanbeevers](https://github.com/duncanbeevers)
-- [#230](https://github.com/chaijs/chai/pull/230) Support `{a:1,b:2}.should.include({a:1})` [@jkroso](https://github.com/jkroso)
-- [#231](https://github.com/chaijs/chai/pull/231) Update Copyright notices to 2014 [@duncanbeevers](https://github.com/duncanbeevers)
-- [#232](https://github.com/chaijs/chai/pull/232) Avoid error instantiation if possible on assert.throws. [@laconbass](https://github.com/laconbass)
-
-Thank you to all who took time to contribute!
-
-### Other Bug Fixes
-
-- [#225](https://github.com/chaijs/chai/pull/225) Improved AMD wrapper provided by upstream `component(1)`.
-- [#185](https://github.com/chaijs/chai/issues/185) `assert.throws()` returns thrown error for further assertions.
-- [#237](https://github.com/chaijs/chai/pull/237) Remove coveralls/jscoverage, include istanbul coverage report in travis test.
-- Update Karma and Sauce runner versions for consistent CI results. No more karma@canary.
-
-## 1.8.1 / 2013-10-10 
-
-The following changes are required if you are upgrading from the previous version:
-
-- **Users:**
-  - Refresh `node_modules` folder for updated dependencies. 
-- **Plugin Developers:** 
-  - No changes required
-- **Core Contributors:** 
-  - Refresh `node_modules` folder for updated dependencies. 
-
-### Browserify
-
-This is a small patch that updates the dependency tree so browserify users can install
-chai. (Remove conditional requires)
-
-## 1.8.0 / 2013-09-18 
-
-The following changes are required if you are upgrading from the previous version:
-
-- **Users:**
-  - See `deep.equal` notes.
-- **Plugin Developers:** 
-  - No changes required
-- **Core Contributors:** 
-  - Refresh `node_modules` folder for updated dependencies. 
-
-### Deep Equals
-
-This version of Chai focused on a overhaul to the deep equal utility. The code for this
-tool has been removed from the core lib and can now be found at: 
-[chai / deep-eql](https://github.com/chaijs/deep-eql). As stated in previous releases,
-this is part of a larger initiative to provide transparency, independent testing, and coverage for
-some of the more complicated internal tools. 
-
-For the most part `.deep.equal` will behave the same as it has. However, in order to provide a 
-consistent ruleset across all types being tested, the following changes have been made and _might_
-require changes to your tests.
-
-**1.** Strict equality for non-traversable nodes according to [egal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
-
-_Previously:_ Non-traversable equal via `===`.
-
-```js
-expect(NaN).to.deep.equal(NaN);
-expect(-0).to.not.deep.equal(+0);
-```
-
-**2.** Arguments are not Arrays (and all types must be equal):
-
-_Previously:_ Some crazy nonsense that led to empty arrays deep equaling empty objects deep equaling dates.
-
-```js
-expect(arguments).to.not.deep.equal([]);
-expect(Array.prototype.slice.call(arguments)).to.deep.equal([]);
-```
-
-- [#156](https://github.com/chaijs/chai/issues/156) Empty object is eql to empty array
-- [#192](https://github.com/chaijs/chai/issues/192) empty object is eql to a Date object
-- [#194](https://github.com/chaijs/chai/issues/194) refactor deep-equal utility
-
-### CI and Browser Testing
-
-Chai now runs the browser CI suite using [Karma](http://karma-runner.github.io/) directed at 
-[SauceLabs](https://saucelabs.com/). This means we get to know where our browser support stands...
-and we get a cool badge:
-
-[![Selenium Test Status](https://saucelabs.com/browser-matrix/logicalparadox.svg)](https://saucelabs.com/u/logicalparadox)
-
-Look for the list of browsers/versions to expand over the coming releases.
-
-- [#195](https://github.com/chaijs/chai/issues/195) karma test framework
-
-## 1.7.2 / 2013-06-27 
-
-The following changes are required if you are upgrading from the previous version:
-
-- **Users:**
-  - No changes required.
-- **Plugin Developers:** 
-  - No changes required
-- **Core Contributors:** 
-  - Refresh `node_modules` folder for updated dependencies. 
-
-### Coverage Reporting
-
-Coverage reporting has always been available for core-developers but the data has never been published
-for our end users. In our ongoing effort to improve accountability this data will now be published via
-the [coveralls.io](https://coveralls.io/) service. A badge has been added to the README and the full report
-can be viewed online at the [chai coveralls project](https://coveralls.io/r/chaijs/chai). Furthermore, PRs 
-will receive automated messages indicating how their PR impacts test coverage. This service is tied to TravisCI.
-
-### Other Fixes
-
-- [#175](https://github.com/chaijs/chai/issues/175) Add `bower.json`. (Fix ignore all)
-
-## 1.7.1 / 2013-06-24 
-
-The following changes are required if you are upgrading from the previous version:
-
-- **Users:**
-  - No changes required.
-- **Plugin Developers:** 
-  - No changes required
-- **Core Contributors:** 
-  - Refresh `node_modules` folder for updated dependencies. 
-
-### Official Bower Support
-
-Support has been added for the Bower Package Manager ([bower.io])(http://bower.io/). Though
-Chai could be installed via Bower in the past, this update adds official support via the `bower.json`
-specification file. 
-
-- [#175](https://github.com/chaijs/chai/issues/175) Add `bower.json`.
-
-## 1.7.0 / 2013-06-17 
-
-The following changes are required if you are upgrading from the previous version:
-
-- **Users:**
-  - No changes required.
-- **Plugin Developers:** 
-  - Review AssertionError update notice.
-- **Core Contributors:** 
-  - Refresh `node_modules` folder for updated dependencies. 
-
-### AssertionError Update Notice
-
-Chai now uses [chaijs/assertion-error](https://github.com/chaijs/assertion-error) instead an internal
-constructor. This will allow for further iteration/experimentation of the AssertionError constructor 
-independant of Chai. Future plans include stack parsing for callsite support. 
-
-This update constructor has a different constructor param signature that conforms more with the standard
-`Error` object. If your plugin throws and `AssertionError` directly you will need to update your plugin 
-with the new signature.
-
-```js
-var AssertionError = require('chai').AssertionError;
-
-/**
- * previous
- *
- * @param {Object} options
- */
-
-throw new AssertionError({
-    message: 'An assertion error occurred'
-  , actual: actual
-  , expect: expect
-  , startStackFunction: arguments.callee
-  , showStack: true
-});
-
-/**
- * new
- *
- * @param {String} message
- * @param {Object} options
- * @param {Function} start stack function
- */
-
-throw new AssertionError('An assertion error occurred', {
-    actual: actual
-  , expect: expect
-  , showStack: true
-}, arguments.callee);
-
-// other signatures
-throw new AssertionError('An assertion error occurred');
-throw new AssertionError('An assertion error occurred', null, arguments.callee);
-```
-
-#### External Dependencies
-
-This is the first non-developement dependency for Chai. As Chai continues to evolve we will begin adding
-more; the next will likely be improved type detection and deep equality. With Chai's userbase continually growing
-there is an higher need for accountability and documentation. External dependencies will allow us to iterate and
-test on features independent from our interfaces. 
-
-Note: The browser packaged version `chai.js` will ALWAYS contain all dependencies needed to run Chai.
-
-### Community Contributions
-
-- [#169](https://github.com/chaijs/chai/pull/169) Fix deep equal comparison for Date/Regexp types. [@katsgeorgeek](https://github.com/katsgeorgeek)
-- [#171](https://github.com/chaijs/chai/pull/171) Add `assert.notOk()`. [@Bartvds](https://github.com/Bartvds)
-- [#173](https://github.com/chaijs/chai/pull/173) Fix `inspect` utility. [@domenic](https://github.com/domenic)
-
-Thank you to all who took the time to contribute!
-
-## 1.6.1 / 2013-06-05 
-
-The following changes are required if you are upgrading from the previous version:
-
-- **Users:**
-  - No changes required.
-- **Plugin Developers:** 
-  - No changes required.
-- **Core Contributors:** 
-  - Refresh `node_modules` folder for updated developement dependencies. 
-
-### Deep Equality
-
-Regular Expressions are now tested as part of all deep equality assertions. In previous versions
-they silently passed for all scenarios. Thanks to [@katsgeorgeek](https://github.com/katsgeorgeek) for the contribution.
-
-### Community Contributions
-
-- [#161](https://github.com/chaijs/chai/pull/161) Fix documented name for assert interface's isDefined method. [@brandonpayton](https://github.com/brandonpayton)
-- [#168](https://github.com/chaijs/chai/pull/168) Fix comparison equality of two regexps for when using deep equality. [@katsgeorgeek](https://github.com/katsgeorgeek)
-
-Thank you to all who took the time to contribute!
-
-### Additional Notes
-
-- Mocha has been locked at version `1.8.x` to ensure `mocha-phantomjs` compatibility.
-
-## 1.6.0 / 2013-04-29 
-
-The following changes are required if you are upgrading from the previous version:
-
-- **Users:**
-  - No changes required.
-- **Plugin Developers:** 
-  - No changes required.
-- **Core Contributors:** 
-  - Refresh `node_modules` folder for updated developement dependencies. 
-
-### New Assertions
-
-#### Array Members Inclusion
-
-Asserts that the target is a superset of `set`, or that the target and `set` have the same members.
-Order is not taken into account. Thanks to [@NickHeiner](https://github.com/NickHeiner) for the contribution.
-
-```js
-// (expect/should) full set
-expect([4, 2]).to.have.members([2, 4]);
-expect([5, 2]).to.not.have.members([5, 2, 1]);
-
-// (expect/should) inclusion
-expect([1, 2, 3]).to.include.members([3, 2]);
-expect([1, 2, 3]).to.not.include.members([3, 2, 8]);
-
-// (assert) full set
-assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members');
-
-// (assert) inclusion 
-assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members');
-
-```
-
-#### Non-inclusion for Assert Interface
-
-Most `assert` functions have a negative version, like `instanceOf()` has a corresponding `notInstaceOf()`. 
-However `include()` did not have a corresponding `notInclude()`. This has been added.
-
-```js
-assert.notInclude([ 1, 2, 3 ], 8);
-assert.notInclude('foobar', 'baz');
-```
-
-### Community Contributions
-
-- [#140](https://github.com/chaijs/chai/pull/140) Restore `call`/`apply` methods for plugin interface. [@RubenVerborgh](https://github.com/RubenVerborgh)
-- [#148](https://github.com/chaijs/chai/issues/148)/[#153](https://github.com/chaijs/chai/pull/153) Add `members` and `include.members` assertions. [#NickHeiner](https://github.com/NickHeiner)
-
-Thank you to all who took time to contribute!
-
-### Other Bug Fixes
-
-- [#142](https://github.com/chaijs/chai/issues/142) `assert#include` will no longer silently pass on wrong-type haystack.
-- [#158](https://github.com/chaijs/chai/issues/158) `assert#notInclude` has been added.
-- Travis-CI now tests Node.js `v0.10.x`. Support for `v0.6.x` has been removed. `v0.8.x` is still tested as before.
-
-## 1.5.0 / 2013-02-03 
-
-### Migration Requirements
-
-The following changes are required if you are upgrading from the previous version:
-
-- **Users:** 
-  - _Update [2013-02-04]:_ Some users may notice a small subset of deep equality assertions will no longer pass. This is the result of 
-  [#120](https://github.com/chaijs/chai/issues/120), an improvement to our deep equality algorithm. Users will need to revise their assertions
-  to be more granular should this occur. Further information: [#139](https://github.com/chaijs/chai/issues/139).
-- **Plugin Developers:** 
-  - No changes required.
-- **Core Contributors:** 
-  - Refresh `node_modules` folder for updated developement dependencies.
-
-### Community Contributions
-
-- [#126](https://github.com/chaijs/chai/pull/126): Add `eqls` alias for `eql`. [@RubenVerborgh](https://github.com/RubenVerborgh)
-- [#127](https://github.com/chaijs/chai/issues/127): Performance refactor for chainable methods. [@RubenVerborgh](https://github.com/RubenVerborgh)
-- [#133](https://github.com/chaijs/chai/pull/133): Assertion `.throw` support for primitives. [@RubenVerborgh](https://github.com/RubenVerborgh)
-- [#137](https://github.com/chaijs/chai/issues/137): Assertion `.throw` support for empty messages. [@timnew](https://github.com/timnew)
-- [#136](https://github.com/chaijs/chai/pull/136): Fix backward negation messages when using `.above()` and `.below()`. [@whatthejeff](https://github.com/whatthejeff)
-
-Thank you to all who took time to contribute!
-
-### Other Bug Fixes
-
-- Improve type detection of `.a()`/`.an()` to work in cross-browser scenarios.
-- [#116](https://github.com/chaijs/chai/issues/116): `.throw()` has cleaner display of errors when WebKit browsers.
-- [#120](https://github.com/chaijs/chai/issues/120): `.eql()` now works to compare dom nodes in browsers.
-
-
-### Usage Updates
-
-#### For Users
-
-**1. Component Support:** Chai now included the proper configuration to be installed as a 
-[component](https://github.com/component/component). Component users are encouraged to consult
-[chaijs.com](http://chaijs.com) for the latest version number as using the master branch
-does not gaurantee stability. 
-
-```js
-// relevant component.json
-  devDependencies: {
-    "chaijs/chai": "1.5.0"
-  }
-```
-
-Alternatively, bleeding-edge is available:
-
-    $ component install chaijs/chai
-
-**2. Configurable showDiff:** Some test runners (such as [mocha](http://visionmedia.github.com/mocha/)) 
-include support for showing the diff of strings and objects when an equality error occurs. Chai has 
-already included support for this, however some users may not prefer this display behavior. To revert to 
-no diff display, the following configuration is available:
-
-```js
-chai.Assertion.showDiff = false; // diff output disabled
-chai.Assertion.showDiff = true; // default, diff output enabled
-```
-
-#### For Plugin Developers
-
-**1. New Utility - type**: The new utility `.type()` is available as a better implementation of `typeof` 
-that can be used cross-browser. It handles the inconsistencies of Array, `null`, and `undefined` detection.
-
-- **@param** _{Mixed}_ object to detect type of
-- **@return** _{String}_ object type
-
-```js
-chai.use(function (c, utils) {
-  // some examples
-  utils.type({}); // 'object'
-  utils.type(null); // `null'
-  utils.type(undefined); // `undefined`
-  utils.type([]); // `array`
-});
-```
-
-#### For Core Contributors
-
-**1. Browser Testing**: Browser testing of the `./chai.js` file is now available in the command line 
-via PhantomJS. `make test` and Travis-CI will now also rebuild and test `./chai.js`. Consequently, all 
-pull requests will now be browser tested in this way. 
-
-_Note: Contributors opening pull requests should still NOT include the browser build._
-
-**2. SauceLabs Testing**: Early SauceLab support has been enabled with the file `./support/mocha-cloud.js`.
-Those interested in trying it out should create a free [Open Sauce](https://saucelabs.com/signup/plan) account
-and include their credentials in `./test/auth/sauce.json`.
diff --git a/polymer_0.5.0/bower_components/chai/bower.json b/polymer_0.5.0/bower_components/chai/bower.json
deleted file mode 100644
index cf9bb7d..0000000
--- a/polymer_0.5.0/bower_components/chai/bower.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-    "name": "chai"
-  , "version": "1.9.2"
-  , "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic."
-  , "license": "MIT"
-  , "keywords": [
-        "test"
-      , "assertion"
-      , "assert"
-      , "testing"
-      , "chai"
-    ]
-  , "main": "chai.js"
-  , "ignore": [
-        "build"
-      , "components"
-      , "lib"
-      , "node_modules"
-      , "support"
-      , "test"
-      , "index.js"
-      , "Makefile"
-      , ".*"
-    ]
-  , "dependencies": {}
-  , "devDependencies": {}
-}
diff --git a/polymer_0.5.0/bower_components/chai/chai.js b/polymer_0.5.0/bower_components/chai/chai.js
deleted file mode 100644
index 33dba96..0000000
--- a/polymer_0.5.0/bower_components/chai/chai.js
+++ /dev/null
@@ -1,4804 +0,0 @@
-;(function(){
-
-/**
- * Require the given path.
- *
- * @param {String} path
- * @return {Object} exports
- * @api public
- */
-
-function require(path, parent, orig) {
-  var resolved = require.resolve(path);
-
-  // lookup failed
-  if (null == resolved) {
-    orig = orig || path;
-    parent = parent || 'root';
-    var err = new Error('Failed to require "' + orig + '" from "' + parent + '"');
-    err.path = orig;
-    err.parent = parent;
-    err.require = true;
-    throw err;
-  }
-
-  var module = require.modules[resolved];
-
-  // perform real require()
-  // by invoking the module's
-  // registered function
-  if (!module._resolving && !module.exports) {
-    var mod = {};
-    mod.exports = {};
-    mod.client = mod.component = true;
-    module._resolving = true;
-    module.call(this, mod.exports, require.relative(resolved), mod);
-    delete module._resolving;
-    module.exports = mod.exports;
-  }
-
-  return module.exports;
-}
-
-/**
- * Registered modules.
- */
-
-require.modules = {};
-
-/**
- * Registered aliases.
- */
-
-require.aliases = {};
-
-/**
- * Resolve `path`.
- *
- * Lookup:
- *
- *   - PATH/index.js
- *   - PATH.js
- *   - PATH
- *
- * @param {String} path
- * @return {String} path or null
- * @api private
- */
-
-require.resolve = function(path) {
-  if (path.charAt(0) === '/') path = path.slice(1);
-
-  var paths = [
-    path,
-    path + '.js',
-    path + '.json',
-    path + '/index.js',
-    path + '/index.json'
-  ];
-
-  for (var i = 0; i < paths.length; i++) {
-    var path = paths[i];
-    if (require.modules.hasOwnProperty(path)) return path;
-    if (require.aliases.hasOwnProperty(path)) return require.aliases[path];
-  }
-};
-
-/**
- * Normalize `path` relative to the current path.
- *
- * @param {String} curr
- * @param {String} path
- * @return {String}
- * @api private
- */
-
-require.normalize = function(curr, path) {
-  var segs = [];
-
-  if ('.' != path.charAt(0)) return path;
-
-  curr = curr.split('/');
-  path = path.split('/');
-
-  for (var i = 0; i < path.length; ++i) {
-    if ('..' == path[i]) {
-      curr.pop();
-    } else if ('.' != path[i] && '' != path[i]) {
-      segs.push(path[i]);
-    }
-  }
-
-  return curr.concat(segs).join('/');
-};
-
-/**
- * Register module at `path` with callback `definition`.
- *
- * @param {String} path
- * @param {Function} definition
- * @api private
- */
-
-require.register = function(path, definition) {
-  require.modules[path] = definition;
-};
-
-/**
- * Alias a module definition.
- *
- * @param {String} from
- * @param {String} to
- * @api private
- */
-
-require.alias = function(from, to) {
-  if (!require.modules.hasOwnProperty(from)) {
-    throw new Error('Failed to alias "' + from + '", it does not exist');
-  }
-  require.aliases[to] = from;
-};
-
-/**
- * Return a require function relative to the `parent` path.
- *
- * @param {String} parent
- * @return {Function}
- * @api private
- */
-
-require.relative = function(parent) {
-  var p = require.normalize(parent, '..');
-
-  /**
-   * lastIndexOf helper.
-   */
-
-  function lastIndexOf(arr, obj) {
-    var i = arr.length;
-    while (i--) {
-      if (arr[i] === obj) return i;
-    }
-    return -1;
-  }
-
-  /**
-   * The relative require() itself.
-   */
-
-  function localRequire(path) {
-    var resolved = localRequire.resolve(path);
-    return require(resolved, parent, path);
-  }
-
-  /**
-   * Resolve relative to the parent.
-   */
-
-  localRequire.resolve = function(path) {
-    var c = path.charAt(0);
-    if ('/' == c) return path.slice(1);
-    if ('.' == c) return require.normalize(p, path);
-
-    // resolve deps by returning
-    // the dep in the nearest "deps"
-    // directory
-    var segs = parent.split('/');
-    var i = lastIndexOf(segs, 'deps') + 1;
-    if (!i) i = 0;
-    path = segs.slice(0, i + 1).join('/') + '/deps/' + path;
-    return path;
-  };
-
-  /**
-   * Check if module is defined at `path`.
-   */
-
-  localRequire.exists = function(path) {
-    return require.modules.hasOwnProperty(localRequire.resolve(path));
-  };
-
-  return localRequire;
-};
-require.register("chaijs-assertion-error/index.js", function(exports, require, module){
-/*!
- * assertion-error
- * Copyright(c) 2013 Jake Luer <jake@qualiancy.com>
- * MIT Licensed
- */
-
-/*!
- * Return a function that will copy properties from
- * one object to another excluding any originally
- * listed. Returned function will create a new `{}`.
- *
- * @param {String} excluded properties ...
- * @return {Function}
- */
-
-function exclude () {
-  var excludes = [].slice.call(arguments);
-
-  function excludeProps (res, obj) {
-    Object.keys(obj).forEach(function (key) {
-      if (!~excludes.indexOf(key)) res[key] = obj[key];
-    });
-  }
-
-  return function extendExclude () {
-    var args = [].slice.call(arguments)
-      , i = 0
-      , res = {};
-
-    for (; i < args.length; i++) {
-      excludeProps(res, args[i]);
-    }
-
-    return res;
-  };
-};
-
-/*!
- * Primary Exports
- */
-
-module.exports = AssertionError;
-
-/**
- * ### AssertionError
- *
- * An extension of the JavaScript `Error` constructor for
- * assertion and validation scenarios.
- *
- * @param {String} message
- * @param {Object} properties to include (optional)
- * @param {callee} start stack function (optional)
- */
-
-function AssertionError (message, _props, ssf) {
-  var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON')
-    , props = extend(_props || {});
-
-  // default values
-  this.message = message || 'Unspecified AssertionError';
-  this.showDiff = false;
-
-  // copy from properties
-  for (var key in props) {
-    this[key] = props[key];
-  }
-
-  // capture stack trace
-  ssf = ssf || arguments.callee;
-  if (ssf && Error.captureStackTrace) {
-    Error.captureStackTrace(this, ssf);
-  }
-}
-
-/*!
- * Inherit from Error.prototype
- */
-
-AssertionError.prototype = Object.create(Error.prototype);
-
-/*!
- * Statically set name
- */
-
-AssertionError.prototype.name = 'AssertionError';
-
-/*!
- * Ensure correct constructor
- */
-
-AssertionError.prototype.constructor = AssertionError;
-
-/**
- * Allow errors to be converted to JSON for static transfer.
- *
- * @param {Boolean} include stack (default: `true`)
- * @return {Object} object that can be `JSON.stringify`
- */
-
-AssertionError.prototype.toJSON = function (stack) {
-  var extend = exclude('constructor', 'toJSON', 'stack')
-    , props = extend({ name: this.name }, this);
-
-  // include stack if exists and not turned off
-  if (false !== stack && this.stack) {
-    props.stack = this.stack;
-  }
-
-  return props;
-};
-
-});
-require.register("chaijs-type-detect/lib/type.js", function(exports, require, module){
-/*!
- * type-detect
- * Copyright(c) 2013 jake luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/*!
- * Primary Exports
- */
-
-var exports = module.exports = getType;
-
-/*!
- * Detectable javascript natives
- */
-
-var natives = {
-    '[object Array]': 'array'
-  , '[object RegExp]': 'regexp'
-  , '[object Function]': 'function'
-  , '[object Arguments]': 'arguments'
-  , '[object Date]': 'date'
-};
-
-/**
- * ### typeOf (obj)
- *
- * Use several different techniques to determine
- * the type of object being tested.
- *
- *
- * @param {Mixed} object
- * @return {String} object type
- * @api public
- */
-
-function getType (obj) {
-  var str = Object.prototype.toString.call(obj);
-  if (natives[str]) return natives[str];
-  if (obj === null) return 'null';
-  if (obj === undefined) return 'undefined';
-  if (obj === Object(obj)) return 'object';
-  return typeof obj;
-}
-
-exports.Library = Library;
-
-/**
- * ### Library
- *
- * Create a repository for custom type detection.
- *
- * ```js
- * var lib = new type.Library;
- * ```
- *
- */
-
-function Library () {
-  this.tests = {};
-}
-
-/**
- * #### .of (obj)
- *
- * Expose replacement `typeof` detection to the library.
- *
- * ```js
- * if ('string' === lib.of('hello world')) {
- *   // ...
- * }
- * ```
- *
- * @param {Mixed} object to test
- * @return {String} type
- */
-
-Library.prototype.of = getType;
-
-/**
- * #### .define (type, test)
- *
- * Add a test to for the `.test()` assertion.
- *
- * Can be defined as a regular expression:
- *
- * ```js
- * lib.define('int', /^[0-9]+$/);
- * ```
- *
- * ... or as a function:
- *
- * ```js
- * lib.define('bln', function (obj) {
- *   if ('boolean' === lib.of(obj)) return true;
- *   var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ];
- *   if ('string' === lib.of(obj)) obj = obj.toLowerCase();
- *   return !! ~blns.indexOf(obj);
- * });
- * ```
- *
- * @param {String} type
- * @param {RegExp|Function} test
- * @api public
- */
-
-Library.prototype.define = function (type, test) {
-  if (arguments.length === 1) return this.tests[type];
-  this.tests[type] = test;
-  return this;
-};
-
-/**
- * #### .test (obj, test)
- *
- * Assert that an object is of type. Will first
- * check natives, and if that does not pass it will
- * use the user defined custom tests.
- *
- * ```js
- * assert(lib.test('1', 'int'));
- * assert(lib.test('yes', 'bln'));
- * ```
- *
- * @param {Mixed} object
- * @param {String} type
- * @return {Boolean} result
- * @api public
- */
-
-Library.prototype.test = function (obj, type) {
-  if (type === getType(obj)) return true;
-  var test = this.tests[type];
-
-  if (test && 'regexp' === getType(test)) {
-    return test.test(obj);
-  } else if (test && 'function' === getType(test)) {
-    return test(obj);
-  } else {
-    throw new ReferenceError('Type test "' + type + '" not defined or invalid.');
-  }
-};
-
-});
-require.register("chaijs-deep-eql/lib/eql.js", function(exports, require, module){
-/*!
- * deep-eql
- * Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/*!
- * Module dependencies
- */
-
-var type = require('type-detect');
-
-/*!
- * Buffer.isBuffer browser shim
- */
-
-var Buffer;
-try { Buffer = require('buffer').Buffer; }
-catch(ex) {
-  Buffer = {};
-  Buffer.isBuffer = function() { return false; }
-}
-
-/*!
- * Primary Export
- */
-
-module.exports = deepEqual;
-
-/**
- * Assert super-strict (egal) equality between
- * two objects of any type.
- *
- * @param {Mixed} a
- * @param {Mixed} b
- * @param {Array} memoised (optional)
- * @return {Boolean} equal match
- */
-
-function deepEqual(a, b, m) {
-  if (sameValue(a, b)) {
-    return true;
-  } else if ('date' === type(a)) {
-    return dateEqual(a, b);
-  } else if ('regexp' === type(a)) {
-    return regexpEqual(a, b);
-  } else if (Buffer.isBuffer(a)) {
-    return bufferEqual(a, b);
-  } else if ('arguments' === type(a)) {
-    return argumentsEqual(a, b, m);
-  } else if (!typeEqual(a, b)) {
-    return false;
-  } else if (('object' !== type(a) && 'object' !== type(b))
-  && ('array' !== type(a) && 'array' !== type(b))) {
-    return sameValue(a, b);
-  } else {
-    return objectEqual(a, b, m);
-  }
-}
-
-/*!
- * Strict (egal) equality test. Ensures that NaN always
- * equals NaN and `-0` does not equal `+0`.
- *
- * @param {Mixed} a
- * @param {Mixed} b
- * @return {Boolean} equal match
- */
-
-function sameValue(a, b) {
-  if (a === b) return a !== 0 || 1 / a === 1 / b;
-  return a !== a && b !== b;
-}
-
-/*!
- * Compare the types of two given objects and
- * return if they are equal. Note that an Array
- * has a type of `array` (not `object`) and arguments
- * have a type of `arguments` (not `array`/`object`).
- *
- * @param {Mixed} a
- * @param {Mixed} b
- * @return {Boolean} result
- */
-
-function typeEqual(a, b) {
-  return type(a) === type(b);
-}
-
-/*!
- * Compare two Date objects by asserting that
- * the time values are equal using `saveValue`.
- *
- * @param {Date} a
- * @param {Date} b
- * @return {Boolean} result
- */
-
-function dateEqual(a, b) {
-  if ('date' !== type(b)) return false;
-  return sameValue(a.getTime(), b.getTime());
-}
-
-/*!
- * Compare two regular expressions by converting them
- * to string and checking for `sameValue`.
- *
- * @param {RegExp} a
- * @param {RegExp} b
- * @return {Boolean} result
- */
-
-function regexpEqual(a, b) {
-  if ('regexp' !== type(b)) return false;
-  return sameValue(a.toString(), b.toString());
-}
-
-/*!
- * Assert deep equality of two `arguments` objects.
- * Unfortunately, these must be sliced to arrays
- * prior to test to ensure no bad behavior.
- *
- * @param {Arguments} a
- * @param {Arguments} b
- * @param {Array} memoize (optional)
- * @return {Boolean} result
- */
-
-function argumentsEqual(a, b, m) {
-  if ('arguments' !== type(b)) return false;
-  a = [].slice.call(a);
-  b = [].slice.call(b);
-  return deepEqual(a, b, m);
-}
-
-/*!
- * Get enumerable properties of a given object.
- *
- * @param {Object} a
- * @return {Array} property names
- */
-
-function enumerable(a) {
-  var res = [];
-  for (var key in a) res.push(key);
-  return res;
-}
-
-/*!
- * Simple equality for flat iterable objects
- * such as Arrays or Node.js buffers.
- *
- * @param {Iterable} a
- * @param {Iterable} b
- * @return {Boolean} result
- */
-
-function iterableEqual(a, b) {
-  if (a.length !==  b.length) return false;
-
-  var i = 0;
-  var match = true;
-
-  for (; i < a.length; i++) {
-    if (a[i] !== b[i]) {
-      match = false;
-      break;
-    }
-  }
-
-  return match;
-}
-
-/*!
- * Extension to `iterableEqual` specifically
- * for Node.js Buffers.
- *
- * @param {Buffer} a
- * @param {Mixed} b
- * @return {Boolean} result
- */
-
-function bufferEqual(a, b) {
-  if (!Buffer.isBuffer(b)) return false;
-  return iterableEqual(a, b);
-}
-
-/*!
- * Block for `objectEqual` ensuring non-existing
- * values don't get in.
- *
- * @param {Mixed} object
- * @return {Boolean} result
- */
-
-function isValue(a) {
-  return a !== null && a !== undefined;
-}
-
-/*!
- * Recursively check the equality of two objects.
- * Once basic sameness has been established it will
- * defer to `deepEqual` for each enumerable key
- * in the object.
- *
- * @param {Mixed} a
- * @param {Mixed} b
- * @return {Boolean} result
- */
-
-function objectEqual(a, b, m) {
-  if (!isValue(a) || !isValue(b)) {
-    return false;
-  }
-
-  if (a.prototype !== b.prototype) {
-    return false;
-  }
-
-  var i;
-  if (m) {
-    for (i = 0; i < m.length; i++) {
-      if ((m[i][0] === a && m[i][1] === b)
-      ||  (m[i][0] === b && m[i][1] === a)) {
-        return true;
-      }
-    }
-  } else {
-    m = [];
-  }
-
-  try {
-    var ka = enumerable(a);
-    var kb = enumerable(b);
-  } catch (ex) {
-    return false;
-  }
-
-  ka.sort();
-  kb.sort();
-
-  if (!iterableEqual(ka, kb)) {
-    return false;
-  }
-
-  m.push([ a, b ]);
-
-  var key;
-  for (i = ka.length - 1; i >= 0; i--) {
-    key = ka[i];
-    if (!deepEqual(a[key], b[key], m)) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-});
-require.register("chai/index.js", function(exports, require, module){
-module.exports = require('./lib/chai');
-
-});
-require.register("chai/lib/chai.js", function(exports, require, module){
-/*!
- * chai
- * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-var used = []
-  , exports = module.exports = {};
-
-/*!
- * Chai version
- */
-
-exports.version = '1.9.2';
-
-/*!
- * Assertion Error
- */
-
-exports.AssertionError = require('assertion-error');
-
-/*!
- * Utils for plugins (not exported)
- */
-
-var util = require('./chai/utils');
-
-/**
- * # .use(function)
- *
- * Provides a way to extend the internals of Chai
- *
- * @param {Function}
- * @returns {this} for chaining
- * @api public
- */
-
-exports.use = function (fn) {
-  if (!~used.indexOf(fn)) {
-    fn(this, util);
-    used.push(fn);
-  }
-
-  return this;
-};
-
-/*!
- * Configuration
- */
-
-var config = require('./chai/config');
-exports.config = config;
-
-/*!
- * Primary `Assertion` prototype
- */
-
-var assertion = require('./chai/assertion');
-exports.use(assertion);
-
-/*!
- * Core Assertions
- */
-
-var core = require('./chai/core/assertions');
-exports.use(core);
-
-/*!
- * Expect interface
- */
-
-var expect = require('./chai/interface/expect');
-exports.use(expect);
-
-/*!
- * Should interface
- */
-
-var should = require('./chai/interface/should');
-exports.use(should);
-
-/*!
- * Assert interface
- */
-
-var assert = require('./chai/interface/assert');
-exports.use(assert);
-
-});
-require.register("chai/lib/chai/assertion.js", function(exports, require, module){
-/*!
- * chai
- * http://chaijs.com
- * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-var config = require('./config');
-
-module.exports = function (_chai, util) {
-  /*!
-   * Module dependencies.
-   */
-
-  var AssertionError = _chai.AssertionError
-    , flag = util.flag;
-
-  /*!
-   * Module export.
-   */
-
-  _chai.Assertion = Assertion;
-
-  /*!
-   * Assertion Constructor
-   *
-   * Creates object for chaining.
-   *
-   * @api private
-   */
-
-  function Assertion (obj, msg, stack) {
-    flag(this, 'ssfi', stack || arguments.callee);
-    flag(this, 'object', obj);
-    flag(this, 'message', msg);
-  }
-
-  Object.defineProperty(Assertion, 'includeStack', {
-    get: function() {
-      console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
-      return config.includeStack;
-    },
-    set: function(value) {
-      console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
-      config.includeStack = value;
-    }
-  });
-
-  Object.defineProperty(Assertion, 'showDiff', {
-    get: function() {
-      console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
-      return config.showDiff;
-    },
-    set: function(value) {
-      console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
-      config.showDiff = value;
-    }
-  });
-
-  Assertion.addProperty = function (name, fn) {
-    util.addProperty(this.prototype, name, fn);
-  };
-
-  Assertion.addMethod = function (name, fn) {
-    util.addMethod(this.prototype, name, fn);
-  };
-
-  Assertion.addChainableMethod = function (name, fn, chainingBehavior) {
-    util.addChainableMethod(this.prototype, name, fn, chainingBehavior);
-  };
-
-  Assertion.overwriteProperty = function (name, fn) {
-    util.overwriteProperty(this.prototype, name, fn);
-  };
-
-  Assertion.overwriteMethod = function (name, fn) {
-    util.overwriteMethod(this.prototype, name, fn);
-  };
-
-  Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) {
-    util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior);
-  };
-
-  /*!
-   * ### .assert(expression, message, negateMessage, expected, actual)
-   *
-   * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass.
-   *
-   * @name assert
-   * @param {Philosophical} expression to be tested
-   * @param {String or Function} message or function that returns message to display if fails
-   * @param {String or Function} negatedMessage or function that returns negatedMessage to display if negated expression fails
-   * @param {Mixed} expected value (remember to check for negation)
-   * @param {Mixed} actual (optional) will default to `this.obj`
-   * @api private
-   */
-
-  Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) {
-    var ok = util.test(this, arguments);
-    if (true !== showDiff) showDiff = false;
-    if (true !== config.showDiff) showDiff = false;
-
-    if (!ok) {
-      var msg = util.getMessage(this, arguments)
-        , actual = util.getActual(this, arguments);
-      throw new AssertionError(msg, {
-          actual: actual
-        , expected: expected
-        , showDiff: showDiff
-      }, (config.includeStack) ? this.assert : flag(this, 'ssfi'));
-    }
-  };
-
-  /*!
-   * ### ._obj
-   *
-   * Quick reference to stored `actual` value for plugin developers.
-   *
-   * @api private
-   */
-
-  Object.defineProperty(Assertion.prototype, '_obj',
-    { get: function () {
-        return flag(this, 'object');
-      }
-    , set: function (val) {
-        flag(this, 'object', val);
-      }
-  });
-};
-
-});
-require.register("chai/lib/chai/config.js", function(exports, require, module){
-module.exports = {
-
-  /**
-   * ### config.includeStack
-   *
-   * User configurable property, influences whether stack trace
-   * is included in Assertion error message. Default of false
-   * suppresses stack trace in the error message.
-   *
-   *     chai.config.includeStack = true;  // enable stack on error
-   *
-   * @param {Boolean}
-   * @api public
-   */
-
-   includeStack: false,
-
-  /**
-   * ### config.showDiff
-   *
-   * User configurable property, influences whether or not
-   * the `showDiff` flag should be included in the thrown
-   * AssertionErrors. `false` will always be `false`; `true`
-   * will be true when the assertion has requested a diff
-   * be shown.
-   *
-   * @param {Boolean}
-   * @api public
-   */
-
-  showDiff: true,
-
-  /**
-   * ### config.truncateThreshold
-   *
-   * User configurable property, sets length threshold for actual and
-   * expected values in assertion errors. If this threshold is exceeded,
-   * the value is truncated.
-   *
-   * Set it to zero if you want to disable truncating altogether.
-   *
-   *     chai.config.truncateThreshold = 0;  // disable truncating
-   *
-   * @param {Number}
-   * @api public
-   */
-
-  truncateThreshold: 40
-
-};
-
-});
-require.register("chai/lib/chai/core/assertions.js", function(exports, require, module){
-/*!
- * chai
- * http://chaijs.com
- * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-module.exports = function (chai, _) {
-  var Assertion = chai.Assertion
-    , toString = Object.prototype.toString
-    , flag = _.flag;
-
-  /**
-   * ### Language Chains
-   *
-   * The following are provided as chainable getters to
-   * improve the readability of your assertions. They
-   * do not provide testing capabilities unless they
-   * have been overwritten by a plugin.
-   *
-   * **Chains**
-   *
-   * - to
-   * - be
-   * - been
-   * - is
-   * - that
-   * - and
-   * - has
-   * - have
-   * - with
-   * - at
-   * - of
-   * - same
-   *
-   * @name language chains
-   * @api public
-   */
-
-  [ 'to', 'be', 'been'
-  , 'is', 'and', 'has', 'have'
-  , 'with', 'that', 'at'
-  , 'of', 'same' ].forEach(function (chain) {
-    Assertion.addProperty(chain, function () {
-      return this;
-    });
-  });
-
-  /**
-   * ### .not
-   *
-   * Negates any of assertions following in the chain.
-   *
-   *     expect(foo).to.not.equal('bar');
-   *     expect(goodFn).to.not.throw(Error);
-   *     expect({ foo: 'baz' }).to.have.property('foo')
-   *       .and.not.equal('bar');
-   *
-   * @name not
-   * @api public
-   */
-
-  Assertion.addProperty('not', function () {
-    flag(this, 'negate', true);
-  });
-
-  /**
-   * ### .deep
-   *
-   * Sets the `deep` flag, later used by the `equal` and
-   * `property` assertions.
-   *
-   *     expect(foo).to.deep.equal({ bar: 'baz' });
-   *     expect({ foo: { bar: { baz: 'quux' } } })
-   *       .to.have.deep.property('foo.bar.baz', 'quux');
-   *
-   * @name deep
-   * @api public
-   */
-
-  Assertion.addProperty('deep', function () {
-    flag(this, 'deep', true);
-  });
-
-  /**
-   * ### .a(type)
-   *
-   * The `a` and `an` assertions are aliases that can be
-   * used either as language chains or to assert a value's
-   * type.
-   *
-   *     // typeof
-   *     expect('test').to.be.a('string');
-   *     expect({ foo: 'bar' }).to.be.an('object');
-   *     expect(null).to.be.a('null');
-   *     expect(undefined).to.be.an('undefined');
-   *
-   *     // language chain
-   *     expect(foo).to.be.an.instanceof(Foo);
-   *
-   * @name a
-   * @alias an
-   * @param {String} type
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  function an (type, msg) {
-    if (msg) flag(this, 'message', msg);
-    type = type.toLowerCase();
-    var obj = flag(this, 'object')
-      , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';
-
-    this.assert(
-        type === _.type(obj)
-      , 'expected #{this} to be ' + article + type
-      , 'expected #{this} not to be ' + article + type
-    );
-  }
-
-  Assertion.addChainableMethod('an', an);
-  Assertion.addChainableMethod('a', an);
-
-  /**
-   * ### .include(value)
-   *
-   * The `include` and `contain` assertions can be used as either property
-   * based language chains or as methods to assert the inclusion of an object
-   * in an array or a substring in a string. When used as language chains,
-   * they toggle the `contain` flag for the `keys` assertion.
-   *
-   *     expect([1,2,3]).to.include(2);
-   *     expect('foobar').to.contain('foo');
-   *     expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
-   *
-   * @name include
-   * @alias contain
-   * @param {Object|String|Number} obj
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  function includeChainingBehavior () {
-    flag(this, 'contains', true);
-  }
-
-  function include (val, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-    var expected = false;
-    if (_.type(obj) === 'array' && _.type(val) === 'object') {
-      for (var i in obj) {
-        if (_.eql(obj[i], val)) {
-          expected = true;
-          break;
-        }
-      }
-    } else if (_.type(val) === 'object') {
-      if (!flag(this, 'negate')) {
-        for (var k in val) new Assertion(obj).property(k, val[k]);
-        return;
-      }
-      var subset = {}
-      for (var k in val) subset[k] = obj[k]
-      expected = _.eql(subset, val);
-    } else {
-      expected = obj && ~obj.indexOf(val)
-    }
-    this.assert(
-        expected
-      , 'expected #{this} to include ' + _.inspect(val)
-      , 'expected #{this} to not include ' + _.inspect(val));
-  }
-
-  Assertion.addChainableMethod('include', include, includeChainingBehavior);
-  Assertion.addChainableMethod('contain', include, includeChainingBehavior);
-
-  /**
-   * ### .ok
-   *
-   * Asserts that the target is truthy.
-   *
-   *     expect('everthing').to.be.ok;
-   *     expect(1).to.be.ok;
-   *     expect(false).to.not.be.ok;
-   *     expect(undefined).to.not.be.ok;
-   *     expect(null).to.not.be.ok;
-   *
-   * @name ok
-   * @api public
-   */
-
-  Assertion.addProperty('ok', function () {
-    this.assert(
-        flag(this, 'object')
-      , 'expected #{this} to be truthy'
-      , 'expected #{this} to be falsy');
-  });
-
-  /**
-   * ### .true
-   *
-   * Asserts that the target is `true`.
-   *
-   *     expect(true).to.be.true;
-   *     expect(1).to.not.be.true;
-   *
-   * @name true
-   * @api public
-   */
-
-  Assertion.addProperty('true', function () {
-    this.assert(
-        true === flag(this, 'object')
-      , 'expected #{this} to be true'
-      , 'expected #{this} to be false'
-      , this.negate ? false : true
-    );
-  });
-
-  /**
-   * ### .false
-   *
-   * Asserts that the target is `false`.
-   *
-   *     expect(false).to.be.false;
-   *     expect(0).to.not.be.false;
-   *
-   * @name false
-   * @api public
-   */
-
-  Assertion.addProperty('false', function () {
-    this.assert(
-        false === flag(this, 'object')
-      , 'expected #{this} to be false'
-      , 'expected #{this} to be true'
-      , this.negate ? true : false
-    );
-  });
-
-  /**
-   * ### .null
-   *
-   * Asserts that the target is `null`.
-   *
-   *     expect(null).to.be.null;
-   *     expect(undefined).not.to.be.null;
-   *
-   * @name null
-   * @api public
-   */
-
-  Assertion.addProperty('null', function () {
-    this.assert(
-        null === flag(this, 'object')
-      , 'expected #{this} to be null'
-      , 'expected #{this} not to be null'
-    );
-  });
-
-  /**
-   * ### .undefined
-   *
-   * Asserts that the target is `undefined`.
-   *
-   *     expect(undefined).to.be.undefined;
-   *     expect(null).to.not.be.undefined;
-   *
-   * @name undefined
-   * @api public
-   */
-
-  Assertion.addProperty('undefined', function () {
-    this.assert(
-        undefined === flag(this, 'object')
-      , 'expected #{this} to be undefined'
-      , 'expected #{this} not to be undefined'
-    );
-  });
-
-  /**
-   * ### .exist
-   *
-   * Asserts that the target is neither `null` nor `undefined`.
-   *
-   *     var foo = 'hi'
-   *       , bar = null
-   *       , baz;
-   *
-   *     expect(foo).to.exist;
-   *     expect(bar).to.not.exist;
-   *     expect(baz).to.not.exist;
-   *
-   * @name exist
-   * @api public
-   */
-
-  Assertion.addProperty('exist', function () {
-    this.assert(
-        null != flag(this, 'object')
-      , 'expected #{this} to exist'
-      , 'expected #{this} to not exist'
-    );
-  });
-
-
-  /**
-   * ### .empty
-   *
-   * Asserts that the target's length is `0`. For arrays, it checks
-   * the `length` property. For objects, it gets the count of
-   * enumerable keys.
-   *
-   *     expect([]).to.be.empty;
-   *     expect('').to.be.empty;
-   *     expect({}).to.be.empty;
-   *
-   * @name empty
-   * @api public
-   */
-
-  Assertion.addProperty('empty', function () {
-    var obj = flag(this, 'object')
-      , expected = obj;
-
-    if (Array.isArray(obj) || 'string' === typeof object) {
-      expected = obj.length;
-    } else if (typeof obj === 'object') {
-      expected = Object.keys(obj).length;
-    }
-
-    this.assert(
-        !expected
-      , 'expected #{this} to be empty'
-      , 'expected #{this} not to be empty'
-    );
-  });
-
-  /**
-   * ### .arguments
-   *
-   * Asserts that the target is an arguments object.
-   *
-   *     function test () {
-   *       expect(arguments).to.be.arguments;
-   *     }
-   *
-   * @name arguments
-   * @alias Arguments
-   * @api public
-   */
-
-  function checkArguments () {
-    var obj = flag(this, 'object')
-      , type = Object.prototype.toString.call(obj);
-    this.assert(
-        '[object Arguments]' === type
-      , 'expected #{this} to be arguments but got ' + type
-      , 'expected #{this} to not be arguments'
-    );
-  }
-
-  Assertion.addProperty('arguments', checkArguments);
-  Assertion.addProperty('Arguments', checkArguments);
-
-  /**
-   * ### .equal(value)
-   *
-   * Asserts that the target is strictly equal (`===`) to `value`.
-   * Alternately, if the `deep` flag is set, asserts that
-   * the target is deeply equal to `value`.
-   *
-   *     expect('hello').to.equal('hello');
-   *     expect(42).to.equal(42);
-   *     expect(1).to.not.equal(true);
-   *     expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });
-   *     expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });
-   *
-   * @name equal
-   * @alias equals
-   * @alias eq
-   * @alias deep.equal
-   * @param {Mixed} value
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  function assertEqual (val, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-    if (flag(this, 'deep')) {
-      return this.eql(val);
-    } else {
-      this.assert(
-          val === obj
-        , 'expected #{this} to equal #{exp}'
-        , 'expected #{this} to not equal #{exp}'
-        , val
-        , this._obj
-        , true
-      );
-    }
-  }
-
-  Assertion.addMethod('equal', assertEqual);
-  Assertion.addMethod('equals', assertEqual);
-  Assertion.addMethod('eq', assertEqual);
-
-  /**
-   * ### .eql(value)
-   *
-   * Asserts that the target is deeply equal to `value`.
-   *
-   *     expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
-   *     expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);
-   *
-   * @name eql
-   * @alias eqls
-   * @param {Mixed} value
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  function assertEql(obj, msg) {
-    if (msg) flag(this, 'message', msg);
-    this.assert(
-        _.eql(obj, flag(this, 'object'))
-      , 'expected #{this} to deeply equal #{exp}'
-      , 'expected #{this} to not deeply equal #{exp}'
-      , obj
-      , this._obj
-      , true
-    );
-  }
-
-  Assertion.addMethod('eql', assertEql);
-  Assertion.addMethod('eqls', assertEql);
-
-  /**
-   * ### .above(value)
-   *
-   * Asserts that the target is greater than `value`.
-   *
-   *     expect(10).to.be.above(5);
-   *
-   * Can also be used in conjunction with `length` to
-   * assert a minimum length. The benefit being a
-   * more informative error message than if the length
-   * was supplied directly.
-   *
-   *     expect('foo').to.have.length.above(2);
-   *     expect([ 1, 2, 3 ]).to.have.length.above(2);
-   *
-   * @name above
-   * @alias gt
-   * @alias greaterThan
-   * @param {Number} value
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  function assertAbove (n, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-    if (flag(this, 'doLength')) {
-      new Assertion(obj, msg).to.have.property('length');
-      var len = obj.length;
-      this.assert(
-          len > n
-        , 'expected #{this} to have a length above #{exp} but got #{act}'
-        , 'expected #{this} to not have a length above #{exp}'
-        , n
-        , len
-      );
-    } else {
-      this.assert(
-          obj > n
-        , 'expected #{this} to be above ' + n
-        , 'expected #{this} to be at most ' + n
-      );
-    }
-  }
-
-  Assertion.addMethod('above', assertAbove);
-  Assertion.addMethod('gt', assertAbove);
-  Assertion.addMethod('greaterThan', assertAbove);
-
-  /**
-   * ### .least(value)
-   *
-   * Asserts that the target is greater than or equal to `value`.
-   *
-   *     expect(10).to.be.at.least(10);
-   *
-   * Can also be used in conjunction with `length` to
-   * assert a minimum length. The benefit being a
-   * more informative error message than if the length
-   * was supplied directly.
-   *
-   *     expect('foo').to.have.length.of.at.least(2);
-   *     expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);
-   *
-   * @name least
-   * @alias gte
-   * @param {Number} value
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  function assertLeast (n, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-    if (flag(this, 'doLength')) {
-      new Assertion(obj, msg).to.have.property('length');
-      var len = obj.length;
-      this.assert(
-          len >= n
-        , 'expected #{this} to have a length at least #{exp} but got #{act}'
-        , 'expected #{this} to have a length below #{exp}'
-        , n
-        , len
-      );
-    } else {
-      this.assert(
-          obj >= n
-        , 'expected #{this} to be at least ' + n
-        , 'expected #{this} to be below ' + n
-      );
-    }
-  }
-
-  Assertion.addMethod('least', assertLeast);
-  Assertion.addMethod('gte', assertLeast);
-
-  /**
-   * ### .below(value)
-   *
-   * Asserts that the target is less than `value`.
-   *
-   *     expect(5).to.be.below(10);
-   *
-   * Can also be used in conjunction with `length` to
-   * assert a maximum length. The benefit being a
-   * more informative error message than if the length
-   * was supplied directly.
-   *
-   *     expect('foo').to.have.length.below(4);
-   *     expect([ 1, 2, 3 ]).to.have.length.below(4);
-   *
-   * @name below
-   * @alias lt
-   * @alias lessThan
-   * @param {Number} value
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  function assertBelow (n, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-    if (flag(this, 'doLength')) {
-      new Assertion(obj, msg).to.have.property('length');
-      var len = obj.length;
-      this.assert(
-          len < n
-        , 'expected #{this} to have a length below #{exp} but got #{act}'
-        , 'expected #{this} to not have a length below #{exp}'
-        , n
-        , len
-      );
-    } else {
-      this.assert(
-          obj < n
-        , 'expected #{this} to be below ' + n
-        , 'expected #{this} to be at least ' + n
-      );
-    }
-  }
-
-  Assertion.addMethod('below', assertBelow);
-  Assertion.addMethod('lt', assertBelow);
-  Assertion.addMethod('lessThan', assertBelow);
-
-  /**
-   * ### .most(value)
-   *
-   * Asserts that the target is less than or equal to `value`.
-   *
-   *     expect(5).to.be.at.most(5);
-   *
-   * Can also be used in conjunction with `length` to
-   * assert a maximum length. The benefit being a
-   * more informative error message than if the length
-   * was supplied directly.
-   *
-   *     expect('foo').to.have.length.of.at.most(4);
-   *     expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);
-   *
-   * @name most
-   * @alias lte
-   * @param {Number} value
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  function assertMost (n, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-    if (flag(this, 'doLength')) {
-      new Assertion(obj, msg).to.have.property('length');
-      var len = obj.length;
-      this.assert(
-          len <= n
-        , 'expected #{this} to have a length at most #{exp} but got #{act}'
-        , 'expected #{this} to have a length above #{exp}'
-        , n
-        , len
-      );
-    } else {
-      this.assert(
-          obj <= n
-        , 'expected #{this} to be at most ' + n
-        , 'expected #{this} to be above ' + n
-      );
-    }
-  }
-
-  Assertion.addMethod('most', assertMost);
-  Assertion.addMethod('lte', assertMost);
-
-  /**
-   * ### .within(start, finish)
-   *
-   * Asserts that the target is within a range.
-   *
-   *     expect(7).to.be.within(5,10);
-   *
-   * Can also be used in conjunction with `length` to
-   * assert a length range. The benefit being a
-   * more informative error message than if the length
-   * was supplied directly.
-   *
-   *     expect('foo').to.have.length.within(2,4);
-   *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);
-   *
-   * @name within
-   * @param {Number} start lowerbound inclusive
-   * @param {Number} finish upperbound inclusive
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  Assertion.addMethod('within', function (start, finish, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object')
-      , range = start + '..' + finish;
-    if (flag(this, 'doLength')) {
-      new Assertion(obj, msg).to.have.property('length');
-      var len = obj.length;
-      this.assert(
-          len >= start && len <= finish
-        , 'expected #{this} to have a length within ' + range
-        , 'expected #{this} to not have a length within ' + range
-      );
-    } else {
-      this.assert(
-          obj >= start && obj <= finish
-        , 'expected #{this} to be within ' + range
-        , 'expected #{this} to not be within ' + range
-      );
-    }
-  });
-
-  /**
-   * ### .instanceof(constructor)
-   *
-   * Asserts that the target is an instance of `constructor`.
-   *
-   *     var Tea = function (name) { this.name = name; }
-   *       , Chai = new Tea('chai');
-   *
-   *     expect(Chai).to.be.an.instanceof(Tea);
-   *     expect([ 1, 2, 3 ]).to.be.instanceof(Array);
-   *
-   * @name instanceof
-   * @param {Constructor} constructor
-   * @param {String} message _optional_
-   * @alias instanceOf
-   * @api public
-   */
-
-  function assertInstanceOf (constructor, msg) {
-    if (msg) flag(this, 'message', msg);
-    var name = _.getName(constructor);
-    this.assert(
-        flag(this, 'object') instanceof constructor
-      , 'expected #{this} to be an instance of ' + name
-      , 'expected #{this} to not be an instance of ' + name
-    );
-  };
-
-  Assertion.addMethod('instanceof', assertInstanceOf);
-  Assertion.addMethod('instanceOf', assertInstanceOf);
-
-  /**
-   * ### .property(name, [value])
-   *
-   * Asserts that the target has a property `name`, optionally asserting that
-   * the value of that property is strictly equal to  `value`.
-   * If the `deep` flag is set, you can use dot- and bracket-notation for deep
-   * references into objects and arrays.
-   *
-   *     // simple referencing
-   *     var obj = { foo: 'bar' };
-   *     expect(obj).to.have.property('foo');
-   *     expect(obj).to.have.property('foo', 'bar');
-   *
-   *     // deep referencing
-   *     var deepObj = {
-   *         green: { tea: 'matcha' }
-   *       , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]
-   *     };
-
-   *     expect(deepObj).to.have.deep.property('green.tea', 'matcha');
-   *     expect(deepObj).to.have.deep.property('teas[1]', 'matcha');
-   *     expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');
-   *
-   * You can also use an array as the starting point of a `deep.property`
-   * assertion, or traverse nested arrays.
-   *
-   *     var arr = [
-   *         [ 'chai', 'matcha', 'konacha' ]
-   *       , [ { tea: 'chai' }
-   *         , { tea: 'matcha' }
-   *         , { tea: 'konacha' } ]
-   *     ];
-   *
-   *     expect(arr).to.have.deep.property('[0][1]', 'matcha');
-   *     expect(arr).to.have.deep.property('[1][2].tea', 'konacha');
-   *
-   * Furthermore, `property` changes the subject of the assertion
-   * to be the value of that property from the original object. This
-   * permits for further chainable assertions on that property.
-   *
-   *     expect(obj).to.have.property('foo')
-   *       .that.is.a('string');
-   *     expect(deepObj).to.have.property('green')
-   *       .that.is.an('object')
-   *       .that.deep.equals({ tea: 'matcha' });
-   *     expect(deepObj).to.have.property('teas')
-   *       .that.is.an('array')
-   *       .with.deep.property('[2]')
-   *         .that.deep.equals({ tea: 'konacha' });
-   *
-   * @name property
-   * @alias deep.property
-   * @param {String} name
-   * @param {Mixed} value (optional)
-   * @param {String} message _optional_
-   * @returns value of property for chaining
-   * @api public
-   */
-
-  Assertion.addMethod('property', function (name, val, msg) {
-    if (msg) flag(this, 'message', msg);
-
-    var descriptor = flag(this, 'deep') ? 'deep property ' : 'property '
-      , negate = flag(this, 'negate')
-      , obj = flag(this, 'object')
-      , value = flag(this, 'deep')
-        ? _.getPathValue(name, obj)
-        : obj[name];
-
-    if (negate && undefined !== val) {
-      if (undefined === value) {
-        msg = (msg != null) ? msg + ': ' : '';
-        throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));
-      }
-    } else {
-      this.assert(
-          undefined !== value
-        , 'expected #{this} to have a ' + descriptor + _.inspect(name)
-        , 'expected #{this} to not have ' + descriptor + _.inspect(name));
-    }
-
-    if (undefined !== val) {
-      this.assert(
-          val === value
-        , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'
-        , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'
-        , val
-        , value
-      );
-    }
-
-    flag(this, 'object', value);
-  });
-
-
-  /**
-   * ### .ownProperty(name)
-   *
-   * Asserts that the target has an own property `name`.
-   *
-   *     expect('test').to.have.ownProperty('length');
-   *
-   * @name ownProperty
-   * @alias haveOwnProperty
-   * @param {String} name
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  function assertOwnProperty (name, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-    this.assert(
-        obj.hasOwnProperty(name)
-      , 'expected #{this} to have own property ' + _.inspect(name)
-      , 'expected #{this} to not have own property ' + _.inspect(name)
-    );
-  }
-
-  Assertion.addMethod('ownProperty', assertOwnProperty);
-  Assertion.addMethod('haveOwnProperty', assertOwnProperty);
-
-  /**
-   * ### .length(value)
-   *
-   * Asserts that the target's `length` property has
-   * the expected value.
-   *
-   *     expect([ 1, 2, 3]).to.have.length(3);
-   *     expect('foobar').to.have.length(6);
-   *
-   * Can also be used as a chain precursor to a value
-   * comparison for the length property.
-   *
-   *     expect('foo').to.have.length.above(2);
-   *     expect([ 1, 2, 3 ]).to.have.length.above(2);
-   *     expect('foo').to.have.length.below(4);
-   *     expect([ 1, 2, 3 ]).to.have.length.below(4);
-   *     expect('foo').to.have.length.within(2,4);
-   *     expect([ 1, 2, 3 ]).to.have.length.within(2,4);
-   *
-   * @name length
-   * @alias lengthOf
-   * @param {Number} length
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  function assertLengthChain () {
-    flag(this, 'doLength', true);
-  }
-
-  function assertLength (n, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-    new Assertion(obj, msg).to.have.property('length');
-    var len = obj.length;
-
-    this.assert(
-        len == n
-      , 'expected #{this} to have a length of #{exp} but got #{act}'
-      , 'expected #{this} to not have a length of #{act}'
-      , n
-      , len
-    );
-  }
-
-  Assertion.addChainableMethod('length', assertLength, assertLengthChain);
-  Assertion.addMethod('lengthOf', assertLength);
-
-  /**
-   * ### .match(regexp)
-   *
-   * Asserts that the target matches a regular expression.
-   *
-   *     expect('foobar').to.match(/^foo/);
-   *
-   * @name match
-   * @param {RegExp} RegularExpression
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  Assertion.addMethod('match', function (re, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-    this.assert(
-        re.exec(obj)
-      , 'expected #{this} to match ' + re
-      , 'expected #{this} not to match ' + re
-    );
-  });
-
-  /**
-   * ### .string(string)
-   *
-   * Asserts that the string target contains another string.
-   *
-   *     expect('foobar').to.have.string('bar');
-   *
-   * @name string
-   * @param {String} string
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  Assertion.addMethod('string', function (str, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-    new Assertion(obj, msg).is.a('string');
-
-    this.assert(
-        ~obj.indexOf(str)
-      , 'expected #{this} to contain ' + _.inspect(str)
-      , 'expected #{this} to not contain ' + _.inspect(str)
-    );
-  });
-
-
-  /**
-   * ### .keys(key1, [key2], [...])
-   *
-   * Asserts that the target has exactly the given keys, or
-   * asserts the inclusion of some keys when using the
-   * `include` or `contain` modifiers.
-   *
-   *     expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']);
-   *     expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar');
-   *
-   * @name keys
-   * @alias key
-   * @param {String...|Array} keys
-   * @api public
-   */
-
-  function assertKeys (keys) {
-    var obj = flag(this, 'object')
-      , str
-      , ok = true;
-
-    keys = keys instanceof Array
-      ? keys
-      : Array.prototype.slice.call(arguments);
-
-    if (!keys.length) throw new Error('keys required');
-
-    var actual = Object.keys(obj)
-      , expected = keys
-      , len = keys.length;
-
-    // Inclusion
-    ok = keys.every(function(key){
-      return ~actual.indexOf(key);
-    });
-
-    // Strict
-    if (!flag(this, 'negate') && !flag(this, 'contains')) {
-      ok = ok && keys.length == actual.length;
-    }
-
-    // Key string
-    if (len > 1) {
-      keys = keys.map(function(key){
-        return _.inspect(key);
-      });
-      var last = keys.pop();
-      str = keys.join(', ') + ', and ' + last;
-    } else {
-      str = _.inspect(keys[0]);
-    }
-
-    // Form
-    str = (len > 1 ? 'keys ' : 'key ') + str;
-
-    // Have / include
-    str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;
-
-    // Assertion
-    this.assert(
-        ok
-      , 'expected #{this} to ' + str
-      , 'expected #{this} to not ' + str
-      , expected.sort()
-      , actual.sort()
-      , true
-    );
-  }
-
-  Assertion.addMethod('keys', assertKeys);
-  Assertion.addMethod('key', assertKeys);
-
-  /**
-   * ### .throw(constructor)
-   *
-   * Asserts that the function target will throw a specific error, or specific type of error
-   * (as determined using `instanceof`), optionally with a RegExp or string inclusion test
-   * for the error's message.
-   *
-   *     var err = new ReferenceError('This is a bad function.');
-   *     var fn = function () { throw err; }
-   *     expect(fn).to.throw(ReferenceError);
-   *     expect(fn).to.throw(Error);
-   *     expect(fn).to.throw(/bad function/);
-   *     expect(fn).to.not.throw('good function');
-   *     expect(fn).to.throw(ReferenceError, /bad function/);
-   *     expect(fn).to.throw(err);
-   *     expect(fn).to.not.throw(new RangeError('Out of range.'));
-   *
-   * Please note that when a throw expectation is negated, it will check each
-   * parameter independently, starting with error constructor type. The appropriate way
-   * to check for the existence of a type of error but for a message that does not match
-   * is to use `and`.
-   *
-   *     expect(fn).to.throw(ReferenceError)
-   *        .and.not.throw(/good function/);
-   *
-   * @name throw
-   * @alias throws
-   * @alias Throw
-   * @param {ErrorConstructor} constructor
-   * @param {String|RegExp} expected error message
-   * @param {String} message _optional_
-   * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
-   * @returns error for chaining (null if no error)
-   * @api public
-   */
-
-  function assertThrows (constructor, errMsg, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-    new Assertion(obj, msg).is.a('function');
-
-    var thrown = false
-      , desiredError = null
-      , name = null
-      , thrownError = null;
-
-    if (arguments.length === 0) {
-      errMsg = null;
-      constructor = null;
-    } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
-      errMsg = constructor;
-      constructor = null;
-    } else if (constructor && constructor instanceof Error) {
-      desiredError = constructor;
-      constructor = null;
-      errMsg = null;
-    } else if (typeof constructor === 'function') {
-      name = constructor.prototype.name || constructor.name;
-      if (name === 'Error' && constructor !== Error) {
-        name = (new constructor()).name;
-      }
-    } else {
-      constructor = null;
-    }
-
-    try {
-      obj();
-    } catch (err) {
-      // first, check desired error
-      if (desiredError) {
-        this.assert(
-            err === desiredError
-          , 'expected #{this} to throw #{exp} but #{act} was thrown'
-          , 'expected #{this} to not throw #{exp}'
-          , (desiredError instanceof Error ? desiredError.toString() : desiredError)
-          , (err instanceof Error ? err.toString() : err)
-        );
-
-        flag(this, 'object', err);
-        return this;
-      }
-
-      // next, check constructor
-      if (constructor) {
-        this.assert(
-            err instanceof constructor
-          , 'expected #{this} to throw #{exp} but #{act} was thrown'
-          , 'expected #{this} to not throw #{exp} but #{act} was thrown'
-          , name
-          , (err instanceof Error ? err.toString() : err)
-        );
-
-        if (!errMsg) {
-          flag(this, 'object', err);
-          return this;
-        }
-      }
-
-      // next, check message
-      var message = 'object' === _.type(err) && "message" in err
-        ? err.message
-        : '' + err;
-
-      if ((message != null) && errMsg && errMsg instanceof RegExp) {
-        this.assert(
-            errMsg.exec(message)
-          , 'expected #{this} to throw error matching #{exp} but got #{act}'
-          , 'expected #{this} to throw error not matching #{exp}'
-          , errMsg
-          , message
-        );
-
-        flag(this, 'object', err);
-        return this;
-      } else if ((message != null) && errMsg && 'string' === typeof errMsg) {
-        this.assert(
-            ~message.indexOf(errMsg)
-          , 'expected #{this} to throw error including #{exp} but got #{act}'
-          , 'expected #{this} to throw error not including #{act}'
-          , errMsg
-          , message
-        );
-
-        flag(this, 'object', err);
-        return this;
-      } else {
-        thrown = true;
-        thrownError = err;
-      }
-    }
-
-    var actuallyGot = ''
-      , expectedThrown = name !== null
-        ? name
-        : desiredError
-          ? '#{exp}' //_.inspect(desiredError)
-          : 'an error';
-
-    if (thrown) {
-      actuallyGot = ' but #{act} was thrown'
-    }
-
-    this.assert(
-        thrown === true
-      , 'expected #{this} to throw ' + expectedThrown + actuallyGot
-      , 'expected #{this} to not throw ' + expectedThrown + actuallyGot
-      , (desiredError instanceof Error ? desiredError.toString() : desiredError)
-      , (thrownError instanceof Error ? thrownError.toString() : thrownError)
-    );
-
-    flag(this, 'object', thrownError);
-  };
-
-  Assertion.addMethod('throw', assertThrows);
-  Assertion.addMethod('throws', assertThrows);
-  Assertion.addMethod('Throw', assertThrows);
-
-  /**
-   * ### .respondTo(method)
-   *
-   * Asserts that the object or class target will respond to a method.
-   *
-   *     Klass.prototype.bar = function(){};
-   *     expect(Klass).to.respondTo('bar');
-   *     expect(obj).to.respondTo('bar');
-   *
-   * To check if a constructor will respond to a static function,
-   * set the `itself` flag.
-   *
-   *     Klass.baz = function(){};
-   *     expect(Klass).itself.to.respondTo('baz');
-   *
-   * @name respondTo
-   * @param {String} method
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  Assertion.addMethod('respondTo', function (method, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object')
-      , itself = flag(this, 'itself')
-      , context = ('function' === _.type(obj) && !itself)
-        ? obj.prototype[method]
-        : obj[method];
-
-    this.assert(
-        'function' === typeof context
-      , 'expected #{this} to respond to ' + _.inspect(method)
-      , 'expected #{this} to not respond to ' + _.inspect(method)
-    );
-  });
-
-  /**
-   * ### .itself
-   *
-   * Sets the `itself` flag, later used by the `respondTo` assertion.
-   *
-   *     function Foo() {}
-   *     Foo.bar = function() {}
-   *     Foo.prototype.baz = function() {}
-   *
-   *     expect(Foo).itself.to.respondTo('bar');
-   *     expect(Foo).itself.not.to.respondTo('baz');
-   *
-   * @name itself
-   * @api public
-   */
-
-  Assertion.addProperty('itself', function () {
-    flag(this, 'itself', true);
-  });
-
-  /**
-   * ### .satisfy(method)
-   *
-   * Asserts that the target passes a given truth test.
-   *
-   *     expect(1).to.satisfy(function(num) { return num > 0; });
-   *
-   * @name satisfy
-   * @param {Function} matcher
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  Assertion.addMethod('satisfy', function (matcher, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-    var result = matcher(obj);
-    this.assert(
-        result
-      , 'expected #{this} to satisfy ' + _.objDisplay(matcher)
-      , 'expected #{this} to not satisfy' + _.objDisplay(matcher)
-      , this.negate ? false : true
-      , result
-    );
-  });
-
-  /**
-   * ### .closeTo(expected, delta)
-   *
-   * Asserts that the target is equal `expected`, to within a +/- `delta` range.
-   *
-   *     expect(1.5).to.be.closeTo(1, 0.5);
-   *
-   * @name closeTo
-   * @param {Number} expected
-   * @param {Number} delta
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  Assertion.addMethod('closeTo', function (expected, delta, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-
-    new Assertion(obj, msg).is.a('number');
-    if (_.type(expected) !== 'number' || _.type(delta) !== 'number') {
-      throw new Error('the arguments to closeTo must be numbers');
-    }
-
-    this.assert(
-        Math.abs(obj - expected) <= delta
-      , 'expected #{this} to be close to ' + expected + ' +/- ' + delta
-      , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta
-    );
-  });
-
-  function isSubsetOf(subset, superset, cmp) {
-    return subset.every(function(elem) {
-      if (!cmp) return superset.indexOf(elem) !== -1;
-
-      return superset.some(function(elem2) {
-        return cmp(elem, elem2);
-      });
-    })
-  }
-
-  /**
-   * ### .members(set)
-   *
-   * Asserts that the target is a superset of `set`,
-   * or that the target and `set` have the same strictly-equal (===) members.
-   * Alternately, if the `deep` flag is set, set members are compared for deep
-   * equality.
-   *
-   *     expect([1, 2, 3]).to.include.members([3, 2]);
-   *     expect([1, 2, 3]).to.not.include.members([3, 2, 8]);
-   *
-   *     expect([4, 2]).to.have.members([2, 4]);
-   *     expect([5, 2]).to.not.have.members([5, 2, 1]);
-   *
-   *     expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]);
-   *
-   * @name members
-   * @param {Array} set
-   * @param {String} message _optional_
-   * @api public
-   */
-
-  Assertion.addMethod('members', function (subset, msg) {
-    if (msg) flag(this, 'message', msg);
-    var obj = flag(this, 'object');
-
-    new Assertion(obj).to.be.an('array');
-    new Assertion(subset).to.be.an('array');
-
-    var cmp = flag(this, 'deep') ? _.eql : undefined;
-
-    if (flag(this, 'contains')) {
-      return this.assert(
-          isSubsetOf(subset, obj, cmp)
-        , 'expected #{this} to be a superset of #{act}'
-        , 'expected #{this} to not be a superset of #{act}'
-        , obj
-        , subset
-      );
-    }
-
-    this.assert(
-        isSubsetOf(obj, subset, cmp) && isSubsetOf(subset, obj, cmp)
-        , 'expected #{this} to have the same members as #{act}'
-        , 'expected #{this} to not have the same members as #{act}'
-        , obj
-        , subset
-    );
-  });
-};
-
-});
-require.register("chai/lib/chai/interface/assert.js", function(exports, require, module){
-/*!
- * chai
- * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-
-module.exports = function (chai, util) {
-
-  /*!
-   * Chai dependencies.
-   */
-
-  var Assertion = chai.Assertion
-    , flag = util.flag;
-
-  /*!
-   * Module export.
-   */
-
-  /**
-   * ### assert(expression, message)
-   *
-   * Write your own test expressions.
-   *
-   *     assert('foo' !== 'bar', 'foo is not bar');
-   *     assert(Array.isArray([]), 'empty arrays are arrays');
-   *
-   * @param {Mixed} expression to test for truthiness
-   * @param {String} message to display on error
-   * @name assert
-   * @api public
-   */
-
-  var assert = chai.assert = function (express, errmsg) {
-    var test = new Assertion(null, null, chai.assert);
-    test.assert(
-        express
-      , errmsg
-      , '[ negation message unavailable ]'
-    );
-  };
-
-  /**
-   * ### .fail(actual, expected, [message], [operator])
-   *
-   * Throw a failure. Node.js `assert` module-compatible.
-   *
-   * @name fail
-   * @param {Mixed} actual
-   * @param {Mixed} expected
-   * @param {String} message
-   * @param {String} operator
-   * @api public
-   */
-
-  assert.fail = function (actual, expected, message, operator) {
-    message = message || 'assert.fail()';
-    throw new chai.AssertionError(message, {
-        actual: actual
-      , expected: expected
-      , operator: operator
-    }, assert.fail);
-  };
-
-  /**
-   * ### .ok(object, [message])
-   *
-   * Asserts that `object` is truthy.
-   *
-   *     assert.ok('everything', 'everything is ok');
-   *     assert.ok(false, 'this will fail');
-   *
-   * @name ok
-   * @param {Mixed} object to test
-   * @param {String} message
-   * @api public
-   */
-
-  assert.ok = function (val, msg) {
-    new Assertion(val, msg).is.ok;
-  };
-
-  /**
-   * ### .notOk(object, [message])
-   *
-   * Asserts that `object` is falsy.
-   *
-   *     assert.notOk('everything', 'this will fail');
-   *     assert.notOk(false, 'this will pass');
-   *
-   * @name notOk
-   * @param {Mixed} object to test
-   * @param {String} message
-   * @api public
-   */
-
-  assert.notOk = function (val, msg) {
-    new Assertion(val, msg).is.not.ok;
-  };
-
-  /**
-   * ### .equal(actual, expected, [message])
-   *
-   * Asserts non-strict equality (`==`) of `actual` and `expected`.
-   *
-   *     assert.equal(3, '3', '== coerces values to strings');
-   *
-   * @name equal
-   * @param {Mixed} actual
-   * @param {Mixed} expected
-   * @param {String} message
-   * @api public
-   */
-
-  assert.equal = function (act, exp, msg) {
-    var test = new Assertion(act, msg, assert.equal);
-
-    test.assert(
-        exp == flag(test, 'object')
-      , 'expected #{this} to equal #{exp}'
-      , 'expected #{this} to not equal #{act}'
-      , exp
-      , act
-    );
-  };
-
-  /**
-   * ### .notEqual(actual, expected, [message])
-   *
-   * Asserts non-strict inequality (`!=`) of `actual` and `expected`.
-   *
-   *     assert.notEqual(3, 4, 'these numbers are not equal');
-   *
-   * @name notEqual
-   * @param {Mixed} actual
-   * @param {Mixed} expected
-   * @param {String} message
-   * @api public
-   */
-
-  assert.notEqual = function (act, exp, msg) {
-    var test = new Assertion(act, msg, assert.notEqual);
-
-    test.assert(
-        exp != flag(test, 'object')
-      , 'expected #{this} to not equal #{exp}'
-      , 'expected #{this} to equal #{act}'
-      , exp
-      , act
-    );
-  };
-
-  /**
-   * ### .strictEqual(actual, expected, [message])
-   *
-   * Asserts strict equality (`===`) of `actual` and `expected`.
-   *
-   *     assert.strictEqual(true, true, 'these booleans are strictly equal');
-   *
-   * @name strictEqual
-   * @param {Mixed} actual
-   * @param {Mixed} expected
-   * @param {String} message
-   * @api public
-   */
-
-  assert.strictEqual = function (act, exp, msg) {
-    new Assertion(act, msg).to.equal(exp);
-  };
-
-  /**
-   * ### .notStrictEqual(actual, expected, [message])
-   *
-   * Asserts strict inequality (`!==`) of `actual` and `expected`.
-   *
-   *     assert.notStrictEqual(3, '3', 'no coercion for strict equality');
-   *
-   * @name notStrictEqual
-   * @param {Mixed} actual
-   * @param {Mixed} expected
-   * @param {String} message
-   * @api public
-   */
-
-  assert.notStrictEqual = function (act, exp, msg) {
-    new Assertion(act, msg).to.not.equal(exp);
-  };
-
-  /**
-   * ### .deepEqual(actual, expected, [message])
-   *
-   * Asserts that `actual` is deeply equal to `expected`.
-   *
-   *     assert.deepEqual({ tea: 'green' }, { tea: 'green' });
-   *
-   * @name deepEqual
-   * @param {Mixed} actual
-   * @param {Mixed} expected
-   * @param {String} message
-   * @api public
-   */
-
-  assert.deepEqual = function (act, exp, msg) {
-    new Assertion(act, msg).to.eql(exp);
-  };
-
-  /**
-   * ### .notDeepEqual(actual, expected, [message])
-   *
-   * Assert that `actual` is not deeply equal to `expected`.
-   *
-   *     assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' });
-   *
-   * @name notDeepEqual
-   * @param {Mixed} actual
-   * @param {Mixed} expected
-   * @param {String} message
-   * @api public
-   */
-
-  assert.notDeepEqual = function (act, exp, msg) {
-    new Assertion(act, msg).to.not.eql(exp);
-  };
-
-  /**
-   * ### .isTrue(value, [message])
-   *
-   * Asserts that `value` is true.
-   *
-   *     var teaServed = true;
-   *     assert.isTrue(teaServed, 'the tea has been served');
-   *
-   * @name isTrue
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isTrue = function (val, msg) {
-    new Assertion(val, msg).is['true'];
-  };
-
-  /**
-   * ### .isFalse(value, [message])
-   *
-   * Asserts that `value` is false.
-   *
-   *     var teaServed = false;
-   *     assert.isFalse(teaServed, 'no tea yet? hmm...');
-   *
-   * @name isFalse
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isFalse = function (val, msg) {
-    new Assertion(val, msg).is['false'];
-  };
-
-  /**
-   * ### .isNull(value, [message])
-   *
-   * Asserts that `value` is null.
-   *
-   *     assert.isNull(err, 'there was no error');
-   *
-   * @name isNull
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isNull = function (val, msg) {
-    new Assertion(val, msg).to.equal(null);
-  };
-
-  /**
-   * ### .isNotNull(value, [message])
-   *
-   * Asserts that `value` is not null.
-   *
-   *     var tea = 'tasty chai';
-   *     assert.isNotNull(tea, 'great, time for tea!');
-   *
-   * @name isNotNull
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isNotNull = function (val, msg) {
-    new Assertion(val, msg).to.not.equal(null);
-  };
-
-  /**
-   * ### .isUndefined(value, [message])
-   *
-   * Asserts that `value` is `undefined`.
-   *
-   *     var tea;
-   *     assert.isUndefined(tea, 'no tea defined');
-   *
-   * @name isUndefined
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isUndefined = function (val, msg) {
-    new Assertion(val, msg).to.equal(undefined);
-  };
-
-  /**
-   * ### .isDefined(value, [message])
-   *
-   * Asserts that `value` is not `undefined`.
-   *
-   *     var tea = 'cup of chai';
-   *     assert.isDefined(tea, 'tea has been defined');
-   *
-   * @name isDefined
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isDefined = function (val, msg) {
-    new Assertion(val, msg).to.not.equal(undefined);
-  };
-
-  /**
-   * ### .isFunction(value, [message])
-   *
-   * Asserts that `value` is a function.
-   *
-   *     function serveTea() { return 'cup of tea'; };
-   *     assert.isFunction(serveTea, 'great, we can have tea now');
-   *
-   * @name isFunction
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isFunction = function (val, msg) {
-    new Assertion(val, msg).to.be.a('function');
-  };
-
-  /**
-   * ### .isNotFunction(value, [message])
-   *
-   * Asserts that `value` is _not_ a function.
-   *
-   *     var serveTea = [ 'heat', 'pour', 'sip' ];
-   *     assert.isNotFunction(serveTea, 'great, we have listed the steps');
-   *
-   * @name isNotFunction
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isNotFunction = function (val, msg) {
-    new Assertion(val, msg).to.not.be.a('function');
-  };
-
-  /**
-   * ### .isObject(value, [message])
-   *
-   * Asserts that `value` is an object (as revealed by
-   * `Object.prototype.toString`).
-   *
-   *     var selection = { name: 'Chai', serve: 'with spices' };
-   *     assert.isObject(selection, 'tea selection is an object');
-   *
-   * @name isObject
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isObject = function (val, msg) {
-    new Assertion(val, msg).to.be.a('object');
-  };
-
-  /**
-   * ### .isNotObject(value, [message])
-   *
-   * Asserts that `value` is _not_ an object.
-   *
-   *     var selection = 'chai'
-   *     assert.isNotObject(selection, 'tea selection is not an object');
-   *     assert.isNotObject(null, 'null is not an object');
-   *
-   * @name isNotObject
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isNotObject = function (val, msg) {
-    new Assertion(val, msg).to.not.be.a('object');
-  };
-
-  /**
-   * ### .isArray(value, [message])
-   *
-   * Asserts that `value` is an array.
-   *
-   *     var menu = [ 'green', 'chai', 'oolong' ];
-   *     assert.isArray(menu, 'what kind of tea do we want?');
-   *
-   * @name isArray
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isArray = function (val, msg) {
-    new Assertion(val, msg).to.be.an('array');
-  };
-
-  /**
-   * ### .isNotArray(value, [message])
-   *
-   * Asserts that `value` is _not_ an array.
-   *
-   *     var menu = 'green|chai|oolong';
-   *     assert.isNotArray(menu, 'what kind of tea do we want?');
-   *
-   * @name isNotArray
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isNotArray = function (val, msg) {
-    new Assertion(val, msg).to.not.be.an('array');
-  };
-
-  /**
-   * ### .isString(value, [message])
-   *
-   * Asserts that `value` is a string.
-   *
-   *     var teaOrder = 'chai';
-   *     assert.isString(teaOrder, 'order placed');
-   *
-   * @name isString
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isString = function (val, msg) {
-    new Assertion(val, msg).to.be.a('string');
-  };
-
-  /**
-   * ### .isNotString(value, [message])
-   *
-   * Asserts that `value` is _not_ a string.
-   *
-   *     var teaOrder = 4;
-   *     assert.isNotString(teaOrder, 'order placed');
-   *
-   * @name isNotString
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isNotString = function (val, msg) {
-    new Assertion(val, msg).to.not.be.a('string');
-  };
-
-  /**
-   * ### .isNumber(value, [message])
-   *
-   * Asserts that `value` is a number.
-   *
-   *     var cups = 2;
-   *     assert.isNumber(cups, 'how many cups');
-   *
-   * @name isNumber
-   * @param {Number} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isNumber = function (val, msg) {
-    new Assertion(val, msg).to.be.a('number');
-  };
-
-  /**
-   * ### .isNotNumber(value, [message])
-   *
-   * Asserts that `value` is _not_ a number.
-   *
-   *     var cups = '2 cups please';
-   *     assert.isNotNumber(cups, 'how many cups');
-   *
-   * @name isNotNumber
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isNotNumber = function (val, msg) {
-    new Assertion(val, msg).to.not.be.a('number');
-  };
-
-  /**
-   * ### .isBoolean(value, [message])
-   *
-   * Asserts that `value` is a boolean.
-   *
-   *     var teaReady = true
-   *       , teaServed = false;
-   *
-   *     assert.isBoolean(teaReady, 'is the tea ready');
-   *     assert.isBoolean(teaServed, 'has tea been served');
-   *
-   * @name isBoolean
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isBoolean = function (val, msg) {
-    new Assertion(val, msg).to.be.a('boolean');
-  };
-
-  /**
-   * ### .isNotBoolean(value, [message])
-   *
-   * Asserts that `value` is _not_ a boolean.
-   *
-   *     var teaReady = 'yep'
-   *       , teaServed = 'nope';
-   *
-   *     assert.isNotBoolean(teaReady, 'is the tea ready');
-   *     assert.isNotBoolean(teaServed, 'has tea been served');
-   *
-   * @name isNotBoolean
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.isNotBoolean = function (val, msg) {
-    new Assertion(val, msg).to.not.be.a('boolean');
-  };
-
-  /**
-   * ### .typeOf(value, name, [message])
-   *
-   * Asserts that `value`'s type is `name`, as determined by
-   * `Object.prototype.toString`.
-   *
-   *     assert.typeOf({ tea: 'chai' }, 'object', 'we have an object');
-   *     assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array');
-   *     assert.typeOf('tea', 'string', 'we have a string');
-   *     assert.typeOf(/tea/, 'regexp', 'we have a regular expression');
-   *     assert.typeOf(null, 'null', 'we have a null');
-   *     assert.typeOf(undefined, 'undefined', 'we have an undefined');
-   *
-   * @name typeOf
-   * @param {Mixed} value
-   * @param {String} name
-   * @param {String} message
-   * @api public
-   */
-
-  assert.typeOf = function (val, type, msg) {
-    new Assertion(val, msg).to.be.a(type);
-  };
-
-  /**
-   * ### .notTypeOf(value, name, [message])
-   *
-   * Asserts that `value`'s type is _not_ `name`, as determined by
-   * `Object.prototype.toString`.
-   *
-   *     assert.notTypeOf('tea', 'number', 'strings are not numbers');
-   *
-   * @name notTypeOf
-   * @param {Mixed} value
-   * @param {String} typeof name
-   * @param {String} message
-   * @api public
-   */
-
-  assert.notTypeOf = function (val, type, msg) {
-    new Assertion(val, msg).to.not.be.a(type);
-  };
-
-  /**
-   * ### .instanceOf(object, constructor, [message])
-   *
-   * Asserts that `value` is an instance of `constructor`.
-   *
-   *     var Tea = function (name) { this.name = name; }
-   *       , chai = new Tea('chai');
-   *
-   *     assert.instanceOf(chai, Tea, 'chai is an instance of tea');
-   *
-   * @name instanceOf
-   * @param {Object} object
-   * @param {Constructor} constructor
-   * @param {String} message
-   * @api public
-   */
-
-  assert.instanceOf = function (val, type, msg) {
-    new Assertion(val, msg).to.be.instanceOf(type);
-  };
-
-  /**
-   * ### .notInstanceOf(object, constructor, [message])
-   *
-   * Asserts `value` is not an instance of `constructor`.
-   *
-   *     var Tea = function (name) { this.name = name; }
-   *       , chai = new String('chai');
-   *
-   *     assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea');
-   *
-   * @name notInstanceOf
-   * @param {Object} object
-   * @param {Constructor} constructor
-   * @param {String} message
-   * @api public
-   */
-
-  assert.notInstanceOf = function (val, type, msg) {
-    new Assertion(val, msg).to.not.be.instanceOf(type);
-  };
-
-  /**
-   * ### .include(haystack, needle, [message])
-   *
-   * Asserts that `haystack` includes `needle`. Works
-   * for strings and arrays.
-   *
-   *     assert.include('foobar', 'bar', 'foobar contains string "bar"');
-   *     assert.include([ 1, 2, 3 ], 3, 'array contains value');
-   *
-   * @name include
-   * @param {Array|String} haystack
-   * @param {Mixed} needle
-   * @param {String} message
-   * @api public
-   */
-
-  assert.include = function (exp, inc, msg) {
-    new Assertion(exp, msg, assert.include).include(inc);
-  };
-
-  /**
-   * ### .notInclude(haystack, needle, [message])
-   *
-   * Asserts that `haystack` does not include `needle`. Works
-   * for strings and arrays.
-   *i
-   *     assert.notInclude('foobar', 'baz', 'string not include substring');
-   *     assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value');
-   *
-   * @name notInclude
-   * @param {Array|String} haystack
-   * @param {Mixed} needle
-   * @param {String} message
-   * @api public
-   */
-
-  assert.notInclude = function (exp, inc, msg) {
-    new Assertion(exp, msg, assert.notInclude).not.include(inc);
-  };
-
-  /**
-   * ### .match(value, regexp, [message])
-   *
-   * Asserts that `value` matches the regular expression `regexp`.
-   *
-   *     assert.match('foobar', /^foo/, 'regexp matches');
-   *
-   * @name match
-   * @param {Mixed} value
-   * @param {RegExp} regexp
-   * @param {String} message
-   * @api public
-   */
-
-  assert.match = function (exp, re, msg) {
-    new Assertion(exp, msg).to.match(re);
-  };
-
-  /**
-   * ### .notMatch(value, regexp, [message])
-   *
-   * Asserts that `value` does not match the regular expression `regexp`.
-   *
-   *     assert.notMatch('foobar', /^foo/, 'regexp does not match');
-   *
-   * @name notMatch
-   * @param {Mixed} value
-   * @param {RegExp} regexp
-   * @param {String} message
-   * @api public
-   */
-
-  assert.notMatch = function (exp, re, msg) {
-    new Assertion(exp, msg).to.not.match(re);
-  };
-
-  /**
-   * ### .property(object, property, [message])
-   *
-   * Asserts that `object` has a property named by `property`.
-   *
-   *     assert.property({ tea: { green: 'matcha' }}, 'tea');
-   *
-   * @name property
-   * @param {Object} object
-   * @param {String} property
-   * @param {String} message
-   * @api public
-   */
-
-  assert.property = function (obj, prop, msg) {
-    new Assertion(obj, msg).to.have.property(prop);
-  };
-
-  /**
-   * ### .notProperty(object, property, [message])
-   *
-   * Asserts that `object` does _not_ have a property named by `property`.
-   *
-   *     assert.notProperty({ tea: { green: 'matcha' }}, 'coffee');
-   *
-   * @name notProperty
-   * @param {Object} object
-   * @param {String} property
-   * @param {String} message
-   * @api public
-   */
-
-  assert.notProperty = function (obj, prop, msg) {
-    new Assertion(obj, msg).to.not.have.property(prop);
-  };
-
-  /**
-   * ### .deepProperty(object, property, [message])
-   *
-   * Asserts that `object` has a property named by `property`, which can be a
-   * string using dot- and bracket-notation for deep reference.
-   *
-   *     assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green');
-   *
-   * @name deepProperty
-   * @param {Object} object
-   * @param {String} property
-   * @param {String} message
-   * @api public
-   */
-
-  assert.deepProperty = function (obj, prop, msg) {
-    new Assertion(obj, msg).to.have.deep.property(prop);
-  };
-
-  /**
-   * ### .notDeepProperty(object, property, [message])
-   *
-   * Asserts that `object` does _not_ have a property named by `property`, which
-   * can be a string using dot- and bracket-notation for deep reference.
-   *
-   *     assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong');
-   *
-   * @name notDeepProperty
-   * @param {Object} object
-   * @param {String} property
-   * @param {String} message
-   * @api public
-   */
-
-  assert.notDeepProperty = function (obj, prop, msg) {
-    new Assertion(obj, msg).to.not.have.deep.property(prop);
-  };
-
-  /**
-   * ### .propertyVal(object, property, value, [message])
-   *
-   * Asserts that `object` has a property named by `property` with value given
-   * by `value`.
-   *
-   *     assert.propertyVal({ tea: 'is good' }, 'tea', 'is good');
-   *
-   * @name propertyVal
-   * @param {Object} object
-   * @param {String} property
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.propertyVal = function (obj, prop, val, msg) {
-    new Assertion(obj, msg).to.have.property(prop, val);
-  };
-
-  /**
-   * ### .propertyNotVal(object, property, value, [message])
-   *
-   * Asserts that `object` has a property named by `property`, but with a value
-   * different from that given by `value`.
-   *
-   *     assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad');
-   *
-   * @name propertyNotVal
-   * @param {Object} object
-   * @param {String} property
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.propertyNotVal = function (obj, prop, val, msg) {
-    new Assertion(obj, msg).to.not.have.property(prop, val);
-  };
-
-  /**
-   * ### .deepPropertyVal(object, property, value, [message])
-   *
-   * Asserts that `object` has a property named by `property` with value given
-   * by `value`. `property` can use dot- and bracket-notation for deep
-   * reference.
-   *
-   *     assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha');
-   *
-   * @name deepPropertyVal
-   * @param {Object} object
-   * @param {String} property
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.deepPropertyVal = function (obj, prop, val, msg) {
-    new Assertion(obj, msg).to.have.deep.property(prop, val);
-  };
-
-  /**
-   * ### .deepPropertyNotVal(object, property, value, [message])
-   *
-   * Asserts that `object` has a property named by `property`, but with a value
-   * different from that given by `value`. `property` can use dot- and
-   * bracket-notation for deep reference.
-   *
-   *     assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha');
-   *
-   * @name deepPropertyNotVal
-   * @param {Object} object
-   * @param {String} property
-   * @param {Mixed} value
-   * @param {String} message
-   * @api public
-   */
-
-  assert.deepPropertyNotVal = function (obj, prop, val, msg) {
-    new Assertion(obj, msg).to.not.have.deep.property(prop, val);
-  };
-
-  /**
-   * ### .lengthOf(object, length, [message])
-   *
-   * Asserts that `object` has a `length` property with the expected value.
-   *
-   *     assert.lengthOf([1,2,3], 3, 'array has length of 3');
-   *     assert.lengthOf('foobar', 5, 'string has length of 6');
-   *
-   * @name lengthOf
-   * @param {Mixed} object
-   * @param {Number} length
-   * @param {String} message
-   * @api public
-   */
-
-  assert.lengthOf = function (exp, len, msg) {
-    new Assertion(exp, msg).to.have.length(len);
-  };
-
-  /**
-   * ### .throws(function, [constructor/string/regexp], [string/regexp], [message])
-   *
-   * Asserts that `function` will throw an error that is an instance of
-   * `constructor`, or alternately that it will throw an error with message
-   * matching `regexp`.
-   *
-   *     assert.throw(fn, 'function throws a reference error');
-   *     assert.throw(fn, /function throws a reference error/);
-   *     assert.throw(fn, ReferenceError);
-   *     assert.throw(fn, ReferenceError, 'function throws a reference error');
-   *     assert.throw(fn, ReferenceError, /function throws a reference error/);
-   *
-   * @name throws
-   * @alias throw
-   * @alias Throw
-   * @param {Function} function
-   * @param {ErrorConstructor} constructor
-   * @param {RegExp} regexp
-   * @param {String} message
-   * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
-   * @api public
-   */
-
-  assert.Throw = function (fn, errt, errs, msg) {
-    if ('string' === typeof errt || errt instanceof RegExp) {
-      errs = errt;
-      errt = null;
-    }
-
-    var assertErr = new Assertion(fn, msg).to.Throw(errt, errs);
-    return flag(assertErr, 'object');
-  };
-
-  /**
-   * ### .doesNotThrow(function, [constructor/regexp], [message])
-   *
-   * Asserts that `function` will _not_ throw an error that is an instance of
-   * `constructor`, or alternately that it will not throw an error with message
-   * matching `regexp`.
-   *
-   *     assert.doesNotThrow(fn, Error, 'function does not throw');
-   *
-   * @name doesNotThrow
-   * @param {Function} function
-   * @param {ErrorConstructor} constructor
-   * @param {RegExp} regexp
-   * @param {String} message
-   * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
-   * @api public
-   */
-
-  assert.doesNotThrow = function (fn, type, msg) {
-    if ('string' === typeof type) {
-      msg = type;
-      type = null;
-    }
-
-    new Assertion(fn, msg).to.not.Throw(type);
-  };
-
-  /**
-   * ### .operator(val1, operator, val2, [message])
-   *
-   * Compares two values using `operator`.
-   *
-   *     assert.operator(1, '<', 2, 'everything is ok');
-   *     assert.operator(1, '>', 2, 'this will fail');
-   *
-   * @name operator
-   * @param {Mixed} val1
-   * @param {String} operator
-   * @param {Mixed} val2
-   * @param {String} message
-   * @api public
-   */
-
-  assert.operator = function (val, operator, val2, msg) {
-    if (!~['==', '===', '>', '>=', '<', '<=', '!=', '!=='].indexOf(operator)) {
-      throw new Error('Invalid operator "' + operator + '"');
-    }
-    var test = new Assertion(eval(val + operator + val2), msg);
-    test.assert(
-        true === flag(test, 'object')
-      , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2)
-      , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) );
-  };
-
-  /**
-   * ### .closeTo(actual, expected, delta, [message])
-   *
-   * Asserts that the target is equal `expected`, to within a +/- `delta` range.
-   *
-   *     assert.closeTo(1.5, 1, 0.5, 'numbers are close');
-   *
-   * @name closeTo
-   * @param {Number} actual
-   * @param {Number} expected
-   * @param {Number} delta
-   * @param {String} message
-   * @api public
-   */
-
-  assert.closeTo = function (act, exp, delta, msg) {
-    new Assertion(act, msg).to.be.closeTo(exp, delta);
-  };
-
-  /**
-   * ### .sameMembers(set1, set2, [message])
-   *
-   * Asserts that `set1` and `set2` have the same members.
-   * Order is not taken into account.
-   *
-   *     assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members');
-   *
-   * @name sameMembers
-   * @param {Array} set1
-   * @param {Array} set2
-   * @param {String} message
-   * @api public
-   */
-
-  assert.sameMembers = function (set1, set2, msg) {
-    new Assertion(set1, msg).to.have.same.members(set2);
-  }
-
-  /**
-   * ### .includeMembers(superset, subset, [message])
-   *
-   * Asserts that `subset` is included in `superset`.
-   * Order is not taken into account.
-   *
-   *     assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members');
-   *
-   * @name includeMembers
-   * @param {Array} superset
-   * @param {Array} subset
-   * @param {String} message
-   * @api public
-   */
-
-  assert.includeMembers = function (superset, subset, msg) {
-    new Assertion(superset, msg).to.include.members(subset);
-  }
-
-  /*!
-   * Undocumented / untested
-   */
-
-  assert.ifError = function (val, msg) {
-    new Assertion(val, msg).to.not.be.ok;
-  };
-
-  /*!
-   * Aliases.
-   */
-
-  (function alias(name, as){
-    assert[as] = assert[name];
-    return alias;
-  })
-  ('Throw', 'throw')
-  ('Throw', 'throws');
-};
-
-});
-require.register("chai/lib/chai/interface/expect.js", function(exports, require, module){
-/*!
- * chai
- * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-module.exports = function (chai, util) {
-  chai.expect = function (val, message) {
-    return new chai.Assertion(val, message);
-  };
-};
-
-
-});
-require.register("chai/lib/chai/interface/should.js", function(exports, require, module){
-/*!
- * chai
- * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-module.exports = function (chai, util) {
-  var Assertion = chai.Assertion;
-
-  function loadShould () {
-    // explicitly define this method as function as to have it's name to include as `ssfi`
-    function shouldGetter() {
-      if (this instanceof String || this instanceof Number) {
-        return new Assertion(this.constructor(this), null, shouldGetter);
-      } else if (this instanceof Boolean) {
-        return new Assertion(this == true, null, shouldGetter);
-      }
-      return new Assertion(this, null, shouldGetter);
-    }
-    function shouldSetter(value) {
-      // See https://github.com/chaijs/chai/issues/86: this makes
-      // `whatever.should = someValue` actually set `someValue`, which is
-      // especially useful for `global.should = require('chai').should()`.
-      //
-      // Note that we have to use [[DefineProperty]] instead of [[Put]]
-      // since otherwise we would trigger this very setter!
-      Object.defineProperty(this, 'should', {
-        value: value,
-        enumerable: true,
-        configurable: true,
-        writable: true
-      });
-    }
-    // modify Object.prototype to have `should`
-    Object.defineProperty(Object.prototype, 'should', {
-      set: shouldSetter
-      , get: shouldGetter
-      , configurable: true
-    });
-
-    var should = {};
-
-    should.equal = function (val1, val2, msg) {
-      new Assertion(val1, msg).to.equal(val2);
-    };
-
-    should.Throw = function (fn, errt, errs, msg) {
-      new Assertion(fn, msg).to.Throw(errt, errs);
-    };
-
-    should.exist = function (val, msg) {
-      new Assertion(val, msg).to.exist;
-    }
-
-    // negation
-    should.not = {}
-
-    should.not.equal = function (val1, val2, msg) {
-      new Assertion(val1, msg).to.not.equal(val2);
-    };
-
-    should.not.Throw = function (fn, errt, errs, msg) {
-      new Assertion(fn, msg).to.not.Throw(errt, errs);
-    };
-
-    should.not.exist = function (val, msg) {
-      new Assertion(val, msg).to.not.exist;
-    }
-
-    should['throw'] = should['Throw'];
-    should.not['throw'] = should.not['Throw'];
-
-    return should;
-  };
-
-  chai.should = loadShould;
-  chai.Should = loadShould;
-};
-
-});
-require.register("chai/lib/chai/utils/addChainableMethod.js", function(exports, require, module){
-/*!
- * Chai - addChainingMethod utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/*!
- * Module dependencies
- */
-
-var transferFlags = require('./transferFlags');
-var flag = require('./flag');
-var config = require('../config');
-
-/*!
- * Module variables
- */
-
-// Check whether `__proto__` is supported
-var hasProtoSupport = '__proto__' in Object;
-
-// Without `__proto__` support, this module will need to add properties to a function.
-// However, some Function.prototype methods cannot be overwritten,
-// and there seems no easy cross-platform way to detect them (@see chaijs/chai/issues/69).
-var excludeNames = /^(?:length|name|arguments|caller)$/;
-
-// Cache `Function` properties
-var call  = Function.prototype.call,
-    apply = Function.prototype.apply;
-
-/**
- * ### addChainableMethod (ctx, name, method, chainingBehavior)
- *
- * Adds a method to an object, such that the method can also be chained.
- *
- *     utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) {
- *       var obj = utils.flag(this, 'object');
- *       new chai.Assertion(obj).to.be.equal(str);
- *     });
- *
- * Can also be accessed directly from `chai.Assertion`.
- *
- *     chai.Assertion.addChainableMethod('foo', fn, chainingBehavior);
- *
- * The result can then be used as both a method assertion, executing both `method` and
- * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`.
- *
- *     expect(fooStr).to.be.foo('bar');
- *     expect(fooStr).to.be.foo.equal('foo');
- *
- * @param {Object} ctx object to which the method is added
- * @param {String} name of method to add
- * @param {Function} method function to be used for `name`, when called
- * @param {Function} chainingBehavior function to be called every time the property is accessed
- * @name addChainableMethod
- * @api public
- */
-
-module.exports = function (ctx, name, method, chainingBehavior) {
-  if (typeof chainingBehavior !== 'function') {
-    chainingBehavior = function () { };
-  }
-
-  var chainableBehavior = {
-      method: method
-    , chainingBehavior: chainingBehavior
-  };
-
-  // save the methods so we can overwrite them later, if we need to.
-  if (!ctx.__methods) {
-    ctx.__methods = {};
-  }
-  ctx.__methods[name] = chainableBehavior;
-
-  Object.defineProperty(ctx, name,
-    { get: function () {
-        chainableBehavior.chainingBehavior.call(this);
-
-        var assert = function assert() {
-          var old_ssfi = flag(this, 'ssfi');
-          if (old_ssfi && config.includeStack === false)
-            flag(this, 'ssfi', assert);
-          var result = chainableBehavior.method.apply(this, arguments);
-          return result === undefined ? this : result;
-        };
-
-        // Use `__proto__` if available
-        if (hasProtoSupport) {
-          // Inherit all properties from the object by replacing the `Function` prototype
-          var prototype = assert.__proto__ = Object.create(this);
-          // Restore the `call` and `apply` methods from `Function`
-          prototype.call = call;
-          prototype.apply = apply;
-        }
-        // Otherwise, redefine all properties (slow!)
-        else {
-          var asserterNames = Object.getOwnPropertyNames(ctx);
-          asserterNames.forEach(function (asserterName) {
-            if (!excludeNames.test(asserterName)) {
-              var pd = Object.getOwnPropertyDescriptor(ctx, asserterName);
-              Object.defineProperty(assert, asserterName, pd);
-            }
-          });
-        }
-
-        transferFlags(this, assert);
-        return assert;
-      }
-    , configurable: true
-  });
-};
-
-});
-require.register("chai/lib/chai/utils/addMethod.js", function(exports, require, module){
-/*!
- * Chai - addMethod utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-var config = require('../config');
-
-/**
- * ### .addMethod (ctx, name, method)
- *
- * Adds a method to the prototype of an object.
- *
- *     utils.addMethod(chai.Assertion.prototype, 'foo', function (str) {
- *       var obj = utils.flag(this, 'object');
- *       new chai.Assertion(obj).to.be.equal(str);
- *     });
- *
- * Can also be accessed directly from `chai.Assertion`.
- *
- *     chai.Assertion.addMethod('foo', fn);
- *
- * Then can be used as any other assertion.
- *
- *     expect(fooStr).to.be.foo('bar');
- *
- * @param {Object} ctx object to which the method is added
- * @param {String} name of method to add
- * @param {Function} method function to be used for name
- * @name addMethod
- * @api public
- */
-var flag = require('./flag');
-
-module.exports = function (ctx, name, method) {
-  ctx[name] = function () {
-    var old_ssfi = flag(this, 'ssfi');
-    if (old_ssfi && config.includeStack === false)
-      flag(this, 'ssfi', ctx[name]);
-    var result = method.apply(this, arguments);
-    return result === undefined ? this : result;
-  };
-};
-
-});
-require.register("chai/lib/chai/utils/addProperty.js", function(exports, require, module){
-/*!
- * Chai - addProperty utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/**
- * ### addProperty (ctx, name, getter)
- *
- * Adds a property to the prototype of an object.
- *
- *     utils.addProperty(chai.Assertion.prototype, 'foo', function () {
- *       var obj = utils.flag(this, 'object');
- *       new chai.Assertion(obj).to.be.instanceof(Foo);
- *     });
- *
- * Can also be accessed directly from `chai.Assertion`.
- *
- *     chai.Assertion.addProperty('foo', fn);
- *
- * Then can be used as any other assertion.
- *
- *     expect(myFoo).to.be.foo;
- *
- * @param {Object} ctx object to which the property is added
- * @param {String} name of property to add
- * @param {Function} getter function to be used for name
- * @name addProperty
- * @api public
- */
-
-module.exports = function (ctx, name, getter) {
-  Object.defineProperty(ctx, name,
-    { get: function () {
-        var result = getter.call(this);
-        return result === undefined ? this : result;
-      }
-    , configurable: true
-  });
-};
-
-});
-require.register("chai/lib/chai/utils/flag.js", function(exports, require, module){
-/*!
- * Chai - flag utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/**
- * ### flag(object ,key, [value])
- *
- * Get or set a flag value on an object. If a
- * value is provided it will be set, else it will
- * return the currently set value or `undefined` if
- * the value is not set.
- *
- *     utils.flag(this, 'foo', 'bar'); // setter
- *     utils.flag(this, 'foo'); // getter, returns `bar`
- *
- * @param {Object} object (constructed Assertion
- * @param {String} key
- * @param {Mixed} value (optional)
- * @name flag
- * @api private
- */
-
-module.exports = function (obj, key, value) {
-  var flags = obj.__flags || (obj.__flags = Object.create(null));
-  if (arguments.length === 3) {
-    flags[key] = value;
-  } else {
-    return flags[key];
-  }
-};
-
-});
-require.register("chai/lib/chai/utils/getActual.js", function(exports, require, module){
-/*!
- * Chai - getActual utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/**
- * # getActual(object, [actual])
- *
- * Returns the `actual` value for an Assertion
- *
- * @param {Object} object (constructed Assertion)
- * @param {Arguments} chai.Assertion.prototype.assert arguments
- */
-
-module.exports = function (obj, args) {
-  return args.length > 4 ? args[4] : obj._obj;
-};
-
-});
-require.register("chai/lib/chai/utils/getEnumerableProperties.js", function(exports, require, module){
-/*!
- * Chai - getEnumerableProperties utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/**
- * ### .getEnumerableProperties(object)
- *
- * This allows the retrieval of enumerable property names of an object,
- * inherited or not.
- *
- * @param {Object} object
- * @returns {Array}
- * @name getEnumerableProperties
- * @api public
- */
-
-module.exports = function getEnumerableProperties(object) {
-  var result = [];
-  for (var name in object) {
-    result.push(name);
-  }
-  return result;
-};
-
-});
-require.register("chai/lib/chai/utils/getMessage.js", function(exports, require, module){
-/*!
- * Chai - message composition utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/*!
- * Module dependancies
- */
-
-var flag = require('./flag')
-  , getActual = require('./getActual')
-  , inspect = require('./inspect')
-  , objDisplay = require('./objDisplay');
-
-/**
- * ### .getMessage(object, message, negateMessage)
- *
- * Construct the error message based on flags
- * and template tags. Template tags will return
- * a stringified inspection of the object referenced.
- *
- * Message template tags:
- * - `#{this}` current asserted object
- * - `#{act}` actual value
- * - `#{exp}` expected value
- *
- * @param {Object} object (constructed Assertion)
- * @param {Arguments} chai.Assertion.prototype.assert arguments
- * @name getMessage
- * @api public
- */
-
-module.exports = function (obj, args) {
-  var negate = flag(obj, 'negate')
-    , val = flag(obj, 'object')
-    , expected = args[3]
-    , actual = getActual(obj, args)
-    , msg = negate ? args[2] : args[1]
-    , flagMsg = flag(obj, 'message');
-
-  if(typeof msg === "function") msg = msg();
-  msg = msg || '';
-  msg = msg
-    .replace(/#{this}/g, objDisplay(val))
-    .replace(/#{act}/g, objDisplay(actual))
-    .replace(/#{exp}/g, objDisplay(expected));
-
-  return flagMsg ? flagMsg + ': ' + msg : msg;
-};
-
-});
-require.register("chai/lib/chai/utils/getName.js", function(exports, require, module){
-/*!
- * Chai - getName utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/**
- * # getName(func)
- *
- * Gets the name of a function, in a cross-browser way.
- *
- * @param {Function} a function (usually a constructor)
- */
-
-module.exports = function (func) {
-  if (func.name) return func.name;
-
-  var match = /^\s?function ([^(]*)\(/.exec(func);
-  return match && match[1] ? match[1] : "";
-};
-
-});
-require.register("chai/lib/chai/utils/getPathValue.js", function(exports, require, module){
-/*!
- * Chai - getPathValue utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * @see https://github.com/logicalparadox/filtr
- * MIT Licensed
- */
-
-/**
- * ### .getPathValue(path, object)
- *
- * This allows the retrieval of values in an
- * object given a string path.
- *
- *     var obj = {
- *         prop1: {
- *             arr: ['a', 'b', 'c']
- *           , str: 'Hello'
- *         }
- *       , prop2: {
- *             arr: [ { nested: 'Universe' } ]
- *           , str: 'Hello again!'
- *         }
- *     }
- *
- * The following would be the results.
- *
- *     getPathValue('prop1.str', obj); // Hello
- *     getPathValue('prop1.att[2]', obj); // b
- *     getPathValue('prop2.arr[0].nested', obj); // Universe
- *
- * @param {String} path
- * @param {Object} object
- * @returns {Object} value or `undefined`
- * @name getPathValue
- * @api public
- */
-
-var getPathValue = module.exports = function (path, obj) {
-  var parsed = parsePath(path);
-  return _getPathValue(parsed, obj);
-};
-
-/*!
- * ## parsePath(path)
- *
- * Helper function used to parse string object
- * paths. Use in conjunction with `_getPathValue`.
- *
- *      var parsed = parsePath('myobject.property.subprop');
- *
- * ### Paths:
- *
- * * Can be as near infinitely deep and nested
- * * Arrays are also valid using the formal `myobject.document[3].property`.
- *
- * @param {String} path
- * @returns {Object} parsed
- * @api private
- */
-
-function parsePath (path) {
-  var str = path.replace(/\[/g, '.[')
-    , parts = str.match(/(\\\.|[^.]+?)+/g);
-  return parts.map(function (value) {
-    var re = /\[(\d+)\]$/
-      , mArr = re.exec(value)
-    if (mArr) return { i: parseFloat(mArr[1]) };
-    else return { p: value };
-  });
-};
-
-/*!
- * ## _getPathValue(parsed, obj)
- *
- * Helper companion function for `.parsePath` that returns
- * the value located at the parsed address.
- *
- *      var value = getPathValue(parsed, obj);
- *
- * @param {Object} parsed definition from `parsePath`.
- * @param {Object} object to search against
- * @returns {Object|Undefined} value
- * @api private
- */
-
-function _getPathValue (parsed, obj) {
-  var tmp = obj
-    , res;
-  for (var i = 0, l = parsed.length; i < l; i++) {
-    var part = parsed[i];
-    if (tmp) {
-      if ('undefined' !== typeof part.p)
-        tmp = tmp[part.p];
-      else if ('undefined' !== typeof part.i)
-        tmp = tmp[part.i];
-      if (i == (l - 1)) res = tmp;
-    } else {
-      res = undefined;
-    }
-  }
-  return res;
-};
-
-});
-require.register("chai/lib/chai/utils/getProperties.js", function(exports, require, module){
-/*!
- * Chai - getProperties utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/**
- * ### .getProperties(object)
- *
- * This allows the retrieval of property names of an object, enumerable or not,
- * inherited or not.
- *
- * @param {Object} object
- * @returns {Array}
- * @name getProperties
- * @api public
- */
-
-module.exports = function getProperties(object) {
-  var result = Object.getOwnPropertyNames(subject);
-
-  function addProperty(property) {
-    if (result.indexOf(property) === -1) {
-      result.push(property);
-    }
-  }
-
-  var proto = Object.getPrototypeOf(subject);
-  while (proto !== null) {
-    Object.getOwnPropertyNames(proto).forEach(addProperty);
-    proto = Object.getPrototypeOf(proto);
-  }
-
-  return result;
-};
-
-});
-require.register("chai/lib/chai/utils/index.js", function(exports, require, module){
-/*!
- * chai
- * Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/*!
- * Main exports
- */
-
-var exports = module.exports = {};
-
-/*!
- * test utility
- */
-
-exports.test = require('./test');
-
-/*!
- * type utility
- */
-
-exports.type = require('./type');
-
-/*!
- * message utility
- */
-
-exports.getMessage = require('./getMessage');
-
-/*!
- * actual utility
- */
-
-exports.getActual = require('./getActual');
-
-/*!
- * Inspect util
- */
-
-exports.inspect = require('./inspect');
-
-/*!
- * Object Display util
- */
-
-exports.objDisplay = require('./objDisplay');
-
-/*!
- * Flag utility
- */
-
-exports.flag = require('./flag');
-
-/*!
- * Flag transferring utility
- */
-
-exports.transferFlags = require('./transferFlags');
-
-/*!
- * Deep equal utility
- */
-
-exports.eql = require('deep-eql');
-
-/*!
- * Deep path value
- */
-
-exports.getPathValue = require('./getPathValue');
-
-/*!
- * Function name
- */
-
-exports.getName = require('./getName');
-
-/*!
- * add Property
- */
-
-exports.addProperty = require('./addProperty');
-
-/*!
- * add Method
- */
-
-exports.addMethod = require('./addMethod');
-
-/*!
- * overwrite Property
- */
-
-exports.overwriteProperty = require('./overwriteProperty');
-
-/*!
- * overwrite Method
- */
-
-exports.overwriteMethod = require('./overwriteMethod');
-
-/*!
- * Add a chainable method
- */
-
-exports.addChainableMethod = require('./addChainableMethod');
-
-/*!
- * Overwrite chainable method
- */
-
-exports.overwriteChainableMethod = require('./overwriteChainableMethod');
-
-
-});
-require.register("chai/lib/chai/utils/inspect.js", function(exports, require, module){
-// This is (almost) directly from Node.js utils
-// https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js
-
-var getName = require('./getName');
-var getProperties = require('./getProperties');
-var getEnumerableProperties = require('./getEnumerableProperties');
-
-module.exports = inspect;
-
-/**
- * Echos the value of a value. Trys to print the value out
- * in the best way possible given the different types.
- *
- * @param {Object} obj The object to print out.
- * @param {Boolean} showHidden Flag that shows hidden (not enumerable)
- *    properties of objects.
- * @param {Number} depth Depth in which to descend in object. Default is 2.
- * @param {Boolean} colors Flag to turn on ANSI escape codes to color the
- *    output. Default is false (no coloring).
- */
-function inspect(obj, showHidden, depth, colors) {
-  var ctx = {
-    showHidden: showHidden,
-    seen: [],
-    stylize: function (str) { return str; }
-  };
-  return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth));
-}
-
-// Returns true if object is a DOM element.
-var isDOMElement = function (object) {
-  if (typeof HTMLElement === 'object') {
-    return object instanceof HTMLElement;
-  } else {
-    return object &&
-      typeof object === 'object' &&
-      object.nodeType === 1 &&
-      typeof object.nodeName === 'string';
-  }
-};
-
-function formatValue(ctx, value, recurseTimes) {
-  // Provide a hook for user-specified inspect functions.
-  // Check that value is an object with an inspect function on it
-  if (value && typeof value.inspect === 'function' &&
-      // Filter out the util module, it's inspect function is special
-      value.inspect !== exports.inspect &&
-      // Also filter out any prototype objects using the circular check.
-      !(value.constructor && value.constructor.prototype === value)) {
-    var ret = value.inspect(recurseTimes);
-    if (typeof ret !== 'string') {
-      ret = formatValue(ctx, ret, recurseTimes);
-    }
-    return ret;
-  }
-
-  // Primitive types cannot have properties
-  var primitive = formatPrimitive(ctx, value);
-  if (primitive) {
-    return primitive;
-  }
-
-  // If this is a DOM element, try to get the outer HTML.
-  if (isDOMElement(value)) {
-    if ('outerHTML' in value) {
-      return value.outerHTML;
-      // This value does not have an outerHTML attribute,
-      //   it could still be an XML element
-    } else {
-      // Attempt to serialize it
-      try {
-        if (document.xmlVersion) {
-          var xmlSerializer = new XMLSerializer();
-          return xmlSerializer.serializeToString(value);
-        } else {
-          // Firefox 11- do not support outerHTML
-          //   It does, however, support innerHTML
-          //   Use the following to render the element
-          var ns = "http://www.w3.org/1999/xhtml";
-          var container = document.createElementNS(ns, '_');
-
-          container.appendChild(value.cloneNode(false));
-          html = container.innerHTML
-            .replace('><', '>' + value.innerHTML + '<');
-          container.innerHTML = '';
-          return html;
-        }
-      } catch (err) {
-        // This could be a non-native DOM implementation,
-        //   continue with the normal flow:
-        //   printing the element as if it is an object.
-      }
-    }
-  }
-
-  // Look up the keys of the object.
-  var visibleKeys = getEnumerableProperties(value);
-  var keys = ctx.showHidden ? getProperties(value) : visibleKeys;
-
-  // Some type of object without properties can be shortcutted.
-  // In IE, errors have a single `stack` property, or if they are vanilla `Error`,
-  // a `stack` plus `description` property; ignore those for consistency.
-  if (keys.length === 0 || (isError(value) && (
-      (keys.length === 1 && keys[0] === 'stack') ||
-      (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack')
-     ))) {
-    if (typeof value === 'function') {
-      var name = getName(value);
-      var nameSuffix = name ? ': ' + name : '';
-      return ctx.stylize('[Function' + nameSuffix + ']', 'special');
-    }
-    if (isRegExp(value)) {
-      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
-    }
-    if (isDate(value)) {
-      return ctx.stylize(Date.prototype.toUTCString.call(value), 'date');
-    }
-    if (isError(value)) {
-      return formatError(value);
-    }
-  }
-
-  var base = '', array = false, braces = ['{', '}'];
-
-  // Make Array say that they are Array
-  if (isArray(value)) {
-    array = true;
-    braces = ['[', ']'];
-  }
-
-  // Make functions say that they are functions
-  if (typeof value === 'function') {
-    var name = getName(value);
-    var nameSuffix = name ? ': ' + name : '';
-    base = ' [Function' + nameSuffix + ']';
-  }
-
-  // Make RegExps say that they are RegExps
-  if (isRegExp(value)) {
-    base = ' ' + RegExp.prototype.toString.call(value);
-  }
-
-  // Make dates with properties first say the date
-  if (isDate(value)) {
-    base = ' ' + Date.prototype.toUTCString.call(value);
-  }
-
-  // Make error with message first say the error
-  if (isError(value)) {
-    return formatError(value);
-  }
-
-  if (keys.length === 0 && (!array || value.length == 0)) {
-    return braces[0] + base + braces[1];
-  }
-
-  if (recurseTimes < 0) {
-    if (isRegExp(value)) {
-      return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
-    } else {
-      return ctx.stylize('[Object]', 'special');
-    }
-  }
-
-  ctx.seen.push(value);
-
-  var output;
-  if (array) {
-    output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
-  } else {
-    output = keys.map(function(key) {
-      return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
-    });
-  }
-
-  ctx.seen.pop();
-
-  return reduceToSingleString(output, base, braces);
-}
-
-
-function formatPrimitive(ctx, value) {
-  switch (typeof value) {
-    case 'undefined':
-      return ctx.stylize('undefined', 'undefined');
-
-    case 'string':
-      var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
-                                               .replace(/'/g, "\\'")
-                                               .replace(/\\"/g, '"') + '\'';
-      return ctx.stylize(simple, 'string');
-
-    case 'number':
-      return ctx.stylize('' + value, 'number');
-
-    case 'boolean':
-      return ctx.stylize('' + value, 'boolean');
-  }
-  // For some reason typeof null is "object", so special case here.
-  if (value === null) {
-    return ctx.stylize('null', 'null');
-  }
-}
-
-
-function formatError(value) {
-  return '[' + Error.prototype.toString.call(value) + ']';
-}
-
-
-function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
-  var output = [];
-  for (var i = 0, l = value.length; i < l; ++i) {
-    if (Object.prototype.hasOwnProperty.call(value, String(i))) {
-      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
-          String(i), true));
-    } else {
-      output.push('');
-    }
-  }
-  keys.forEach(function(key) {
-    if (!key.match(/^\d+$/)) {
-      output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
-          key, true));
-    }
-  });
-  return output;
-}
-
-
-function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
-  var name, str;
-  if (value.__lookupGetter__) {
-    if (value.__lookupGetter__(key)) {
-      if (value.__lookupSetter__(key)) {
-        str = ctx.stylize('[Getter/Setter]', 'special');
-      } else {
-        str = ctx.stylize('[Getter]', 'special');
-      }
-    } else {
-      if (value.__lookupSetter__(key)) {
-        str = ctx.stylize('[Setter]', 'special');
-      }
-    }
-  }
-  if (visibleKeys.indexOf(key) < 0) {
-    name = '[' + key + ']';
-  }
-  if (!str) {
-    if (ctx.seen.indexOf(value[key]) < 0) {
-      if (recurseTimes === null) {
-        str = formatValue(ctx, value[key], null);
-      } else {
-        str = formatValue(ctx, value[key], recurseTimes - 1);
-      }
-      if (str.indexOf('\n') > -1) {
-        if (array) {
-          str = str.split('\n').map(function(line) {
-            return '  ' + line;
-          }).join('\n').substr(2);
-        } else {
-          str = '\n' + str.split('\n').map(function(line) {
-            return '   ' + line;
-          }).join('\n');
-        }
-      }
-    } else {
-      str = ctx.stylize('[Circular]', 'special');
-    }
-  }
-  if (typeof name === 'undefined') {
-    if (array && key.match(/^\d+$/)) {
-      return str;
-    }
-    name = JSON.stringify('' + key);
-    if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
-      name = name.substr(1, name.length - 2);
-      name = ctx.stylize(name, 'name');
-    } else {
-      name = name.replace(/'/g, "\\'")
-                 .replace(/\\"/g, '"')
-                 .replace(/(^"|"$)/g, "'");
-      name = ctx.stylize(name, 'string');
-    }
-  }
-
-  return name + ': ' + str;
-}
-
-
-function reduceToSingleString(output, base, braces) {
-  var numLinesEst = 0;
-  var length = output.reduce(function(prev, cur) {
-    numLinesEst++;
-    if (cur.indexOf('\n') >= 0) numLinesEst++;
-    return prev + cur.length + 1;
-  }, 0);
-
-  if (length > 60) {
-    return braces[0] +
-           (base === '' ? '' : base + '\n ') +
-           ' ' +
-           output.join(',\n  ') +
-           ' ' +
-           braces[1];
-  }
-
-  return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
-}
-
-function isArray(ar) {
-  return Array.isArray(ar) ||
-         (typeof ar === 'object' && objectToString(ar) === '[object Array]');
-}
-
-function isRegExp(re) {
-  return typeof re === 'object' && objectToString(re) === '[object RegExp]';
-}
-
-function isDate(d) {
-  return typeof d === 'object' && objectToString(d) === '[object Date]';
-}
-
-function isError(e) {
-  return typeof e === 'object' && objectToString(e) === '[object Error]';
-}
-
-function objectToString(o) {
-  return Object.prototype.toString.call(o);
-}
-
-});
-require.register("chai/lib/chai/utils/objDisplay.js", function(exports, require, module){
-/*!
- * Chai - flag utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/*!
- * Module dependancies
- */
-
-var inspect = require('./inspect');
-var config = require('../config');
-
-/**
- * ### .objDisplay (object)
- *
- * Determines if an object or an array matches
- * criteria to be inspected in-line for error
- * messages or should be truncated.
- *
- * @param {Mixed} javascript object to inspect
- * @name objDisplay
- * @api public
- */
-
-module.exports = function (obj) {
-  var str = inspect(obj)
-    , type = Object.prototype.toString.call(obj);
-
-  if (config.truncateThreshold && str.length >= config.truncateThreshold) {
-    if (type === '[object Function]') {
-      return !obj.name || obj.name === ''
-        ? '[Function]'
-        : '[Function: ' + obj.name + ']';
-    } else if (type === '[object Array]') {
-      return '[ Array(' + obj.length + ') ]';
-    } else if (type === '[object Object]') {
-      var keys = Object.keys(obj)
-        , kstr = keys.length > 2
-          ? keys.splice(0, 2).join(', ') + ', ...'
-          : keys.join(', ');
-      return '{ Object (' + kstr + ') }';
-    } else {
-      return str;
-    }
-  } else {
-    return str;
-  }
-};
-
-});
-require.register("chai/lib/chai/utils/overwriteMethod.js", function(exports, require, module){
-/*!
- * Chai - overwriteMethod utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/**
- * ### overwriteMethod (ctx, name, fn)
- *
- * Overwites an already existing method and provides
- * access to previous function. Must return function
- * to be used for name.
- *
- *     utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) {
- *       return function (str) {
- *         var obj = utils.flag(this, 'object');
- *         if (obj instanceof Foo) {
- *           new chai.Assertion(obj.value).to.equal(str);
- *         } else {
- *           _super.apply(this, arguments);
- *         }
- *       }
- *     });
- *
- * Can also be accessed directly from `chai.Assertion`.
- *
- *     chai.Assertion.overwriteMethod('foo', fn);
- *
- * Then can be used as any other assertion.
- *
- *     expect(myFoo).to.equal('bar');
- *
- * @param {Object} ctx object whose method is to be overwritten
- * @param {String} name of method to overwrite
- * @param {Function} method function that returns a function to be used for name
- * @name overwriteMethod
- * @api public
- */
-
-module.exports = function (ctx, name, method) {
-  var _method = ctx[name]
-    , _super = function () { return this; };
-
-  if (_method && 'function' === typeof _method)
-    _super = _method;
-
-  ctx[name] = function () {
-    var result = method(_super).apply(this, arguments);
-    return result === undefined ? this : result;
-  }
-};
-
-});
-require.register("chai/lib/chai/utils/overwriteProperty.js", function(exports, require, module){
-/*!
- * Chai - overwriteProperty utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/**
- * ### overwriteProperty (ctx, name, fn)
- *
- * Overwites an already existing property getter and provides
- * access to previous value. Must return function to use as getter.
- *
- *     utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) {
- *       return function () {
- *         var obj = utils.flag(this, 'object');
- *         if (obj instanceof Foo) {
- *           new chai.Assertion(obj.name).to.equal('bar');
- *         } else {
- *           _super.call(this);
- *         }
- *       }
- *     });
- *
- *
- * Can also be accessed directly from `chai.Assertion`.
- *
- *     chai.Assertion.overwriteProperty('foo', fn);
- *
- * Then can be used as any other assertion.
- *
- *     expect(myFoo).to.be.ok;
- *
- * @param {Object} ctx object whose property is to be overwritten
- * @param {String} name of property to overwrite
- * @param {Function} getter function that returns a getter function to be used for name
- * @name overwriteProperty
- * @api public
- */
-
-module.exports = function (ctx, name, getter) {
-  var _get = Object.getOwnPropertyDescriptor(ctx, name)
-    , _super = function () {};
-
-  if (_get && 'function' === typeof _get.get)
-    _super = _get.get
-
-  Object.defineProperty(ctx, name,
-    { get: function () {
-        var result = getter(_super).call(this);
-        return result === undefined ? this : result;
-      }
-    , configurable: true
-  });
-};
-
-});
-require.register("chai/lib/chai/utils/overwriteChainableMethod.js", function(exports, require, module){
-/*!
- * Chai - overwriteChainableMethod utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/**
- * ### overwriteChainableMethod (ctx, name, fn)
- *
- * Overwites an already existing chainable method
- * and provides access to the previous function or
- * property.  Must return functions to be used for
- * name.
- *
- *     utils.overwriteChainableMethod(chai.Assertion.prototype, 'length',
- *       function (_super) {
- *       }
- *     , function (_super) {
- *       }
- *     );
- *
- * Can also be accessed directly from `chai.Assertion`.
- *
- *     chai.Assertion.overwriteChainableMethod('foo', fn, fn);
- *
- * Then can be used as any other assertion.
- *
- *     expect(myFoo).to.have.length(3);
- *     expect(myFoo).to.have.length.above(3);
- *
- * @param {Object} ctx object whose method / property is to be overwritten
- * @param {String} name of method / property to overwrite
- * @param {Function} method function that returns a function to be used for name
- * @param {Function} chainingBehavior function that returns a function to be used for property
- * @name overwriteChainableMethod
- * @api public
- */
-
-module.exports = function (ctx, name, method, chainingBehavior) {
-  var chainableBehavior = ctx.__methods[name];
-
-  var _chainingBehavior = chainableBehavior.chainingBehavior;
-  chainableBehavior.chainingBehavior = function () {
-    var result = chainingBehavior(_chainingBehavior).call(this);
-    return result === undefined ? this : result;
-  };
-
-  var _method = chainableBehavior.method;
-  chainableBehavior.method = function () {
-    var result = method(_method).apply(this, arguments);
-    return result === undefined ? this : result;
-  };
-};
-
-});
-require.register("chai/lib/chai/utils/test.js", function(exports, require, module){
-/*!
- * Chai - test utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/*!
- * Module dependancies
- */
-
-var flag = require('./flag');
-
-/**
- * # test(object, expression)
- *
- * Test and object for expression.
- *
- * @param {Object} object (constructed Assertion)
- * @param {Arguments} chai.Assertion.prototype.assert arguments
- */
-
-module.exports = function (obj, args) {
-  var negate = flag(obj, 'negate')
-    , expr = args[0];
-  return negate ? !expr : expr;
-};
-
-});
-require.register("chai/lib/chai/utils/transferFlags.js", function(exports, require, module){
-/*!
- * Chai - transferFlags utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/**
- * ### transferFlags(assertion, object, includeAll = true)
- *
- * Transfer all the flags for `assertion` to `object`. If
- * `includeAll` is set to `false`, then the base Chai
- * assertion flags (namely `object`, `ssfi`, and `message`)
- * will not be transferred.
- *
- *
- *     var newAssertion = new Assertion();
- *     utils.transferFlags(assertion, newAssertion);
- *
- *     var anotherAsseriton = new Assertion(myObj);
- *     utils.transferFlags(assertion, anotherAssertion, false);
- *
- * @param {Assertion} assertion the assertion to transfer the flags from
- * @param {Object} object the object to transfer the flags too; usually a new assertion
- * @param {Boolean} includeAll
- * @name getAllFlags
- * @api private
- */
-
-module.exports = function (assertion, object, includeAll) {
-  var flags = assertion.__flags || (assertion.__flags = Object.create(null));
-
-  if (!object.__flags) {
-    object.__flags = Object.create(null);
-  }
-
-  includeAll = arguments.length === 3 ? includeAll : true;
-
-  for (var flag in flags) {
-    if (includeAll ||
-        (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) {
-      object.__flags[flag] = flags[flag];
-    }
-  }
-};
-
-});
-require.register("chai/lib/chai/utils/type.js", function(exports, require, module){
-/*!
- * Chai - type utility
- * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
- * MIT Licensed
- */
-
-/*!
- * Detectable javascript natives
- */
-
-var natives = {
-    '[object Arguments]': 'arguments'
-  , '[object Array]': 'array'
-  , '[object Date]': 'date'
-  , '[object Function]': 'function'
-  , '[object Number]': 'number'
-  , '[object RegExp]': 'regexp'
-  , '[object String]': 'string'
-};
-
-/**
- * ### type(object)
- *
- * Better implementation of `typeof` detection that can
- * be used cross-browser. Handles the inconsistencies of
- * Array, `null`, and `undefined` detection.
- *
- *     utils.type({}) // 'object'
- *     utils.type(null) // `null'
- *     utils.type(undefined) // `undefined`
- *     utils.type([]) // `array`
- *
- * @param {Mixed} object to detect type of
- * @name type
- * @api private
- */
-
-module.exports = function (obj) {
-  var str = Object.prototype.toString.call(obj);
-  if (natives[str]) return natives[str];
-  if (obj === null) return 'null';
-  if (obj === undefined) return 'undefined';
-  if (obj === Object(obj)) return 'object';
-  return typeof obj;
-};
-
-});
-
-
-
-
-require.alias("chaijs-assertion-error/index.js", "chai/deps/assertion-error/index.js");
-require.alias("chaijs-assertion-error/index.js", "chai/deps/assertion-error/index.js");
-require.alias("chaijs-assertion-error/index.js", "assertion-error/index.js");
-require.alias("chaijs-assertion-error/index.js", "chaijs-assertion-error/index.js");
-require.alias("chaijs-deep-eql/lib/eql.js", "chai/deps/deep-eql/lib/eql.js");
-require.alias("chaijs-deep-eql/lib/eql.js", "chai/deps/deep-eql/index.js");
-require.alias("chaijs-deep-eql/lib/eql.js", "deep-eql/index.js");
-require.alias("chaijs-type-detect/lib/type.js", "chaijs-deep-eql/deps/type-detect/lib/type.js");
-require.alias("chaijs-type-detect/lib/type.js", "chaijs-deep-eql/deps/type-detect/index.js");
-require.alias("chaijs-type-detect/lib/type.js", "chaijs-type-detect/index.js");
-require.alias("chaijs-deep-eql/lib/eql.js", "chaijs-deep-eql/index.js");
-require.alias("chai/index.js", "chai/index.js");if (typeof exports == "object") {
-  module.exports = require("chai");
-} else if (typeof define == "function" && define.amd) {
-  define([], function(){ return require("chai"); });
-} else {
-  this["chai"] = require("chai");
-}})();
\ No newline at end of file
diff --git a/polymer_0.5.0/bower_components/chai/component.json b/polymer_0.5.0/bower_components/chai/component.json
deleted file mode 100644
index 3d9029b..0000000
--- a/polymer_0.5.0/bower_components/chai/component.json
+++ /dev/null
@@ -1,49 +0,0 @@
-{
-    "name": "chai"
-  , "repo": "chaijs/chai"
-  , "version": "1.9.2"
-  , "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic."
-  , "license": "MIT"
-  , "keywords": [
-        "test"
-      , "assertion"
-      , "assert"
-      , "testing"
-      , "chai"
-    ]
-  , "main": "index.js"
-  , "scripts": [
-        "index.js"
-      , "lib/chai.js"
-      , "lib/chai/assertion.js"
-      , "lib/chai/config.js"
-      , "lib/chai/core/assertions.js"
-      , "lib/chai/interface/assert.js"
-      , "lib/chai/interface/expect.js"
-      , "lib/chai/interface/should.js"
-      , "lib/chai/utils/addChainableMethod.js"
-      , "lib/chai/utils/addMethod.js"
-      , "lib/chai/utils/addProperty.js"
-      , "lib/chai/utils/flag.js"
-      , "lib/chai/utils/getActual.js"
-      , "lib/chai/utils/getEnumerableProperties.js"
-      , "lib/chai/utils/getMessage.js"
-      , "lib/chai/utils/getName.js"
-      , "lib/chai/utils/getPathValue.js"
-      , "lib/chai/utils/getProperties.js"
-      , "lib/chai/utils/index.js"
-      , "lib/chai/utils/inspect.js"
-      , "lib/chai/utils/objDisplay.js"
-      , "lib/chai/utils/overwriteMethod.js"
-      , "lib/chai/utils/overwriteProperty.js"
-      , "lib/chai/utils/overwriteChainableMethod.js"
-      , "lib/chai/utils/test.js"
-      , "lib/chai/utils/transferFlags.js"
-      , "lib/chai/utils/type.js"
-    ]
-  , "dependencies": {
-        "chaijs/assertion-error": "1.0.0"
-      , "chaijs/deep-eql": "0.1.3"
-    }
-  , "development": {}
-}
diff --git a/polymer_0.5.0/bower_components/chai/karma.conf.js b/polymer_0.5.0/bower_components/chai/karma.conf.js
deleted file mode 100644
index b0dfe6a..0000000
--- a/polymer_0.5.0/bower_components/chai/karma.conf.js
+++ /dev/null
@@ -1,28 +0,0 @@
-module.exports = function(config) {
-  config.set({
-      frameworks: [ 'mocha' ]
-    , files: [
-          'build/build.js'
-        , 'test/bootstrap/karma.js'
-        , 'test/*.js'
-      ]
-    , reporters: [ 'progress' ]
-    , colors: true
-    , logLevel: config.LOG_INFO
-    , autoWatch: false
-    , browsers: [ 'PhantomJS' ]
-    , browserDisconnectTimeout: 10000
-    , browserDisconnectTolerance: 2
-    , browserNoActivityTimeout: 20000
-    , singleRun: true
-  });
-
-  switch (process.env.CHAI_TEST_ENV) {
-    case 'sauce':
-      require('./karma.sauce')(config);
-      break;
-    default:
-      // ...
-      break;
-  };
-};
diff --git a/polymer_0.5.0/bower_components/chai/karma.sauce.js b/polymer_0.5.0/bower_components/chai/karma.sauce.js
deleted file mode 100644
index e57d5e0..0000000
--- a/polymer_0.5.0/bower_components/chai/karma.sauce.js
+++ /dev/null
@@ -1,41 +0,0 @@
-var version = require('./package.json').version;
-var ts = new Date().getTime();
-
-module.exports = function(config) {
-  var auth;
-
-  try {
-    auth = require('./test/auth/index');
-  } catch(ex) {
-    auth = {};
-    auth.SAUCE_USERNAME = process.env.SAUCE_USERNAME || null;
-    auth.SAUCE_ACCESS_KEY = process.env.SAUCE_ACCESS_KEY || null;
-  }
-
-  if (!auth.SAUCE_USERNAME || !auth.SAUCE_ACCESS_KEY) return;
-  if (process.env.SKIP_SAUCE) return;
-
-  var branch = process.env.TRAVIS_BRANCH || 'local'
-  var browserConfig = require('./sauce.browsers');
-  var browsers = Object.keys(browserConfig);
-  var tags = [ 'chaijs_' + version, auth.SAUCE_USERNAME + '@' + branch ];
-  var tunnel = process.env.TRAVIS_JOB_NUMBER || ts;
-
-  if (process.env.TRAVIS_JOB_NUMBER) {
-    tags.push('travis@' + process.env.TRAVIS_JOB_NUMBER);
-  }
-
-  config.browsers = config.browsers.concat(browsers);
-  config.customLaunchers = browserConfig;
-  config.reporters.push('saucelabs');
-  config.transports = [ 'xhr-polling' ];
-
-  config.sauceLabs = {
-      username: auth.SAUCE_USERNAME
-    , accessKey: auth.SAUCE_ACCESS_KEY
-    , startConnect: true
-    , tags: tags
-    , testName: 'ChaiJS'
-    , tunnelIdentifier: tunnel
-  };
-};
diff --git a/polymer_0.5.0/bower_components/chai/package.json b/polymer_0.5.0/bower_components/chai/package.json
deleted file mode 100644
index 92594b9..0000000
--- a/polymer_0.5.0/bower_components/chai/package.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
-  "author": "Jake Luer <jake@alogicalparadox.com>",
-  "name": "chai",
-  "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic.",
-  "keywords": [ "test", "assertion", "assert", "testing", "chai" ],
-  "homepage": "http://chaijs.com",
-  "license": "MIT",
-  "contributors": [
-    "Jake Luer <jake@alogicalparadox.com>",
-    "Domenic Denicola <domenic@domenicdenicola.com> (http://domenicdenicola.com)",
-    "Veselin Todorov <hi@vesln.com>",
-    "John Firebaugh <john.firebaugh@gmail.com>"
-  ],
-  "version": "1.9.2",
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/chaijs/chai"
-  },
-  "bugs": {
-    "url": "https://github.com/chaijs/chai/issues"
-  },
-  "main": "./index",
-  "scripts": {
-    "test": "make test"
-  },
-  "engines": {
-    "node": ">= 0.4.0"
-  },
-  "dependencies": {
-      "assertion-error": "1.0.0"
-    , "deep-eql": "0.1.3"
-  },
-  "devDependencies": {
-      "component": "*"
-    , "karma": "0.12.x"
-    , "karma-mocha": "*"
-    , "karma-sauce-launcher": "0.2.x"
-    , "karma-phantomjs-launcher": "0.1.1"
-    , "mocha": "1.21.x"
-    , "istanbul": "0.2.x"
-  }
-}
diff --git a/polymer_0.5.0/bower_components/chai/sauce.browsers.js b/polymer_0.5.0/bower_components/chai/sauce.browsers.js
deleted file mode 100644
index 690c7cc..0000000
--- a/polymer_0.5.0/bower_components/chai/sauce.browsers.js
+++ /dev/null
@@ -1,128 +0,0 @@
-
-/*!
- * Chrome
- */
-
-exports['SL_Chrome'] = {
-    base: 'SauceLabs'
-  , browserName: 'chrome'
-};
-
-/*!
- * Firefox
- */
-
-/*!
- * TODO: Karma doesn't seem to like this, though sauce boots its up
- *
-
-exports['SL_Firefox_23'] = {
-    base: 'SauceLabs'
-  , browserName: 'firefox'
-  , platform: 'Windows XP'
-  , version: '23'
-};
-
-*/
-
-exports['SL_Firefox_22'] = {
-    base: 'SauceLabs'
-  , browserName: 'firefox'
-  , platform: 'Windows 7'
-  , version: '22'
-};
-
-/*!
- * Opera
- */
-
-exports['SL_Opera_12'] = {
-    base: 'SauceLabs'
-  , browserName: 'opera'
-  , platform: 'Windows 7'
-  , version: '12'
-};
-
-exports['SL_Opera_11'] = {
-    base: 'SauceLabs'
-  , browserName: 'opera'
-  , platform: 'Windows 7'
-  , version: '11'
-};
-
-/*!
- * Internet Explorer
- */
-
-exports['SL_IE_10'] = {
-    base: 'SauceLabs'
-  , browserName: 'internet explorer'
-  , platform: 'Windows 2012'
-  , version: '10'
-};
-
-/*!
- * Safari
- */
-
-exports['SL_Safari_6'] = {
-    base: 'SauceLabs'
-  , browserName: 'safari'
-  , platform: 'Mac 10.8'
-  , version: '6'
-};
-
-exports['SL_Safari_5'] = {
-    base: 'SauceLabs'
-  , browserName: 'safari'
-  , platform: 'Mac 10.6'
-  , version: '5'
-};
-
-/*!
- * iPhone
- */
-
-/*!
- * TODO: These take forever to boot or shut down. Causes timeout.
- *
-
-exports['SL_iPhone_6'] = {
-    base: 'SauceLabs'
-  , browserName: 'iphone'
-  , platform: 'Mac 10.8'
-  , version: '6'
-};
-
-exports['SL_iPhone_5-1'] = {
-    base: 'SauceLabs'
-  , browserName: 'iphone'
-  , platform: 'Mac 10.8'
-  , version: '5.1'
-};
-
-exports['SL_iPhone_5'] = {
-    base: 'SauceLabs'
-  , browserName: 'iphone'
-  , platform: 'Mac 10.6'
-  , version: '5'
-};
-
-*/
-
-/*!
- * Android
- */
-
-/*!
- * TODO: fails because of error serialization
- *
-
-exports['SL_Android_4'] = {
-    base: 'SauceLabs'
-  , browserName: 'android'
-  , platform: 'Linux'
-  , version: '4'
-};
-
-*/
diff --git a/polymer_0.5.0/bower_components/chartnewjs/.bower.json b/polymer_0.5.0/bower_components/chartnewjs/.bower.json
deleted file mode 100644
index 4801372..0000000
--- a/polymer_0.5.0/bower_components/chartnewjs/.bower.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-  "name": "ChartNew.js",
-  "description": "Simple HTML5 Charts using the canvas element",
-  "keywords": [
-    "charts"
-  ],
-  "homepage": "https://github.com/FVANCOP/ChartNew.js",
-  "author": "FVANCOP",
-  "main": [
-    "ChartNew.js"
-  ],
-  "dependencies": {},
-  "_release": "666265b8e2",
-  "_resolution": {
-    "type": "branch",
-    "branch": "master",
-    "commit": "666265b8e202b4e8a706b5b32c4e3cba08fd4710"
-  },
-  "_source": "git://github.com/FVANCOP/ChartNew.js.git",
-  "_target": "*",
-  "_originalSource": "chartnewjs"
-}
\ No newline at end of file
diff --git a/polymer_0.5.0/bower_components/chartnewjs/Add-ins/format.js b/polymer_0.5.0/bower_components/chartnewjs/Add-ins/format.js
deleted file mode 100644
index 12debdf..0000000
--- a/polymer_0.5.0/bower_components/chartnewjs/Add-ins/format.js
+++ /dev/null
@@ -1,79 +0,0 @@
-//
-// Additional formats for ChartNew.js
-//
-// see https://github.com/FVANCOP/ChartNew.js/wiki/900_010_format.js
-//
-function fmtChartJSPerso(config, value, fmt) {
-	switch (fmt.split(/[\s,]+/)[0].toUpperCase()) {
-		case "DATE":
-			spltdt = fmt.replace(/,/g, " ").replace(/:/g, " ").split(/[\s,]+/);
-			var options = new Array();
-			for (var i = 1; i < spltdt.length; i++) {
-				switch (spltdt[i].toUpperCase()) {
-					case "WEEKDAY":
-					case "YEAR":
-					case "MONTH":
-					case "DAY":
-						options[spltdt[i]] = spltdt[i + 1];
-						break;
-					default:
-						break;
-				}
-			}
-			return_value = value.toLocaleDateString(fmt.split(" ")[1], options);
-			break;
-		case "FMTDATE":
-			spltdt = fmt.split(/[\s,]+/)[1].toUpperCase();
-			return_value = spltdt.replaceArray(["DD", "MM", "YYYY", "YY"], [value.getDate(), 1 + value.getMonth(), value.getFullYear(), value.getYear() % 100]);
-			break;
-		case "TIME":
-			return_value = value.toLocaleTimeString();
-			break;
-		case "FMTTIME":
-			spltdt = fmt.split(/[\s,]+/)[1].toUpperCase();
-			return_value = spltdt.replaceArray(["HH", "MM", "SS"], [
-				value.getHours() < 10 ? '0' + value.getHours() : value.getHours(),
-				value.getMinutes() < 10 ? '0' + value.getMinutes() : value.getMinutes(),
-				value.getSeconds() < 10 ? '0' + value.getSeconds() : value.getSeconds()
-			]);
-			break;
-		case "FMTDATETIME":
-			spltdt = fmt.splitLimit(/[\s,]+/, 2)[1];
-			return_value = spltdt.replaceArray(["DD", "MM", "YYYY", "YY", "HH", "mm", "ss"], [
-				value.getDate(), 1 + value.getMonth(), value.getFullYear(), value.getYear() % 100,
-				value.getHours() < 10 ? '0' + value.getHours() : value.getHours(),
-				value.getMinutes() < 10 ? '0' + value.getMinutes() : value.getMinutes(),
-				value.getSeconds() < 10 ? '0' + value.getSeconds() : value.getSeconds()
-			]);
-			break;
-		default:
-			return_value = value;
-			break;
-	}
-	return (return_value);
-}
-String.prototype.replaceArray = function(find, replace) {
-	var replaceString = this;
-	var regex;
-	for (var i = 0; i < find.length; i++) {
-		regex = new RegExp(find[i], "g");
-		replaceString = replaceString.replace(regex, replace[i]);
-	}
-	return replaceString;
-};
-/**
- * split a string into an array with limit entries
- * The last entry contains the last part of the string, which can contain the separator)
- * @param separator {string} string separator
- * @param limit {integer} number of entries in the array
- * @return array of separated strings
- */
-String.prototype.splitLimit = function(separator, limit) {
-	var splitString = this;
-	var result = [];
-	var pos = splitString.search(separator);
-	if (pos < 0) return false;
-	result.push(splitString.substring(0, pos));
-	result.push(splitString.substring(pos + 1));
-	return result;
-}
diff --git a/polymer_0.5.0/bower_components/chartnewjs/Add-ins/gradientColor.js b/polymer_0.5.0/bower_components/chartnewjs/Add-ins/gradientColor.js
deleted file mode 100644
index 7d83062..0000000
--- a/polymer_0.5.0/bower_components/chartnewjs/Add-ins/gradientColor.js
+++ /dev/null
@@ -1,85 +0,0 @@
-//
-// See ..\Samples\issue_102.html
-//
-// Module intially written by Ole Kroger
-// Change 1 : Omar Sedki - possibility to specify a percentage 
-// Change 2 : Vancoppenolle François - generalized for all graph types
-//
-
-
-function gradientColor(area,ctx,data,statData,posi,posj,othervars) {
-	// v0 = left xAxis of rectangle or xAxis of center
-	// v1 = top yAxis of rectangle or yAxis of center
-	// v2 = right xAxis of rectangle or internal radius (=0 for PolarArea, Pie and Radar)
-	// v3 = bottom yAxis or rectangle or external radius
-	var grd;
-	switch(ctx.tpchart) {
-		case "Radar" :
-			if (area == "COLOR") {
-				var grd = ctx.createRadialGradient(othervars.midPosX, othervars.midPosY, 0, othervars.midPosX, othervars.midPosY , othervars.ext_radius);
-			} else {
-				var grd = ctx.createRadialGradient(othervars.xPosLeft + (othervars.xPosRight - othervars.xPosLeft) / 2, othervars.yPosBottom + (othervars.yPosTop - othervars.yPosBottom) / 2, 0, othervars.xPosLeft + (othervars.xPosRight - othervars.xPosLeft) / 2, othervars.yPosBottom + (othervars.yPosTop - othervars.yPosBottom) / 2, Math.max((othervars.xPosRight - othervars.xPosLeft) / 2, (othervars.yPosTop - othervars.yPosBottom) / 2));
-			}
-			var gradientColors = data.datasets[posi].gradientColors;
-			break;
-		case "PolarArea" :
-		case "Pie" : 
-		case "Doughnut" :
-			if (area == "COLOR") {
-				var grd = ctx.createRadialGradient(statData[0].midPosX, statData[0].midPosY, othervars.scaleAnimation*statData[0].int_radius, statData[0].midPosX, statData[0].midPosY , othervars.scaleAnimation* statData[0].radiusOffset);
-			} else {
-				var grd = ctx.createRadialGradient(othervars.xPosLeft + (othervars.xPosRight - othervars.xPosLeft) / 2, othervars.yPosBottom + (othervars.yPosTop - othervars.yPosBottom) / 2, 0, othervars.xPosLeft + (othervars.xPosRight - othervars.xPosLeft) / 2, othervars.yPosBottom + (othervars.yPosTop - othervars.yPosBottom) / 2, Math.max((othervars.xPosRight - othervars.xPosLeft) / 2, (othervars.yPosTop - othervars.yPosBottom) / 2));
-			}
-			var gradientColors = data[posi].gradientColors;
-			break;
-		case "Line" :
-		case "Bar" :
-		case "StackedBar" :
-			grd = ctx.createLinearGradient(othervars.xPosLeft, othervars.yPosBottom, othervars.xPosLeft, othervars.yPosTop);
-			var gradientColors = data.datasets[posi].gradientColors;
-			break;
-		case "HorizontalBar" :
-		case "HorizontalStackedBar" :
-			grd = ctx.createLinearGradient(othervars.xPosLeft, othervars.yPosBottom, othervars.xPosRight, othervars.yPosBottom);
-			var gradientColors = data.datasets[posi].gradientColors;
-			break;
-		default : 
-			break;
-		
-	}
-	
-	var steps = gradientColors.length;
-	var currentStepValue = 0;
-	var stepValues = [];
-	var PERCENT_REGEX = /(\d{1,2}|100)%\s*?$/g
-	for (var iter = 0; iter < steps; iter++) {
-		var userStepValue = gradientColors[iter].match(PERCENT_REGEX);
-		if (!userStepValue) {
-			stepValues[iter] = false;
-			continue;
-		}
-		userStepValue = parseFloat(userStepValue) / 100.0;
-		stepValues[iter] = userStepValue;
-	}
-	for (var iter = 0; iter < steps; iter++) {
-		if (stepValues[iter] === false) {
-			if (iter == 0) {
-				stepValues[iter] = 0;
-			} else if (iter == steps - 1) {
-				stepValues[iter] = 1;
-			} else {
-				// found next stepValue which isn't false
-				var s = iter + 1;
-				while (s < steps - 1 && stepValues[s] === false) {
-					s++;
-				}
-				var lastStep = ((iter == 0) ? 0 : stepValues[iter - 1]);
-				stepValues[iter] = ((s >= steps - 1) ? 1 : stepValues[s + 1]) - lastStep;
-				stepValues[iter] = lastStep + stepValues[iter] / (s - iter + 1);
-			}
-		}
-		GradientcolorsWithoutStep = gradientColors[iter].replace(PERCENT_REGEX, "").trim();
-		grd.addColorStop(stepValues[iter], GradientcolorsWithoutStep);
-	}
-	return grd;
-}
diff --git a/polymer_0.5.0/bower_components/chartnewjs/Add-ins/stats.js b/polymer_0.5.0/bower_components/chartnewjs/Add-ins/stats.js
deleted file mode 100644
index 9f8228d..0000000
--- a/polymer_0.5.0/bower_components/chartnewjs/Add-ins/stats.js
+++ /dev/null
@@ -1,819 +0,0 @@
-
-function stats(data, config) {
-	data.stats = {};
-	if (typeof data.datasets == 'undefined') { // Pie structure;
-		PSbasic(data);
-	} else { // line structure;
-		LSbasic(data);
-		Linear_Regression(data);
-	}
-	replace_stats(data, config);
-	return;
-};
-
-function isStat(val) {
-	if (typeof val == "string") {
-		if (val.indexOf("#") >= 0) return true;
-	}
-	return false;
-};
-
-function Linear_Regression(data) {
-	// compute Means - source of algorithm : http://fr.wikipedia.org/wiki/R%C3%A9gression_lin%C3%A9aire
-	data.stats.linear_regression_count_xPos = 0;
-	data.stats.linear_regression_sum_xPos = 0;
-	data.stats.linear_regression_sum_data = 0;
-	for (var i = 0; i < data.datasets.length; i++) {
-		if (!(typeof data.datasets[i].xPos == "undefined")) {
-			data.datasets[i].stats.linear_regression_sum_xPos = 0;
-			data.datasets[i].stats.linear_regression_sum_data = 0;
-			data.datasets[i].stats.linear_regression_count_xPos = 0;
-			data.datasets[i].stats.count_data = 0;
-			for (var j = 0; j < data.datasets[i].data.length; j++) {
-				if (!(typeof data.datasets[i].data[j] == "undefined") && !(typeof data.datasets[i].xPos[j] == "undefined")) {
-					data.stats.linear_regression_count_xPos++;
-					data.stats.linear_regression_sum_xPos += data.datasets[i].xPos[j];
-					data.stats.linear_regression_sum_data += data.datasets[i].data[j];
-					data.datasets[i].stats.linear_regression_count_xPos++;
-					data.datasets[i].stats.linear_regression_sum_xPos += data.datasets[i].xPos[j];
-					data.datasets[i].stats.linear_regression_sum_data += data.datasets[i].data[j];
-				}
-			}
-			if (data.datasets[i].stats.linear_regression_count_xPos > 0) {
-				data.datasets[i].stats.linear_regression_mean_xPos = data.datasets[i].stats.linear_regression_sum_xPos / data.datasets[i].stats.linear_regression_count_xPos;
-				data.datasets[i].stats.linear_regression_mean_data = data.datasets[i].stats.linear_regression_sum_data / data.datasets[i].stats.linear_regression_count_xPos;
-			}
-		}
-	}
-	// mean;
-	if (data.stats.linear_regression_count_xPos > 0) {
-		data.stats.linear_regression_mean_xPos = data.stats.linear_regression_sum_xPos / data.stats.linear_regression_count_xPos;
-		data.stats.linear_regression_mean_data = data.stats.linear_regression_sum_data / data.stats.linear_regression_count_xPos;
-	}
-	// Covariance - variance;
-	data.stats.linear_regression_covariance = 0;
-	data.stats.linear_regression_variance = 0;
-	for (var i = 0; i < data.datasets.length; i++) {
-		if (!(typeof data.datasets[i].xPos == "undefined")) {
-			data.datasets[i].stats.linear_regression_covariance = 0;
-			data.datasets[i].stats.linear_regression_variance = 0;
-			for (var j = 0; j < data.datasets[i].data.length; j++) {
-				if (!(typeof data.datasets[i].data[j] == "undefined") && !(typeof data.datasets[i].xPos[j] == "undefined")) {
-					data.stats.linear_regression_covariance += (data.datasets[i].xPos[j] - data.stats.linear_regression_mean_xPos) * (data.datasets[i].data[j] - data.stats.linear_regression_mean_data);
-					data.stats.linear_regression_variance += (data.datasets[i].xPos[j] - data.stats.linear_regression_mean_xPos) * (data.datasets[i].xPos[j] - data.stats.linear_regression_mean_xPos);
-					data.datasets[i].stats.linear_regression_covariance += (data.datasets[i].xPos[j] - data.datasets[i].stats.linear_regression_mean_xPos) * (data.datasets[i].data[j] - data.datasets[i].stats.linear_regression_mean_data);
-					data.datasets[i].stats.linear_regression_variance += (data.datasets[i].xPos[j] - data.datasets[i].stats.linear_regression_mean_xPos) * (data.datasets[i].xPos[j] - data.datasets[i].stats.linear_regression_mean_xPos);
-				}
-			}
-			if (data.datasets[i].stats.linear_regression_count_xPos > 0) {
-				data.datasets[i].stats.linear_regression_covariance /= data.datasets[i].stats.linear_regression_count_xPos;
-				data.datasets[i].stats.linear_regression_variance /= data.datasets[i].stats.linear_regression_count_xPos;
-				data.datasets[i].stats.linear_regression_b1 = data.datasets[i].stats.linear_regression_covariance / data.datasets[i].stats.linear_regression_variance;
-				data.datasets[i].stats.linear_regression_b0 = data.datasets[i].stats.linear_regression_mean_data - data.datasets[i].stats.linear_regression_b1 * data.datasets[i].stats.linear_regression_mean_xPos;
-			}
-		}
-	}
-	// b1 - b0;
-	if (data.stats.linear_regression_count_xPos > 0) {
-		data.stats.linear_regression_covariance /= data.stats.linear_regression_count_xPos;
-		data.stats.linear_regression_variance /= data.stats.linear_regression_count_xPos;
-		data.stats.linear_regression_b1 = data.stats.linear_regression_covariance / data.stats.linear_regression_variance;
-		data.stats.linear_regression_b0 = data.stats.linear_regression_mean_data - data.stats.linear_regression_b1 * data.stats.linear_regression_mean_xPos;
-	}
-}
-
-function PSbasic(data) {
-	data.stats.sum = 0;
-	data.stats.count_all = 0;
-	data.stats.count_missing = 0;
-	data.stats.count_not_missing = 0;
-	data.stats.mean = undefined;
-	data.stats.sum_square_diff_mean = 0;
-	data.stats.standard_deviation = undefined;
-	data.stats.standard_deviation_estimation = undefined;
-	data.stats.student_t_test = undefined;
-	data.stats.coefficient_variation = undefined;
-	data.stats.data_with_stats = false;
-	for (var i = 0; i < data["length"]; i++) {
-		if (!isStat(data[i].value)) {
-			(data.stats.count_all) ++;
-		} else data.stats.data_with_stats = true;
-		if (typeof data[i].value == "undefined") {
-			(data.stats.count_missing) ++;
-		} else if (isStat(data[i].value)) {} else {
-			(data.stats.count_not_missing) ++;
-			(data.stats.sum) += 1 * data[i].value;
-		}
-	}
-	if (data.stats.count_not_missing > 0) {
-		data.stats.mean = data.stats.sum / data.stats.count_not_missing;
-	}
-	// sum of (val-mean)2;
-	// sum of (val-mean)3;
-	data.stats.sum_square_diff_mean = 0;
-	data.stats.sum_pow3_diff_mean = 0;
-	data.stats.sum_pow4_diff_mean = 0;
-	for (var i = 0; i < data["length"]; i++) {
-		if (typeof data[i].value != "undefined" && !isStat(data[i].value)) {
-			data.stats.sum_square_diff_mean += Math.pow(data[i].value - data.stats.mean, 2);
-			data.stats.sum_pow3_diff_mean += Math.pow(data[i].value - data.stats.mean, 3);
-			data.stats.sum_pow4_diff_mean += Math.pow(data[i].value - data.stats.mean, 4);
-		}
-	}
-	// standard deviation;
-	if (data.stats.count_not_missing > 0) {
-		data.stats.variance = data.stats.sum_square_diff_mean / data.stats.count_not_missing;
-		data.stats.standard_deviation = Math.sqrt(data.stats.sum_square_diff_mean / data.stats.count_not_missing);
-		data.stats.standard_error_mean = Math.sqrt(data.stats.sum_square_diff_mean) / data.stats.count_not_missing;
-	}
-	// standard deviation estimation;
-	if (data.stats.count_not_missing > 1) {
-		data.stats.standard_deviation_estimation = Math.sqrt(data.stats.sum_square_diff_mean / (data.stats.count_not_missing - 1));
-		if (data.stats.mean > 0) data.stats.coefficient_variation = 100 * data.stats.standard_deviation_estimation / data.stats.mean;
-		if (data.stats.standard_deviation_estimation > 0) data.stats.student_t_test = data.stats.mean / (data.stats.standard_deviation_estimation / Math.sqrt(data.stats.count_not_missing));
-		console.log(data.stats.mean);
-		console.log(data.stats.standard_deviation_estimation);
-		console.log(data.stats.count_not_missing);
-	}
-	// skewness;
-	if (data.stats.count_not_missing > 2) {
-		data.stats.skewness = (data.stats.count_not_missing * data.stats.sum_pow3_diff_mean) / (Math.pow(data.stats.standard_deviation_estimation, 3) * (data.stats.count_not_missing - 1) * (data.stats.count_not_missing - 2));
-	} else {
-		data.stats.skewness = undefined;
-	}
-	// kutosis;
-	if (data.stats.count_not_missing > 3) {
-		data.stats.kurtosis = (data.stats.count_not_missing * (data.stats.count_not_missing + 1) * data.stats.sum_pow4_diff_mean) / (Math.pow(data.stats.standard_deviation_estimation, 4) * (data.stats.count_not_missing - 1) * (data.stats.count_not_missing - 2) * (data.stats.count_not_missing - 3)) - 3 * (data.stats.count_not_missing - 1) * (data.stats.count_not_missing - 1) / ((data.stats.count_not_missing - 2) * (data.stats.count_not_missing - 3));
-	} else {
-		data.stats.kurtosis = undefined;
-	}
-	// ordering stats;
-	var orderStat = new Array();
-	cnt = 0;
-	for (i = 0; i < data.length; i++) {
-		if (typeof data[i].value != "undefined" && !isStat(data[i].value)) {
-			orderStat[cnt] = {
-				val: 1 * data[i].value,
-				one: 1
-			};
-			cnt++;
-		}
-	}
-	var setStat = new Array();
-	setStat = Pstats(orderStat, "one");
-	for (i = 0; i < setStat.length; i++) {
-		data.stats.minimum = setStat[i].res.minimum;
-		data.stats.maximum = setStat[i].res.maximum;
-		data.stats.Q0 = setStat[i].res.Q0;
-		data.stats.Q1 = setStat[i].res.Q1;
-		data.stats.Q5 = setStat[i].res.Q5;
-		data.stats.Q10 = setStat[i].res.Q10;
-		data.stats.Q25 = setStat[i].res.Q25;
-		data.stats.Q50 = setStat[i].res.Q50;
-		data.stats.Q75 = setStat[i].res.Q75;
-		data.stats.Q90 = setStat[i].res.Q90;
-		data.stats.Q95 = setStat[i].res.Q95;
-		data.stats.Q99 = setStat[i].res.Q99;
-		data.stats.Q100 = setStat[i].res.Q100;
-		data.stats.median = setStat[i].res.median;
-		data.stats.interquartile_range = data.stats.Q75 - data.stats.Q25;
-	}
-};
-
-function LSbasic(data) {
-	data.stats.sum = 0;
-	data.stats.count_all = 0;
-	data.stats.count_missing = 0;
-	data.stats.count_not_missing = 0;
-	data.stats.mean = undefined;
-	data.stats.sum_square_diff_mean = 0;
-	data.stats.sum_pow3_diff_mean = 0;
-	data.stats.sum_pow4_diff_mean = 0;
-	data.stats.standard_deviation = undefined;
-	data.stats.standard_deviation_estimation = undefined;
-	data.stats.student_t_test = undefined;
-	data.stats.coefficient_variation = undefined;
-	data.stats.data_with_stats = false;
-	data.stats.data_minimum = {};
-	data.stats.data_maximum = {};
-	data.stats.data_Q0 = {};
-	data.stats.data_Q1 = {};
-	data.stats.data_Q5 = {};
-	data.stats.data_Q10 = {};
-	data.stats.data_Q25 = {};
-	data.stats.data_Q50 = {};
-	data.stats.data_Q75 = {};
-	data.stats.data_Q90 = {};
-	data.stats.data_Q95 = {};
-	data.stats.data_Q99 = {};
-	data.stats.data_Q100 = {};
-	data.stats.data_median = {};
-	data.stats.data_sum = {};
-	data.stats.data_count_all = {};
-	data.stats.data_count_missing = {};
-	data.stats.data_count_not_missing = {};
-	data.stats.data_mean = {};
-	data.stats.data_sum_square_diff_mean = {};
-	data.stats.data_sum_pow3_diff_mean = {};
-	data.stats.data_sum_pow4_diff_mean = {};
-	data.stats.data_variance = {};
-	data.stats.data_standard_deviation = {};
-	data.stats.data_standard_error_mean = {};
-	data.stats.data_standard_deviation_estimation = {};
-	data.stats.data_student_t_test = {};
-	data.stats.data_coefficient_variation = {};
-	data.stats.data_skewness = {};
-	data.stats.data_kurtosis = {};
-	data.stats.data_interquartile_range = {};
-	data.stats.max_number_data = 0;
-	data.stats.min_number_data = Number.MAX_VALUE;
-	for (var i = 0; i < data.datasets["length"]; i++) {
-		data.datasets[i].stats = {};
-		data.datasets[i].stats.sum = 0;
-		data.datasets[i].stats.count_all = 0;
-		data.datasets[i].stats.count_missing = 0;
-		data.datasets[i].stats.count_not_missing = 0;
-		data.datasets[i].stats.mean = undefined;
-		data.datasets[i].stats.sum_square_diff_mean = 0;
-		data.datasets[i].stats.sum_pow3_diff_mean = 0;
-		data.datasets[i].stats.sum_pow4_diff_mean = 0;
-		data.datasets[i].stats.standard_deviation = undefined;
-		if (data.datasets[i].data["length"] > data.stats.max_number_data) {
-			for (var k = data.stats.max_number_data; k < data.datasets[i].data["length"]; k++) {
-				data.stats.data_sum[k] = 0;
-				data.stats.data_count_all[k] = 0;
-				data.stats.data_count_missing[k] = 0;
-				data.stats.data_count_not_missing[k] = 0;
-				data.stats.data_mean[k] = undefined;
-				data.stats.data_sum_square_diff_mean[k] = 0;
-				data.stats.data_sum_pow3_diff_mean[k] = 0;
-				data.stats.data_sum_pow4_diff_mean[k] = 0;
-				data.stats.data_standard_deviation[k] = undefined;
-				data.stats.data_standard_deviation_estimation[k] = undefined;
-				data.stats.data_student_t_test[k] = undefined;
-				data.stats.data_coefficient_variation[k] = undefined;
-			}
-			data.stats.max_number_data = data.datasets[i].data["length"];
-			data.stats.min_number_data = Math.min(data.stats.min_number_data, data.datasets[i].data["length"]);
-		}
-		for (var j = 0; j < data.datasets[i].data["length"]; j++) {
-			if (!isStat(data.datasets[i].data[j])) {
-				(data.stats.count_all) ++;
-				(data.datasets[i].stats.count_all) ++;
-				(data.stats.data_count_all[j]) ++;
-			} else {
-				data.stats.data_with_stats = true;
-			}
-			if (typeof data.datasets[i].data[j] == "undefined") {
-				(data.stats.count_missing) ++;
-				(data.datasets[i].stats.count_missing) ++;
-				(data.stats.data_count_missing[j]) ++;
-			} else if (isStat(data.datasets[i].data[j])) {} else {
-				(data.stats.count_not_missing) ++;
-				(data.datasets[i].stats.count_not_missing) ++;
-				(data.stats.data_count_not_missing[j]) ++;
-				(data.stats.sum) += 1 * data.datasets[i].data[j];
-				(data.datasets[i].stats.sum) += 1 * data.datasets[i].data[j];
-				(data.stats.data_sum[j]) += 1 * data.datasets[i].data[j];
-			}
-		}
-		if (data.datasets[i].stats.count_not_missing == 0) {
-			data.datasets[i].stats.minimum = undefined;
-			data.datasets[i].stats.maximum = undefined;
-			data.datasets[i].stats.sum = undefined;
-			data.datasets[i].stats.mean = undefined;
-		} else {
-			data.datasets[i].stats.mean = data.datasets[i].stats.sum / data.datasets[i].stats.count_not_missing;
-		}
-	}
-	if (data.stats.count_not_missing > 0) {
-		data.stats.mean = data.stats.sum / data.stats.count_not_missing;
-	}
-	for (i = 0; i < data.stats.max_number_data; i++) {
-		if (data.stats.data_count_not_missing[i] > 0) {
-			data.stats.data_mean[i] = data.stats.data_sum[i] / data.stats.data_count_not_missing[i];
-		}
-	}
-	// sum of (val-mean)2;
-	data.stats.sum_square_diff_mean = 0;
-	data.stats.sum_pow3_diff_mean = 0;
-	data.stats.sum_pow4_diff_mean = 0;
-	for (var i = 0; i < data.datasets["length"]; i++) {
-		data.datasets[i].stats.sum_square_diff_mean = 0;
-		data.datasets[i].stats.sum_pow3_diff_mean = 0;
-		data.datasets[i].stats.sum_pow4_diff_mean = 0;
-		for (var j = 0; j < data.datasets[i].data["length"]; j++) {
-			if (typeof data.datasets[i].data[j] != "undefined" && !isStat(data.datasets[i].data[j].value)) {
-				data.stats.sum_square_diff_mean += Math.pow(data.datasets[i].data[j] - data.stats.mean, 2);
-				data.stats.sum_pow3_diff_mean += Math.pow(data.datasets[i].data[j] - data.stats.mean, 3);
-				data.stats.sum_pow4_diff_mean += Math.pow(data.datasets[i].data[j] - data.stats.mean, 4);
-				data.stats.data_sum_square_diff_mean[j] += Math.pow(data.datasets[i].data[j] - data.stats.data_mean[j], 2);
-				data.stats.data_sum_pow3_diff_mean[j] += Math.pow(data.datasets[i].data[j] - data.stats.data_mean[j], 3);
-				data.stats.data_sum_pow4_diff_mean[j] += Math.pow(data.datasets[i].data[j] - data.stats.data_mean[j], 4);
-				data.datasets[i].stats.sum_square_diff_mean += Math.pow(data.datasets[i].data[j] - data.datasets[i].stats.mean, 2);
-				data.datasets[i].stats.sum_pow3_diff_mean += Math.pow(data.datasets[i].data[j] - data.datasets[i].stats.mean, 3);
-				data.datasets[i].stats.sum_pow4_diff_mean += Math.pow(data.datasets[i].data[j] - data.datasets[i].stats.mean, 4);
-			}
-		}
-	}
-	// standard deviation;
-	if (data.stats.count_not_missing > 0) {
-		data.stats.variance = data.stats.sum_square_diff_mean / data.stats.count_not_missing;
-		data.stats.standard_deviation = Math.sqrt(data.stats.sum_square_diff_mean / data.stats.count_not_missing);
-		data.stats.standard_error_mean = Math.sqrt(data.stats.sum_square_diff_mean) / data.stats.count_not_missing;
-	}
-	for (i = 0; i < data.datasets["length"]; i++) {
-		if (data.datasets[i].stats.count_not_missing > 0) {
-			data.datasets[i].stats.variance = data.datasets[i].stats.sum_square_diff_mean / data.datasets[i].stats.count_not_missing;
-			data.datasets[i].stats.standard_deviation = Math.sqrt(data.datasets[i].stats.sum_square_diff_mean / data.datasets[i].stats.count_not_missing);
-			data.datasets[i].stats.standard_error_mean = Math.sqrt(data.datasets[i].stats.sum_square_diff_mean) / data.datasets[i].stats.count_not_missing;
-		}
-	}
-	for (j = 0; j < data.stats.max_number_data; j++) {
-		if (data.stats.data_count_not_missing[j] > 0) {
-			data.stats.data_variance[j] = data.stats.data_sum_square_diff_mean[j] / data.stats.data_count_not_missing[j];
-			data.stats.data_standard_deviation[j] = Math.sqrt(data.stats.data_sum_square_diff_mean[j] / data.stats.data_count_not_missing[j]);
-			data.stats.data_standard_error_mean[j] = Math.sqrt(data.stats.data_sum_square_diff_mean[j]) / data.stats.data_count_not_missing[j];
-		}
-	}
-	// standard deviation estimation;
-	if (data.stats.count_not_missing > 1) {
-		data.stats.standard_deviation_estimation = Math.sqrt(data.stats.sum_square_diff_mean / (data.stats.count_not_missing - 1));
-		if (data.stats.mean > 0) data.stats.coefficient_variation = 100 * data.stats.standard_deviation_estimation / data.stats.mean;
-		if (data.stats.standard_deviation_estimation > 0) data.stats.student_t_test = data.stats.mean / (data.stats.standard_deviation_estimation / Math.sqrt(data.stats.count_not_missing));
-	}
-	for (i = 0; i < data.datasets["length"]; i++) {
-		if (data.datasets[i].stats.count_not_missing > 1) {
-			data.datasets[i].stats.standard_deviation_estimation = Math.sqrt(data.datasets[i].stats.sum_square_diff_mean / (data.datasets[i].stats.count_not_missing - 1));
-			if (data.datasets[i].stats.mean > 0) data.datasets[i].stats.coefficient_variation = 100 * data.datasets[i].stats.standard_deviation_estimation / data.datasets[i].stats.mean;
-			if (data.datasets[i].stats.standard_deviation_estimation > 0) data.datasets[i].stats.student_t_test = data.datasets[i].stats.mean / (data.datasets[i].stats.standard_deviation_estimation / Math.sqrt(data.datasets[i].stats.count_not_missing));
-		}
-	}
-	for (j = 0; j < data.stats.max_number_data; j++) {
-		if (data.stats.data_count_not_missing[j] > 1) {
-			data.stats.data_standard_deviation_estimation[j] = Math.sqrt(data.stats.data_sum_square_diff_mean[j] / (data.stats.data_count_not_missing[j] - 1));
-			if (data.stats.data_mean[j] > 0) data.stats.data_coefficient_variation[j] = 100 * data.stats.data_standard_deviation_estimation[j] / data.stats.data_mean[j];
-			if (data.stats.data_standard_deviation_estimation[j] > 0) data.stats.data_student_t_test[j] = data.stats.data_mean[j] / (data.stats.data_standard_deviation_estimation[j] / Math.sqrt(data.stats.data_count_not_missing[j]));
-		}
-	}
-	// skewness;
-	if (data.stats.count_not_missing >= 2) {
-		data.stats.skewness = (data.stats.count_not_missing * data.stats.sum_pow3_diff_mean) / (Math.pow(data.stats.standard_deviation_estimation, 3) * (data.stats.count_not_missing - 1) * (data.stats.count_not_missing - 2));
-	} else {
-		data.stats.skewness = undefined;
-	}
-	// kurtosis;
-	if (data.stats.count_not_missing >= 3) {
-		data.stats.kurtosis = (data.stats.count_not_missing * (data.stats.count_not_missing + 1) * data.stats.sum_pow4_diff_mean) / (Math.pow(data.stats.standard_deviation_estimation, 4) * (data.stats.count_not_missing - 1) * (data.stats.count_not_missing - 2) * (data.stats.count_not_missing - 3)) - 3 * (data.stats.count_not_missing - 1) * (data.stats.count_not_missing - 1) / ((data.stats.count_not_missing - 2) * (data.stats.count_not_missing - 3));
-	} else {
-		data.stats.kurtosis = undefined;
-	}
-	for (i = 0; i < data.datasets["length"]; i++) {
-		if (data.datasets[i].stats.count_not_missing >= 2) {
-			data.datasets[i].stats.skewness = (data.datasets[i].stats.count_not_missing * data.datasets[i].stats.sum_pow3_diff_mean) / (Math.pow(data.datasets[i].stats.standard_deviation_estimation, 3) * (data.datasets[i].stats.count_not_missing - 1) * (data.datasets[i].stats.count_not_missing - 2));
-		} else {
-			data.datasets[i].stats.skewness = undefined;
-		}
-		if (data.datasets[i].stats.count_not_missing >= 3) {
-			data.datasets[i].stats.kurtosis = (data.datasets[i].stats.count_not_missing * (data.datasets[i].stats.count_not_missing + 1) * data.datasets[i].stats.sum_pow4_diff_mean) / (Math.pow(data.datasets[i].stats.standard_deviation_estimation, 4) * (data.datasets[i].stats.count_not_missing - 1) * (data.datasets[i].stats.count_not_missing - 2) * (data.datasets[i].stats.count_not_missing - 3)) - 3 * (data.datasets[i].stats.count_not_missing - 1) * (data.datasets[i].stats.count_not_missing - 1) / ((data.datasets[i].stats.count_not_missing - 2) * (data.datasets[i].stats.count_not_missing - 3));
-		} else {
-			data.datasets[i].stats.kurtosis = undefined;
-		}
-	}
-	for (j = 0; j < data.stats.max_number_data; j++) {
-		if (data.stats.data_count_not_missing[j] >= 2) {
-			data.stats.data_skewness[j] = (data.stats.data_count_not_missing[j] * data.stats.data_sum_pow3_diff_mean[j]) / (Math.pow(data.stats.data_standard_deviation_estimation[j], 3) * (data.stats.data_count_not_missing[j] - 1) * (data.stats.data_count_not_missing[j] - 2));
-		} else {
-			data.stats.data_skewness[j] = undefined;
-		}
-		if (data.stats.data_count_not_missing[j] >= 3) {
-			data.stats.data_kurtosis[j] = (data.stats.data_count_not_missing[j] * (data.stats.data_count_not_missing[j] + 1) * data.stats.data_sum_pow4_diff_mean[j]) / (Math.pow(data.stats.data_standard_deviation_estimation[j], 4) * (data.stats.data_count_not_missing[j] - 1) * (data.stats.data_count_not_missing[j] - 2) * (data.stats.data_count_not_missing[j] - 3)) - 3 * (data.stats.data_count_not_missing[j] - 1) * (data.stats.data_count_not_missing[j] - 1) / ((data.stats.data_count_not_missing[j] - 2) * (data.stats.data_count_not_missing[j] - 3));
-		} else {
-			data.stats.data_kurtosis[j] = undefined;
-		}
-	}
-	// ordering stats;
-	var orderStat = new Array();
-	cnt = 0;
-	for (i = 0; i < data.datasets["length"]; i++) {
-		for (j = 0; j < data.datasets[i].data["length"]; j++) {
-			if (typeof data.datasets[i].data[j] != "undefined" && !isStat(data.datasets[i].data[j].value)) {
-				orderStat[cnt] = {
-					val: 1 * data.datasets[i].data[j],
-					dataset: i,
-					col: j,
-					one: 1
-				};
-				cnt++;
-			}
-		}
-	}
-	var setStat = new Array();
-	setStat = Pstats(orderStat, "one");
-	for (i = 0; i < setStat.length; i++) {
-		data.stats.minimum = setStat[i].res.minimum;
-		data.stats.maximum = setStat[i].res.maximum;
-		data.stats.Q0 = setStat[i].res.Q0;
-		data.stats.Q1 = setStat[i].res.Q1;
-		data.stats.Q5 = setStat[i].res.Q5;
-		data.stats.Q10 = setStat[i].res.Q10;
-		data.stats.Q25 = setStat[i].res.Q25;
-		data.stats.Q50 = setStat[i].res.Q50;
-		data.stats.Q75 = setStat[i].res.Q75;
-		data.stats.Q90 = setStat[i].res.Q90;
-		data.stats.Q95 = setStat[i].res.Q95;
-		data.stats.Q99 = setStat[i].res.Q99;
-		data.stats.Q100 = setStat[i].res.Q100;
-		data.stats.median = setStat[i].res.median;
-		data.stats.interquartile_range = data.stats.Q75 - data.stats.Q25;
-	}
-	setStat = Pstats(orderStat, "dataset");
-	for (i = 0; i < setStat.length; i++) {
-		data.datasets[setStat[i].secvalue].stats.minimum = setStat[i].res.minimum;
-		data.datasets[setStat[i].secvalue].stats.maximum = setStat[i].res.maximum;
-		data.datasets[setStat[i].secvalue].stats.Q0 = setStat[i].res.Q0;
-		data.datasets[setStat[i].secvalue].stats.Q1 = setStat[i].res.Q1;
-		data.datasets[setStat[i].secvalue].stats.Q5 = setStat[i].res.Q5;
-		data.datasets[setStat[i].secvalue].stats.Q10 = setStat[i].res.Q10;
-		data.datasets[setStat[i].secvalue].stats.Q25 = setStat[i].res.Q25;
-		data.datasets[setStat[i].secvalue].stats.Q50 = setStat[i].res.Q50;
-		data.datasets[setStat[i].secvalue].stats.Q75 = setStat[i].res.Q75;
-		data.datasets[setStat[i].secvalue].stats.Q90 = setStat[i].res.Q90;
-		data.datasets[setStat[i].secvalue].stats.Q95 = setStat[i].res.Q95;
-		data.datasets[setStat[i].secvalue].stats.Q99 = setStat[i].res.Q99;
-		data.datasets[setStat[i].secvalue].stats.Q100 = setStat[i].res.Q100;
-		data.datasets[setStat[i].secvalue].stats.median = setStat[i].res.median;
-		data.datasets[setStat[i].secvalue].stats.interquartile_range = data.datasets[setStat[i].secvalue].stats.Q75 - data.datasets[setStat[i].secvalue].stats.Q25;
-	}
-	setStat = Pstats(orderStat, "col");
-	for (i = 0; i < setStat.length; i++) {
-		data.stats.data_minimum[setStat[i].secvalue] = setStat[i].res.minimum;
-		data.stats.data_maximum[setStat[i].secvalue] = setStat[i].res.maximum;
-		data.stats.data_Q0[setStat[i].secvalue] = setStat[i].res.Q0;
-		data.stats.data_Q1[setStat[i].secvalue] = setStat[i].res.Q1;
-		data.stats.data_Q5[setStat[i].secvalue] = setStat[i].res.Q5;
-		data.stats.data_Q10[setStat[i].secvalue] = setStat[i].res.Q10;
-		data.stats.data_Q25[setStat[i].secvalue] = setStat[i].res.Q25;
-		data.stats.data_Q50[setStat[i].secvalue] = setStat[i].res.Q50;
-		data.stats.data_Q75[setStat[i].secvalue] = setStat[i].res.Q75;
-		data.stats.data_Q90[setStat[i].secvalue] = setStat[i].res.Q90;
-		data.stats.data_Q95[setStat[i].secvalue] = setStat[i].res.Q95;
-		data.stats.data_Q99[setStat[i].secvalue] = setStat[i].res.Q99;
-		data.stats.data_Q100[setStat[i].secvalue] = setStat[i].res.Q100;
-		data.stats.data_median[setStat[i].secvalue] = setStat[i].res.median;
-		data.stats.data_interquartile_range[setStat[i].secvalue] = data.stats.data_Q75[setStat[i].secvalue] - data.stats.data_Q25[setStat[i].secvalue];
-	}
-};
-
-function Pstats(orderStat, secVar) {
-	var result = new Array();
-	orderStat.sort(function(a, b) {
-		if (a[secVar] < b[secVar]) return -1
-		else if (a[secVar] > b[secVar]) return 1
-		if (a.val < b.val) return -1
-		else if (a.val > b.val) return 1
-		else return 0
-	});
-	var deb = 0,
-		fin = 0;
-	for (i = 1; i < orderStat.length; i++) {
-		if (orderStat[i][secVar] == orderStat[deb][secVar]) fin++;
-		else {
-			result[result.length] = {
-				secvalue: orderStat[deb][secVar],
-				res: P2stats(deb, fin, orderStat)
-			};
-			fin++;
-			deb = fin;
-		}
-	}
-	result[result.length] = {
-		secvalue: orderStat[deb][secVar],
-		res: P2stats(deb, fin, orderStat)
-	};
-	return result;
-};
-
-function P2stats(deb, fin, orderStat) {
-	return {
-		minimum: orderStat[deb].val,
-		maximum: orderStat[fin].val,
-		Q0: orderStat[deb].val,
-		Q1: Quantile(1, deb, fin, orderStat),
-		Q5: Quantile(5, deb, fin, orderStat),
-		Q10: Quantile(10, deb, fin, orderStat),
-		Q25: Quantile(25, deb, fin, orderStat),
-		Q50: Quantile(50, deb, fin, orderStat),
-		Q75: Quantile(75, deb, fin, orderStat),
-		Q90: Quantile(90, deb, fin, orderStat),
-		Q95: Quantile(95, deb, fin, orderStat),
-		Q99: Quantile(99, deb, fin, orderStat),
-		Q100: orderStat[fin].val,
-		median: Quantile(50, deb, fin, orderStat)
-	}
-};
-
-function Quantile(quant, deb, fin, orderStat) {
-	var nbobs = fin - deb + 1;
-	if (quant <= 50.01) {
-		var v1 = Math.ceil((nbobs * quant / 100) - 0.000001) - 1;
-		var v2 = Math.ceil(((nbobs + 1) * quant / 100) - 0.000001) - 1;
-	} else {
-		var v1 = Math.ceil((nbobs * (100 - quant) / 100) - 0.000001) - 1;
-		v1 = nbobs - v1 - 1;
-		var v2 = Math.ceil(((nbobs + 1) * (100 - quant) / 100) - 0.000001) - 1;
-		v2 = nbobs - v2 - 1;
-	}
-	//  if(deb+v2>fin)v2=fin-deb-1;
-	return ((orderStat[deb + v1].val + orderStat[deb + v2].val) / 2);
-};
-
-function disp_stats(data) {
-	document.write("data.stats.count_all=" + data.stats.count_all + "<BR>");
-	document.write("data.stats.count_missing=" + data.stats.count_missing + "<BR>");
-	document.write("data.stats.count_not_missing=" + data.stats.count_not_missing + "<BR>");
-	document.write("data.stats.minimum=" + data.stats.minimum + "<BR>");
-	document.write("data.stats.maximum=" + data.stats.maximum + "<BR>");
-	document.write("data.stats.sum=" + data.stats.sum + "<BR>");
-	document.write("data.stats.mean=" + data.stats.mean + "<BR>");
-	document.write("data.stats.sum_square_diff_mean=" + data.stats.sum_square_diff_mean + "<BR>");
-	document.write("data.stats.variance=" + data.stats.variance + "<BR>");
-	document.write("data.stats.standard _deviation=" + data.stats.standard_deviation + "<BR>");
-	document.write("data.stats.standard_error_mean=" + data.stats.standard_error_mean + "<BR>");
-	document.write("data.stats.standard_deviation_estimation=" + data.stats.standard_deviation_estimation + "<BR>");
-	document.write("data.stats.coefficient_variation=" + data.stats.coefficient_variation + "<BR>");
-	document.write("data.stats.skewness=" + data.stats.skewness + "<BR>");
-	document.write("data.stats.kurtosis=" + data.stats.kurtosis + "<BR>");
-	document.write("data.stats.student_t_test=" + data.stats.student_t_test + "<BR>");
-	document.write("data.stats.Q0" + data.stats.Q0 + "<BR>");
-	document.write("data.stats.Q1=" + data.stats.Q1 + "<BR>");
-	document.write("data.stats.Q5=" + data.stats.Q5 + "<BR>");
-	document.write("data.stats.Q10=" + data.stats.Q10 + "<BR>");
-	document.write("data.stats.Q25=" + data.stats.Q25 + "<BR>");
-	document.write("data.stats.Q50=" + data.stats.Q50 + "<BR>");
-	document.write("data.stats.Q75=" + data.stats.Q75 + "<BR>");
-	document.write("data.stats.Q90=" + data.stats.Q90 + "<BR>");
-	document.write("data.stats.Q95=" + data.stats.Q95 + "<BR>");
-	document.write("data.stats.Q99=" + data.stats.Q99 + "<BR>");
-	document.write("data.stats.Q100=" + data.stats.Q100 + "<BR>");
-	document.write("data.stats.median=" + data.stats.median + "<BR>");
-	document.write("data.stats.interquartile_range=" + data.stats.interquartile_range + "<BR>");
-	document.write("<hr>")
-	if (typeof data.datasets != 'undefined') {
-		for (i = 0; i < data.datasets.length; i++) {
-			document.write("<hr>")
-			document.write("DATASET: " + i + "<BR>");
-			document.write("data.datasets[" + i + "].stats.count_all=" + data.datasets[i].stats.count_all + "<BR>");
-			document.write("data.datasets[" + i + "].stats.count_missing=" + data.datasets[i].stats.count_missing + "<BR>");
-			document.write("data.datasets[" + i + "].stats.count_not_missing=" + data.datasets[i].stats.count_not_missing + "<BR>");
-			document.write("data.datasets[" + i + "].stats.minimum=" + data.datasets[i].stats.minimum + "<BR>");
-			document.write("data.datasets[" + i + "].stats.maximum=" + data.datasets[i].stats.maximum + "<BR>");
-			document.write("data.datasets[" + i + "].stats.sum=" + data.datasets[i].stats.sum + "<BR>");
-			document.write("data.datasets[" + i + "].stats.mean=" + data.datasets[i].stats.mean + "<BR>");
-			document.write("data.datasets[" + i + "].stats.sum_square_diff_mean=" + data.datasets[i].stats.sum_square_diff_mean + "<BR>");
-			document.write("data.datasets[" + i + "].stats.variance=" + data.datasets[i].stats.variance + "<BR>");
-			document.write("data.datasets[" + i + "].stats.standard_deviation=" + data.datasets[i].stats.standard_deviation + "<BR>");
-			document.write("data.datasets[" + i + "].stats.standard_error_mean=" + data.datasets[i].stats.standard_error_mean + "<BR>");
-			document.write("data.datasets[" + i + "].stats.standard_deviation_estimation=" + data.datasets[i].stats.standard_deviation_estimation + "<BR>");
-			document.write("data.datasets[" + i + "].stats.student_t_test=" + data.datasets[i].stats.student_t_test + "<BR>");
-			document.write("data.datasets[" + i + "].stats.coefficient_variation=" + data.datasets[i].stats.coefficient_variation + "<BR>");
-			document.write("data.datasets[" + i + "]stats.skewness=" + data.datasets[i].stats.skewness + "<BR>");
-			document.write("data.datasets[" + i + "]stats.kurtosis=" + data.datasets[i].stats.kurtosis + "<BR>");
-			document.write("data.datasets[" + i + "].stats.Q0=" + data.datasets[i].stats.Q0 + "<BR>");
-			document.write("data.datasets[" + i + "].stats.Q1=" + data.datasets[i].stats.Q1 + "<BR>");
-			document.write("data.datasets[" + i + "].stats.Q5=" + data.datasets[i].stats.Q5 + "<BR>");
-			document.write("data.datasets[" + i + "].stats.Q10=" + data.datasets[i].stats.Q10 + "<BR>");
-			document.write("data.datasets[" + i + "].stats.Q25=" + data.datasets[i].stats.Q25 + "<BR>");
-			document.write("data.datasets[" + i + "].stats.Q50=" + data.datasets[i].stats.Q50 + "<BR>");
-			document.write("data.datasets[" + i + "].stats.Q75=" + data.datasets[i].stats.Q75 + "<BR>");
-			document.write("data.datasets[" + i + "].stats.Q90=" + data.datasets[i].stats.Q90 + "<BR>");
-			document.write("data.datasets[" + i + "].stats.Q95=" + data.datasets[i].stats.Q95 + "<BR>");
-			document.write("data.datasets[" + i + "].stats.Q99=" + data.datasets[i].stats.Q99 + "<BR>");
-			document.write("data.datasets[" + i + "].stats.Q100=" + data.datasets[i].stats.Q100 + "<BR>");
-			document.write("data.datasets[" + i + "].stats.median=" + data.datasets[i].stats.median + "<BR>");
-			document.write("data.datasets[" + i + "].stats.interquartile_range=" + data.datasets[i].stats.interquartile_range + "<BR>");
-		}
-		document.write("<hr>")
-		for (i = 0; i < data.stats.max_number_data; i++) {
-			document.write("<hr>")
-			document.write("Data: " + i + "<BR>");
-			document.write("data.stats.data_count_all[" + i + "]=" + data.stats.data_count_all[i] + "<BR>");
-			document.write("data.stats.data_count_missing[" + i + "]=" + data.stats.data_count_missing[i] + "<BR>");
-			document.write("data.stats.data_count_not_missing[" + i + "]=" + data.stats.data_count_not_missing[i] + "<BR>");
-			document.write("data.stats.data_minimum[" + i + "]=" + data.stats.data_minimum[i] + "<BR>");
-			document.write("data.stats.data_maximum[" + i + "]=" + data.stats.data_maximum[i] + "<BR>");
-			document.write("data.stats.data_sum[" + i + "]=" + data.stats.data_sum[i] + "<BR>");
-			document.write("data.stats.data_mean[" + i + "]=" + data.stats.data_mean[i] + "<BR>");
-			document.write("data.stats.data_sum_square_diff_mean[" + i + "]=" + data.stats.data_sum_square_diff_mean[i] + "<BR>");
-			document.write("data.stats.data_variance[" + i + "]=" + data.stats.data_variance[i] + "<BR>");
-			document.write("data.stats.data_standard_deviation[" + i + "]=" + data.stats.data_standard_deviation[i] + "<BR>");
-			document.write("data.stats.data_standard_error_mean[" + i + "]=" + data.stats.data_standard_error_mean[i] + "<BR>");
-			document.write("data.stats.data_standard_deviation_estimation[" + i + "]=" + data.stats.data_standard_deviation_estimation[i] + "<BR>");
-			document.write("data.stats.data_student_t_test[" + i + "]=" + data.stats.data_student_t_test[i] + "<BR>");
-			document.write("data.stats.data_coefficient_variation[" + i + "]=" + data.stats.data_coefficient_variation[i] + "<BR>");
-			document.write("data.stats.data_skewness[" + i + "]=" + data.stats.data_skewness[i] + "<BR>");
-			document.write("data.stats.data_kurtosis[" + i + "]=" + data.stats.data_kurtosis[i] + "<BR>");
-			document.write("data.stats.data_Q0[" + i + "]=" + data.stats.data_Q0[i] + "<BR>");
-			document.write("data.stats.data_Q1[" + i + "]=" + data.stats.data_Q1[i] + "<BR>");
-			document.write("data.stats.data_Q5[" + i + "]=" + data.stats.data_Q5[i] + "<BR>");
-			document.write("data.stats.data_Q10[" + i + "]=" + data.stats.data_Q10[i] + "<BR>");
-			document.write("data.stats.data_Q25[" + i + "]=" + data.stats.data_Q25[i] + "<BR>");
-			document.write("data.stats.data_Q50[" + i + "]=" + data.stats.data_Q50[i] + "<BR>");
-			document.write("data.stats.data_Q75[" + i + "]=" + data.stats.data_Q75[i] + "<BR>");
-			document.write("data.stats.data_Q90[" + i + "]=" + data.stats.data_Q90[i] + "<BR>");
-			document.write("data.stats.data_Q95[" + i + "]=" + data.stats.data_Q95[i] + "<BR>");
-			document.write("data.stats.data_Q99[" + i + "]=" + data.stats.data_Q99[i] + "<BR>");
-			document.write("data.stats.data_Q100[" + i + "]=" + data.stats.data_Q100[i] + "<BR>");
-			document.write("data.stats.data_median[" + i + "]=" + data.stats.data_median[i] + "<BR>");
-			document.write("data.stats.data_interquartile_range[" + i + "]=" + data.stats.data_interquartile_range[i] + "<BR>");
-		}
-	}
-};
-
-function replace_stats(data, config) {
-	// replace in the data
-	if (data.stats.data_with_stats) {
-		if (typeof data.datasets == 'undefined') { // Pie structure;
-			for (i = 0; i < data.length; i++) {
-				if (isStat(data[i].value)) data[i].value = replace_Stats_In(data[i].value, data, -1, -1);
-				// templates ?
-				if (isTemplate(data[i].value)) {
-					data[i].value = tmplStat(data[i].value, {
-						V1: 1
-					});
-				}
-			}
-		} else { // line structure;
-			for (var i = 0; i < data.datasets["length"]; i++) {
-				for (var j = 0; j < data.datasets[i].data["length"]; j++) {
-					if (isStat(data.datasets[i].data[j])) {
-						data.datasets[i].data[j] = replace_Stats_In(data.datasets[i].data[j], data, i, j);
-					}
-					// templates ?
-					if (isTemplate(data.datasets[i].data[j])) {
-						data.datasets[i].data[j] = tmplStat(data.datasets[i].data[j], {
-							V1: 1
-						});
-					}
-				}
-			}
-		}
-	}
-	// replace in other part of the data (titles)
-	if (typeof data.datasets == 'undefined') { // Pie structure;
-		for (i = 0; i < data.length; i++) {
-			if (isStat(data[i].title)) data[i].title = replace_Stats_In(data[i].title, data, -1, -1);
-			// templates ?
-			if (isTemplate(data[i].title)) {
-				data[i].title = tmplStat(data[i].title, {
-					V1: 1
-				});
-			}
-		}
-	} else { // line structure;
-		for (var i = 0; i < data.datasets["length"]; i++) {
-			if (isStat(data.datasets[i].title)) {
-				data.datasets[i].title = replace_Stats_In(data.datasets[i].title, data, i, -1);
-			}
-			// templates ?
-			if (isTemplate(data.datasets[i].title)) {
-				data.datasets[i].title = tmplStat(data.datasets[i].title, {
-					V1: 1
-				});
-			}
-		}
-	}
-	// replace in options
-	replace_in_object(config, data);
-};
-
-function replace_in_object(obj, data) {
-	for (var attrname in obj) {
-		if (typeof obj[attrname] == "object") {
-			replace_in_object(obj[attrname], data);
-		} else if (isStat(obj[attrname])) {
-			obj[attrname] = replace_Stats_In(obj[attrname], data, -1, -1);
-			// templates if not a template option....
-			if (!(attrname == "annotateLabel" || attrname == "inGraphDataTmpl" || attrname == "scaleLabel")) {
-				if (isTemplate(obj[attrname])) {
-					obj[attrname] = tmplStat(obj[attrname], {
-						V1: 1
-					});
-				}
-			}
-		}
-	}
-};
-
-function tmplStat(str, data) {
-	// Figure out if we're getting a template, or if we need to
-	// load the template - and be sure to cache the result.
-	var fn = !/\W/.test(str) ?
-		cachebis[str] = cachebis[str] ||
-		tmplbis(document.getElementById(str).innerHTML) :
-		// Generate a reusable function that will serve as a template
-		// generator (and which will be cached).
-		new Function("obj",
-			"var p=[],print=function(){p.push.apply(p,arguments);};" +
-			// Introduce the data as local variables using with(){}
-			"with(obj){p.push('" +
-			// Convert the template into pure JavaScript
-			str
-			.replace(/[\r\t\n]/g, " ")
-			.split("<%").join("\t")
-			.replace(/((^|%>)[^\t]*)'/g, "$1\r")
-			.replace(/\t=(.*?)%>/g, "',$1,'")
-			.split("\t").join("');")
-			.split("%>").join("p.push('")
-			.split("\r").join("\\'") + "');}return p.join('');");
-	// Provide some basic currying to the user
-	return data ? fn(data) : fn;
-};
-
-function isTemplate(strvar) {
-	if (typeof strvar == "string") {
-		if (strvar.indexOf("<%") >= 0) {
-			if (strvar.indexOf(">", strvar.indexOf("%>")) > 0) {
-				return true;
-			}
-		}
-	}
-	return false;
-};
-
-function replace_Stats_In(strval, data, dataset, coldata) {
-	var resval = "";
-	var start = 0;
-	var prevstat = true;
-	while (strval.indexOf("#", start) >= 0) {
-		// strval.substring(start,)           ;
-		if (!prevstat) {
-			var statOf = convertStat(strval.substring(start, strval.indexOf("#", start)), data, dataset, coldata);
-			if (statOf.found) {
-				resval = resval + statOf.resval;
-				start = strval.indexOf("#", start) + 1;
-				prevstat = true;
-			} else {
-				resval = resval + "#" + statOf.resval;
-				start = strval.indexOf("#", start) + 1;
-			}
-		} else {
-			if (start > 0) resval = resval;
-			resval = resval + strval.substring(start, strval.indexOf("#", start));
-			start = strval.indexOf("#", start) + 1;
-			prevstat = false;
-		}
-	}
-	if (!prevstat) resval = resval + "#";
-	resval = resval + strval.substring(start, strval.length);
-	return resval;
-};
-
-function convertStat(statval, data, dataset, coldata) {
-	var resval = statval;
-	var found = false;
-	if (typeof data.stats[statval.toLowerCase()] != "undefined" && typeof data.stats[statval.toLowerCase()] != "object") {
-		resval = data.stats[statval.toLowerCase()];
-		found = true;
-	} else if (statval.toLowerCase().substring(0, 3) == "ds_") {
-		stat = statval.toLowerCase().substring(3);
-		if (stat.indexOf("(") > 0) {
-			var vdataset = stat.substring(stat.indexOf("(") + 1);
-			vdataset = 1 * vdataset.substring(0, vdataset.indexOf(")"));
-			var stat = stat.substring(0, stat.indexOf("("));
-		} else {
-			vdataset = Math.max(1 * dataset, 0);
-		}
-		if (typeof data.datasets == "object") {
-			if (typeof data.datasets[vdataset] == "object") {
-				if (typeof data.datasets[vdataset].stats == "object") {
-					if (typeof data.datasets[vdataset].stats[stat] == "number") {
-						resval = data.datasets[vdataset].stats[stat];
-						found = true;
-					}
-				}
-			}
-		}
-	} else if (statval.toLowerCase().substring(0, 5) == "data_") {
-		stat = statval.toLowerCase().substring(5);
-		if (stat.indexOf("(") > 0) {
-			vdataset = stat.substring(stat.indexOf("(") + 1);
-			vdataset = 1 * vdataset.substring(0, vdataset.indexOf(")"));
-			stat = stat.substring(0, stat.indexOf("("));
-		} else {
-			vdataset = Math.max(1 * coldata, 0);
-		}
-		if (typeof data.datasets == "object") {
-			if (typeof data.stats["data_" + stat] == "object") {
-				if (typeof data.stats["data_" + stat][vdataset] == "number") {
-					resval = data.stats["data_" + stat][vdataset];
-					found = true;
-				}
-			}
-		}
-	}
-	return {
-		found: found,
-		resval: resval
-	};
-};
diff --git a/polymer_0.5.0/bower_components/chartnewjs/ChartNew.js b/polymer_0.5.0/bower_components/chartnewjs/ChartNew.js
deleted file mode 100644
index 6698094..0000000
--- a/polymer_0.5.0/bower_components/chartnewjs/ChartNew.js
+++ /dev/null
@@ -1,6574 +0,0 @@
-/*              ²
- * ChartNew.js  
- *
- * Vancoppenolle Francois - January 2014
- * francois.vancoppenolle@favomo.be
- *
- * Source location : http:\\www.favomo.be\graphjs
- * GitHub community : https://github.com/FVANCOP/ChartNew.js
- *
- * This file is originally an adaptation of the chart.js source developped by Nick Downie (2013)
- * https://github.com/nnnick/Chart.js. But since june 2014, Nick puts a new version with a
- * refunded code. Current code of ChartNew.js is no more comparable to the code of Chart.js 
- *
- * new charts compared to Chart.js
- *
- *     horizontalBar
- *     horizontalStackedBar
- *
- * Added items compared to Chart.js:
- *
- *     Title, Subtitle, footnotes, axis labels, unit label
- *     Y Axis on the right and/or the left
- *     canvas Border
- *     Legend
- *     crossText, crossImage
- *     graphMin, graphMax
- *     logarithmic y-axis (for line and bar)
- *     rotateLabels
- *     and lot of others...
- *
- */
-// non standard functions;
-if (typeof String.prototype.trim !== 'function') {
-	String.prototype.trim = function() {
-		return this.replace(/^\s+|\s+$/g, '');
-	}
-};
-if (!Array.prototype.indexOf) {
-	Array.prototype.indexOf = function(searchElement /*, fromIndex */ ) {
-		"use strict";
-		if (this == null) {
-			throw new TypeError();
-		}
-		var t = Object(this);
-		var len = t.length >>> 0;
-		if (len === 0) {
-			return -1;
-		}
-		var n = 0;
-		if (arguments.length > 0) {
-			n = Number(arguments[1]);
-			if (n != n) { // shortcut for verifying if it's NaN
-				n = 0;
-			} else if (n != 0 && n != Infinity && n != -Infinity) {
-				n = (n > 0 || -1) * Math.floor(Math.abs(n));
-			}
-		}
-		if (n >= len) {
-			return -1;
-		}
-		var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
-		for (; k < len; k++) {
-			if (k in t && t[k] === searchElement) {
-				return k;
-			}
-		}
-		return -1;
-	}
-};
-var charJSPersonalDefaultOptions = {};
-var charJSPersonalDefaultOptionsLine = {} ;
-var charJSPersonalDefaultOptionsRadar = {} ;
-var charJSPersonalDefaultOptionsPolarArea = {} ;
-var charJSPersonalDefaultOptionsPie = {};
-var charJSPersonalDefaultOptionsDoughnut = {};
-var charJSPersonalDefaultOptionsBar = {};
-var charJSPersonalDefaultOptionsStackedBar = {};
-var charJSPersonalDefaultOptionsHorizontalBar = {};
-var charJSPersonalDefaultOptionsHorizontalStackedBar = {};
-	///////// FUNCTIONS THAN CAN BE USED IN THE TEMPLATES ///////////////////////////////////////////
-
-function roundToWithThousands(config, num, place) {
-	var newval = 1 * unFormat(config, num);
-	if (typeof(newval) == "number" && place != "none") {
-		if (place <= 0) {
-			var roundVal = -place;
-			newval = +(Math.round(newval + "e+" + roundVal) + "e-" + roundVal);
-		} else {
-			var roundVal = place;
-			var divval = "1e+" + roundVal;
-			newval = +(Math.round(newval / divval)) * divval;
-		}
-	}
-	newval = fmtChartJS(config, newval, "none");
-	return (newval);
-};
-
-function unFormat(config, num) {
-	if ((config.decimalSeparator != "." || config.thousandSeparator != "") && typeof(num) == "string") {
-		var v1 = "" + num;
-		if (config.thousandSeparator != "") {
-			while (v1.indexOf(config.thousandSeparator) >= 0) v1 = "" + v1.replace(config.thousandSeparator, "");
-		}
-		if (config.decimalSeparator != ".") v1 = "" + v1.replace(config.decimalSeparator, ".")
-		return 1 * v1;
-	} else {
-		return num;
-	}
-};
-///////// ANNOTATE PART OF THE SCRIPT ///////////////////////////////////////////
-/********************************************************************************
-Copyright (C) 1999 Thomas Brattli
-This script is made by and copyrighted to Thomas Brattli
-Visit for more great scripts. This may be used freely as long as this msg is intact!
-I will also appriciate any links you could give me.
-Distributed by Hypergurl
-********************************************************************************/
-var cachebis = {};
-
-function fmtChartJSPerso(config, value, fmt) {
-	switch (fmt) {
-		case "SampleJS_Format":
-			if (typeof(value) == "number") return_value = "My Format : " + value.toString() + " $";
-			else return_value = value + "XX";
-			break;
-		case "Change_Month":
-			if (typeof(value) == "string") return_value = value.toString() + " 2014";
-			else return_value = value.toString() + "YY";
-			break;
-		default:
-			return_value = value;
-			break;
-	}
-	return (return_value);
-};
-
-function fmtChartJS(config, value, fmt) {
-	var return_value;
-	if (fmt == "notformatted") {
-		return_value = value;
-	} else if (fmt == "none" && typeof(value) == "number") {
-		if (config.roundNumber != "none") {
-			if (config.roundNumber <= 0) {
-				var roundVal = -config.roundNumber;
-				value = +(Math.round(value + "e+" + roundVal) + "e-" + roundVal);
-			} else {
-				var roundVal = config.roundNumber;
-				var divval = "1e+" + roundVal;
-				value = +(Math.round(value / divval)) * divval;
-			}
-		}
-		if (config.decimalSeparator != "." || config.thousandSeparator != "") {
-			return_value = value.toString().replace(/\./g, config.decimalSeparator);
-			if (config.thousandSeparator != "") {
-				var part1 = return_value;
-				var part2 = "";
-				var posdec = part1.indexOf(config.decimalSeparator);
-				if (posdec >= 0) {
-					part2 = part1.substring(posdec + 1, part1.length);
-					part2 = part2.split('').reverse().join(''); // reverse string
-					part1 = part1.substring(0, posdec);
-				}
-				part1 = part1.toString().replace(/\B(?=(\d{3})+(?!\d))/g, config.thousandSeparator);
-				part2 = part2.split('').reverse().join(''); // reverse string
-				return_value = part1
-				if (part2 != "") return_value = return_value + config.decimalSeparator + part2;
-			}
-		} else return_value = value;
-	} else if (fmt != "none" && fmt != "notformatted") {
-		return_value = fmtChartJSPerso(config, value, fmt);
-	} else {
-		return_value = value;
-	}
-	return (return_value);
-};
-
-function addParameters2Function(data, fctName, fctList) {
-	var mathFunctions = {
-		mean: {
-			data: data.data,
-			datasetNr: data.v11
-		},
-		varianz: {
-			data: data.data,
-			datasetNr: data.v11
-		},
-		stddev: {
-			data: data.data,
-			datasetNr: data.v11
-		},
-		cv: {
-			data: data.data,
-			datasetNr: data.v11
-		},
-		median: {
-			data: data.data,
-			datasetNr: data.v11
-		}
-	};
-	// difference to current value (v3)
-	dif = false;
-	if (fctName.substr(-3) == "Dif") {
-		fctName = fctName.substr(0, fctName.length - 3);
-		dif = true;
-	}
-	if (typeof eval(fctName) == "function") {
-		var parameter = eval(fctList + "." + fctName);
-		if (dif) {
-			// difference between v3 (current value) and math function
-			return data.v3 - window[fctName](parameter);
-		}
-		return window[fctName](parameter);
-	}
-	return;
-};
-
-function isNumber(n) {
-	return !isNaN(parseFloat(n)) && isFinite(n);
-};
-
-function tmplbis(str, data) {
-	var mathFunctionList = ["mean", "varianz", "stddev", "cv", "median"];
-	var regexMath = new RegExp('<%=((?:(?:.*?)\\W)??)((?:' + mathFunctionList.join('|') + ')(?:Dif)?)\\(([0-9]*?)\\)(.*?)%>', 'g');
-	while (regexMath.test(str)) {
-		str = str.replace(regexMath, function($0, $1, $2, $3, $4) {
-			if ($3) {
-				var rndFac = $3;
-			} else {
-				var rndFac = 2;
-			}
-			var value = addParameters2Function(data, $2, "mathFunctions");
-			if (isNumber(value)) {
-				return '<%=' + $1 + '' + Math.round(Math.pow(10, rndFac) * value) / Math.pow(10, rndFac) + '' + $4 + '%>';
-			}
-			return '<%= %>';
-		});
-	}
-	// Figure out if we're getting a template, or if we need to
-	// load the template - and be sure to cache the result.
-	// first check if it's can be an id
-	var fn = /^[A-Za-z][-A-Za-z0-9_:.]*$/.test(str) ? cachebis[str] = cachebis[str] ||
-		tmplbis(document.getElementById(str).innerHTML) :
-		// Generate a reusable function that will serve as a template
-		// generator (and which will be cached).
-		new Function("obj",
-			"var p=[],print=function(){p.push.apply(p,arguments);};" +
-			// Introduce the data as local variables using with(){}
-			"with(obj){p.push('" +
-			// Convert the template into pure JavaScript
-			str
-			.replace(/[\r\n]/g, "\\n")
-			.replace(/[\t]/g, " ")
-			.split("<%").join("\t")
-			.replace(/((^|%>)[^\t]*)'/g, "$1\r")
-			.replace(/\t=(.*?)%>/g, "',$1,'")
-			.split("\t").join("');")
-			.split("%>").join("p.push('")
-			.split("\r").join("\\'") + "');}return p.join('');");
-	// Provide some basic currying to the user
-	return data ? fn(data) : fn;
-};
-if (typeof CanvasRenderingContext2D !== 'undefined') {
-	/**
-	 * ctx.prototype
-	 * fillText option for canvas Multiline Support
-	 * @param text string \n for newline
-	 * @param x x position
-	 * @param y y position
-	 * @param yLevel = "bottom" => last line has this y-Pos [default], = "middle" => the middle line has this y-Pos)
-	 * @param lineHeight lineHeight
-	 */
-	CanvasRenderingContext2D.prototype.fillTextMultiLine = function(text, x, y, yLevel, lineHeight,horizontal) {
-		var lines = ("" + text).split("\n");
-		// if its one line => in the middle 
-		// two lines one above the mid one below etc.	
-		if (yLevel == "middle") {
-			if(horizontal)y -= ((lines.length - 1) / 2) * lineHeight;
-		} else if (yLevel == "bottom") { // default
-			if(horizontal)y -= (lines.length - 1) * lineHeight;
-		}
-		for (var i = 0; i < lines.length; i++) {
-			this.fillText(lines[i], x, y);
-			y += lineHeight;
-		}	
-	};
-	CanvasRenderingContext2D.prototype.measureTextMultiLine = function(text, lineHeight) {
-		var textWidth = 0;
-		var lg;
-		var lines = ("" + text).split("\n");
-		var textHeight = lines.length * lineHeight;
-		// if its one line => in the middle 
-		// two lines one above the mid one below etc.	
-		for (var i = 0; i < lines.length; i++) {
-			lg = this.measureText(lines[i]).width;
-			if (lg > textWidth) textWidth = lg;
-		}
-		return {
-			textWidth: textWidth,
-			textHeight: textHeight
-		};
-	};
-};
-cursorDivCreated = false;
-
-function createCursorDiv() {
-	if (cursorDivCreated == false) {
-		var div = document.createElement('divCursor');
-		div.id = 'divCursor';
-		div.style.position = 'absolute';
-		document.body.appendChild(div);
-		cursorDivCreated = true;
-	}
-};
-
-initChartJsResize = false;
-var jsGraphResize = new Array();
-
-function addResponsiveChart(id,ctx,data,config) {
-	initChartResize();
-	var newSize=resizeGraph(ctx,config);
-
-	if(typeof ctx.prevWidth != "undefined") {
-		resizeCtx(ctx,newSize.newWidth,newSize.newHeight);
-		ctx.prevWidth=newSize.newWidth;
-	}
-	ctx.prevWidth=newSize.newWidth;
-	ctx.prevHeight=newSize.newHeight;
-	jsGraphResize[jsGraphResize.length]= [id,ctx.tpchart,ctx,data,config];
-};
-
-function initChartResize() {
-	if(initChartJsResize==false) {
-		if (window.addEventListener) {
-			window.addEventListener("resize", chartJsResize);
-		} else {
-			window.attachEvent("resize", chartJsResize);
-		}
-	}
-};
-
-function getMaximumWidth(domNode){
-	var container = domNode.parentNode;
-	return container.clientWidth;
-};
-
-function getMaximumHeight(domNode){
-	var container = domNode.parentNode;
-	return container.clientHeight;
-};
-
-
-function resizeCtx(ctx,newWidth,newHeight)
-{
-	if (window.devicePixelRatio) {    // Retina device
-
-		ctx.canvas.style.width = newWidth/window.devicePixelRatio + "px";
-		ctx.canvas.style.height = newHeight/window.devicePixelRatio + "px";
-		ctx.canvas.height = newHeight/window.devicePixelRatio * window.devicePixelRatio;
-		ctx.canvas.width = newWidth/window.devicePixelRatio * window.devicePixelRatio;
-		ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
-	} else {
-		ctx.canvas.height = newHeight ;
-		ctx.canvas.width = newWidth;
-	}
-};
-
-function resizeGraph(ctx,config) {
-	if(typeof config.maintainAspectRatio == "undefined")config.maintainAspectRatio=true;
-	if(typeof config.responiveMinWidth == "undefined")config.responsiveMinWidth=0;
-	if(typeof config.responsiveMinHeight  == "undefined")config.responsiveMinHeight=0;
-	if(typeof config.responsiveMaxWidth  == "undefined")config.responsiveMaxWidth=9999999;
-	if(typeof config.responsiveMaxHeight  == "undefined")config.responsiveMaxHeight=9999999;
-	var canvas = ctx.canvas;
-	if(typeof ctx.aspectRatio == "undefined") {
-		ctx.aspectRatio = canvas.width / canvas.height;
-	}
-	
-  	var newWidth = getMaximumWidth(canvas);
-	var newHeight = config.maintainAspectRatio ? newWidth / ctx.aspectRatio : getMaximumHeight(canvas);
-	newWidth=Math.min(config.responsiveMaxWidth,Math.max(config.responsiveMinWidth,newWidth));
-	newHeight=Math.min(config.responsiveMaxHeight,Math.max(config.responsiveMinHeight,newHeight));
-        return { newWidth : parseInt(newWidth), newHeight :  parseInt(newHeight)};
-};
-
-
-
-function chartJsResize() {
-	for (var i=0;i<jsGraphResize.length;i++)  {
-		if(typeof jsGraphResize[i][2].firstPass != "undefined") {
-			if(jsGraphResize[i][2].firstPass == 5)jsGraphResize[i][2].firstPass=6;
-		}
-		subUpdateChart(jsGraphResize[i][2],jsGraphResize[i][3],jsGraphResize[i][4]);
-	}
-};
-
-function testRedraw(ctx,data,config) {
-	if (ctx.firstPass==2 || ctx.firstPass==4 || ctx.firstPass==9) {
-		ctx.firstPass=6;
-		subUpdateChart(ctx,data,config) ;
-		return true;
-	} else {
-		ctx.firstPass=5;
-		return false;
-	}		
-};
-
-function updateChart(ctx,data,config,animation,runanimationcompletefunction) {
-	if (ctx.firstPass==5)
-	{
-		ctx.runanimationcompletefunction=runanimationcompletefunction;
-		if(animation)ctx.firstPass=0;
-		else if (config.responsive) ctx.firstPass=7;
-		else ctx.firstPass=7;
-		subUpdateChart(ctx,data,config) ;
-		
-	}
-};
-
-function subUpdateChart(ctx,data,config) {
-	// ctx.firstPass==undefined => graph never drawn
-	// ctx.firstPass==0 => graph is drawn but need to be redrawn with animation
-	// ctx.firstPass==1 => graph is drawn with animation 
-	// ctx.firstPass==2 => graph is in animation but at the end the graph need perhaps to be redrawn;
-	// ctx.firstPass==3 => graph currently drawing without animation; 
-	// ctx.firstPass==4 => graph currently drawing without animationb but at the end, the graph need perhaps to be redrawn;
-	// ctx.firstPass==5 => graph is displayed ; 
-	// ctx.firstPass==6 => graph is displayed but need to be redraw without animation (because of a resize);
-	// ctx.firstPass==7 => graph is displayed but need to be redraw without responsivity;
-	if(!dynamicFunction(data, config, ctx)) { return; }
-
-	if(typeof ctx.firstPass == "undefined") { 
-		ctx.firstPass=1;
-		var newSize=resizeGraph(ctx,config);
-		if(config.responsive) {
-			resizeCtx(ctx,newSize.newWidth,newSize.newHeight);
-			ctx.prevWidth=newSize.newWidth;
-			ctx.prevHeight=newSize.newHeight;
-		} else {
-			ctx.prevWidth=0;
-			ctx.prevHeight=0;
-		}
-		ctx.runanimationcompletefunction=true;
-		redrawGraph(ctx,data,config);
-	} else if(ctx.firstPass == 0) { 
-		ctx.firstPass=1;
-		var newSize=resizeGraph(ctx,config);
-		if(config.responsive) {
-			resizeCtx(ctx,newSize.newWidth,newSize.newHeight);
-			ctx.prevWidth=newSize.newWidth;
-			ctx.prevHeight=newSize.newHeight;
-		} else {
-			ctx.prevWidth=0;
-			ctx.prevHeight=0;
-		}
-		redrawGraph(ctx,data,config);
-	} else if(ctx.firstPass==1 || ctx.firstPass==2) {
-		ctx.firstPass=2;
-	} else if (ctx.firstPass==3 || ctx.firstPass==4) {
-		ctx.firstPass=4;
-	} else if(ctx.firstPass==5) {
-		ctx.firstPass=1;
-		redrawGraph(ctx,data,config);
-	} else if(ctx.firstPass==6) {
-		var newSize=resizeGraph(ctx,config);
-		if (newSize.newWidth!=ctx.prevWidth || newSize.newHeight != ctx.prevHeight) {
-			ctx.firstPass=3;
-			ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-			if(config.responsive) {
-				resizeCtx(ctx,newSize.newWidth,newSize.newHeight);
-				ctx.prevWidth=newSize.newWidth;
-				ctx.prevHeight=newSize.newHeight;
-			} else {
-				ctx.prevWidth=0;
-				ctx.prevHeight=0;
-			}
-			redrawGraph(ctx,data,config);
-		} else ctx.firstPass=5;
-	} else if(ctx.firstPass==7) {
-		var newSize=resizeGraph(ctx,config);
-		ctx.firstPass=3;
-		ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
-		if(config.responsive) {
-			resizeCtx(ctx,newSize.newWidth,newSize.newHeight);
-			ctx.prevWidth=newSize.newWidth;
-			ctx.prevHeight=newSize.newHeight;
-		} else {
-			ctx.prevWidth=0;
-			ctx.prevHeight=0;
-		}
-		redrawGraph(ctx,data,config);
-	} 
-};
-
-function redrawGraph(ctx,data,config) {
-	var myGraph = new Chart(ctx);	
-	switch (ctx.tpchart) {
-		case "Bar":
-			myGraph.Bar(data,config);
-			break;
-		case "Pie":
-			myGraph.Pie(data,config);
-			break;
-		case "Doughnut":
-			myGraph.Doughnut(data,config);
-			break;
-		case "Radar":
-			myGraph.Radar(data,config);
-			break;
-		case "PolarArea":
-			myGraph.PolarArea(data,config);
-			break;
-		case "HorizontalBar":
-			myGraph.HorizontalBar(data,config);
-			break;
-		case "StackedBar":
-			myGraph.StackedBar(data,config);
-			break;
-		case "HorizontalStackedBar":
-			myGraph.HorizontalStackedBar(data,config);
-			break;
-		case "Line":
-			myGraph.Line(data,config);
-			break;
-	}
-};
-
-
-//Default browsercheck, added to all scripts!                                   
-function checkBrowser() {
-	this.ver = navigator.appVersion
-	this.dom = document.getElementById ? 1 : 0
-	this.ie5 = (this.ver.indexOf("MSIE 5") > -1 && this.dom) ? 1 : 0;
-	this.ie4 = (document.all && !this.dom) ? 1 : 0;
-	this.ns5 = (this.dom && parseInt(this.ver) >= 5) ? 1 : 0;
-	this.ns4 = (document.layers && !this.dom) ? 1 : 0;
-	this.bw = (this.ie5 || this.ie4 || this.ns4 || this.ns5)
-	return this
-};
-bw = new checkBrowser();
-//Set these variables:
-fromLeft = 10; // How much from the left of the cursor should the div be?
-fromTop = 10; // How much from the top of the cursor should the div be?
-/********************************************************************
-Initilizes the objects
-*********************************************************************/
-function cursorInit() {
-	scrolled = bw.ns4 || bw.ns5 ? "window.pageYOffset" : "document.body.scrollTop"
-	if (bw.ns4) document.captureEvents(Event.MOUSEMOVE)
-};
-/********************************************************************
-Contructs the cursorobjects
-*********************************************************************/
-function makeCursorObj(obj, nest) {
-	createCursorDiv();
-	nest = (!nest) ? '' : 'document.' + nest + '.'
-	this.css = bw.dom ? document.getElementById(obj).style : bw.ie4 ? document.all[obj].style : bw.ns4 ? eval(nest + "document.layers." + obj) : 0;
-	this.moveIt = b_moveIt;
-	cursorInit();
-	return this
-};
-
-function b_moveIt(x, y) {
-	this.x = x;
-	this.y = y;
-	this.css.left = this.x + "px";
-	this.css.top = this.y + "px";
-};
-
-function isIE() {
-	var myNav = navigator.userAgent.toLowerCase();
-	return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
-};
-
-function mergeChartConfig(defaults, userDefined) {
-	var returnObj = {};
-	for (var attrname in defaults) {
-		returnObj[attrname] = defaults[attrname];
-	}
-	for (var attrname in userDefined) {
-		returnObj[attrname] = userDefined[attrname];
-	}
-	return returnObj;
-};
-
-function sleep(ms) {
-	var dt = new Date();
-	dt.setTime(dt.getTime() + ms);
-	while (new Date().getTime() < dt.getTime()) {};
-};
-
-function saveCanvas(ctx, data, config) {
-	cvSave = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
-	var saveCanvasConfig = {
-		savePng: false,
-		annotateDisplay: false,
-		animation: false,
-		dynamicDisplay: false
-	};
-	var savePngConfig = mergeChartConfig(config, saveCanvasConfig);
-	savePngConfig.clearRect = false;
-	/* And ink them */
-
-	redrawGraph(ctx,data,savePngConfig);
-	if (config.savePngOutput == "NewWindow") {
-		var image = ctx.canvas.toDataURL();
-		ctx.putImageData(cvSave, 0, 0);
-		window.open(image, '_blank');
-	}
-	if (config.savePngOutput == "CurrentWindow") {
-		var image = ctx.canvas.toDataURL();
-		ctx.putImageData(cvSave, 0, 0);
-		window.location.href = image;
-	}
-	if (config.savePngOutput == "Save") {
-		var image = ctx.canvas.toDataURL();
-		var downloadLink = document.createElement("a");
-		downloadLink.href = image;
-		downloadLink.download = config.savePngName + ".png";
-		document.body.appendChild(downloadLink);
-		downloadLink.click();
-		document.body.removeChild(downloadLink);
-	}
-};
-if (typeof String.prototype.trim !== 'function') {
-	String.prototype.trim = function() {
-		return this.replace(/^\s+|\s+$/g, '');
-	}
-};
-var dynamicDisplay = new Array();
-var dynamicDisplayList = new Array();
-
-function dynamicFunction(data, config, ctx) {
-
-	if (isIE() < 9 && isIE() != false) return(true);
-
-
-	if (config.dynamicDisplay) {
-		if (ctx.canvas.id == "") {
-			var cvdate = new Date();
-			var cvmillsec = cvdate.getTime();
-			ctx.canvas.id = "Canvas_" + cvmillsec;
-		}
-		if (typeof(dynamicDisplay[ctx.canvas.id]) == "undefined") {
-			dynamicDisplayList[dynamicDisplayList["length"]] = ctx.canvas.id;
-			dynamicDisplay[ctx.canvas.id] = [ctx, false, false, data, config, ctx.canvas];
-			dynamicDisplay[ctx.canvas.id][1] = isScrolledIntoView(ctx.canvas);
-			window.onscroll = scrollFunction;
-		} else if (dynamicDisplay[ctx.canvas.id][2] == false) {
-			dynamicDisplay[ctx.canvas.id][1] = isScrolledIntoView(ctx.canvas);
-		}
-		if (dynamicDisplay[ctx.canvas.id][1] == false && dynamicDisplay[ctx.canvas.id][2] == false) {
-			return false;
-		}
-		dynamicDisplay[ctx.canvas.id][2] = true;
-	}
-	return true;
-};
-
-function isScrolledIntoView(element) {
-	var xPosition = 0;
-	var yPosition = 0;
-	elem = element;
-	while (elem) {
-		xPosition += (elem.offsetLeft - elem.scrollLeft + elem.clientLeft);
-		yPosition += (elem.offsetTop - elem.scrollTop + elem.clientTop);
-		elem = elem.offsetParent;
-	}
-	if (xPosition + element.width / 2 >= window.pageXOffset &&
-		xPosition + element.width / 2 <= window.pageXOffset + window.innerWidth &&
-		yPosition + element.height / 2 >= window.pageYOffset &&
-		yPosition + element.height / 2 <= window.pageYOffset + window.innerHeight
-	) return (true);
-	else return false;
-};
-
-function scrollFunction() {
-	for (var i = 0; i < dynamicDisplayList["length"]; i++) {
-		if (isScrolledIntoView(dynamicDisplay[dynamicDisplayList[i]][5]) && dynamicDisplay[dynamicDisplayList[i]][2] == false) {
-			dynamicDisplay[dynamicDisplayList[i]][1] = true;
-			redrawGraph(dynamicDisplay[dynamicDisplayList[i]][0],dynamicDisplay[dynamicDisplayList[i]][3], dynamicDisplay[dynamicDisplayList[i]][4]);
-		}
-	}
-};
-
-var jsGraphAnnotate = new Array();
-
-function clearAnnotate(ctxid) {
-	jsGraphAnnotate[ctxid] = [];
-};
-
-function getMousePos(canvas, evt) {
-	var rect = canvas.getBoundingClientRect();
-	return {
-		x: evt.clientX - rect.left,
-		y: evt.clientY - rect.top
-	};
-};
-
-function doMouseAction(config, ctx, event, data, action, funct) {
-
-	var onData = false;
-	if (action == "annotate") {
-		var annotateDIV = document.getElementById('divCursor');
-		var show = false;
-		annotateDIV.className = (config.annotateClassName) ? config.annotateClassName : '';
-		annotateDIV.style.border = (config.annotateClassName) ? '' : config.annotateBorder;
-		annotateDIV.style.padding = (config.annotateClassName) ? '' : config.annotatePadding;
-		annotateDIV.style.borderRadius = (config.annotateClassName) ? '' : config.annotateBorderRadius;
-		annotateDIV.style.backgroundColor = (config.annotateClassName) ? '' : config.annotateBackgroundColor;
-		annotateDIV.style.color = (config.annotateClassName) ? '' : config.annotateFontColor;
-		annotateDIV.style.fontFamily = (config.annotateClassName) ? '' : config.annotateFontFamily;
-		annotateDIV.style.fontSize = (config.annotateClassName) ? '' : config.annotateFontSize + "pt";
-		annotateDIV.style.fontStyle = (config.annotateClassName) ? '' : config.annotateFontStyle;
-	}
-	if (action=="annotate") {
-		show=false;
-		annotateDIV.style.display = show ? '' : 'none';
-	}
-	canvas_pos = getMousePos(ctx.canvas, event);
-	for (var i = 0; i < jsGraphAnnotate[ctx.ChartNewId]["length"]; i++) {
-		if (jsGraphAnnotate[ctx.ChartNewId][i][0] == "ARC") {
-			myStatData=jsGraphAnnotate[ctx.ChartNewId][i][3][jsGraphAnnotate[ctx.ChartNewId][i][1]];
-			distance = Math.sqrt((canvas_pos.x - myStatData.midPosX) * (canvas_pos.x - myStatData.midPosX) + (canvas_pos.y - myStatData.midPosY) * (canvas_pos.y - myStatData.midPosY));
-			if (distance > myStatData.int_radius && distance < myStatData.radiusOffset) {
-				angle = (Math.acos((canvas_pos.x - myStatData.midPosX) / distance) % (2* Math.PI) + 2*Math.PI) % (2*Math.PI);
-				if (canvas_pos.y < myStatData.midPosY) angle = -angle;
-				angle = (((angle  + 2 * Math.PI) % (2 * Math.PI)) + 2* Math.PI) % (2* Math.PI) ; 
-				myStatData.startAngle=(((myStatData.startAngle  + 2 * Math.PI) % (2 * Math.PI)) + 2* Math.PI) % (2* Math.PI);
-				myStatData.endAngle=(((myStatData.endAngle  + 2 * Math.PI) % (2 * Math.PI)) + 2* Math.PI) % (2* Math.PI);
-				if(myStatData.endAngle<myStatData.startAngle)myStatData.endAngle+=2 * Math.PI;
-				if ((angle > myStatData.startAngle && angle < myStatData.endAngle) || (angle > myStatData.startAngle - 2 * Math.PI && angle < myStatData.endAngle - 2 * Math.PI) || (angle > myStatData.startAngle + 2 * Math.PI && angle < myStatData.endAngle + 2 * Math.PI)) {
-					myStatData.graphPosX = canvas_pos.x;
-					myStatData.graphPosY = canvas_pos.y;
-					onData = true;
-					if (action == "annotate") {
-						dispString = tmplbis(setOptionValue("ANNOTATELABEL",ctx,data,jsGraphAnnotate[ctx.ChartNewId][i][3],undefined,config.annotateLabel,jsGraphAnnotate[ctx.ChartNewId][i][12],-1,{otherVal:true}), myStatData);
-						annotateDIV.innerHTML = dispString;
-						show = true;
-					} else {
-						funct(event, ctx, config, data, myStatData );
-					}
-					if (action == "annotate") {
-						x = bw.ns4 || bw.ns5 ? event.pageX : event.x;
-						y = bw.ns4 || bw.ns5 ? event.pageY : event.y;
-						if (bw.ie4 || bw.ie5) y = y + eval(scrolled);
-						oCursor.moveIt(x + fromLeft, y + fromTop);
-					}
-				}
-			}
-		} else if (jsGraphAnnotate[ctx.ChartNewId][i][0] == "RECT") {
-			myStatData=jsGraphAnnotate[ctx.ChartNewId][i][3][jsGraphAnnotate[ctx.ChartNewId][i][1]][jsGraphAnnotate[ctx.ChartNewId][i][2]];
-			
-			if (canvas_pos.x > Math.min(myStatData.xPosLeft,myStatData.xPosRight) && canvas_pos.x < Math.max(myStatData.xPosLeft,myStatData.xPosRight) && canvas_pos.y < Math.max(myStatData.yPosBottom,myStatData.yPosTop) && canvas_pos.y > Math.min(myStatData.yPosBottom,myStatData.yPosTop)) {
-				myStatData.graphPosX = canvas_pos.x;
-				myStatData.graphPosY = canvas_pos.y;
-				onData = true;
-				if (action == "annotate") {
-					dispString = tmplbis(setOptionValue("ANNOTATELABEL",ctx,data,jsGraphAnnotate[ctx.ChartNewId][i][3],undefined,config.annotateLabel,jsGraphAnnotate[ctx.ChartNewId][i][1],jsGraphAnnotate[ctx.ChartNewId][i][2],{otherVal:true}), myStatData);
-					annotateDIV.innerHTML = dispString;
-					show = true;
-				} else {
-					funct(event, ctx, config, data, myStatData );
-				}
-				if (action == "annotate") {
-					x = bw.ns4 || bw.ns5 ? event.pageX : event.x;
-					y = bw.ns4 || bw.ns5 ? event.pageY : event.y;
-					if (bw.ie4 || bw.ie5) y = y + eval(scrolled);
-					oCursor.moveIt(x + fromLeft, y + fromTop);
-				}
-			}
-		} else if (jsGraphAnnotate[ctx.ChartNewId][i][0] == "POINT") {
-			myStatData=jsGraphAnnotate[ctx.ChartNewId][i][3][jsGraphAnnotate[ctx.ChartNewId][i][1]][jsGraphAnnotate[ctx.ChartNewId][i][2]];
-			var distance;
-			if(config.detectAnnotateOnFullLine) {
-				if(canvas_pos.x < Math.min(myStatData.annotateStartPosX,myStatData.annotateEndPosX)-config.pointHitDetectionRadius || canvas_pos.x > Math.max(myStatData.annotateStartPosX,myStatData.annotateEndPosX)+config.pointHitDetectionRadius || canvas_pos.y < Math.min(myStatData.annotateStartPosY,myStatData.annotateEndPosY)-config.pointHitDetectionRadius || canvas_pos.y > Math.max(myStatData.annotateStartPosY,myStatData.annotateEndPosY)+config.pointHitDetectionRadius) {
-					distance=config.pointHitDetectionRadius+1;
-				} else { 
-					if(typeof myStatData.D1A=="undefined") {
-						distance=Math.abs(canvas_pos.x-myStatData.posX);
-					} else if(typeof myStatData.D2A=="undefined") {
-						distance=Math.abs(canvas_pos.y-myStatData.posY);
-					} else {
-						var D2B=-myStatData.D2A*canvas_pos.x+canvas_pos.y;
-						var g=-(myStatData.D1B-D2B)/(myStatData.D1A-myStatData.D2A);
-						var h=myStatData.D2A*g+D2B;
-						distance=Math.sqrt((canvas_pos.x - g) * (canvas_pos.x - g) + (canvas_pos.y - h) * (canvas_pos.y - h));
-					}
-					
-				}
-								
-			} else {
-				distance = Math.sqrt((canvas_pos.x - myStatData.posX) * (canvas_pos.x - myStatData.posX) + (canvas_pos.y - myStatData.posY) * (canvas_pos.y - myStatData.posY));
-			}
-			if (distance < config.pointHitDetectionRadius) {
-				myStatData.graphPosX = canvas_pos.x;
-				myStatData.graphPosY = canvas_pos.y;
-				onData = true;
-				if (action == "annotate") {
-					dispString = tmplbis(setOptionValue("ANNOTATELABEL",ctx,data,jsGraphAnnotate[ctx.ChartNewId][i][3],undefined,config.annotateLabel,jsGraphAnnotate[ctx.ChartNewId][i][1],jsGraphAnnotate[ctx.ChartNewId][i][2],{otherVal:true}), myStatData);
-					annotateDIV.innerHTML = dispString;
-					show = true;
-				} else {
-					funct(event, ctx, config, data, myStatData);
-				}
-				if (action == "annotate") {
-					x = bw.ns4 || bw.ns5 ? event.pageX : event.x;
-					y = bw.ns4 || bw.ns5 ? event.pageY : event.y;
-					if (bw.ie4 || bw.ie5) y = y + eval(scrolled);
-					oCursor.moveIt(x + fromLeft, y + fromTop);
-				}
-			}
-		}
-		if (action == "annotate") {
-			annotateDIV.style.display = show ? '' : 'none';
-		}
-	}
-	if (onData == false && action != "annotate") {
-		funct(event, ctx, config, data, null);
-	}
-};
-///////// GRAPHICAL PART OF THE SCRIPT ///////////////////////////////////////////
-//Define the global Chart Variable as a class.
-window.Chart = function(context) {
-	var chart = this;
-	//Easing functions adapted from Robert Penner's easing equations
-	//http://www.robertpenner.com/easing/
-	var animationOptions = {
-		linear: function(t) {
-			return t;
-		},
-		easeInQuad: function(t) {
-			return t * t;
-		},
-		easeOutQuad: function(t) {
-			return -1 * t * (t - 2);
-		},
-		easeInOutQuad: function(t) {
-			if ((t /= 1 / 2) < 1) return 1 / 2 * t * t;
-			return -1 / 2 * ((--t) * (t - 2) - 1);
-		},
-		easeInCubic: function(t) {
-			return t * t * t;
-		},
-		easeOutCubic: function(t) {
-			return 1 * ((t = t / 1 - 1) * t * t + 1);
-		},
-		easeInOutCubic: function(t) {
-			if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t;
-			return 1 / 2 * ((t -= 2) * t * t + 2);
-		},
-		easeInQuart: function(t) {
-			return t * t * t * t;
-		},
-		easeOutQuart: function(t) {
-			return -1 * ((t = t / 1 - 1) * t * t * t - 1);
-		},
-		easeInOutQuart: function(t) {
-			if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t;
-			return -1 / 2 * ((t -= 2) * t * t * t - 2);
-		},
-		easeInQuint: function(t) {
-			return 1 * (t /= 1) * t * t * t * t;
-		},
-		easeOutQuint: function(t) {
-			return 1 * ((t = t / 1 - 1) * t * t * t * t + 1);
-		},
-		easeInOutQuint: function(t) {
-			if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t * t;
-			return 1 / 2 * ((t -= 2) * t * t * t * t + 2);
-		},
-		easeInSine: function(t) {
-			return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;
-		},
-		easeOutSine: function(t) {
-			return 1 * Math.sin(t / 1 * (Math.PI / 2));
-		},
-		easeInOutSine: function(t) {
-			return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);
-		},
-		easeInExpo: function(t) {
-			return (t == 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));
-		},
-		easeOutExpo: function(t) {
-			return (t == 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);
-		},
-		easeInOutExpo: function(t) {
-			if (t == 0) return 0;
-			if (t == 1) return 1;
-			if ((t /= 1 / 2) < 1) return 1 / 2 * Math.pow(2, 10 * (t - 1));
-			return 1 / 2 * (-Math.pow(2, -10 * --t) + 2);
-		},
-		easeInCirc: function(t) {
-			if (t >= 1) return t;
-			return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);
-		},
-		easeOutCirc: function(t) {
-			return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);
-		},
-		easeInOutCirc: function(t) {
-			if ((t /= 1 / 2) < 1) return -1 / 2 * (Math.sqrt(1 - t * t) - 1);
-			return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);
-		},
-		easeInElastic: function(t) {
-			var s = 1.70158;
-			var p = 0;
-			var a = 1;
-			if (t == 0) return 0;
-			if ((t /= 1) == 1) return 1;
-			if (!p) p = 1 * .3;
-			if (a < Math.abs(1)) {
-				a = 1;
-				var s = p / 4;
-			} else var s = p / (2 * Math.PI) * Math.asin(1 / a);
-			return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
-		},
-		easeOutElastic: function(t) {
-			var s = 1.70158;
-			var p = 0;
-			var a = 1;
-			if (t == 0) return 0;
-			if ((t /= 1) == 1) return 1;
-			if (!p) p = 1 * .3;
-			if (a < Math.abs(1)) {
-				a = 1;
-				var s = p / 4;
-			} else var s = p / (2 * Math.PI) * Math.asin(1 / a);
-			return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;
-		},
-		easeInOutElastic: function(t) {
-			var s = 1.70158;
-			var p = 0;
-			var a = 1;
-			if (t == 0) return 0;
-			if ((t /= 1 / 2) == 2) return 1;
-			if (!p) p = 1 * (.3 * 1.5);
-			if (a < Math.abs(1)) {
-				a = 1;
-				var s = p / 4;
-			} else var s = p / (2 * Math.PI) * Math.asin(1 / a);
-			if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
-			return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * .5 + 1;
-		},
-		easeInBack: function(t) {
-			var s = 1.70158;
-			return 1 * (t /= 1) * t * ((s + 1) * t - s);
-		},
-		easeOutBack: function(t) {
-			var s = 1.70158;
-			return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);
-		},
-		easeInOutBack: function(t) {
-			var s = 1.70158;
-			if ((t /= 1 / 2) < 1) return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));
-			return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
-		},
-		easeInBounce: function(t) {
-			return 1 - animationOptions.easeOutBounce(1 - t);
-		},
-		easeOutBounce: function(t) {
-			if ((t /= 1) < (1 / 2.75)) {
-				return 1 * (7.5625 * t * t);
-			} else if (t < (2 / 2.75)) {
-				return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + .75);
-			} else if (t < (2.5 / 2.75)) {
-				return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375);
-			} else {
-				return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375);
-			}
-		},
-		easeInOutBounce: function(t) {
-			if (t < 1 / 2) return animationOptions.easeInBounce(t * 2) * .5;
-			return animationOptions.easeOutBounce(t * 2 - 1) * .5 + 1 * .5;
-		}
-	};
-	//Variables global to the chart
-	var width = context.canvas.width;
-	var height = context.canvas.height;
-	//High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
-	if (window.devicePixelRatio) {
-		context.canvas.style.width = width + "px";
-		context.canvas.style.height = height + "px";
-		context.canvas.height = height * window.devicePixelRatio;
-		context.canvas.width = width * window.devicePixelRatio;
-		context.scale(window.devicePixelRatio, window.devicePixelRatio);
-	};
-	this.PolarArea = function(data, options) {
-		chart.PolarArea.defaults = {
-			inGraphDataShow: false,
-			inGraphDataPaddingRadius: 5,
-			inGraphDataPaddingAngle: 0,
-			inGraphDataTmpl: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>",
-			inGraphDataAlign: "off-center", // "right", "center", "left", "off-center" or "to-center"
-			inGraphDataVAlign: "off-center", // "bottom", "center", "top", "off-center" or "to-center"
-			inGraphDataRotate: 0, // rotateAngle value (0->360) , "inRadiusAxis" or "inRadiusAxisRotateLabels"
-			inGraphDataFontFamily: "'Arial'",
-			inGraphDataFontSize: 12,
-			inGraphDataFontStyle: "normal",
-			inGraphDataFontColor: "#666",
-			inGraphDataRadiusPosition: 3,
-			inGraphDataAnglePosition: 2,
-			scaleOverlay: true,
-			scaleOverride: false,
-			scaleOverride2: false,
-			scaleSteps: null,
-			scaleStepWidth: null,
-			scaleStartValue: null,
-			scaleShowLine: true,
-			scaleLineColor: "rgba(0,0,0,.1)",
-			scaleLineWidth: 1,
-			scaleShowLabels: true,
-			scaleShowLabels2: true,
-			scaleLabel: "<%=value%>",
-			scaleFontFamily: "'Arial'",
-			scaleFontSize: 12,
-			scaleFontStyle: "normal",
-			scaleFontColor: "#666",
-			scaleShowLabelBackdrop: true,
-			scaleBackdropColor: "rgba(255,255,255,0.75)",
-			scaleBackdropPaddingY: 2,
-			scaleBackdropPaddingX: 2,
-			segmentShowStroke: true,
-			segmentStrokeColor: "#fff",
-			segmentStrokeWidth: 2,
-			animation: true,
-			animationByData : "ByArc",
-			animationSteps: 100,
-			animationEasing: "easeOutBounce",
-			animateRotate: true,
-			animateScale: false,
-			onAnimationComplete: null,
-			annotateLabel: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>",
-			startAngle: 90
-		};
-		chart.PolarArea.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.PolarArea.defaults);
-		chart.PolarArea.defaults = mergeChartConfig(chart.PolarArea.defaults, charJSPersonalDefaultOptions);
-		chart.PolarArea.defaults = mergeChartConfig(chart.PolarArea.defaults, charJSPersonalDefaultOptionsPolarArea);
-		var config = (options) ? mergeChartConfig(chart.PolarArea.defaults, options) : chart.PolarArea.defaults;
-		return new PolarArea(data, config, context);
-	};
-	this.Radar = function(data, options) {
-		chart.Radar.defaults = {
-			inGraphDataShow: false,
-			inGraphDataPaddingRadius: 5,
-			inGraphDataTmpl: "<%=v3%>",
-			inGraphDataAlign: "off-center", // "right", "center", "left", "off-center" or "to-center"
-			inGraphDataVAlign: "off-center", // "right", "center", "left", "off-center" or "to-center"
-			inGraphDataRotate: 0, // rotateAngle value (0->360) , "inRadiusAxis" or "inRadiusAxisRotateLabels"
-			inGraphDataFontFamily: "'Arial'",
-			inGraphDataFontSize: 12,
-			inGraphDataFontStyle: "normal",
-			inGraphDataFontColor: "#666",
-			inGraphDataRadiusPosition: 3,
-			yAxisMinimumInterval: "none",
-			scaleOverlay: false,
-			scaleOverride: false,
-			scaleOverride2: false,
-			scaleSteps: null,
-			scaleStepWidth: null,
-			scaleStartValue: null,
-			scaleShowLine: true,
-			scaleLineColor: "rgba(0,0,0,.1)",
-			scaleLineWidth: 1,
-			scaleShowLabels: false,
-			scaleShowLabels2: true,
-			scaleLabel: "<%=value%>",
-			scaleFontFamily: "'Arial'",
-			scaleFontSize: 12,
-			scaleFontStyle: "normal",
-			scaleFontColor: "#666",
-			scaleShowLabelBackdrop: true,
-			scaleBackdropColor: "rgba(255,255,255,0.75)",
-			scaleBackdropPaddingY: 2,
-			scaleBackdropPaddingX: 2,
-			angleShowLineOut: true,
-			angleLineColor: "rgba(0,0,0,.1)",
-			angleLineWidth: 1,
-			pointLabelFontFamily: "'Arial'",
-			pointLabelFontStyle: "normal",
-			pointLabelFontSize: 12,
-			pointLabelFontColor: "#666",
-			pointDot: true,
-			pointDotRadius: 3,
-			pointDotStrokeWidth: 1,
-			datasetFill: true,
-			datasetStrokeWidth: 2,
-			animation: true,
-			animationSteps: 60,
-			animationEasing: "easeOutQuart",
-			onAnimationComplete: null,
-			annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3%>",
-			pointHitDetectionRadius : 10,
-			startAngle: 90,
-			graphMaximized: false // if true, the graph will not be centered in the middle of the canvas
-		};
-		// merge annotate defaults
-		chart.Radar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Radar.defaults);
-		chart.Radar.defaults = mergeChartConfig(chart.Radar.defaults, charJSPersonalDefaultOptions);
-		chart.Radar.defaults = mergeChartConfig(chart.Radar.defaults, charJSPersonalDefaultOptionsRadar);
-		var config = (options) ? mergeChartConfig(chart.Radar.defaults, options) : chart.Radar.defaults;
-		return new Radar(data, config, context);
-	};
-	this.Pie = function(data, options) {
-		chart.Pie.defaults = {
-			inGraphDataShow: false,
-			inGraphDataPaddingRadius: 5,
-			inGraphDataPaddingAngle: 0,
-			inGraphDataTmpl: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>",
-			inGraphDataAlign: "off-center", // "right", "center", "left", "off-center" or "to-center"
-			inGraphDataVAlign: "off-center", // "bottom", "center", "top", "off-center" or "to-center"
-			inGraphDataRotate: 0, // rotateAngle value (0->360) , "inRadiusAxis" or "inRadiusAxisRotateLabels"
-			inGraphDataFontFamily: "'Arial'",
-			inGraphDataFontSize: 12,
-			inGraphDataFontStyle: "normal",
-			inGraphDataFontColor: "#666",
-			inGraphDataRadiusPosition: 3,
-			inGraphDataAnglePosition: 2,
-			inGraphDataMinimumAngle : 0,
-			segmentShowStroke: true,
-			segmentStrokeColor: "#fff",
-			segmentStrokeWidth: 2,
-			animation: true,
-			animationByData : false,
-			animationSteps: 100,
-			animationEasing: "easeOutBounce",
-			animateRotate: true,
-			animateScale: false,
-			onAnimationComplete: null,
-			annotateLabel: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>",
-			startAngle: 90,
-			radiusScale: 1
-		};
-		// merge annotate defaults
-		chart.Pie.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Pie.defaults);
-		chart.Pie.defaults = mergeChartConfig(chart.Pie.defaults, charJSPersonalDefaultOptions);
-		chart.Pie.defaults = mergeChartConfig(chart.Pie.defaults, charJSPersonalDefaultOptionsPie);
-		var config = (options) ? mergeChartConfig(chart.Pie.defaults, options) : chart.Pie.defaults;
-		return new Pie(data, config, context);
-	};
-	this.Doughnut = function(data, options) {
-		chart.Doughnut.defaults = {
-			inGraphDataShow: false,
-			inGraphDataPaddingRadius: 5,
-			inGraphDataPaddingAngle: 0,
-			inGraphDataTmpl: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>",
-			inGraphDataAlign: "off-center", // "right", "center", "left", "off-center" or "to-center"
-			inGraphDataVAlign: "off-center", // "bottom", "middle", "top", "off-center" or "to-center"
-			inGraphDataRotate: 0, // rotateAngle value (0->360) , "inRadiusAxis" or "inRadiusAxisRotateLabels"
-			inGraphDataFontFamily: "'Arial'",
-			inGraphDataFontSize: 12,
-			inGraphDataFontStyle: "normal",
-			inGraphDataFontColor: "#666",
-			inGraphDataRadiusPosition: 3,
-			inGraphDataAnglePosition: 2,
-		        inGraphDataMinimumAngle : 0,
-			segmentShowStroke: true,
-			segmentStrokeColor: "#fff",
-			segmentStrokeWidth: 2,
-			percentageInnerCutout: 50,
-			animation: true,
-			animationByData : false,
-			animationSteps: 100,
-			animationEasing: "easeOutBounce",
-			animateRotate: true,
-			animateScale: false,
-			onAnimationComplete: null,
-			annotateLabel: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>",
-			startAngle: 90,
-			radiusScale: 1
-		};
-		// merge annotate defaults
-		chart.Doughnut.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Doughnut.defaults);
-		chart.Doughnut.defaults = mergeChartConfig(chart.Doughnut.defaults, charJSPersonalDefaultOptions);
-		chart.Doughnut.defaults = mergeChartConfig(chart.Doughnut.defaults, charJSPersonalDefaultOptionsDoughnut);
-		var config = (options) ? mergeChartConfig(chart.Doughnut.defaults, options) : chart.Doughnut.defaults;
-		return new Doughnut(data, config, context);
-	};
-	this.Line = function(data, options) {
-		chart.Line.defaults = {
-			inGraphDataShow: false,
-			inGraphDataPaddingX: 3,
-			inGraphDataPaddingY: 3,
-			inGraphDataTmpl: "<%=v3%>",
-			inGraphDataAlign: "left",
-			inGraphDataVAlign: "bottom",
-			inGraphDataRotate: 0,
-			inGraphDataFontFamily: "'Arial'",
-			inGraphDataFontSize: 12,
-			inGraphDataFontStyle: "normal",
-			inGraphDataFontColor: "#666",
-			drawXScaleLine: [{
-				position: "bottom"
-			}],
-			scaleOverlay: false,
-			scaleOverride: false,
-			scaleOverride2: false,
-			scaleSteps: null,
-			scaleStepWidth: null,
-			scaleStartValue: null,
-			scaleSteps2: null,
-			scaleStepWidth2: null,
-			scaleStartValue2: null,
-			scaleLabel2 : "<%=value%>",
-			scaleLineColor: "rgba(0,0,0,.1)",
-			scaleLineWidth: 1,
-			scaleShowLabels: true,
-			scaleShowLabels2: true,
-			scaleLabel: "<%=value%>",
-			scaleFontFamily: "'Arial'",
-			scaleFontSize: 12,
-			scaleFontStyle: "normal",
-			scaleFontColor: "#666",
-			scaleShowGridLines: true,
-			scaleXGridLinesStep: 1,
-			scaleYGridLinesStep: 1,
-			scaleGridLineColor: "rgba(0,0,0,.05)",
-			scaleGridLineWidth: 1,
-			showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels)
-			rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre; 
-			// you can force an integer value between 0 and 180 degres
-			logarithmic: false, // can be 'fuzzy',true and false ('fuzzy' => if the gap between min and maximum is big it's using a logarithmic y-Axis scale
-			logarithmic2: false, // can be 'fuzzy',true and false ('fuzzy' => if the gap between min and maximum is big it's using a logarithmic y-Axis scale
-			scaleTickSizeLeft: 5,
-			scaleTickSizeRight: 5,
-			scaleTickSizeBottom: 5,
-			scaleTickSizeTop: 5,
-			bezierCurve: true,
-			bezierCurveTension : 0.4,
-			pointDot: true,
-			pointDotRadius: 4,
-			pointDotStrokeWidth: 2,
-			datasetStrokeWidth: 2,
-			datasetFill: true,
-			animation: true,
-			animationSteps: 60,
-			animationEasing: "easeOutQuart",
-			extrapolateMissingData: true,
-			onAnimationComplete: null,
-			annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3%>",
-			pointHitDetectionRadius : 10
-		};
-		// merge annotate defaults
-		chart.Line.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Line.defaults);
-		chart.Line.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.Line.defaults);
-		chart.Line.defaults = mergeChartConfig(chart.Line.defaults, charJSPersonalDefaultOptions);
-		chart.Line.defaults = mergeChartConfig(chart.Line.defaults, charJSPersonalDefaultOptionsLine);
-		var config = (options) ? mergeChartConfig(chart.Line.defaults, options) : chart.Line.defaults;
-		return new Line(data, config, context);
-	};
-	this.StackedBar = function(data, options) {
-		chart.StackedBar.defaults = {
-			inGraphDataShow: false,
-			inGraphDataPaddingX: 0,
-			inGraphDataPaddingY: -3,
-			inGraphDataTmpl: "<%=v3%>",
-			inGraphDataAlign: "center",
-			inGraphDataVAlign: "top",
-			inGraphDataRotate: 0,
-			inGraphDataFontFamily: "'Arial'",
-			inGraphDataFontSize: 12,
-			inGraphDataFontStyle: "normal",
-			inGraphDataFontColor: "#666",
-			inGraphDataXPosition: 2,
-			inGraphDataYPosition: 3,
-			scaleOverlay: false,
-			scaleOverride: false,
-			scaleOverride2: false,
-			scaleSteps: null,
-			scaleStepWidth: null,
-			scaleStartValue: null,
-			scaleLineColor: "rgba(0,0,0,.1)",
-			scaleLineWidth: 1,
-			scaleShowLabels: true,
-			scaleShowLabels2: true,
-			scaleLabel: "<%=value%>",
-			scaleFontFamily: "'Arial'",
-			scaleFontSize: 12,
-			scaleFontStyle: "normal",
-			scaleFontColor: "#666",
-			scaleShowGridLines: true,
-			scaleXGridLinesStep: 1,
-			scaleYGridLinesStep: 1,
-			scaleGridLineColor: "rgba(0,0,0,.05)",
-			scaleGridLineWidth: 1,
-			showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels)
-			rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre; 
-			// you can force an integer value between 0 and 180 degres
-			scaleTickSizeLeft: 5,
-			scaleTickSizeRight: 5,
-			scaleTickSizeBottom: 5,
-			scaleTickSizeTop: 5,
-			barShowStroke: true,
-			barStrokeWidth: 2,
-			barValueSpacing: 5,
-			barDatasetSpacing: 1,
-			spaceBetweenBar : 0,
-			animation: true,
-			animationSteps: 60,
-			animationEasing: "easeOutQuart",
-			onAnimationComplete: null,
-			annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3 + ' (' + v6 + ' %)'%>"
-		};
-		// merge annotate defaults
-		chart.StackedBar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.StackedBar.defaults);
-		chart.StackedBar.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.StackedBar.defaults);
-		chart.StackedBar.defaults = mergeChartConfig(chart.StackedBar.defaults, charJSPersonalDefaultOptions);
-		chart.StackedBar.defaults = mergeChartConfig(chart.StackedBar.defaults, charJSPersonalDefaultOptionsStackedBar);
-		var config = (options) ? mergeChartConfig(chart.StackedBar.defaults, options) : chart.StackedBar.defaults;
-		return new StackedBar(data, config, context);
-	};
-	this.HorizontalStackedBar = function(data, options) {
-		chart.HorizontalStackedBar.defaults = {
-			inGraphDataShow: false,
-			inGraphDataPaddingX: -3,
-			inGraphDataPaddingY: 0,
-			inGraphDataTmpl: "<%=v3%>",
-			inGraphDataAlign: "right",
-			inGraphDataVAlign: "middle",
-			inGraphDataRotate: 0,
-			inGraphDataFontFamily: "'Arial'",
-			inGraphDataFontSize: 12,
-			inGraphDataFontStyle: "normal",
-			inGraphDataFontColor: "#666",
-			inGraphDataXPosition: 3,
-			inGraphDataYPosition: 2,
-			scaleOverlay: false,
-			scaleOverride: false,
-			scaleOverride2: false,
-			scaleSteps: null,
-			scaleStepWidth: null,
-			scaleStartValue: null,
-			scaleLineColor: "rgba(0,0,0,.1)",
-			scaleLineWidth: 1,
-			scaleShowLabels: true,
-			scaleShowLabels2: true,
-			scaleLabel: "<%=value%>",
-			scaleFontFamily: "'Arial'",
-			scaleFontSize: 12,
-			scaleFontStyle: "normal",
-			scaleFontColor: "#666",
-			scaleShowGridLines: true,
-			scaleXGridLinesStep: 1,
-			scaleYGridLinesStep: 1,
-			scaleGridLineColor: "rgba(0,0,0,.05)",
-			scaleGridLineWidth: 1,
-			scaleTickSizeLeft: 5,
-			scaleTickSizeRight: 5,
-			scaleTickSizeBottom: 5,
-			scaleTickSizeTop: 5,
-			showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels)
-			rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre; 
-			barShowStroke: true,
-			barStrokeWidth: 2,
-			barValueSpacing: 5,
-			barDatasetSpacing: 1,
-			spaceBetweenBar : 0,
-			animation: true,
-			animationSteps: 60,
-			animationEasing: "easeOutQuart",
-			onAnimationComplete: null,
-			annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3 + ' (' + v6 + ' %)'%>",
-			reverseOrder: false
-		};
-		// merge annotate defaults
-		chart.HorizontalStackedBar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.HorizontalStackedBar.defaults);
-		chart.HorizontalStackedBar.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.HorizontalStackedBar.defaults);
-		chart.HorizontalStackedBar.defaults = mergeChartConfig(chart.HorizontalStackedBar.defaults, charJSPersonalDefaultOptions);
-		chart.HorizontalStackedBar.defaults = mergeChartConfig(chart.HorizontalStackedBar.defaults, charJSPersonalDefaultOptionsHorizontalStackedBar);
-		var config = (options) ? mergeChartConfig(chart.HorizontalStackedBar.defaults, options) : chart.HorizontalStackedBar.defaults;
-		return new HorizontalStackedBar(data, config, context);
-	};
-	this.Bar = function(data, options) {
-		chart.Bar.defaults = {
-			inGraphDataShow: false,
-			inGraphDataPaddingX: 0,
-			inGraphDataPaddingY: 3,
-			inGraphDataTmpl: "<%=v3%>",
-			inGraphDataAlign: "center",
-			inGraphDataVAlign: "bottom",
-			inGraphDataRotate: 0,
-			inGraphDataFontFamily: "'Arial'",
-			inGraphDataFontSize: 12,
-			inGraphDataFontStyle: "normal",
-			inGraphDataFontColor: "#666",
-			inGraphDataXPosition: 2,
-			inGraphDataYPosition: 3,
-			scaleOverlay: false,
-			scaleOverride: false,
-			scaleOverride2: false,
-			scaleSteps: null,
-			scaleStepWidth: null,
-			scaleStartValue: null,
-			scaleSteps2: null,
-			scaleStepWidth2: null,
-			scaleStartValue2: null,
-			scaleLineColor: "rgba(0,0,0,.1)",
-			scaleLineWidth: 1,
-			scaleShowLabels: true,
-			scaleShowLabels2: true,
-			scaleLabel: "<%=value%>",
-			scaleLabel2: "<%=value%>",
-			scaleFontFamily: "'Arial'",
-			scaleFontSize: 12,
-			scaleFontStyle: "normal",
-			scaleFontColor: "#666",
-			scaleShowGridLines: true,
-			scaleXGridLinesStep: 1,
-			scaleYGridLinesStep: 1,
-			scaleGridLineColor: "rgba(0,0,0,.05)",
-			scaleGridLineWidth: 1,
-			showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels)
-			rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre; 
-			// you can force an integer value between 0 and 180 degres
-			logarithmic: false, // can be 'fuzzy',true and false ('fuzzy' => if the gap between min and maximum is big it's using a logarithmic y-Axis scale
-			logarithmic2: false, // can be 'fuzzy',true and false ('fuzzy' => if the gap between min and maximum is big it's using a logarithmic y-Axis scale
-			scaleTickSizeLeft: 5,
-			scaleTickSizeRight: 5,
-			scaleTickSizeBottom: 5,
-			scaleTickSizeTop: 5,
-			barShowStroke: true,
-			barStrokeWidth: 2,
-			barValueSpacing: 5,
-			barDatasetSpacing: 1,
-			barBorderRadius: 0,
-			extrapolateMissingData: true,
-			animation: true,
-			animationSteps: 60,
-			animationEasing: "easeOutQuart",
-			onAnimationComplete: null,
-			pointDot: true,
-			bezierCurve: true,
-			bezierCurveTension : 0.4,
-			annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3 + ' (' + v6 + ' %)'%>"
-		};
-		// merge annotate defaults
-		chart.Bar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Bar.defaults);
-		chart.Bar.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.Bar.defaults);
-		chart.Bar.defaults = mergeChartConfig(chart.Bar.defaults, charJSPersonalDefaultOptions);
-		chart.Bar.defaults = mergeChartConfig(chart.Bar.defaults, charJSPersonalDefaultOptionsBar);
-		var config = (options) ? mergeChartConfig(chart.Bar.defaults, options) : chart.Bar.defaults;
-		return new Bar(data, config, context);
-	};
-	this.HorizontalBar = function(data, options) {
-		chart.HorizontalBar.defaults = {
-			inGraphDataShow: false,
-			inGraphDataPaddingX: 3,
-			inGraphDataPaddingY: 0,
-			inGraphDataTmpl: "<%=v3%>",
-			inGraphDataAlign: "left",
-			inGraphDataVAlign: "middle",
-			inGraphDataRotate: 0,
-			inGraphDataFontFamily: "'Arial'",
-			inGraphDataFontSize: 12,
-			inGraphDataFontStyle: "normal",
-			inGraphDataFontColor: "#666",
-			inGraphDataXPosition: 3,
-			inGraphDataYPosition: 2,
-			scaleOverlay: false,
-			scaleOverride: false,
-			scaleOverride2: false,
-			scaleSteps: null,
-			scaleStepWidth: null,
-			scaleStartValue: null,
-			scaleLineColor: "rgba(0,0,0,.1)",
-			scaleLineWidth: 1,
-			scaleShowLabels: true,
-			scaleShowLabels2: true,
-			scaleLabel: "<%=value%>",
-			scaleFontFamily: "'Arial'",
-			scaleFontSize: 12,
-			scaleFontStyle: "normal",
-			scaleFontColor: "#666",
-			scaleShowGridLines: true,
-			scaleXGridLinesStep: 1,
-			scaleYGridLinesStep: 1,
-			scaleGridLineColor: "rgba(0,0,0,.05)",
-			scaleGridLineWidth: 1,
-			scaleTickSizeLeft: 5,
-			scaleTickSizeRight: 5,
-			scaleTickSizeBottom: 5,
-			scaleTickSizeTop: 5,
-			showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels)
-			rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre; 
-			barShowStroke: true,
-			barStrokeWidth: 2,
-			barValueSpacing: 5,
-			barDatasetSpacing: 1,
-			barBorderRadius: 0,
-			animation: true,
-			animationSteps: 60,
-			animationEasing: "easeOutQuart",
-			onAnimationComplete: null,
-			annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3 + ' (' + v6 + ' %)'%>",
-			reverseOrder: false
-		};
-		// merge annotate defaults
-		chart.HorizontalBar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.HorizontalBar.defaults);
-		chart.HorizontalBar.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.HorizontalBar.defaults);
-		chart.HorizontalBar.defaults = mergeChartConfig(chart.HorizontalBar.defaults, charJSPersonalDefaultOptions);
-		chart.HorizontalBar.defaults = mergeChartConfig(chart.HorizontalBar.defaults, charJSPersonalDefaultOptionsHorizontalBar);
-		var config = (options) ? mergeChartConfig(chart.HorizontalBar.defaults, options) : chart.HorizontalBar.defaults;
-		return new HorizontalBar(data, config, context);
-	};
-	chart.defaults = {};
-	chart.defaults.commonOptions = {
-		multiGraph: false,
-		clearRect: true, // do not change clearRect options; for internal use only
-		dynamicDisplay: false,
-		graphSpaceBefore: 5,
-		graphSpaceAfter: 5,
-		canvasBorders: false,
-		canvasBackgroundColor: "none",
-		canvasBordersWidth: 3,
-		canvasBordersColor: "black",
-		zeroValue : 0.0000000001,
-		graphTitle: "",
-		graphTitleFontFamily: "'Arial'",
-		graphTitleFontSize: 24,
-		graphTitleFontStyle: "bold",
-		graphTitleFontColor: "#666",
-		graphTitleSpaceBefore: 5,
-		graphTitleSpaceAfter: 5,
-		graphSubTitle: "",
-		graphSubTitleFontFamily: "'Arial'",
-		graphSubTitleFontSize: 18,
-		graphSubTitleFontStyle: "normal",
-		graphSubTitleFontColor: "#666",
-		graphSubTitleSpaceBefore: 5,
-		graphSubTitleSpaceAfter: 5,
-		footNote: "",
-		footNoteFontFamily: "'Arial'",
-		footNoteFontSize: 8,
-		footNoteFontStyle: "bold",
-		footNoteFontColor: "#666",
-		footNoteSpaceBefore: 5,
-		footNoteSpaceAfter: 5,
-		legend : false,
-		showSingleLegend: false,
-		maxLegendCols : 999,
-		legendPosY :4,
-		legendPosX : -2, 
-		legendFontFamily: "'Arial'",
-		legendFontSize: 12,
-		legendFontStyle: "normal",
-		legendFontColor: "#666",
-		legendBlockSize: 15,
-		legendBorders: true,
-		legendBordersWidth: 1,
-		legendBordersColors: "#666",
-		legendBordersSpaceBefore: 5,
-		legendBordersSpaceAfter: 5,
-		legendBordersSpaceLeft: 5,
-		legendBordersSpaceRight: 5,
-		legendSpaceBeforeText: 5,
-		legendSpaceAfterText: 5,
-		legendSpaceLeftText: 5,
-		legendSpaceRightText: 5,
-		legendSpaceBetweenTextVertical: 5,
-		legendSpaceBetweenTextHorizontal: 5,
-		legendSpaceBetweenBoxAndText: 5,
-		legendFillColor : "rgba(0,0,0,0)",
-		legendXPadding : 0,
-		legendYPadding : 0,
-		annotateDisplay: false,
-		savePng: false,
-		savePngOutput: "NewWindow", // Allowed values : "NewWindow", "CurrentWindow", "Save"
-		savePngFunction: "mousedown right",
-		savePngBackgroundColor: 'WHITE',
-		annotateFunction: "mousemove",
-		annotateFontFamily: "'Arial'",
-		annotateBorder: 'none',
-		annotateBorderRadius: '2px',
-		annotateBackgroundColor: 'rgba(0,0,0,0.8)',
-		annotateFontSize: 12,
-		annotateFontColor: 'white',
-		annotateFontStyle: "normal",
-		annotatePadding: "3px",
-		annotateClassName: "",
-		crossText: [""],
-		crossTextIter: ["all"],
-		crossTextOverlay: [true],
-		crossTextFontFamily: ["'Arial'"],
-		crossTextFontSize: [12],
-		crossTextFontStyle: ["normal"],
-		crossTextFontColor: ["rgba(220,220,220,1)"],
-		crossTextRelativePosX: [2],
-		crossTextRelativePosY: [2],
-		crossTextBaseline: ["middle"],
-		crossTextAlign: ["center"],
-		crossTextPosX: [0],
-		crossTextPosY: [0],
-		crossTextAngle: [0],
-		crossTextFunction: null,
-		crossImage: [undefined],
-		crossImageIter: ["all"],
-		crossImageOverlay: [true],
-		crossImageRelativePosX: [2],
-		crossImageRelativePosY: [2],
-		crossImageBaseline: ["middle"],
-		crossImageAlign: ["center"],
-		crossImagePosX: [0],
-		crossImagePosY: [0],
-		crossImageAngle: [0],
-		spaceTop: 0,
-		spaceBottom: 0,
-		spaceRight: 0,
-		spaceLeft: 0,
-		decimalSeparator: ".",
-		thousandSeparator: "",
-		roundNumber: "none",
-		roundPct: -1,
-		fmtV1: "none",
-		fmtV2: "none",
-		fmtV3: "none",
-		fmtV4: "none",
-		fmtV5: "none",
-		fmtV6: "none",
-		fmtV7: "none",
-		fmtV8: "none",
-		fmtV9: "none",
-		fmtV10: "none",
-		fmtV11: "none",
-		fmtV12: "none",
-		fmtV13: "none",
-		fmtXLabel: "none",
-		fmtYLabel: "none",
-		fmtYLabel2: "none",
-		fmtLegend: "none",
-		animationStartValue: 0,
-		animationStopValue: 1,
-		animationCount: 1,
-		animationPauseTime: 5,
-		animationBackward: false,
-		animationStartWithDataset: 1,
-		animationStartWithData: 1,
-		animationLeftToRight: false,
-		animationByDataset: false,
-		defaultStrokeColor: "rgba(220,220,220,1)",
-		defaultFillColor: "rgba(220,220,220,0.5)",
-		defaultLineWidth : 2,
-		mouseDownRight: null,
-		mouseDownLeft: null,
-		mouseDownMiddle: null,
-		mouseMove: null,
-		mouseOut: null,
-		mouseWheel : null,
-		savePngName: "canvas",
-		responsive : false,
-		responsiveMinWidth : 0,
-		responsiveMinHeight : 0,
-		responsiveMaxWidth : 9999999,
-		responsiveMaxHeight : 9999999,
-		maintainAspectRatio: true,
-		pointMarker : "circle"    // "circle","cross","plus","diamond","triangle","square"
-	};
-	chart.defaults.xyAxisCommonOptions = {
-		yAxisMinimumInterval: "none",
-		yAxisMinimumInterval2: "none",
-		yScaleLabelsMinimumWidth: 0,
-		xScaleLabelsMinimumWidth: 0,
-		yAxisLeft: true,
-		yAxisRight: false,
-		xAxisBottom: true,
-		xAxisTop: false,
-		xAxisSpaceBetweenLabels: 5,
-		fullWidthGraph: false,
-		yAxisLabel: "",
-		yAxisLabel2: "",
-		yAxisFontFamily: "'Arial'",
-		yAxisFontSize: 16,
-		yAxisFontStyle: "normal",
-		yAxisFontColor: "#666",
-		yAxisLabelSpaceRight: 5,
-		yAxisLabelSpaceLeft: 5,
-		yAxisSpaceRight: 5,
-		yAxisSpaceLeft: 5,
-		xAxisLabel: "",
-		xAxisFontFamily: "'Arial'",
-		xAxisFontSize: 16,
-		xAxisFontStyle: "normal",
-		xAxisFontColor: "#666",
-		xAxisLabelSpaceBefore: 5,
-		xAxisLabelSpaceAfter: 5,
-		xAxisSpaceBefore: 5,
-		xAxisSpaceAfter: 5,
-		yAxisUnit: "",
-		yAxisUnit2: "",
-		yAxisUnitFontFamily: "'Arial'",
-		yAxisUnitFontSize: 8,
-		yAxisUnitFontStyle: "normal",
-		yAxisUnitFontColor: "#666",
-		yAxisUnitSpaceBefore: 5,
-		yAxisUnitSpaceAfter: 5
-	};
-	var clear = function(c) {
-		c.clearRect(0, 0, width, height);
-	};
-
-	function init_and_start(ctx,data,config) {
-	
-		if (typeof ctx.ChartNewId === typeof undefined) {
-			ctx.runanimationcompletefunction=true;
-			var cvdate = new Date();
-			var cvmillsec = cvdate.getTime();
-			ctx.ChartNewId = ctx.tpchart + '_' + cvmillsec;
-			ctx._eventListeners = {};
-		}
-		if (!dynamicFunction(data, config, ctx)) { 
-	        	if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } }
-			return false; 
-		}
-        	if(config.responsive && typeof ctx.firstPass == "undefined") {
-        		if(!config.multiGraph) {
-				addResponsiveChart(ctx.ChartNewId,ctx,data,config);
-        			subUpdateChart(ctx,data,config);
-        			return false;
-        		} else { ctx.firstPass=1; }
-		} 
-
-		if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array();
-		else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId);
-
-		defMouse(ctx, data, config);
-
-		setRect(ctx, config);
-
-		return true;
-	} ;
-
-	var PolarArea = function(data, config, ctx) {
-		var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, msr, midPosX, midPosY;
-		ctx.tpchart="PolarArea";
-		
-	        if (!init_and_start(ctx,data,config)) return;
-		var statData=initPassVariableData_part1(data,config,ctx);
-
-		valueBounds = getValueBounds();
-
-		config.logarithmic = false;
-		config.logarithmic2 = false;
-
-		//Check and set the scale
-		labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
-		if (!config.scaleOverride) {
-			calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
-			msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, false, false, true, "PolarArea");
-		} else {
-			var scaleStartValue= setOptionValue("SCALESTARTVALUE",ctx,data,statData,undefined,config.scaleStartValue,-1,-1,{nullValue : true} );
-			var scaleSteps =setOptionValue("SCALESTEPS",ctx,data,statData,undefined,config.scaleSteps,-1,-1,{nullValue : true} );
-			var scaleStepWidth = setOptionValue("SCALESTEPWIDTH",ctx,data,statData,undefined,config.scaleStepWidth,-1,-1,{nullValue : true} );
-
-			calculatedScale = {
-				steps: scaleSteps,
-				stepValue: scaleStepWidth,
-				graphMin: scaleStartValue,
-				graphMax: scaleStartValue + scaleSteps * scaleStepWidth,
-				labels: []
-			}
-			populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, scaleStartValue, calculatedScale.graphMax, scaleStepWidth);
-			msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, false, false, true, "PolarArea");
-		}
-
-		midPosX = msr.leftNotUsableSize + (msr.availableWidth / 2);
-		midPosY = msr.topNotUsableSize + (msr.availableHeight / 2);
-		scaleHop = Math.floor(((Min([msr.availableHeight, msr.availableWidth]) / 2) - 5) / calculatedScale.steps);
-		//Wrap in an animation loop wrapper
- 		if(scaleHop > 0) {
-			initPassVariableData_part2(statData,data,config,ctx,{midPosX : midPosX,midPosY : midPosY,int_radius : 0,ext_radius : scaleHop*calculatedScale.steps, calculatedScale : calculatedScale, scaleHop : scaleHop});
-			animationLoop(config, drawScale, drawAllSegments, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, midPosX, midPosY, midPosX - ((Min([msr.availableHeight, msr.availableWidth]) / 2) - 5), midPosY + ((Min([msr.availableHeight, msr.availableWidth]) / 2) - 5), data);
-		} else {
-			testRedraw(ctx,data,config);
-		}
-
-		function drawAllSegments(animationDecimal) {
-
-			for (var i = 0; i < data.length; i++) {
-				var	scaleAnimation = 1,
-					rotateAnimation = 1;
-                	
-				if (config.animation) {
-					if (config.animateScale) {
-						scaleAnimation = animationDecimal;
-					}
-					if (config.animateRotate) {
-						rotateAnimation = animationDecimal;
-					}
-				}
-				correctedRotateAnimation = animationCorrection(rotateAnimation, data, config, i, -1, 0).mainVal;
-				if (!(typeof(data[i].value) == 'undefined')) {
-					ctx.beginPath();
-					if(config.animationByData == "ByArc") {
-						endAngle=statData[i].startAngle+correctedRotateAnimation*statData[i].segmentAngle;
-						ctx.arc(midPosX, midPosY, scaleAnimation * statData[i].radiusOffset, statData[i].startAngle, endAngle, false);
-					} else if(config.animationByData) {
-						if(statData[i].startAngle-statData[i].firstAngle < correctedRotateAnimation*2*Math.PI ) {
-							endAngle=statData[i].endAngle;
-							if((statData[i].endAngle-statData[i].firstAngle)> correctedRotateAnimation*2*Math.PI) endAngle=statData[i].firstAngle+correctedRotateAnimation*2*Math.PI;							
-							ctx.arc(midPosX, midPosY, scaleAnimation * statData[i].radiusOffset, statData[i].startAngle, endAngle, false);
-							
-						}
-						else continue;
-					} else {
-						ctx.arc(midPosX, midPosY, scaleAnimation * statData[i].radiusOffset, statData[i].firstAngle+correctedRotateAnimation * (statData[i].startAngle-statData[i].firstAngle), statData[i].firstAngle+correctedRotateAnimation * (statData[i].endAngle-statData[i].firstAngle));
-					}
-					ctx.lineTo(midPosX, midPosY);
-					ctx.closePath();
-					ctx.fillStyle=setOptionValue("COLOR",ctx,data,statData,data[i].color,config.defaultFillColor,i,-1,{animationDecimal: animationDecimal, scaleAnimation : scaleAnimation} );
-					ctx.fill();
-					if (config.segmentShowStroke) {
-						ctx.strokeStyle = config.segmentStrokeColor;
-						ctx.lineWidth = config.segmentStrokeWidth;
-						ctx.stroke();
-					}
-				}
-			}
-
-
-			if (animationDecimal >= config.animationStopValue) {
-				for (var i = 0; i < data.length; i++) {
-					if (typeof(data[i].value) == 'undefined') continue;
-					if (setOptionValue("ANNOTATEDISPLAY",ctx,data,statData,undefined,config.annotateDisplay,i,-1,{nullValue : true})) {
-						jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["ARC", i, -1,statData];
-					}
-					if (setOptionValue("INGRAPHDATASHOW",ctx,data,statData,undefined,config.inGraphDataShow,i,-1,{nullValue : true})) {
-						if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 1) posAngle = statData[i].realStartAngle + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						else if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 2) posAngle = (2*statData[i].realStartAngle - statData[i].segmentAngle) / 2 + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						else if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 3) posAngle = statData[i].realStartAngle - statData[i].segmentAngle + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						if (setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,i,-1,{nullValue : true} ) == 1) labelRadius = 0 + setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} );
-						else if (setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,i,-1,{nullValue : true} ) == 2) labelRadius = statData[i].radiusOffset / 2 + setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} );
-						else if (setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,i,-1,{nullValue : true} ) == 3) labelRadius = statData[i].radiusOffset + setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} );
-						else if (setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,i,-1,{nullValue : true} ) == 4) labelRadius = scaleHop * calculatedScale.steps + setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} );
-						ctx.save()
-						if (setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,-1,{nullValue: true  }) == "off-center") {
-							if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "left";
-							else ctx.textAlign = "right";
-						} else if (setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,-1,{nullValue: true  }) == "to-center") {
-							if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "right";
-							else ctx.textAlign = "left";
-						} else ctx.textAlign = setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,-1,{nullValue: true  });
-						if (setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,-1,{nullValue : true} ) == "off-center") {
-							if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "top";
-							else ctx.textBaseline = "bottom";
-						} else if (setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,-1,{nullValue : true} ) == "to-center") {
-							if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "bottom";
-							else ctx.textBaseline = "top";
-						} else ctx.textBaseline = setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,-1,{nullValue : true} );
-						ctx.font = setOptionValue("INGRAPHDATAFONTSTYLE",ctx,data,statData,undefined,config.inGraphDataFontStyle,i,-1,{nullValue : true} ) + ' ' + setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,-1,{nullValue : true} ) + 'px ' + setOptionValue("INGRAPHDATAFONTFAMILY",ctx,data,statData,undefined,config.inGraphDataFontFamily,i,-1,{nullValue : true} );
-						ctx.fillStyle = setOptionValue("INGRAPHDATAFONTCOLOR",ctx,data,statData,undefined,config.inGraphDataFontColor,i,-1,{nullValue : true} );
-						var dispString = tmplbis(setOptionValue("INGRAPHDATATMPL",ctx,data,statData,undefined,config.inGraphDataTmpl,i,-1,{nullValue : true} ), statData[i]);
-						ctx.translate(midPosX + labelRadius * Math.cos(posAngle), midPosY - labelRadius * Math.sin(posAngle));
-						if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxis") ctx.rotate(2 * Math.PI - posAngle);
-						else if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxisRotateLabels") {
-							if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI / 2 && (posAngle + 2 * Math.PI) % (2 * Math.PI) < 3 * Math.PI / 2) ctx.rotate(3 * Math.PI - posAngle);
-							else ctx.rotate(2 * Math.PI - posAngle);
-						} else ctx.rotate(setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) * (Math.PI / 180));
-						ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,-1,{nullValue : true} ), true);
-						ctx.restore();
-					}
-				}
-			}
-			if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"PolarArea");
-		};
-
-		function drawScale() {
-			for (var i = 0; i < calculatedScale.steps; i++) {
-				if (config.scaleShowLine) {
-					ctx.beginPath();
-					ctx.arc(midPosX, midPosY, scaleHop * (i + 1), 0, (Math.PI * 2), true);
-					ctx.strokeStyle = config.scaleLineColor;
-					ctx.lineWidth = config.scaleLineWidth;
-					ctx.stroke();
-				}
-				if (config.scaleShowLabels) {
-					ctx.textAlign = "center";
-					ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
-					var label = calculatedScale.labels[i + 1];
-					if (config.scaleShowLabelBackdrop) {
-						var textWidth = ctx.measureTextMultiLine(label, config.scaleFontSize).textWidth;
-						ctx.fillStyle = config.scaleBackdropColor;
-						ctx.beginPath();
-						ctx.rect(
-							Math.round(midPosX - textWidth / 2 - config.scaleBackdropPaddingX), //X
-							Math.round(midPosY - (scaleHop * (i + 1)) - config.scaleFontSize * 0.5 - config.scaleBackdropPaddingY), //Y
-							Math.round(textWidth + (config.scaleBackdropPaddingX * 2)), //Width
-							Math.round(config.scaleFontSize + (config.scaleBackdropPaddingY * 2)) //Height
-						);
-						ctx.fill();
-					}
-					ctx.textBaseline = "middle";
-					ctx.fillStyle = config.scaleFontColor;
-					ctx.fillTextMultiLine(label, midPosX, midPosY - (scaleHop * (i + 1)), ctx.textBaseline, config.scaleFontSize,true);
-				}
-			}
-		};
-
-		function getValueBounds() {
-			var upperValue = -Number.MAX_VALUE;
-			var lowerValue = Number.MAX_VALUE;
-			for (var i = 0; i < data.length; i++) {
-				if(typeof data[i].value == "undefined") continue;
-				if (1 * data[i].value > upperValue) {
-					upperValue = 1 * data[i].value;
-				}
-				if (1 * data[i].value < lowerValue) {
-					lowerValue = 1 * data[i].value;
-				}
-			};
-			if(upperValue<lowerValue){upperValue=0;lowerValue=0;}
-			if (Math.abs(upperValue - lowerValue) < config.zeroValue) {
-				if(Math.abs(upperValue)< config.zeroValue) upperValue = .9;
-				if(upperValue>0) {
-					upperValue=upperValue*1.1;
-					lowerValue=lowerValue*0.9;
-				} else {
-					upperValue=upperValue*0.9;
-					lowerValue=lowerValue*1.1;
-				}
-			}
-			if(typeof config.graphMin=="function") lowerValue= setOptionValue("GRAPHMIN",ctx,data,statData,undefined,config.graphMin,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
-			if(typeof config.graphMax=="function") upperValue= setOptionValue("GRAPHMAX",ctx,data,statData,undefined,config.graphMax,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMax)) upperValue = config.graphMax;
-			var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66)));
-			var minSteps = Math.floor((scaleHeight / labelHeight * 0.5));
-			return {
-				maxValue: upperValue,
-				minValue: lowerValue,
-				maxSteps: maxSteps,
-				minSteps: minSteps
-			};
-		};
-	};
-	var Radar = function(data, config, ctx) {
-		var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, msr, midPosX, midPosY;
-
-		ctx.tpchart="Radar";
-	        if (!init_and_start(ctx,data,config)) return;
-		var statData=initPassVariableData_part1(data,config,ctx);
-
-		valueBounds = getValueBounds();
-
-		config.logarithmic = false;
-		config.logarithmic2 = false;
-		//If no labels are defined set to an empty array, so referencing length for looping doesn't blow up.
-		if (!data.labels) data.labels = [];
-		//Check and set the scale
-		labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
-		if (!config.scaleOverride) {
-			calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
-			msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, false, true, config.datasetFill, "Radar");
-		} else {
-			var scaleStartValue= setOptionValue("SCALESTARTVALUE",ctx,data,statData,undefined,config.scaleStartValue,-1,-1,{nullValue : true} );
-			var scaleSteps =setOptionValue("SCALESTEPS",ctx,data,statData,undefined,config.scaleSteps,-1,-1,{nullValue : true} );
-			var scaleStepWidth = setOptionValue("SCALESTEPWIDTH",ctx,data,statData,undefined,config.scaleStepWidth,-1,-1,{nullValue : true} );
-			calculatedScale = {
-				steps: scaleSteps,
-				stepValue: scaleStepWidth,
-				graphMin: scaleStartValue,
-				graphMax: scaleStartValue + scaleSteps * scaleStepWidth,
-				labels: []
-			}
-			populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, scaleStartValue, calculatedScale.graphMax, scaleStepWidth);
-			msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, false, true, config.datasetFill, "Radar");
-		}
-
-		calculateDrawingSizes();
-		midPosY = msr.topNotUsableSize + (msr.availableHeight / 2);
-		scaleHop = maxSize / (calculatedScale.steps);
-		//Wrap in an animation loop wrapper
-		initPassVariableData_part2(statData,data,config,ctx,{midPosX : midPosX, midPosY : midPosY, calculatedScale: calculatedScale, scaleHop: scaleHop, maxSize:maxSize});
-		animationLoop(config, drawScale, drawAllDataPoints, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, midPosX, midPosY, midPosX - maxSize, midPosY + maxSize, data);
-		//Radar specific functions.
-		function drawAllDataPoints(animationDecimal) {
-			var rotationDegree = (2 * Math.PI) / data.datasets[0].data.length;
-			ctx.save();
-			//We accept multiple data sets for radar charts, so show loop through each set
-			for (var i = 0; i < data.datasets.length; i++) {
-				var fPt = -1;
-				for (var j = 0; j < data.datasets[i].data.length; j++) {
-					var currentAnimPc = animationCorrection(animationDecimal, data, config, i, j, 1).animVal;
-					if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1;
-					if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
-						if (fPt == -1) {
-							ctx.beginPath();
-							ctx.moveTo(midPosX + currentAnimPc * statData[i][j].offsetX, midPosY - currentAnimPc * statData[i][j].offsetY);
-							fPt = j;
-						} else {
-							ctx.lineTo(midPosX + currentAnimPc * statData[i][j].offsetX, midPosY - currentAnimPc * statData[i][j].offsetY);
-						}
-					}
-				}
-				ctx.closePath();
-				if (config.datasetFill) {
-					ctx.fillStyle=setOptionValue("COLOR",ctx,data,statData,data.datasets[i].fillColor,config.defaultFillColor,i,-1,{animationValue : currentAnimPc, midPosX : statData[i][0].midPosX, midPosY : statData[i][0].midPosY, ext_radius : (config.animationLeftToRight ? 1 : currentAnimPc) * (statData[i][0].calculated_offset_max)} );
-				} else ctx.fillStyle = "rgba(0,0,0,0)";
-
-				ctx.strokeStyle=setOptionValue("STROKECOLOR",ctx,data,statData,data.datasets[i].strokeColor,config.defaultStrokeColor,i,-1,{nullvalue : null} );
-
-				ctx.lineWidth = config.datasetStrokeWidth;
-				ctx.fill();
-				ctx.stroke();
-				if (config.pointDot && (!config.animationLeftToRight || (config.animationLeftToRight && animationDecimal >= 1))) {
-					ctx.beginPath();
-					ctx.fillStyle=setOptionValue("MARKERFILLCOLOR",ctx,data,statData,data.datasets[i].pointColor,config.defaultStrokeColor,i,-1,{nullvalue: true} );
-					ctx.strokeStyle=setOptionValue("MARKERSTROKESTYLE",ctx,data,statData,data.datasets[i].pointStrokeColor,config.defaultStrokeColor,i,-1,{nullvalue: true} );
-					ctx.lineWidth=setOptionValue("MARKERLINEWIDTH",ctx,data,statData,data.datasets[i].pointDotStrokeWidth,config.pointDotStrokeWidth,i,-1,{nullvalue: true} );
-
-					for (var k = 0; k < data.datasets[i].data.length; k++) {
-						if (!(typeof(data.datasets[i].data[k]) == 'undefined')) {
-							ctx.beginPath();
-							var markerShape=setOptionValue("MARKERSHAPE",ctx,data,statData,data.datasets[i].markerShape,config.markerShape,i,j,{nullvalue: true} );
-							var markerRadius=setOptionValue("MARKERRADIUS",ctx,data,statData,data.datasets[i].pointDotRadius,config.pointDotRadius,i,j,{nullvalue: true} );
-							drawMarker(ctx,midPosX + currentAnimPc * statData[i][k].offsetX, midPosY - currentAnimPc * statData[i][k].offsetY, markerShape,markerRadius);							
-						}
-					}
-				}
-			}
-			ctx.restore();
-			if (animationDecimal >= config.animationStopValue) {
-				for (var i = 0; i < data.datasets.length; i++) {
-					for (var j = 0; j < data.datasets[i].data.length; j++) {
-						if (typeof(data.datasets[i].data[j]) == 'undefined') continue;
-						if (setOptionValue("ANNOTATEDISPLAY",ctx,data,statData,undefined,config.annotateDisplay,i,j,{nullValue : true})) {
-							jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["POINT", i,j,statData];
-						}
-						if(setOptionValue("INGRAPHDATASHOW",ctx,data,statData,undefined,config.inGraphDataShow,i,j,{nullValue : true})) {
-
-
-							ctx.save();
-							ctx.beginPath();
-							ctx.textAlign = setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,-1,{nullValue: true  });
-							ctx.textBaseline = setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,-1,{nullValue : true} );
-							if (setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,-1,{nullValue: true  }) == "off-center") {
-								if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxis" || (config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) <= Math.PI / 2) ctx.textAlign = "left";
-								else ctx.textAlign = "right";
-							} else if (setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,-1,{nullValue: true  }) == "to-center") {
-								if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxis" || (config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "right";
-								else ctx.textAlign = "left";
-							} else ctx.textAlign = setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,-1,{nullValue: true  });
-							if (setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,-1,{nullValue : true} ) == "off-center") {
-								if ((config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "bottom";
-								else ctx.textBaseline = "top";
-							} else if (setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,-1,{nullValue : true} ) == "to-center") {
-								if ((config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "top";
-								else ctx.textBaseline = "bottom";
-							} else ctx.textBaseline = setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,-1,{nullValue : true} );
-							ctx.font = setOptionValue("INGRAPHDATAFONTSTYLE",ctx,data,statData,undefined,config.inGraphDataFontStyle,i,-1,{nullValue : true} ) + ' ' + setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,-1,{nullValue : true} ) + 'px ' + setOptionValue("INGRAPHDATAFONTFAMILY",ctx,data,statData,undefined,config.inGraphDataFontFamily,i,-1,{nullValue : true} );
-							ctx.fillStyle = setOptionValue("INGRAPHDATAFONTCOLOR",ctx,data,statData,undefined,config.inGraphDataFontColor,i,-1,{nullValue : true} );
-							var radiusPrt;
-							if (setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,i,-1,{nullValue : true} ) == 1) radiusPrt = 0 + setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} );
-							else if (setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,i,-1,{nullValue : true} ) == 2) radiusPrt = (statData[i][j].calculated_offset) / 2 + setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} );
-							else if (setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,i,-1,{nullValue : true} ) == 3) radiusPrt = (statData[i][j].calculated_offset) + setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} );
-							if(statData[i][j].calculated_offset>0) {
-								ctx.translate(midPosX + statData[i][j].offsetX * (radiusPrt/statData[i][j].calculated_offset), midPosY - statData[i][j].offsetY * (radiusPrt/statData[i][j].calculated_offset));
-							} else {
-								ctx.translate(midPosX, midPosY);
-							}
-							if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxis") ctx.rotate(j * rotationDegree);
-							else if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxisRotateLabels") {
-								if ((j * rotationDegree + 2 * Math.PI) % (2 * Math.PI) > Math.PI / 2 && (j * rotationDegree + 2 * Math.PI) % (2 * Math.PI) < 3 * Math.PI / 2) ctx.rotate(3 * Math.PI + j * rotationDegree);
-								else ctx.rotate(2 * Math.PI + j * rotationDegree);
-							} else ctx.rotate(setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) * (Math.PI / 180));
-							var dispString = tmplbis(setOptionValue("INGRAPHDATATMPL",ctx,data,statData,undefined,config.inGraphDataTmpl,i,-1,{nullValue : true} ), statData[i][j]);
-							ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,-1,{nullValue : true} ),true);
-							ctx.restore();
-						}
-					}
-				}
-			}
-			if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Radar");
-		};
-
-		function drawScale() {
-			var rotationDegree = (2 * Math.PI) / data.datasets[0].data.length;
-			ctx.save();
-			ctx.translate(midPosX, midPosY);
-			ctx.rotate((90 - config.startAngle) * Math.PI / 180);
-			if (config.angleShowLineOut) {
-				ctx.strokeStyle = config.angleLineColor;
-				ctx.lineWidth = config.angleLineWidth;
-				for (var h = 0; h < data.datasets[0].data.length; h++) {
-					ctx.rotate(rotationDegree);
-					ctx.beginPath();
-					ctx.moveTo(0, 0);
-					ctx.lineTo(0, -maxSize);
-					ctx.stroke();
-				}
-			}
-			for (var i = 0; i < calculatedScale.steps; i++) {
-				ctx.beginPath();
-				if (config.scaleShowLine) {
-					ctx.strokeStyle = config.scaleLineColor;
-					ctx.lineWidth = config.scaleLineWidth;
-					ctx.moveTo(0, -scaleHop * (i + 1));
-					for (var j = 0; j < data.datasets[0].data.length; j++) {
-						ctx.rotate(rotationDegree);
-						ctx.lineTo(0, -scaleHop * (i + 1));
-					}
-					ctx.closePath();
-					ctx.stroke();
-				}
-			}
-			ctx.rotate(-(90 - config.startAngle) * Math.PI / 180);
-			if (config.scaleShowLabels) {
-				for (var i = 0; i < calculatedScale.steps; i++) {
-					ctx.textAlign = 'center';
-					ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
-					ctx.textBaseline = "middle";
-					if (config.scaleShowLabelBackdrop) {
-						var textWidth = ctx.measureTextMultiLine(calculatedScale.labels[i + 1], config.scaleFontSize).textWidth;
-						ctx.fillStyle = config.scaleBackdropColor;
-						ctx.beginPath();
-						ctx.rect(
-							Math.round(Math.cos(config.startAngle * Math.PI / 180) * (scaleHop * (i + 1)) - textWidth / 2 - config.scaleBackdropPaddingX), //X
-							Math.round((-Math.sin(config.startAngle * Math.PI / 180) * scaleHop * (i + 1)) - config.scaleFontSize * 0.5 - config.scaleBackdropPaddingY), //Y
-							Math.round(textWidth + (config.scaleBackdropPaddingX * 2)), //Width
-							Math.round(config.scaleFontSize + (config.scaleBackdropPaddingY * 2)) //Height
-						);
-						ctx.fill();
-					}
-					ctx.fillStyle = config.scaleFontColor;
-					ctx.fillTextMultiLine(calculatedScale.labels[i + 1], Math.cos(config.startAngle * Math.PI / 180) * (scaleHop * (i + 1)), -Math.sin(config.startAngle * Math.PI / 180) * scaleHop * (i + 1), ctx.textBaseline, config.scaleFontSize,true);
-				}
-			}
-			for (var k = 0; k < data.labels.length; k++) {
-				ctx.font = config.pointLabelFontStyle + " " + config.pointLabelFontSize + "px " + config.pointLabelFontFamily;
-				ctx.fillStyle = config.pointLabelFontColor;
-				var opposite = Math.sin((90 - config.startAngle) * Math.PI / 180 + rotationDegree * k) * (maxSize + config.pointLabelFontSize);
-				var adjacent = Math.cos((90 - config.startAngle) * Math.PI / 180 + rotationDegree * k) * (maxSize + config.pointLabelFontSize);
-				var vangle = (90 - config.startAngle) * Math.PI / 180 + rotationDegree * k;
-				while (vangle < 0) vangle = vangle + 2 * Math.PI;
-				while (vangle > 2 * Math.PI) vangle = vangle - 2 * Math.PI;
-				if (vangle == Math.PI || vangle == 0) {
-					ctx.textAlign = "center";
-				} else if (vangle > Math.PI) {
-					ctx.textAlign = "right";
-				} else {
-					ctx.textAlign = "left";
-				}
-				ctx.textBaseline = "middle";
-				ctx.fillTextMultiLine(data.labels[k], opposite, -adjacent, ctx.textBaseline, config.pointLabelFontSize,true);
-			}
-			ctx.restore();
-		};
-
-		function calculateDrawingSizes() {
-			var midX, mxlb, maxL, maxR, iter, nbiter, prevMaxSize, prevMidX;
-			var rotationDegree = (2 * Math.PI) / data.datasets[0].data.length;
-			var rotateAngle = config.startAngle * Math.PI / 180;
-			// Compute range for Mid Point of graph
-			ctx.font = config.pointLabelFontStyle + " " + config.pointLabelFontSize + "px " + config.pointLabelFontFamily;
-			if (!config.graphMaximized) {
-				maxR = msr.availableWidth / 2;
-				maxL = msr.availableWidth / 2;
-				nbiter = 1;
-			} else {
-				maxR = msr.availableWidth / 2;
-				maxL = msr.availableWidth / 2;
-				nbiter = 40;
-				for (var i = 0; i < data.labels.length; i++) {
-					var textMeasurement = ctx.measureTextMultiLine(data.labels[i], config.scaleFontSize).textWidth + ctx.measureTextMultiLine(data.labels[i], config.scaleFontSize).textHeight;
-					mxlb = (msr.availableWidth - textMeasurement) / (1 + Math.abs(Math.cos(rotateAngle)));
-					if ((rotateAngle < Math.PI / 2 && rotateAngle > -Math.PI / 2) || rotateAngle > 3 * Math.PI / 2) {
-						if (mxlb < maxR) maxR = mxlb;
-					} else if (Math.cos(rotateAngle) != 0) {
-						if (mxlb < maxL) maxL = mxlb;
-					}
-					rotateAngle -= rotationDegree;
-				}
-			}
-			// compute max Radius and midPoint in that range
-			prevMaxSize = 0;
-			prevMidX = 0;
-			midPosX = maxR + msr.rightNotUsableSize;
-			for (midX = maxR, iter = 0; iter < nbiter; ++iter, midX += (msr.availableWidth - maxL - maxR) / nbiter) {
-				maxSize = Max([midX, msr.availableWidth - midX]);
-				var rotateAngle = config.startAngle * Math.PI / 180;
-				mxlb = msr.available;
-				for (var i = 0; i < data.labels.length; i++) {
-					var textMeasurement = ctx.measureTextMultiLine(data.labels[i], config.scaleFontSize).textWidth + ctx.measureTextMultiLine(data.labels[i], config.scaleFontSize).textHeight;
-					if ((rotateAngle < Math.PI / 2 && rotateAngle > -Math.PI / 2) || rotateAngle > 3 * Math.PI / 2) {
-						mxlb = ((msr.availableWidth - midX) - textMeasurement) / Math.abs(Math.cos(rotateAngle));
-					} else if (Math.cos(rotateAngle != 0)) {
-						mxlb = (midX - textMeasurement) / Math.abs(Math.cos(rotateAngle));
-					}
-					if (mxlb < maxSize) maxSize = mxlb;
-					if (Math.sin(rotateAngle) * msr.availableHeight / 2 > msr.availableHeight / 2 - config.scaleFontSize * 2) {
-						mxlb = Math.sin(rotateAngle) * msr.availableHeight / 2 - 1.5 * config.scaleFontSize;
-						if (mxlb < maxSize) maxSize = mxlb;
-					}
-					rotateAngle -= rotationDegree;
-				}
-				if (maxSize > prevMaxSize) {
-					prevMaxSize = maxSize;
-					midPosX = midX + msr.rightNotUsableSize;
-				}
-			}
-			maxSize = prevMaxSize - config.scaleFontSize / 2;
-			//If the label height is less than 5, set it to 5 so we don't have lines on top of each other.
-			labelHeight = Default(labelHeight, 5);
-		};
-
-		function getValueBounds() {
-			var upperValue = -Number.MAX_VALUE;
-			var lowerValue = Number.MAX_VALUE;
-			for (var i = 0; i < data.datasets.length; i++) {
-				for (var j = 0; j < data.datasets[i].data.length; j++) {
-					if(typeof data.datasets[i].data[j]=="undefined")continue;
-					if (1 * data.datasets[i].data[j] > upperValue) {
-						upperValue = 1 * data.datasets[i].data[j]
-					}
-					if (1 * data.datasets[i].data[j] < lowerValue) {
-						lowerValue = 1 * data.datasets[i].data[j]
-					}
-				}
-			}
-			if(upperValue<lowerValue){upperValue=0;lowerValue=0;}
-			if (Math.abs(upperValue - lowerValue) < config.zeroValue) {
-				if(Math.abs(upperValue)< config.zeroValue){ upperValue = .9;lowerValue=-.9;}
-				if(upperValue>0) {
-					upperValue=upperValue*1.1;
-					lowerValue=lowerValue*0.9;
-				} else {
-					upperValue=upperValue*0.9;
-					lowerValue=lowerValue*1.1;
-				}
-			}
-			if(typeof config.graphMin=="function") lowerValue= setOptionValue("GRAPHMIN",ctx,data,statData,undefined,config.graphMin,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
-			if(typeof config.graphMax=="function") upperValue= setOptionValue("GRAPHMAX",ctx,data,statData,undefined,config.graphMax,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMax)) upperValue = config.graphMax;
-			var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66)));
-			var minSteps = Math.floor((scaleHeight / labelHeight * 0.5));
-			return {
-				maxValue: upperValue,
-				minValue: lowerValue,
-				maxSteps: maxSteps,
-				minSteps: minSteps
-			};
-		};
-	};
-
-
-	var Pie = function(data, config, ctx) {
-		var totvalue = 0;
-		var msr, midPieX, midPieY, pieRadius;
-
-		ctx.tpchart="Pie";
-	        if (!init_and_start(ctx,data,config)) return;
-		var statData=initPassVariableData_part1(data,config,ctx);
-		config.logarithmic = false;
-		config.logarithmic2 = false;
-		msr = setMeasures(data, config, ctx, height, width, "none", null, true, false, false, false, true, "Pie");
-		calculateDrawingSize();
-		if(pieRadius > 0) {
-			initPassVariableData_part2(statData,data,config,ctx,{midPosX : midPieX,midPosY : midPieY,int_radius : 0,ext_radius : pieRadius});
-			animationLoop(config, null, drawPieSegments, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, midPieX, midPieY, midPieX - pieRadius, midPieY + pieRadius, data);
-		} else {
-			testRedraw(ctx,data,config);
-		}
-		function drawPieSegments(animationDecimal) {
-			for (var i = 0; i < data.length; i++) {
-				var	scaleAnimation = 1,
-					rotateAnimation = 1;
-                	
-				if (config.animation) {
-					if (config.animateScale) {
-						scaleAnimation = animationDecimal;
-					}
-					if (config.animateRotate) {
-						rotateAnimation = animationDecimal;
-					}
-				}
-				correctedRotateAnimation = animationCorrection(rotateAnimation, data, config, i, -1, 0).mainVal;
-				if (!(typeof(data[i].value) == 'undefined')&& 1*data[i].value >=0) {
-					ctx.beginPath();
-					if(config.animationByData == "ByArc") {
-						endAngle=statData[i].startAngle+correctedRotateAnimation*statData[i].segmentAngle;
-						ctx.arc(midPieX, midPieY, scaleAnimation * pieRadius, statData[i].startAngle, endAngle);
-					} else if(config.animationByData) {
-						if(statData[i].startAngle-statData[i].firstAngle < correctedRotateAnimation*2*Math.PI ) {
-							endAngle=statData[i].endAngle;
-							if((statData[i].endAngle-statData[i].firstAngle)> correctedRotateAnimation*2*Math.PI) endAngle=statData[i].firstAngle+correctedRotateAnimation*2*Math.PI;							
-							ctx.arc(midPieX, midPieY, scaleAnimation * pieRadius, statData[i].startAngle, endAngle);
-							
-						}
-						else continue;
-					} else {
-						ctx.arc(midPieX, midPieY, scaleAnimation * pieRadius, statData[i].firstAngle+correctedRotateAnimation * (statData[i].startAngle-statData[i].firstAngle), statData[i].firstAngle+correctedRotateAnimation * (statData[i].endAngle-statData[i].firstAngle));
-					}
-					ctx.lineTo(midPieX, midPieY);
-					ctx.closePath();
-					ctx.fillStyle=setOptionValue("COLOR",ctx,data,statData,data[i].color,config.defaultFillColor,i,-1,{animationDecimal: animationDecimal, scaleAnimation : scaleAnimation} );
-					ctx.fill();
-					if (config.segmentShowStroke) {
-						ctx.lineWidth = config.segmentStrokeWidth;
-						ctx.strokeStyle = config.segmentStrokeColor;
-						ctx.stroke();
-					}
-				}
-			}
-			if (animationDecimal >= config.animationStopValue) {
-				for (var i = 0; i < data.length; i++) {
-					if (typeof(data[i].value) == 'undefined' || 1*data[i].value<0) continue;
-					if (setOptionValue("ANNOTATEDISPLAY",ctx,data,statData,undefined,config.annotateDisplay,i,-1,{nullValue : true})) {
-						jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["ARC", i,-1,statData];
-					}
-					if (setOptionValue("INGRAPHDATASHOW",ctx,data,statData,undefined,config.inGraphDataShow,i,-1,{nullValue : true}) && statData[i]["segmentAngle"] >= (Math.PI/180) * setOptionValue("INGRAPHDATAMINIMUMANGLE",ctx,data,statData,undefined,config.inGraphDataMinimumAngle,i,-1,{nullValue : true} )) {
-						if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 1) posAngle = statData[i].realStartAngle + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						else if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 2) posAngle = statData[i].realStartAngle - statData[i]["segmentAngle"] / 2 + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						else if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 3) posAngle = statData[i].realStartAngle - statData[i].segmentAngle + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						if (setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,i,-1,{nullValue : true} ) == 1) labelRadius = 0 + setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} );
-						else if (setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,i,-1,{nullValue : true} ) == 2) labelRadius = pieRadius / 2 + setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} );
-						else if (setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,i,-1,{nullValue : true} ) == 3) labelRadius = pieRadius + setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} );
-						ctx.save();
-						if (setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,-1,{nullValue: true  }) == "off-center") {
-							if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "left";
-							else ctx.textAlign = "right";
-						} else if (setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,-1,{nullValue: true  }) == "to-center") {
-							if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "right";
-							else ctx.textAlign = "left";
-						} else ctx.textAlign = setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,-1,{nullValue: true  });
-						if (setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,-1,{nullValue : true} ) == "off-center") {
-							if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "top";
-							else ctx.textBaseline = "bottom";
-						} else if (setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,-1,{nullValue : true} ) == "to-center") {
-							if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "bottom";
-							else ctx.textBaseline = "top";
-						} else ctx.textBaseline = setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,-1,{nullValue : true} );
-						ctx.font = setOptionValue("INGRAPHDATAFONTSTYLE",ctx,data,statData,undefined,config.inGraphDataFontStyle,i,-1,{nullValue : true} ) + ' ' + setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,-1,{nullValue : true} ) + 'px ' + setOptionValue("INGRAPHDATAFONTFAMILY",ctx,data,statData,undefined,config.inGraphDataFontFamily,i,-1,{nullValue : true} );
-						ctx.fillStyle = setOptionValue("INGRAPHDATAFONTCOLOR",ctx,data,statData,undefined,config.inGraphDataFontColor,i,-1,{nullValue : true} );
-						var dispString = tmplbis(setOptionValue("INGRAPHDATATMPL",ctx,data,statData,undefined,config.inGraphDataTmpl,i,-1,{nullValue : true} ), statData[i]);
-						ctx.translate(midPieX + labelRadius * Math.cos(posAngle), midPieY - labelRadius * Math.sin(posAngle));
-						if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxis") ctx.rotate(2 * Math.PI - posAngle);
-						else if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxisRotateLabels") {
-							if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI / 2 && (posAngle + 2 * Math.PI) % (2 * Math.PI) < 3 * Math.PI / 2) ctx.rotate(3 * Math.PI - posAngle);
-							else ctx.rotate(2 * Math.PI - posAngle);
-						} else ctx.rotate(setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) * (Math.PI / 180));
-						ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,-1,{nullValue : true} ),true);
-						ctx.restore();
-					}
-				}
-
-			}
-			if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Pie");
-		};
-
-		function calculateDrawingSize() {
-			midPieX = msr.leftNotUsableSize + (msr.availableWidth / 2);
-			midPieY = msr.topNotUsableSize + (msr.availableHeight / 2);
-			pieRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - 5;
-			// Computerange Pie Radius
-			if (isBooleanOptionTrue(undefined,config.inGraphDataShow) && setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,0,-1,{nullValue : true} ) == 3 && setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,0,-1,{nullValue: true  }) == "off-center" && setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,0,-1,{nullValue : true} ) == 0) {
-				pieRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,0,-1,{nullValue : true} ) - setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,0,-1,{nullValue: true} ) - 5;
-				var realCumulativeAngle = ((config.startAngle * (Math.PI / 180) + 2 * Math.PI) % (2*Math.PI) + 2*Math.PI) % (2*Math.PI);
-				for (var i = 0; i < data.length; i++) {
-					if (!(typeof(data[i].value) == 'undefined') && 1*data[i].value>=0) {
-						ctx.font = setOptionValue("INGRAPHDATAFONTSTYLE",ctx,data,statData,undefined,config.inGraphDataFontStyle,i,-1,{nullValue : true} ) + ' ' + setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,0,-1,{nullValue : true} ) + 'px ' + setOptionValue("INGRAPHDATAFONTFAMILY",ctx,data,statData,undefined,config.inGraphDataFontFamily,i,-1,{nullValue : true} );
-						if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 1) posAngle = realCumulativeAngle + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						else if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 2) posAngle = realCumulativeAngle - statData[i].segmentAngle / 2 + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						else if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 3) posAngle = realCumulativeAngle - statData[i].segmentAngle + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						realCumulativeAngle -= statData[i].segmentAngle;
-						var dispString = tmplbis(setOptionValue("INGRAPHDATATMPL",ctx,data,statData,undefined,config.inGraphDataTmpl,i,-1,{nullValue : true} ), statData[i]);
-						var textMeasurement = ctx.measureText(dispString).width;
-						var MaxRadiusX = Math.abs((msr.availableWidth / 2 - textMeasurement) / Math.cos(posAngle)) - setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} ) - 5;
-						if (MaxRadiusX < pieRadius) pieRadius = MaxRadiusX;
-					}
-				}
-			}
-			pieRadius = pieRadius * config.radiusScale;
-		};
-	};
-	var Doughnut = function(data, config, ctx) {
-		var msr, midPieX, midPieY, doughnutRadius;
-
-		ctx.tpchart="Doughnut";
-	        if (!init_and_start(ctx,data,config)) return;
-		var statData=initPassVariableData_part1(data,config,ctx);
-
-		var realCumulativeAngle = (((config.startAngle * (Math.PI / 180) + 2 * Math.PI) % (2 * Math.PI)) + 2* Math.PI) % (2* Math.PI) ; 
-		config.logarithmic = false;
-		config.logarithmic2 = false;
-		msr = setMeasures(data, config, ctx, height, width, "none", null, true, false, false, false, true, "Doughnut");
-		calculateDrawingSize();
-
-		var cutoutRadius = doughnutRadius * (config.percentageInnerCutout / 100);
-		if(doughnutRadius > 0) {
-			initPassVariableData_part2(statData,data,config,ctx,{midPosX : midPieX,midPosY : midPieY ,int_radius : cutoutRadius ,ext_radius : doughnutRadius});
-			animationLoop(config, null, drawPieSegments, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, midPieX, midPieY, midPieX - doughnutRadius, midPieY + doughnutRadius, data);
-		} else {
-			testRedraw(ctx,data,config);
-		}
-
-
-		function drawPieSegments(animationDecimal) {
-			var cumulativeAngle = (((-config.startAngle * (Math.PI / 180) + 2 * Math.PI) % (2 * Math.PI)) + 2* Math.PI) % (2* Math.PI) ; 
-
-			for (var i = 0; i < data.length; i++) {
-				var	scaleAnimation = 1,
-					rotateAnimation = 1;
-                	
-				if (config.animation) {
-					if (config.animateScale) {
-						scaleAnimation = animationDecimal;
-					}
-					if (config.animateRotate) {
-						rotateAnimation = animationDecimal;
-					}
-				}
-				correctedRotateAnimation = animationCorrection(rotateAnimation, data, config, i, -1, 0).mainVal;
-				if (!(typeof(data[i].value) == 'undefined') && 1*data[i].value >=0) {
-					ctx.beginPath();
-					if (config.animationByData == "ByArc") {
-						endAngle=statData[i].startAngle+correctedRotateAnimation*statData[i].segmentAngle;
-						ctx.arc(midPieX, midPieY, scaleAnimation * doughnutRadius, statData[i].startAngle, endAngle,false);
-						ctx.arc(midPieX, midPieY, scaleAnimation * cutoutRadius, endAngle,statData[i].startAngle, true);
-					} else if(config.animationByData) {
-						if(statData[i].startAngle-statData[i].firstAngle < correctedRotateAnimation*2*Math.PI ) {
-							endAngle=statData[i].endAngle;
-							if((statData[i].endAngle-statData[i].firstAngle)> correctedRotateAnimation*2*Math.PI) endAngle=statData[i].firstAngle+correctedRotateAnimation*2*Math.PI;							
-							ctx.arc(midPieX, midPieY, scaleAnimation * doughnutRadius, statData[i].startAngle, endAngle,false);
-							ctx.arc(midPieX, midPieY, scaleAnimation * cutoutRadius, endAngle,statData[i].startAngle, true);
-							
-						}
-						else continue;
-					} else {
-						ctx.arc(midPieX, midPieY, scaleAnimation * doughnutRadius, statData[i].firstAngle+correctedRotateAnimation * (statData[i].startAngle-statData[i].firstAngle), statData[i].firstAngle+correctedRotateAnimation * (statData[i].endAngle-statData[i].firstAngle),false);
-						ctx.arc(midPieX, midPieY, scaleAnimation * cutoutRadius, statData[i].firstAngle+correctedRotateAnimation * (statData[i].endAngle-statData[i].firstAngle), statData[i].firstAngle+correctedRotateAnimation * (statData[i].startAngle-statData[i].firstAngle), true);
-					}
-					ctx.closePath();
-					ctx.fillStyle=setOptionValue("COLOR",ctx,data,statData,data[i].color,config.defaultFillColor,i,-1,{animationDecimal: animationDecimal, scaleAnimation : scaleAnimation} );
-					ctx.fill();
-					if (config.segmentShowStroke) {
-						ctx.lineWidth = config.segmentStrokeWidth;
-						ctx.strokeStyle = config.segmentStrokeColor;
-						ctx.stroke();
-					}
-				}
-			}
-			if (animationDecimal >= config.animationStopValue) {
-				for (var i = 0; i < data.length; i++) {
-					if (typeof(data[i].value) == 'undefined' || 1*data[i].value<0) continue;
-					if(setOptionValue("ANNOTATEDISPLAY",ctx,data,statData,undefined,config.annotateDisplay,i,-1,{nullValue : true})) {
-						jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["ARC", i,-1,statData];
-					}
-					if (setOptionValue("INGRAPHDATASHOW",ctx,data,statData,undefined,config.inGraphDataShow,i,-1,{nullValue : true}) && statData[i].segmentAngle >= (Math.PI/180) * setOptionValue("INGRAPHDATAMINIMUMANGLE",ctx,data,statData,undefined,config.inGraphDataMinimumAngle,i,-1,{nullValue : true} )) {
-						if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 1) posAngle = statData[i].realStartAngle + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						else if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 2) posAngle = statData[i].realStartAngle- statData[i].segmentAngle / 2 + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						else if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 3) posAngle = statData[i].realStartAngle - statData[i].segmentAngle + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						if (setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,i,-1,{nullValue : true} ) == 1) labelRadius = cutoutRadius + setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} );
-						else if (setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,i,-1,{nullValue : true} ) == 2) labelRadius = cutoutRadius + (doughnutRadius - cutoutRadius) / 2 + setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} );
-						else if (setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,i,-1,{nullValue : true} ) == 3) labelRadius = doughnutRadius + setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} );
-						ctx.save();
-						if (setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,-1,{nullValue: true  }) == "off-center") {
-							if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "left";
-							else ctx.textAlign = "right";
-						} else if (setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,-1,{nullValue: true  }) == "to-center") {
-							if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "right";
-							else ctx.textAlign = "left";
-						} else ctx.textAlign = setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,-1,{nullValue: true  });
-						if (setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,-1,{nullValue : true} ) == "off-center") {
-							if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "top";
-							else ctx.textBaseline = "bottom";
-						} else if (setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,-1,{nullValue : true} ) == "to-center") {
-							if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "bottom";
-							else ctx.textBaseline = "top";
-						} else ctx.textBaseline = setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,-1,{nullValue : true} );
-						ctx.font = setOptionValue("INGRAPHDATAFONTSTYLE",ctx,data,statData,undefined,config.inGraphDataFontStyle,i,-1,{nullValue : true} ) + ' ' + setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,-1,{nullValue : true} ) + 'px ' + setOptionValue("INGRAPHDATAFONTFAMILY",ctx,data,statData,undefined,config.inGraphDataFontFamily,i,-1,{nullValue : true} );
-						ctx.fillStyle = setOptionValue("INGRAPHDATAFONTCOLOR",ctx,data,statData,undefined,config.inGraphDataFontColor,i,-1,{nullValue : true} );
-						var dispString = tmplbis(setOptionValue("INGRAPHDATATMPL",ctx,data,statData,undefined,config.inGraphDataTmpl,i,-1,{nullValue : true} ), statData[i]);
-						ctx.translate(midPieX + labelRadius * Math.cos(posAngle), midPieY - labelRadius * Math.sin(posAngle));
-						if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxis") ctx.rotate(2 * Math.PI - posAngle);
-						else if (setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) == "inRadiusAxisRotateLabels") {
-							if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI / 2 && (posAngle + 2 * Math.PI) % (2 * Math.PI) < 3 * Math.PI / 2) ctx.rotate(3 * Math.PI - posAngle);
-							else ctx.rotate(2 * Math.PI - posAngle);
-						} else ctx.rotate(setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,-1,{nullValue : true} ) * (Math.PI / 180));
-						ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,-1,{nullValue : true} ),true);
-						ctx.restore();
-					}
-				}
-			}
-			if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Doughnut");
-		};
-
-		function calculateDrawingSize() {
-			midPieX = msr.leftNotUsableSize + (msr.availableWidth / 2);
-			midPieY = msr.topNotUsableSize + (msr.availableHeight / 2);
-			doughnutRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - 5;
-			// Computerange Pie Radius
-			if (isBooleanOptionTrue(undefined,config.inGraphDataShow) && setOptionValue("INGRAPHDATARADIUSPOSITION",ctx,data,statData,undefined,config.inGraphDataRadiusPosition,0,-1,{nullValue : true} ) == 3 && setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,0,-1,{nullValue: true  }) == "off-center" && setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,0,-1,{nullValue : true} ) == 0) {
-				doughnutRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,0,-1,{nullValue : true} ) - setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,0,-1,{nullValue: true} ) - 5;
-				var realCumulativeAngle = (((config.startAngle * (Math.PI / 180) + 2 * Math.PI) % (2 * Math.PI)) + 2* Math.PI) % (2* Math.PI) ; 
-				var posAngle;
-				for (var i = 0; i < data.length; i++) {
-					if (!(typeof(data[i].value) == 'undefined') && 1*data[i].value>=0) {
-						ctx.font = setOptionValue("INGRAPHDATAFONTSTYLE",ctx,data,statData,undefined,config.inGraphDataFontStyle,i,-1,{nullValue : true} ) + ' ' + setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,-1,{nullValue : true} ) + 'px ' + setOptionValue("INGRAPHDATAFONTFAMILY",ctx,data,statData,undefined,config.inGraphDataFontFamily,i,-1,{nullValue : true} );
-						if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 1) posAngle = realCumulativeAngle + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						else if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 2) posAngle = realCumulativeAngle - statData[i].segmentAngle / 2 + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						else if (setOptionValue("INGRAPHDATAANGLEPOSITION",ctx,data,statData,undefined,config.inGraphDataAnglePosition,i,-1,{nullValue : true} ) == 3) posAngle = realCumulativeAngle - statData[i].segmentAngle + setOptionValue("INGRAPHDATAPADDINANGLE",ctx,data,statData,undefined,config.inGraphDataPaddingAngle,i,-1,{nullValue: true  }) * (Math.PI / 180);
-						realCumulativeAngle -= statData[i].segmentAngle;
-						var dispString = tmplbis(setOptionValue("INGRAPHDATATMPL",ctx,data,statData,undefined,config.inGraphDataTmpl,i,-1,{nullValue : true} ), statData[i]);
-						var textMeasurement = ctx.measureText(dispString).width;
-						var MaxRadiusX = Math.abs((msr.availableWidth / 2 - textMeasurement) / Math.cos(posAngle)) - setOptionValue("INGRAPHDATAPADDINGRADIUS",ctx,data,statData,undefined,config.inGraphDataPaddingRadius,i,-1,{nullValue: true} ) - 5;
-						if (MaxRadiusX < doughnutRadius) doughnutRadius = MaxRadiusX;
-					}
-				}
-			}
-			doughnutRadius = doughnutRadius * config.radiusScale;
-		};
-	};
-	var Line = function(data, config, ctx) {
-		var maxSize, scaleHop, scaleHop2, calculatedScale, calculatedScale2, labelHeight, scaleHeight, valueBounds, labelTemplateString, labelTemplateString2;
-		var valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, rotateLabels = 0,
-			msr;
-		var zeroY = 0;
-		var zeroY2 = 0;
-		ctx.tpchart="Line";
-	        if (!init_and_start(ctx,data,config)) return;
-		var statData=initPassVariableData_part1(data,config,ctx);
-		// adapt data when length is 1;
-		var mxlgt = 0;
-		for (var i = 0; i < data.datasets.length; i++) {statData[i][0].tpchart="Line";mxlgt = Max([mxlgt, data.datasets[i].data.length]);}
-		if (mxlgt == 1) {
-			if (typeof(data.labels[0]) == "string") data.labels = ["", data.labels[0], ""];
-			for (var i = 0; i < data.datasets.length; i++) {
-				if (typeof(data.datasets[i].data[0] != "undefined")) data.datasets[i].data = [undefined, data.datasets[i].data[0], undefined];
-			}
-		}
-		msr = setMeasures(data, config, ctx, height, width, "nihil", [""], false, false, true, true, config.datasetFill, "Line");
-		valueBounds = getValueBounds();
-		// true or fuzzy (error for negativ values (included 0))
-		if (config.logarithmic !== false) {
-			if (valueBounds.minValue <= 0) {
-				config.logarithmic = false;
-			}
-		}
-		if (config.logarithmic2 !== false) {
-			if (valueBounds.minValue2 <= 0) {
-				config.logarithmic2 = false;
-			}
-		}
-		// Check if logarithmic is meanigful
-		var OrderOfMagnitude = calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.maxValue) + 1)) - calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.minValue)));
-		if ((config.logarithmic == 'fuzzy' && OrderOfMagnitude < 4) || config.scaleOverride) {
-			config.logarithmic = false;
-		}
-		// Check if logarithmic is meanigful
-		var OrderOfMagnitude2 = calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.maxValue2) + 1)) - calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.minValue2)));
-		if ((config.logarithmic2 == 'fuzzy' && OrderOfMagnitude2 < 4) || config.scaleOverride2) {
-			config.logarithmic2 = false;
-		}
-		//Check and set the scale
-		labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
-		labelTemplateString2 = (config.scaleShowLabels2) ? config.scaleLabel2 : "";
-		if (!config.scaleOverride) {
-			if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
-				calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
-			}
-		} else {
-			var scaleStartValue= setOptionValue("SCALESTARTVALUE",ctx,data,statData,undefined,config.scaleStartValue,-1,-1,{nullValue : true} );
-			var scaleSteps =setOptionValue("SCALESTEPS",ctx,data,statData,undefined,config.scaleSteps,-1,-1,{nullValue : true} );
-			var scaleStepWidth = setOptionValue("SCALESTEPWIDTH",ctx,data,statData,undefined,config.scaleStepWidth,-1,-1,{nullValue : true} );
-			calculatedScale = {
-				steps: scaleSteps,
-				stepValue: scaleStepWidth,
-				graphMin: scaleStartValue,
-				graphMax: scaleStartValue + scaleSteps * scaleStepWidth,
-				labels: []
-			}
-			populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, scaleStartValue, calculatedScale.graphMax, scaleStepWidth);
-		}
-
-		if (valueBounds.dbAxis) {
-			if (!config.scaleOverride2) {
-				if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
-					calculatedScale2 = calculateScale(2, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue2, valueBounds.minValue2, labelTemplateString);
-				}
-			} else {
-				var scaleStartValue2= setOptionValue("SCALESTARTVALUE2",ctx,data,statData,undefined,config.scaleStartValue2,-1,-1,{nullValue : true} );
-				var scaleSteps2 =setOptionValue("SCALESTEPS2",ctx,data,statData,undefined,config.scaleSteps2,-1,-1,{nullValue : true} );
-				var scaleStepWidth2 = setOptionValue("SCALESTEPWIDTH2",ctx,data,statData,undefined,config.scaleStepWidth2,-1,-1,{nullValue : true} );
-
-				calculatedScale2 = {
-					steps: scaleSteps2,
-					stepValue: scaleStepWidth2,
-					graphMin: scaleStartValue2,
-					graphMax: scaleStartValue2 + scaleSteps2 * scaleStepWidth2,
-					labels: []
-				}
-				populateLabels(2, config, labelTemplateString2, calculatedScale2.labels, calculatedScale2.steps, scaleStartValue2, calculatedScale2.graphMax, scaleStepWidth2);
-			}
-		} else {
-			calculatedScale2 = {
-				steps: 0,
-				stepValue: 0,
-				graphMin: 0,
-				graphMax: 0,
-				labels: null
-			}
-		}
-		if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
-			msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, calculatedScale2.labels, false, false, true, true, config.datasetFill, "Line");
-			var prevHeight=msr.availableHeight;
-			msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop;
-			msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight;
-			scaleHop = Math.floor(msr.availableHeight / calculatedScale.steps);
-			scaleHop2 = Math.floor(msr.availableHeight / calculatedScale2.steps);
-			valueHop = Math.floor(msr.availableWidth / (data.labels.length - 1));
-			if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / (data.labels.length - 1));
-			msr.clrwidth = msr.clrwidth - (msr.availableWidth - (data.labels.length - 1) * valueHop);
-			msr.availableWidth = (data.labels.length - 1) * valueHop;
-			msr.availableHeight = (calculatedScale.steps) * scaleHop;
-			msr.xLabelPos+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight));
-			msr.clrheight+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight));
-  			yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft;
-			xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop;
-			drawLabels();
-			if (valueBounds.minValue < 0) {
-				zeroY = calculateOffset(config.logarithmic, 0, calculatedScale, scaleHop);
-			}
-			if (valueBounds.minValue2 < 0) {
-				zeroY2 = calculateOffset(config.logarithmic2, 0, calculatedScale2, scaleHop2);
-			}
-			initPassVariableData_part2(statData,data,config,ctx,{
-				xAxisPosY : xAxisPosY,
-				yAxisPosX : yAxisPosX,
-				valueHop : valueHop,
-				nbValueHop : data.labels.length - 1,
-				scaleHop : scaleHop,
-				zeroY : zeroY,
-				calculatedScale : calculatedScale,
-				logarithmic  : config.logarithmic,
-				scaleHop2: scaleHop2,
-				zeroY2: zeroY2,
-				msr : msr,
-				calculatedScale2: calculatedScale2,
-				logarithmic2: config.logarithmic2} );
-			animationLoop(config, drawScale, drawLines, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data);
-		} else {
-			testRedraw(ctx,data,config);
-		}
-
-
-		function drawLines(animPc) {
-		
-			drawLinesDataset(animPc, data, config, ctx, statData,{xAxisPosY : xAxisPosY,yAxisPosX : yAxisPosX, valueHop : valueHop, nbValueHop : data.labels.length - 1 });
-			if (animPc >= 1) {
-				if (typeof drawMath == "function") {
-					drawMath(ctx, config, data, msr, {
-						xAxisPosY: xAxisPosY,
-						yAxisPosX: yAxisPosX,
-						valueHop: valueHop,
-						scaleHop: scaleHop,
-						zeroY: zeroY,
-						calculatedScale: calculatedScale,
-						calculateOffset: calculateOffset,
-						statData : statData
-
-					});
-				}
-			}
-			if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Line");
-		};
-
-		function drawScale() {
-			//X axis line
-			// if the xScale should be drawn
-			if (config.drawXScaleLine !== false) {
-				for (var s = 0; s < config.drawXScaleLine.length; s++) {
-					// get special lineWidth and lineColor for this xScaleLine
-					ctx.lineWidth = config.drawXScaleLine[s].lineWidth ? config.drawXScaleLine[s].lineWidth : config.scaleLineWidth;
-					ctx.strokeStyle = config.drawXScaleLine[s].lineColor ? config.drawXScaleLine[s].lineColor : config.scaleLineColor;
-					ctx.beginPath();
-					var yPosXScale;
-					switch (config.drawXScaleLine[s].position) {
-						case "bottom":
-							yPosXScale = xAxisPosY;
-							break;
-						case "top":
-							yPosXScale = xAxisPosY - msr.availableHeight - config.scaleTickSizeTop;
-							break;
-						case "0":
-						case 0:
-							// check if zero exists
-							if (zeroY != 0) {
-								yPosXScale = xAxisPosY - zeroY;
-							}
-							break;
-					}
-					// draw the scale line
-					ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, yPosXScale);
-					ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, yPosXScale);
-					ctx.stroke();
-				}
-			}
-			for (var i = 0; i < data.labels.length; i++) {
-				ctx.beginPath();
-				ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom);
-				ctx.lineWidth = config.scaleGridLineWidth;
-				ctx.strokeStyle = config.scaleGridLineColor;
-				//Check i isnt 0, so we dont go over the Y axis twice.
-				if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) {
-					ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
-				} else {
-					ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY);
-				}
-				ctx.stroke();
-			}
-			//Y axis
-			ctx.lineWidth = config.scaleLineWidth;
-			ctx.strokeStyle = config.scaleLineColor;
-			ctx.beginPath();
-			ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom);
-			ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
-			ctx.stroke();
-			for (var j = 0; j < calculatedScale.steps; j++) {
-				ctx.beginPath();
-				ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop));
-				ctx.lineWidth = config.scaleGridLineWidth;
-				ctx.strokeStyle = config.scaleGridLineColor;
-				if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) {
-					ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY - ((j + 1) * scaleHop));
-				} else {
-					ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop));
-				}
-				ctx.stroke();
-			}
-		};
-
-		function drawLabels() {
-			ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
-			//X Labels     
-			if (config.xAxisTop || config.xAxisBottom) {
-				ctx.textBaseline = "top";
-				if (msr.rotateLabels > 90) {
-					ctx.save();
-					ctx.textAlign = "left";
-				} else if (msr.rotateLabels > 0) {
-					ctx.save();
-					ctx.textAlign = "right";
-				} else {
-					ctx.textAlign = "center";
-				}
-				ctx.fillStyle = config.scaleFontColor;
-				if (config.xAxisBottom) {
-					for (var i = 0; i < data.labels.length; i++) {
-						ctx.save();
-						if (msr.rotateLabels > 0) {
-							ctx.translate(yAxisPosX + i * valueHop - msr.highestXLabel / 2, msr.xLabelPos);
-							ctx.rotate(-(msr.rotateLabels * (Math.PI / 180)));
-							ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), 0, 0, ctx.textBaseline, config.scaleFontSize,true);
-						} else {
-							ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), yAxisPosX + i * valueHop, msr.xLabelPos, ctx.textBaseline, config.scaleFontSize,true);
-						}
-						ctx.restore();
-					}
-				}
-			}
-			//Y Labels
-			ctx.textAlign = "right";
-			ctx.textBaseline = "middle";
-			for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale.steps; j++) {
-				if (config.scaleShowLabels) {
-					if (config.yAxisLeft) {
-						ctx.textAlign = "right";
-						ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize,true);
-					}
-					if (config.yAxisRight && !valueBounds.dbAxis) {
-						ctx.textAlign = "left";
-						ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize,true);
-					}
-				}
-			}
-			if (config.yAxisRight && valueBounds.dbAxis) {
-				for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale2.steps; j++) {
-					if (config.scaleShowLabels) {
-						ctx.textAlign = "left";
-						ctx.fillTextMultiLine(calculatedScale2.labels[j + 1], yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop2), ctx.textBaseline, config.scaleFontSize,true);
-					}
-				}
-			}
-		};
-
-		function getValueBounds() {
-			var upperValue = -Number.MAX_VALUE;
-			var lowerValue = Number.MAX_VALUE;
-			var upperValue2 = -Number.MAX_VALUE;
-			var lowerValue2 = Number.MAX_VALUE;
-			var secondAxis = false;
-			var firstAxis = false;
-			for (var i = 0; i < data.datasets.length; i++) {
-				var mathFctName = data.datasets[i].drawMathDeviation;
-				var mathValueHeight = 0;
-				if (typeof eval(mathFctName) == "function") {
-					var parameter = {
-						data: data,
-						datasetNr: i
-					};
-					mathValueHeight = window[mathFctName](parameter);
-				}
-				for (var j = 0; j < data.datasets[i].data.length; j++) {
-					if(typeof data.datasets[i].data[j] == "undefined") continue;
-					if (data.datasets[i].axis == 2) {
-						secondAxis = true;
-						if (1 * data.datasets[i].data[j] + mathValueHeight > upperValue2) {
-							upperValue2 = 1 * data.datasets[i].data[j] + mathValueHeight
-						};
-						if (1 * data.datasets[i].data[j] - mathValueHeight < lowerValue2) {
-							lowerValue2 = 1 * data.datasets[i].data[j] - mathValueHeight
-						};
-					} else {
-						firstAxis = true;
-						if (1 * data.datasets[i].data[j] + mathValueHeight > upperValue) {
-							upperValue = 1 * data.datasets[i].data[j] + mathValueHeight
-						};
-						if (1 * data.datasets[i].data[j] - mathValueHeight < lowerValue) {
-							lowerValue = 1 * data.datasets[i].data[j] - mathValueHeight
-						};
-					}
-				}
-			};
-			if(upperValue<lowerValue){upperValue=0;lowerValue=0;}
-			if (Math.abs(upperValue - lowerValue) < config.zeroValue) {
-				if(Math.abs(upperValue)< config.zeroValue) upperValue = .9;
-				if(upperValue>0) {
-					upperValue=upperValue*1.1;
-					lowerValue=lowerValue*0.9;
-				} else {
-					upperValue=upperValue*0.9;
-					lowerValue=lowerValue*1.1;
-				}
-				
-			}
-			if(typeof config.graphMin=="function")lowerValue= setOptionValue("GRAPHMIN",ctx,data,statData,undefined,config.graphMin,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
-			if(typeof config.graphMax=="function") upperValue= setOptionValue("GRAPHMAX",ctx,data,statData,undefined,config.graphMax,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMax)) upperValue = config.graphMax;
-
-			if (secondAxis) {
-				if(upperValue2<lowerValue2){upperValue2=0;lowerValue2=0;}
-				if (Math.abs(upperValue2 - lowerValue2) < config.zeroValue) {
-					if(Math.abs(upperValue2)< config.zeroValue) upperValue2 = .9;
-					if(upperValue2>0) {
-						upperValue2=upperValue2*1.1;
-						lowerValue2=lowerValue2*0.9;
-					} else {
-						upperValue2=upperValue2*0.9;
-						lowerValue2=lowerValue2*1.1;
-					}
-				}
-				if(typeof config.graphMin2=="function")lowerValue2= setOptionValue("GRAPHMIN",ctx,data,statData,undefined,config.graphMin2,-1,-1,{nullValue : true})
-				else if (!isNaN(config.graphMin2)) lowerValue2 = config.graphMin2;
-				if(typeof config.graphMax2=="function") upperValue2= setOptionValue("GRAPHMAX",ctx,data,statData,undefined,config.graphMax2,-1,-1,{nullValue : true})
-				else if (!isNaN(config.graphMax2)) upperValue2 = config.graphMax2;
-			}
-
-			if (!firstAxis && secondAxis) {
-				upperValue = upperValue2;
-				lowerValue = lowerValue2;
-			}
-			
-			labelHeight = config.scaleFontSize;
-			scaleHeight = msr.availableHeight;
-			var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66)));
-			var minSteps = Math.floor((scaleHeight / labelHeight * 0.5));
-			return {
-				maxValue: upperValue,
-				minValue: lowerValue,
-				maxValue2: upperValue2,
-				minValue2: lowerValue2,
-				dbAxis: secondAxis,
-				maxSteps: maxSteps,
-				minSteps: minSteps
-			};
-		};
-	};
-	var StackedBar = function(data, config, ctx) {
-		var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, barWidth, rotateLabels = 0,
-			msr;
-		ctx.tpchart="StackedBar";
-	        if (!init_and_start(ctx,data,config)) return;
-		var statData=initPassVariableData_part1(data,config,ctx);
-
-		config.logarithmic = false;
-		msr = setMeasures(data, config, ctx, height, width, "nihil", [""], true, false, true, true, true, "StackedBar");
-		valueBounds = getValueBounds();
-		
-		if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
-			//Check and set the scale
-			labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
-			if (!config.scaleOverride) {
-				calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
-				msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, true, true, true, "StackedBar");
-			} else {
-				var scaleStartValue= setOptionValue("SCALESTARTVALUE",ctx,data,statData,undefined,config.scaleStartValue,-1,-1,{nullValue : true} );
-				var scaleSteps =setOptionValue("SCALESTEPS",ctx,data,statData,undefined,config.scaleSteps,-1,-1,{nullValue : true} );
-				var scaleStepWidth = setOptionValue("SCALESTEPWIDTH",ctx,data,statData,undefined,config.scaleStepWidth,-1,-1,{nullValue : true} );
-
-				calculatedScale = {
-					steps: scaleSteps,
-					stepValue: scaleStepWidth,
-					graphMin: scaleStartValue,
-					labels: []
-				}
-				for (var i = 0; i <= calculatedScale.steps; i++) {
-					if (labelTemplateString) {
-						calculatedScale.labels.push(tmpl(labelTemplateString, {
-							value: fmtChartJS(config, 1 * ((scaleStartValue + (scaleStepWidth * i)).toFixed(getDecimalPlaces(scaleStepWidth))), config.fmtYLabel)
-						}));
-					}
-				}
-				msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, true, true, true, "StackedBar");
-			}
-       	
-			var prevHeight=msr.availableHeight;
-       	
-			msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop;
-			msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight;
-			scaleHop = Math.floor(msr.availableHeight / calculatedScale.steps);
-			valueHop = Math.floor(msr.availableWidth / (data.labels.length));
-			if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / data.labels.length);
-			msr.clrwidth = msr.clrwidth - (msr.availableWidth - ((data.labels.length) * valueHop));
-			msr.availableWidth = (data.labels.length) * valueHop;
-			msr.availableHeight = (calculatedScale.steps) * scaleHop;
-			msr.xLabelPos+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight));
-			msr.clrheight+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight));
-       	
-			yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft;
-			xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop;
-			barWidth = (valueHop - config.scaleGridLineWidth * 2 - (config.barValueSpacing * 2) - (config.barDatasetSpacing * data.datasets.length - 1) - (config.barStrokeWidth / 2) - 1);
-			if(barWidth>=0 && barWidth<=1)barWidth=1;
-			if(barWidth<0 && barWidth>=-1)barWidth=-1;
-       	
-			drawLabels();
-			initPassVariableData_part2(statData,data,config,ctx,{ 
-				calculatedScale : calculatedScale,
-				scaleHop : scaleHop,
-				valueHop : valueHop,
-				yAxisPosX : yAxisPosX,
-				xAxisPosY : xAxisPosY,
-				barWidth : barWidth
-			 });
-			animationLoop(config, drawScale, drawBars, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data);
-		} else {
-			testRedraw(ctx,data,config);
-		}
-		function drawBars(animPc) {
-			ctx.lineWidth = config.barStrokeWidth;
-			for (var i = 0; i < data.datasets.length; i++) {
-				for (var j = 0; j < data.datasets[i].data.length; j++) {
-					var currentAnimPc = animationCorrection(animPc, data, config, i, j, 1).animVal;
-					if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1;
-					if ((typeof data.datasets[i].data[j] == 'undefined') || 1*data.datasets[i].data[j] == 0 ) continue;
-					if(config.animationByDataset) {
-						var botBar=statData[i][j].yPosBottom;
-						var topBar=statData[i][j].yPosTop;
-						topBar=botBar+currentAnimPc*(topBar-botBar);
-					} else {
-						var botBar=statData[statData[i][j].firstNotMissing][j].yPosBottom - currentAnimPc*(statData[statData[i][j].firstNotMissing][j].yPosBottom-statData[i][j].yPosBottom);
-						var topBar=statData[statData[i][j].firstNotMissing][j].yPosBottom - currentAnimPc*(statData[statData[i][j].firstNotMissing][j].yPosBottom-statData[i][j].yPosTop);
-					}
-					ctx.fillStyle=setOptionValue("COLOR",ctx,data,statData,data.datasets[i].fillColor,config.defaultFillColor,i,j,{animationValue: currentAnimPc, xPosLeft : statData[i][j].xPosLeft, yPosBottom : botBar, xPosRight : statData[i][j].xPosRight, yPosTop : topBar} );
-					ctx.strokeStyle=setOptionValue("STROKECOLOR",ctx,data,statData,data.datasets[i].strokeColor,config.defaultStrokeColor,i,j,{nullvalue : null} );
-
-					if(currentAnimPc !=0 && botBar!=topBar) {
-						ctx.beginPath();
-						ctx.moveTo(statData[i][j].xPosLeft, botBar);
-						ctx.lineTo(statData[i][j].xPosLeft, topBar);
-						ctx.lineTo(statData[i][j].xPosRight, topBar);
-						ctx.lineTo(statData[i][j].xPosRight, botBar);
-						if (config.barShowStroke) ctx.stroke();
-						ctx.closePath();
-						ctx.fill();
-					}
-				}
-			}
-			if (animPc >= config.animationStopValue) {
-				var 	yPos = 0,
-					xPos = 0;
-				for (var i = 0; i < data.datasets.length; i++) {
-					for (var j = 0; j < data.datasets[i].data.length; j++) {
-						if (typeof(data.datasets[i].data[j]) == 'undefined') continue;
-						if(setOptionValue("ANNOTATEDISPLAY",ctx,data,statData,undefined,config.annotateDisplay,i,j,{nullValue : true})) {
-							jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", i, j, statData];
-						}
-						if(setOptionValue("INGRAPHDATASHOW",ctx,data,statData,undefined,config.inGraphDataShow,i,j,{nullValue : true})) {
-							ctx.save();
-							ctx.textAlign = setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,j,{nullValue: true  });
-							ctx.textBaseline = setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,j,{nullValue : true} );
-							ctx.font = setOptionValue("INGRAPHDATAFONTSTYLE",ctx,data,statData,undefined,config.inGraphDataFontStyle,i,j,{nullValue : true} ) + ' ' + setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,j,{nullValue : true} ) + 'px ' + setOptionValue("INGRAPHDATAFONTFAMILY",ctx,data,statData,undefined,config.inGraphDataFontFamily,i,j,{nullValue : true} );
-							ctx.fillStyle = setOptionValue("INGRAPHDATAFONTCOLOR",ctx,data,statData,undefined,config.inGraphDataFontColor,i,j,{nullValue : true} );
-							var dispString = tmplbis(setOptionValue("INGRAPHDATATMPL",ctx,data,statData,undefined,config.inGraphDataTmpl,i,j,{nullValue : true} ), statData[i][j]);
-							ctx.beginPath();
-							ctx.beginPath();
-							yPos = 0;
-							xPos = 0;
-							if (setOptionValue("INGRAPHDATAXPOSITION",ctx,data,statData,undefined,config.inGraphDataXPosition,i,j,{nullValue : true} ) == 1) {
-								xPos = statData[i][j].xPosLeft + setOptionValue("INGRAPHDATAPADDINGX",ctx,data,statData,undefined,config.inGraphDataPaddingX,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAXPOSITION",ctx,data,statData,undefined,config.inGraphDataXPosition,i,j,{nullValue : true} ) == 2) {
-								xPos = statData[i][j].xPosLeft + barWidth / 2 + setOptionValue("INGRAPHDATAPADDINGX",ctx,data,statData,undefined,config.inGraphDataPaddingX,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAXPOSITION",ctx,data,statData,undefined,config.inGraphDataXPosition,i,j,{nullValue : true} ) == 3) {
-								xPos = statData[i][j].xPosLeft+ barWidth + setOptionValue("INGRAPHDATAPADDINGX",ctx,data,statData,undefined,config.inGraphDataPaddingX,i,j,{nullValue : true} );
-							}
-							if (setOptionValue("INGRAPHDATAYPOSITION",ctx,data,statData,undefined,config.inGraphDataYPosition,i,j,{nullValue : true} ) == 1) {
-								yPos = statData[i][j].yPosBottom - setOptionValue("INGRAPHDATAPADDINGY",ctx,data,statData,undefined,config.inGraphDataPaddingY,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAYPOSITION",ctx,data,statData,undefined,config.inGraphDataYPosition,i,j,{nullValue : true} ) == 2) {
-								yPos = (statData[i][j].yPosTop + statData[i][j].yPosBottom)/2 - setOptionValue("INGRAPHDATAPADDINGY",ctx,data,statData,undefined,config.inGraphDataPaddingY,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAYPOSITION",ctx,data,statData,undefined,config.inGraphDataYPosition,i,j,{nullValue : true} ) == 3) {
-								yPos = statData[i][j].yPosTop - setOptionValue("INGRAPHDATAPADDINGY",ctx,data,statData,undefined,config.inGraphDataPaddingY,i,j,{nullValue : true} );
-							}
-							if(yPos>msr.topNotUsableSize) {
-								ctx.translate(xPos, yPos);
-								ctx.rotate(setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,j,{nullValue : true} ) * (Math.PI / 180));
-								ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,j,{nullValue : true} ),true);
-							}
-							ctx.restore();
-						}
-					}
-				}
-			}
-			if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"StackedBar");
-		};
-
-		function drawScale() {
-			//X axis line                                                          
-			ctx.lineWidth = config.scaleLineWidth;
-			ctx.strokeStyle = config.scaleLineColor;
-			ctx.beginPath();
-			ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY);
-			ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY);
-			ctx.stroke();
-			for (var i = 0; i < data.labels.length; i++) {
-				ctx.beginPath();
-				ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom);
-				ctx.lineWidth = config.scaleGridLineWidth;
-				ctx.strokeStyle = config.scaleGridLineColor;
-				//Check i isnt 0, so we dont go over the Y axis twice.
-				if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) {
-					ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
-				} else {
-					ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY);
-				}
-				ctx.stroke();
-			}
-			//Y axis
-			ctx.lineWidth = config.scaleLineWidth;
-			ctx.strokeStyle = config.scaleLineColor;
-			ctx.beginPath();
-			ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom);
-			ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
-			ctx.stroke();
-			for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale.steps; j++) {
-				ctx.beginPath();
-				ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop));
-				ctx.lineWidth = config.scaleGridLineWidth;
-				ctx.strokeStyle = config.scaleGridLineColor;
-				if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) {
-					ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY - ((j + 1) * scaleHop));
-				} else {
-					ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop));
-				}
-				ctx.stroke();
-			}
-		};
-
-		function drawLabels() {
-			ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
-			//X axis labels                                                          
-			if (config.xAxisTop || config.xAxisBottom) {
-				ctx.textBaseline = "top";
-				if (msr.rotateLabels > 90) {
-					ctx.save();
-					ctx.textAlign = "left";
-				} else if (msr.rotateLabels > 0) {
-					ctx.save();
-					ctx.textAlign = "right";
-				} else {
-					ctx.textAlign = "center";
-				}
-				ctx.fillStyle = config.scaleFontColor;
-				if (config.xAxisBottom) {
-					for (var i = 0; i < data.labels.length; i++) {
-						ctx.save();
-						if (msr.rotateLabels > 0) {
-							ctx.translate(yAxisPosX + config.barValueSpacing + i * valueHop + (barWidth / 2) - msr.highestXLabel / 2, msr.xLabelPos);
-							ctx.rotate(-(msr.rotateLabels * (Math.PI / 180)));
-							ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), 0, 0, ctx.textBaseline, config.scaleFontSize,true);
-						} else {
-							ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), yAxisPosX + config.barValueSpacing + i * valueHop + (barWidth / 2), msr.xLabelPos, ctx.textBaseline, config.scaleFontSize,true);
-						}
-						ctx.restore();
-					}
-				}
-			}
-			//Y axis
-			ctx.textAlign = "right";
-			ctx.textBaseline = "middle";
-			for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale.steps; j++) {
-				if (config.scaleShowLabels) {
-					if (config.yAxisLeft) {
-						ctx.textAlign = "right";
-						ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize,true);
-					}
-					if (config.yAxisRight) {
-						ctx.textAlign = "left";
-						ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize,true);
-					}
-				}
-			}
-		};
-
-		function getValueBounds() {
-			var upperValue = -Number.MAX_VALUE;
-			var lowerValue = Number.MAX_VALUE;
-			var minvl = new Array(data.datasets.length);
-			var maxvl = new Array(data.datasets.length);
-			for (var i = 0; i < data.datasets.length; i++) {
-				for (var j = 0; j < data.datasets[i].data.length; j++) {
-					var k = i;
-					var tempp = 0;
-					var tempn = 0;
-					if (!(typeof(data.datasets[0].data[j]) == 'undefined')) {
-						if(1 * data.datasets[0].data[j] > 0) {
-							tempp += 1 * data.datasets[0].data[j];
-							if (tempp > upperValue) {
-								upperValue = tempp;
-							};
-							if (tempp < lowerValue) {
-								lowerValue = tempp;
-							};
-						} else {
-							tempn += 1 * data.datasets[0].data[j];
-							if (tempn > upperValue) {
-								upperValue = tempn;
-							};
-							if (tempn < lowerValue) {
-								lowerValue = tempn;
-							};
-						}
-					}
-					while (k > 0) { //get max of stacked data
-						if (!(typeof(data.datasets[k].data[j]) == 'undefined')) {
-							if(1 * data.datasets[k].data[j] > 0) {
-								tempp += 1 * data.datasets[k].data[j];
-								if (tempp > upperValue) {
-									upperValue = tempp;
-								};
-								if (tempp < lowerValue) {
-									lowerValue = tempp;
-								};
-							} else {
-								tempn += 1 * data.datasets[k].data[j];
-								if (tempn > upperValue) {
-									upperValue = tempn;
-								};
-								if (tempn < lowerValue) {
-									lowerValue = tempn;
-								};
-							}
-						}
-						k--;
-					}
-				}
-			};
-			if(typeof config.graphMin=="function")lowerValue= setOptionValue("GRAPHMIN",ctx,data,statData,undefined,config.graphMin,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
-			if(typeof config.graphMax=="function") upperValue= setOptionValue("GRAPHMAX",ctx,data,statData,undefined,config.graphMax,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMax)) upperValue = config.graphMax;
-			if(upperValue<lowerValue){upperValue=0;lowerValue=0;}
-			if (Math.abs(upperValue - lowerValue) < config.zeroValue) {
-				if(Math.abs(upperValue)< config.zeroValue) upperValue = .9;
-				if(upperValue>0) {
-					upperValue=upperValue*1.1;
-					lowerValue=lowerValue*0.9;
-				} else {
-					upperValue=upperValue*0.9;
-					lowerValue=lowerValue*1.1;
-				}
-			}
-			labelHeight = config.scaleFontSize;
-			scaleHeight = msr.availableHeight;
-			var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66)));
-			var minSteps = Math.floor((scaleHeight / labelHeight * 0.5));
-			return {
-				maxValue: upperValue,
-				minValue: lowerValue,
-				maxSteps: maxSteps,
-				minSteps: minSteps
-			};
-		};
-	};
-	/**
-	 * Reverse the data structure for horizontal charts
-	 * - reverse labels and every array inside datasets
-	 * @param {object} data datasets and labels for the chart
-	 * @return return the reversed data
-	 */
-	function reverseData(data) {
-		data.labels = data.labels.reverse();
-		for (var i = 0; i < data.datasets.length; i++) {
-			for (var key in data.datasets[i]) {
-				if (Array.isArray(data.datasets[i][key])) {
-					data.datasets[i][key] = data.datasets[i][key].reverse();
-				}
-			}
-		}
-		return data;
-	};
-	var HorizontalStackedBar = function(data, config, ctx) {
-		var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, barWidth, rotateLabels = 0,
-			msr;
-
-		if (config.reverseOrder && typeof ctx.reversed == "undefined") {
-			ctx.reversed=true;
-			data = reverseData(data);
-		}
-
-		ctx.tpchart="HorizontalStackedBar";
-	        if (!init_and_start(ctx,data,config)) return;
-		var statData=initPassVariableData_part1(data,config,ctx);
-
-		config.logarithmic = false;
-		msr = setMeasures(data, config, ctx, height, width, "nihil", [""], true, true, true, true, true, "HorizontalStackedBar");
- 		valueBounds = getValueBounds();
-		
-		if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
-			//Check and set the scale
-			labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
-			if (!config.scaleOverride) {
-				calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
-				msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, true, true, true, true, "HorizontalStackedBar");
-			} else {
-				var scaleStartValue= setOptionValue("SCALESTARTVALUE",ctx,data,statData,undefined,config.scaleStartValue,-1,-1,{nullValue : true} );
-				var scaleSteps =setOptionValue("SCALESTEPS",ctx,data,statData,undefined,config.scaleSteps,-1,-1,{nullValue : true} );
-				var scaleStepWidth = setOptionValue("SCALESTEPWIDTH",ctx,data,statData,undefined,config.scaleStepWidth,-1,-1,{nullValue : true} );
-
-				calculatedScale = {
-					steps: scaleSteps,
-					stepValue: scaleStepWidth,
-					graphMin: scaleStartValue,
-					labels: []
-				}
-				for (var i = 0; i <= calculatedScale.steps; i++) {
-					if (labelTemplateString) {
-						calculatedScale.labels.push(tmpl(labelTemplateString, {
-							value: fmtChartJS(config, 1 * ((scaleStartValue + (scaleStepWidth * i)).toFixed(getDecimalPlaces(scaleStepWidth))), config.fmtYLabel)
-						}));
-					}
-				}
-				msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, true, true, true, true, "HorizontalStackedBar");
-			}
-			msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop;
-			msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight;
-			scaleHop = Math.floor(msr.availableHeight / data.labels.length);
-			valueHop = Math.floor(msr.availableWidth / (calculatedScale.steps));
-			if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / (calculatedScale.steps));
-			msr.clrwidth = msr.clrwidth - (msr.availableWidth - (calculatedScale.steps * valueHop));
-			msr.availableWidth = (calculatedScale.steps) * valueHop;
-			msr.availableHeight = (data.labels.length) * scaleHop;
-			yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft;
-			xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop;
-			barWidth = (scaleHop - config.scaleGridLineWidth * 2 - (config.barValueSpacing * 2) - (config.barDatasetSpacing * data.datasets.length - 1) - (config.barStrokeWidth / 2) - 1);
-			if(barWidth>=0 && barWidth<=1)barWidth=1;
-			if(barWidth<0 && barWidth>=-1)barWidth=-1;
-			drawLabels();
-			zeroY=  HorizontalCalculateOffset(0 , calculatedScale, scaleHop);
-			initPassVariableData_part2(statData,data,config,ctx,{ 
-				yAxisPosX : yAxisPosX,
-				xAxisPosY : xAxisPosY,
-				barWidth : barWidth,
-				zeroY : zeroY,
-				scaleHop : scaleHop,
-				valueHop : valueHop,
-				calculatedScale : calculatedScale
-			});
-			
-			animationLoop(config, drawScale, drawBars, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data);
-		} else {
-			testRedraw(ctx,data,config);
-		}
-		function HorizontalCalculateOffset(val, calculatedScale, scaleHop) {
-			var outerValue = calculatedScale.steps * calculatedScale.stepValue;
-			var adjustedValue = val - calculatedScale.graphMin;
-			var scalingFactor = CapValue(adjustedValue / outerValue, 1, 0);
-			return (scaleHop * calculatedScale.steps) * scalingFactor;
-		};
-
-		function drawBars(animPc) {
-			ctx.lineWidth = config.barStrokeWidth;
-			for (var i = 0; i < data.datasets.length; i++) {
-				for (var j = 0; j < data.datasets[i].data.length; j++) {
-					var currentAnimPc = animationCorrection(animPc, data, config, i, j, 1).animVal;
-					if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1;
-					if ((typeof(data.datasets[i].data[j]) == 'undefined') || 1*data.datasets[i].data[j] == 0 ) continue;
-					if(config.animationByDataset) {
-						var leftBar= statData[i][j].xPosLeft;
-						var rightBar= statData[i][j].xPosRight;
-						rightBar=leftBar+currentAnimPc*(rightBar-leftBar);
-					} else {
-						var leftBar=statData[statData[i][j].firstNotMissing][j].xPosLeft + currentAnimPc*(statData[i][j].xPosLeft-statData[statData[i][j].firstNotMissing][j].xPosLeft);
-						var rightBar=statData[statData[i][j].firstNotMissing][j].xPosLeft + currentAnimPc*(statData[i][j].xPosRight-statData[statData[i][j].firstNotMissing][j].xPosLeft);
-					}
-					ctx.fillStyle=setOptionValue("COLOR",ctx,data,statData,data.datasets[i].fillColor,config.defaultFillColor,i,j,{animationValue: currentAnimPc, xPosLeft : leftBar, yPosBottom : statData[i][j].yPosBottom, xPosRight : rightBar, yPosTop : statData[i][j].yPosBottom} );
-
-					ctx.strokeStyle=setOptionValue("STROKECOLOR",ctx,data,statData,data.datasets[i].strokeColor,config.defaultStrokeColor,i,j,{nullvalue : null} );
-
-					if(currentAnimPc !=0 && statData[i][j].xPosLeft!=statData[i][j].xPosRight ) {
-						ctx.beginPath();
-						ctx.moveTo(leftBar, statData[i][j].yPosTop);
-						ctx.lineTo(rightBar, statData[i][j].yPosTop);
-						ctx.lineTo(rightBar, statData[i][j].yPosBottom);
-						ctx.lineTo(leftBar, statData[i][j].yPosBottom);
-						ctx.lineTo(leftBar, statData[i][j].yPosTop);
-						if (config.barShowStroke) ctx.stroke();
-						ctx.closePath();
-						ctx.fill();
-					}
-				}
-			}
-			if (animPc >= config.animationStopValue) {
-				var yPos = 0,
-					xPos = 0;
-				for (var i = 0; i < data.datasets.length; i++) {
-					for (var j = 0; j < data.datasets[i].data.length; j++) {
-						if ((typeof(data.datasets[i].data[j]) == 'undefined')) continue;
-						if (setOptionValue("ANNOTATEDISPLAY",ctx,data,statData,undefined,config.annotateDisplay,i,j,{nullValue : true})) {
-							jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", i ,j, statData];
-						}
-						if(setOptionValue("INGRAPHDATASHOW",ctx,data,statData,undefined,config.inGraphDataShow,i,j,{nullValue : true})) {
-							ctx.save();
-							ctx.textAlign = setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,j,{nullValue: true  });
-							ctx.textBaseline = setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,j,{nullValue : true} );
-							ctx.font = setOptionValue("INGRAPHDATAFONTSTYLE",ctx,data,statData,undefined,config.inGraphDataFontStyle,i,j,{nullValue : true} ) + ' ' + setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,j,{nullValue : true} ) + 'px ' + setOptionValue("INGRAPHDATAFONTFAMILY",ctx,data,statData,undefined,config.inGraphDataFontFamily,i,j,{nullValue : true} );
-							ctx.fillStyle = setOptionValue("INGRAPHDATAFONTCOLOR",ctx,data,statData,undefined,config.inGraphDataFontColor,i,j,{nullValue : true} );
-							var dispString = tmplbis(setOptionValue("INGRAPHDATATMPL",ctx,data,statData,undefined,config.inGraphDataTmpl,i,j,{nullValue : true} ),statData[i][j]);
-							ctx.beginPath();
-							yPos = 0;
-							xPos = 0;
-							if (setOptionValue("INGRAPHDATAXPOSITION",ctx,data,statData,undefined,config.inGraphDataXPosition,i,j,{nullValue : true} ) == 1) {
-								xPos = statData[i][j].xPosLeft + setOptionValue("INGRAPHDATAPADDINGX",ctx,data,statData,undefined,config.inGraphDataPaddingX,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAXPOSITION",ctx,data,statData,undefined,config.inGraphDataXPosition,i,j,{nullValue : true} ) == 2) {
-								xPos = statData[i][j].xPosLeft + (statData[i][j].xPosRight-statData[i][j].xPosLeft)/2 + setOptionValue("INGRAPHDATAPADDINGX",ctx,data,statData,undefined,config.inGraphDataPaddingX,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAXPOSITION",ctx,data,statData,undefined,config.inGraphDataXPosition,i,j,{nullValue : true} ) == 3) {
-								xPos = statData[i][j].xPosRight + setOptionValue("INGRAPHDATAPADDINGX",ctx,data,statData,undefined,config.inGraphDataPaddingX,i,j,{nullValue : true} );
-							}
-							if (setOptionValue("INGRAPHDATAYPOSITION",ctx,data,statData,undefined,config.inGraphDataYPosition,i,j,{nullValue : true} ) == 1) {
-								yPos = statData[i][j].yPosBottom - setOptionValue("INGRAPHDATAPADDINGY",ctx,data,statData,undefined,config.inGraphDataPaddingY,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAYPOSITION",ctx,data,statData,undefined,config.inGraphDataYPosition,i,j,{nullValue : true} ) == 2) {
-								yPos = statData[i][j].yPosBottom - barWidth / 2 - setOptionValue("INGRAPHDATAPADDINGY",ctx,data,statData,undefined,config.inGraphDataPaddingY,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAYPOSITION",ctx,data,statData,undefined,config.inGraphDataYPosition,i,j,{nullValue : true} ) == 3) {
-								yPos = statData[i][j].yPosTop - setOptionValue("INGRAPHDATAPADDINGY",ctx,data,statData,undefined,config.inGraphDataPaddingY,i,j,{nullValue : true} );
-							}
-							if(xPos<=msr.availableWidth+msr.leftNotUsableSize) {
-								ctx.translate(xPos, yPos);
-								ctx.rotate(setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,j,{nullValue : true} ) * (Math.PI / 180));
-								ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,j,{nullValue : true} ),true);
-								ctx.restore();
-							}
-						}
-					}
-				}
-			}
-			if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"HorizontalStackedBar");
-		};
-
-		function drawScale() {
-			//X axis line                                                          
-			ctx.lineWidth = config.scaleLineWidth;
-			ctx.strokeStyle = config.scaleLineColor;
-			ctx.beginPath();
-			ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY);
-			ctx.lineTo(yAxisPosX + msr.availableWidth, xAxisPosY);
-			ctx.stroke();
-			for (var i = ((config.showYAxisMin) ? -1 : 0); i < calculatedScale.steps; i++) {
-				if (i >= 0) {
-					ctx.beginPath();
-					ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom);
-					ctx.lineWidth = config.scaleGridLineWidth;
-					ctx.strokeStyle = config.scaleGridLineColor;
-					//Check i isnt 0, so we dont go over the Y axis twice.
-					if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) {
-						ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
-					} else {
-						ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY);
-					}
-					ctx.stroke();
-				}
-			}
-			//Y axis
-			ctx.lineWidth = config.scaleLineWidth;
-			ctx.strokeStyle = config.scaleLineColor;
-			ctx.beginPath();
-			ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom);
-			ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
-			ctx.stroke();
-			for (var j = 0; j < data.labels.length; j++) {
-				ctx.beginPath();
-				ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop));
-				ctx.lineWidth = config.scaleGridLineWidth;
-				ctx.strokeStyle = config.scaleGridLineColor;
-				if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) {
-					ctx.lineTo(yAxisPosX + msr.availableWidth, xAxisPosY - ((j + 1) * scaleHop));
-				} else {
-					ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop));
-				}
-				ctx.stroke();
-			}
-		};
-
-		function drawLabels() {
-			ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
-			//X axis line                                                          
-			if (config.scaleShowLabels && (config.xAxisTop || config.xAxisBottom)) {
-				ctx.textBaseline = "top";
-				if (msr.rotateLabels > 90) {
-					ctx.save();
-					ctx.textAlign = "left";
-				} else if (msr.rotateLabels > 0) {
-					ctx.save();
-					ctx.textAlign = "right";
-				} else {
-					ctx.textAlign = "center";
-				}
-				ctx.fillStyle = config.scaleFontColor;
-				if (config.xAxisBottom) {
-					for (var i = ((config.showYAxisMin) ? -1 : 0); i < calculatedScale.steps; i++) {
-						ctx.save();
-						if (msr.rotateLabels > 0) {
-							ctx.translate(yAxisPosX + (i + 1) * valueHop - msr.highestXLabel / 2, msr.xLabelPos);
-							ctx.rotate(-(msr.rotateLabels * (Math.PI / 180)));
-							ctx.fillTextMultiLine(calculatedScale.labels[i + 1], 0, 0, ctx.textBaseline, config.scaleFontSize,true);
-						} else {
-							ctx.fillTextMultiLine(calculatedScale.labels[i + 1], yAxisPosX + ((i + 1) * valueHop), msr.xLabelPos, ctx.textBaseline, config.scaleFontSize,true);
-						}
-						ctx.restore();
-					}
-				}
-			}
-			//Y axis
-			ctx.textAlign = "right";
-			ctx.textBaseline = "middle";
-			for (var j = 0; j < data.labels.length; j++) {
-				if (config.yAxisLeft) {
-					ctx.textAlign = "right";
-					ctx.fillTextMultiLine(fmtChartJS(config, data.labels[j], config.fmtXLabel), yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop) + barWidth / 2, ctx.textBaseline, config.scaleFontSize,true);
-				}
-				if (config.yAxisRight) {
-					ctx.textAlign = "left";
-					ctx.fillTextMultiLine(fmtChartJS(config, data.labels[j], config.fmtXLabel), yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop) + barWidth / 2, ctx.textBaseline, config.scaleFontSize,true);
-				}
-			}
-		};
-
-		function getValueBounds() {
-			var upperValue = -Number.MAX_VALUE;
-			var lowerValue = Number.MAX_VALUE;
-			var minvl = new Array(data.datasets.length);
-			var maxvl = new Array(data.datasets.length);
-			for (var i = 0; i < data.datasets.length; i++) {
-				for (var j = 0; j < data.datasets[i].data.length; j++) {
-					var k = i;
-					var tempp = 0;
-					var tempn = 0;
-					if (!(typeof(data.datasets[0].data[j]) == 'undefined')) {
-						if(1 * data.datasets[0].data[j] > 0) {
-							tempp += 1 * data.datasets[0].data[j];
-							if (tempp > upperValue) {
-								upperValue = tempp;
-							};
-							if (tempp < lowerValue) {
-								lowerValue = tempp;
-							};
-						} else {
-							tempn += 1 * data.datasets[0].data[j];
-							if (tempn > upperValue) {
-								upperValue = tempn;
-							};
-							if (tempn < lowerValue) {
-								lowerValue = tempn;
-							};
-						}
-					}
-					while (k > 0) { //get max of stacked data
-						if (!(typeof(data.datasets[k].data[j]) == 'undefined')) {
-							if(1 * data.datasets[k].data[j] > 0) {
-								tempp += 1 * data.datasets[k].data[j];
-								if (tempp > upperValue) {
-									upperValue = tempp;
-								};
-								if (tempp < lowerValue) {
-									lowerValue = tempp;
-								};
-							} else {
-								tempn += 1 * data.datasets[k].data[j];
-								if (tempn > upperValue) {
-									upperValue = tempn;
-								};
-								if (tempn < lowerValue) {
-									lowerValue = tempn;
-								};
-							}
-						}
-						k--;
-					}
-				}
-			};
-			if(typeof config.graphMin=="function")lowerValue= setOptionValue("GRAPHMIN",ctx,data,statData,undefined,config.graphMin,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
-			if(typeof config.graphMax=="function") upperValue= setOptionValue("GRAPHMAX",ctx,data,statData,undefined,config.graphMax,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMax)) upperValue = config.graphMax;
-			if(upperValue<lowerValue){upperValue=0;lowerValue=0;}
-			if (Math.abs(upperValue - lowerValue) < config.zeroValue) {
-				if(Math.abs(upperValue)< config.zeroValue) upperValue = .9;
-				if(upperValue>0) {
-					upperValue=upperValue*1.1;
-					lowerValue=lowerValue*0.9;
-				} else {
-					upperValue=upperValue*0.9;
-					lowerValue=lowerValue*1.1;
-				}
-			}
-			labelHeight = config.scaleFontSize;
-			scaleHeight = msr.availableHeight;
-			var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66)));
-			var minSteps = Math.floor((scaleHeight / labelHeight * 0.5));
-			return {
-				maxValue: upperValue,
-				minValue: lowerValue,
-				maxSteps: maxSteps,
-				minSteps: minSteps
-			};
-
-
-		};
-	};
-	var Bar = function(data, config, ctx) {
-		var maxSize, scaleHop, scaleHop2, calculatedScale, calculatedScale2, labelHeight, scaleHeight, valueBounds, labelTemplateString, labelTemplateString2, valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, barWidth, rotateLabels = 0,
-			msr;
-	
-		ctx.tpchart="Bar";
-	        if (!init_and_start(ctx,data,config)) return;
-		var statData=initPassVariableData_part1(data,config,ctx);
-
-		var nrOfBars = data.datasets.length;
-		for (var i = 0; i < data.datasets.length; i++) {
-			if (data.datasets[i].type == "Line") { statData[i][0].tpchart="Line";nrOfBars--;}
-			else statData[i][0].tpchart="Bar";	
-		}                               
-
-
-		// change the order (at first all bars then the lines) (form of BubbleSort)
-		var bufferDataset, l = 0;
-		
-
-		msr = setMeasures(data, config, ctx, height, width, "nihil", [""], true, false, true, true, true, "Bar");
-		valueBounds = getValueBounds();
-		if(valueBounds.minValue<=0)config.logarithmic=false;
-		if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
-
-			// true or fuzzy (error for negativ values (included 0))
-			if (config.logarithmic !== false) {
-				if (valueBounds.minValue <= 0) {
-					config.logarithmic = false;
-				}
-			}
-			if (config.logarithmic2 !== false) {
-				if (valueBounds.minValue2 <= 0) {
-					config.logarithmic2 = false;
-				}
-			}
-			// Check if logarithmic is meanigful
-			var OrderOfMagnitude = calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.maxValue) + 1)) - calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.minValue)));
-			if ((config.logarithmic == 'fuzzy' && OrderOfMagnitude < 4) || config.scaleOverride) {
-				config.logarithmic = false;
-			}
-			// Check if logarithmic is meanigful
-			var OrderOfMagnitude2 = calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.maxValue2) + 1)) - calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.minValue2)));
-			if ((config.logarithmic2 == 'fuzzy' && OrderOfMagnitude2 < 4) || config.scaleOverride2) {
-				config.logarithmic2 = false;
-			}
-
-			//Check and set the scale
-			labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
-			labelTemplateString2 = (config.scaleShowLabels2) ? config.scaleLabel2 : "";
-			if (!config.scaleOverride) {
-				calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
-			} else {
-				var scaleStartValue= setOptionValue("SCALESTARTVALUE",ctx,data,statData,undefined,config.scaleStartValue,-1,-1,{nullValue : true} );
-				var scaleSteps =setOptionValue("SCALESTEPS",ctx,data,statData,undefined,config.scaleSteps,-1,-1,{nullValue : true} );
-				var scaleStepWidth = setOptionValue("SCALESTEPWIDTH",ctx,data,statData,undefined,config.scaleStepWidth,-1,-1,{nullValue : true} );
-
-				calculatedScale = {
-					steps: scaleSteps,
-					stepValue: scaleStepWidth,
-					graphMin: scaleStartValue,
-					graphMax: scaleStartValue + scaleSteps * scaleStepWidth,
-					labels: []
-				}
-				populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, scaleStartValue, calculatedScale.graphMax, scaleStepWidth);
-			}
-			if (valueBounds.dbAxis) {
-				if (!config.scaleOverride2) {
-					calculatedScale2 = calculateScale(2, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue2, valueBounds.minValue2, labelTemplateString);
-				} else {
-					var scaleStartValue2= setOptionValue("SCALESTARTVALUE2",ctx,data,statData,undefined,config.scaleStartValue2,-1,-1,{nullValue : true} );
-					var scaleSteps2 =setOptionValue("SCALESTEPS2",ctx,data,statData,undefined,config.scaleSteps2,-1,-1,{nullValue : true} );
-					var scaleStepWidth2 = setOptionValue("SCALESTEPWIDTH2",ctx,data,statData,undefined,config.scaleStepWidth2,-1,-1,{nullValue : true} );
-
-					calculatedScale2 = {
-						steps: scaleSteps2,
-						stepValue: scaleStepWidth2,
-						graphMin: scaleStartValue2,
-						graphMax: scaleStartValue2 + scaleSteps2 * scaleStepWidth2,
-						labels: []
-					}
-					populateLabels(2, config, labelTemplateString2, calculatedScale2.labels, calculatedScale2.steps, scaleStartValue2, calculatedScale2.graphMax, scaleStepWidth2);
-				}
-			} else {
-				calculatedScale2 = {
-					steps: 0,
-					stepValue: 0,
-					graphMin: 0,
-					graphMax: 0,
-					labels: null
-				}
-			}
-			msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, calculatedScale2.labels, true, false, true, true, true, "Bar");
-
-			var prevHeight=msr.availableHeight;
-
-			msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop;
-			msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight;
-			scaleHop = Math.floor(msr.availableHeight / calculatedScale.steps);
-			scaleHop2 = Math.floor(msr.availableHeight / calculatedScale2.steps);
-			valueHop = Math.floor(msr.availableWidth / (data.labels.length));
-			if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / data.labels.length);
-			msr.clrwidth = msr.clrwidth - (msr.availableWidth - ((data.labels.length) * valueHop));
-			msr.availableWidth = (data.labels.length) * valueHop;
-			msr.availableHeight = (calculatedScale.steps) * scaleHop;
-			msr.xLabelPos+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight));
-			msr.clrheight+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight));
-
-			yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft;
-			xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop;
-			barWidth = (valueHop - config.scaleGridLineWidth * 2 - (config.barValueSpacing * 2) - (config.barDatasetSpacing * nrOfBars - 1) - ((config.barStrokeWidth / 2) * nrOfBars - 1)) / nrOfBars;
-			if(barWidth>=0 && barWidth<=1)barWidth=1;
-			if(barWidth<0 && barWidth>=-1)barWidth=-1;
-			var zeroY = 0;
-			var zeroY2 = 0;
-			if (valueBounds.minValue < 0) {
-				var zeroY = calculateOffset(config.logarithmic, 0, calculatedScale, scaleHop);
-			}
-			if (valueBounds.minValue2 < 0) {
-				var zeroY2 = calculateOffset(config.logarithmic2, 0, calculatedScale2, scaleHop2);
-			}
-			initPassVariableData_part2(statData,data,config,ctx,{ 
-				msr: msr,
-				yAxisPosX : yAxisPosX,
-				xAxisPosY : xAxisPosY,
-				valueHop : valueHop,
-				barWidth : barWidth,
-				zeroY : zeroY,
-				zeroY2 : zeroY2,
-				calculatedScale : calculatedScale,
-				calculatedScale2 : calculatedScale2,
-				scaleHop : scaleHop,	
-				scaleHop2 : scaleHop2	
-			});
-			drawLabels();
-			animationLoop(config, drawScale, drawBars, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data);
-		} else {
-			testRedraw(ctx,data,config);
-		}
-
-		function drawBars(animPc) {
-			var t1, t2, t3;
-
-
-			ctx.lineWidth = config.barStrokeWidth;
-			for (var i = 0; i < data.datasets.length; i++) {
-				if(data.datasets[i].type=="Line") continue;
-				for (var j = 0; j < data.datasets[i].data.length; j++) {
-					if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
-						var currentAnimPc = animationCorrection(animPc, data, config, i, j, 1).animVal;
-						if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1;
-						var barHeight = currentAnimPc * (statData[i][j].barHeight) + (config.barStrokeWidth / 2);
-						ctx.fillStyle=setOptionValue("COLOR",ctx,data,statData,data.datasets[i].fillColor,config.defaultFillColor,i,j,{animationValue: currentAnimPc, xPosLeft : statData[i][j].xPosLeft, yPosBottom : statData[i][j].yPosBottom, xPosRight : statData[i][j].xPosLeft+barWidth, yPosTop : statData[i][j].yPosBottom-barHeight} );
-						ctx.strokeStyle=setOptionValue("STROKECOLOR",ctx,data,statData,data.datasets[i].strokeColor,config.defaultStrokeColor,i,j,{nullvalue : null} );
-						roundRect(ctx, statData[i][j].xPosLeft, statData[i][j].yPosBottom, barWidth, barHeight, config.barShowStroke, config.barBorderRadius);
-					}
-				}
-			}
-			drawLinesDataset(animPc, data, config, ctx, statData,{xAxisPosY : xAxisPosY,yAxisPosX : yAxisPosX, valueHop : valueHop, nbValueHop : data.labels.length });
-
-			if (animPc >= config.animationStopValue) {
-
-				for (var i = 0; i < data.datasets.length; i++) {
-					for (var j = 0; j < data.datasets[i].data.length; j++) {
-						if (typeof(data.datasets[i].data[j]) == 'undefined') continue;
-						if (data.datasets[i].type == "Line") continue;
-						if(setOptionValue("ANNOTATEDISPLAY",ctx,data,statData,undefined,config.annotateDisplay,i,j,{nullValue : true}))
-							jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", i , j, statData];
-						if(setOptionValue("INGRAPHDATASHOW",ctx,data,statData,undefined,config.inGraphDataShow,i,j,{nullValue : true})) {
-							ctx.save();
-							ctx.textAlign = setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,j,{nullValue: true  });
-							ctx.textBaseline = setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,j,{nullValue : true} );
-							ctx.font = setOptionValue("INGRAPHDATAFONTSTYLE",ctx,data,statData,undefined,config.inGraphDataFontStyle,i,j,{nullValue : true} ) + ' ' + setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,j,{nullValue : true} ) + 'px ' + setOptionValue("INGRAPHDATAFONTFAMILY",ctx,data,statData,undefined,config.inGraphDataFontFamily,i,j,{nullValue : true} );
-							ctx.fillStyle = setOptionValue("INGRAPHDATAFONTCOLOR",ctx,data,statData,undefined,config.inGraphDataFontColor,i,j,{nullValue : true} );
-							t1 = statData[i][j].yPosBottom;
-							t2 = statData[i][j].yPosTop;
-							ctx.beginPath();
-							var yPos = 0,
-								xPos = 0;
-							if (setOptionValue("INGRAPHDATAXPOSITION",ctx,data,statData,undefined,config.inGraphDataXPosition,i,j,{nullValue : true} ) == 1) {
-								xPos = statData[i][j].xPosLeft + setOptionValue("INGRAPHDATAPADDINGX",ctx,data,statData,undefined,config.inGraphDataPaddingX,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAXPOSITION",ctx,data,statData,undefined,config.inGraphDataXPosition,i,j,{nullValue : true} ) == 2) {
-								xPos = statData[i][j].xPosLeft + barWidth / 2 + setOptionValue("INGRAPHDATAPADDINGX",ctx,data,statData,undefined,config.inGraphDataPaddingX,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAXPOSITION",ctx,data,statData,undefined,config.inGraphDataXPosition,i,j,{nullValue : true} ) == 3) {
-								xPos = statData[i][j].xPosLeft + barWidth + setOptionValue("INGRAPHDATAPADDINGX",ctx,data,statData,undefined,config.inGraphDataPaddingX,i,j,{nullValue : true} );
-							}
-							if (setOptionValue("INGRAPHDATAYPOSITION",ctx,data,statData,undefined,config.inGraphDataYPosition,i,j,{nullValue : true} ) == 1) {
-								yPos = statData[i][j].yPosBottom - setOptionValue("INGRAPHDATAPADDINGY",ctx,data,statData,undefined,config.inGraphDataPaddingY,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAYPOSITION",ctx,data,statData,undefined,config.inGraphDataYPosition,i,j,{nullValue : true} ) == 2) {
-								yPos = (statData[i][j].yPosBottom+statData[i][j].yPosTop)/2 - setOptionValue("INGRAPHDATAPADDINGY",ctx,data,statData,undefined,config.inGraphDataPaddingY,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAYPOSITION",ctx,data,statData,undefined,config.inGraphDataYPosition,i,j,{nullValue : true} ) == 3) {
-								yPos = statData[i][j].yPosTop - setOptionValue("INGRAPHDATAPADDINGY",ctx,data,statData,undefined,config.inGraphDataPaddingY,i,j,{nullValue : true} );
-							}
-							ctx.translate(xPos, yPos);
-							var dispString = tmplbis(setOptionValue("INGRAPHDATATMPL",ctx,data,statData,undefined,config.inGraphDataTmpl,i,j,{nullValue : true} ), statData[i][j]);
-							ctx.rotate(setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,j,{nullValue : true} ) * (Math.PI / 180));
-							ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,j,{nullValue : true} ),true);
-							ctx.restore();
-						}
-					}
-				}
-			}
-			if (animPc >= 1 && typeof drawMath == "function") {
-				drawMath(ctx, config, data, msr, {
-					xAxisPosY: xAxisPosY,
-					yAxisPosX: yAxisPosX,
-					valueHop: valueHop,
-					scaleHop: scaleHop,
-					zeroY: zeroY,
-					calculatedScale: calculatedScale,
-					calculateOffset: calculateOffset,
-					barWidth: barWidth
-				});
-			}
-			if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Bar");
-		};
-
-		function roundRect(ctx, x, y, w, h, stroke, radius) {
-			ctx.beginPath();
-			ctx.moveTo(x + radius, y);
-			ctx.lineTo(x + w - radius, y);
-			ctx.quadraticCurveTo(x + w, y, x + w, y);
-			ctx.lineTo(x + w, y - h + radius);
-			ctx.quadraticCurveTo(x + w, y - h, x + w - radius, y - h);
-			ctx.lineTo(x + radius, y - h);
-			ctx.quadraticCurveTo(x, y - h, x, y - h + radius);
-			ctx.lineTo(x, y);
-			ctx.quadraticCurveTo(x, y, x + radius, y);
-			if (stroke) ctx.stroke();
-			ctx.closePath();
-			ctx.fill();
-		};
-
-		function drawScale() {
-			//X axis line                                                          
-			ctx.lineWidth = config.scaleLineWidth;
-			ctx.strokeStyle = config.scaleLineColor;
-			ctx.beginPath();
-
-
-			ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY);
-			ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY);
-			ctx.stroke();
-			for (var i = 0; i < data.labels.length; i++) {
-				ctx.beginPath();
-				ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom);
-				ctx.lineWidth = config.scaleGridLineWidth;
-				ctx.strokeStyle = config.scaleGridLineColor;
-				//Check i isnt 0, so we dont go over the Y axis twice.
-				if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) {
-					ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
-				} else {
-					ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY);
-				}
-				ctx.stroke();
-			}
-			//Y axis
-			ctx.lineWidth = config.scaleLineWidth;
-			ctx.strokeStyle = config.scaleLineColor;
-			ctx.beginPath();
-			ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom);
-			ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
-			ctx.stroke();
-			for (var j = 0; j < calculatedScale.steps; j++) {
-				ctx.beginPath();
-				ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop));
-				ctx.lineWidth = config.scaleGridLineWidth;
-				ctx.strokeStyle = config.scaleGridLineColor;
-				if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) {
-					ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY - ((j + 1) * scaleHop));
-				} else {
-					ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop));
-				}
-				ctx.stroke();
-			}
-		};
-
-		function drawLabels() {
-			ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
-			//X axis line                                                          
-			if (config.xAxisTop || config.xAxisBottom) {
-				ctx.textBaseline = "top";
-				if (msr.rotateLabels > 90) {
-					ctx.save();
-					ctx.textAlign = "left";
-				} else if (msr.rotateLabels > 0) {
-					ctx.save();
-					ctx.textAlign = "right";
-				} else {
-					ctx.textAlign = "center";
-				}
-				ctx.fillStyle = config.scaleFontColor;
-				if (config.xAxisBottom) {
-					for (var i = 0; i < data.labels.length; i++) {
-						ctx.save();
-						if (msr.rotateLabels > 0) {
-
-							ctx.translate(yAxisPosX + i * valueHop + (valueHop / 2) - msr.highestXLabel / 2, msr.xLabelPos);
-							ctx.rotate(-(msr.rotateLabels * (Math.PI / 180)));
-							ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), 0, 0, ctx.textBaseline, config.scaleFontSize,true);
-						} else {
-							ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), yAxisPosX + i * valueHop + (valueHop / 2), msr.xLabelPos, ctx.textBaseline, config.scaleFontSize,true);
-						}
-						ctx.restore();
-					}
-				}
-			}
-			//Y axis
-			ctx.textAlign = "right";
-			ctx.textBaseline = "middle";
-			for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale.steps; j++) {
-				if (config.scaleShowLabels) {
-					if (config.yAxisLeft) {
-						ctx.textAlign = "right";
-						ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize,true);
-					}
-					if (config.yAxisRight && !valueBounds.dbAxis) {
-						ctx.textAlign = "left";
-						ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize,true);
-					}
-				}
-			}
-			if (config.yAxisRight && valueBounds.dbAxis) {
-				for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale2.steps; j++) {
-					if (config.scaleShowLabels) {
-						ctx.textAlign = "left";
-						ctx.fillTextMultiLine(calculatedScale2.labels[j + 1], yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop2), ctx.textBaseline, config.scaleFontSize,true);
-					}
-				}
-			}
-		};
-
-		function getValueBounds() {
-			var upperValue = -Number.MAX_VALUE;
-			var lowerValue = Number.MAX_VALUE;
-			var upperValue2 = -Number.MAX_VALUE;
-			var lowerValue2 = Number.MAX_VALUE;
-			var secondAxis = false;
-			var firstAxis = false;
-			
-			for (var i = 0; i < data.datasets.length; i++) {
-				var mathFctName = data.datasets[i].drawMathDeviation;
-				var mathValueHeight = 0;
-				if (typeof eval(mathFctName) == "function") {
-					var parameter = {
-						data: data,
-						datasetNr: i
-					};
-					mathValueHeight = window[mathFctName](parameter);
-				}
-				for (var j = 0; j < data.datasets[i].data.length; j++) {
-					if(typeof data.datasets[i].data[j]=="undefined")continue;
-					if (data.datasets[i].axis == 2) {
-						secondAxis = true;
-						if (1 * data.datasets[i].data[j] + mathValueHeight > upperValue2) {
-							upperValue2 = 1 * data.datasets[i].data[j] + mathValueHeight;
-						};
-						if (1 * data.datasets[i].data[j] - mathValueHeight < lowerValue2) {
-							lowerValue2 = 1 * data.datasets[i].data[j] - mathValueHeight;
-						};
-					} else {
-						firstAxis=true;
-						if (1 * data.datasets[i].data[j] + mathValueHeight > upperValue) {
-							upperValue = 1 * data.datasets[i].data[j] + mathValueHeight;
-						};
-						if (1 * data.datasets[i].data[j] - mathValueHeight < lowerValue) {
-							lowerValue = 1 * data.datasets[i].data[j] - mathValueHeight;
-						};
-					}
-				}
-			};
-			if(upperValue<lowerValue){upperValue=0;lowerValue=0;}
-			if (Math.abs(upperValue - lowerValue) < config.zeroValue) {
-				if(Math.abs(upperValue)< config.zeroValue) upperValue = .9;
-				if(upperValue>0) {
-					upperValue=upperValue*1.1;
-					lowerValue=lowerValue*0.9;
-				} else {
-					upperValue=upperValue*0.9;
-					lowerValue=lowerValue*1.1;
-				}
-			}
-			if(typeof config.graphMin=="function")lowerValue= setOptionValue("GRAPHMIN",ctx,data,statData,undefined,config.graphMin,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
-			if(typeof config.graphMax=="function") upperValue= setOptionValue("GRAPHMAX",ctx,data,statData,undefined,config.graphMax,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMax)) upperValue = config.graphMax;
-
-			if (secondAxis) {
-				if(upperValue2<lowerValue2){upperValue2=0;lowerValue2=0;}
-				if (Math.abs(upperValue2 - lowerValue2) < config.zeroValue) {
-					if(Math.abs(upperValue2)< config.zeroValue) upperValue2 = .9;
-					if(upperValue2>0) {
-						upperValue2=upperValue2*1.1;
-						lowerValue2=lowerValue2*0.9;
-					} else {
-						upperValue2=upperValue2*0.9;
-						lowerValue2=lowerValue2*1.1;
-					}
-				}
-				if(typeof config.graphMin2=="function")lowerValue2= setOptionValue("GRAPHMIN",ctx,data,statData,undefined,config.graphMin2,-1,-1,{nullValue : true})
-				else if (!isNaN(config.graphMin2)) lowerValue2 = config.graphMin2;
-				if(typeof config.graphMax2=="function") upperValue2= setOptionValue("GRAPHMAX",ctx,data,statData,undefined,config.graphMax2,-1,-1,{nullValue : true})
-				else if (!isNaN(config.graphMax2)) upperValue2 = config.graphMax2;
-			}
-			if (!firstAxis && secondAxis) {
-				upperValue = upperValue2;
-				lowerValue = lowerValue2;
-			}
-
-			labelHeight = config.scaleFontSize;
-			scaleHeight = msr.availableHeight;
-			var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66)));
-			var minSteps = Math.floor((scaleHeight / labelHeight * 0.5));
-			return {
-				maxValue: upperValue,
-				minValue: lowerValue,
-				maxValue2: upperValue2,
-				minValue2: lowerValue2,
-				dbAxis: secondAxis,
-				maxSteps: maxSteps,
-				minSteps: minSteps
-			};
-		};
-	};
-
-	var HorizontalBar = function(data, config, ctx) {
-		var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, barWidth, rotateLabels = 0,
-			msr;
-		ctx.tpchart="HorizontalBar";
-	        if (!init_and_start(ctx,data,config)) return;
-		var statData=initPassVariableData_part1(data,config,ctx);
-
-		if (config.reverseOrder && typeof ctx.reversed == "undefined") {
-			ctx.reversed=true;
-			data = reverseData(data);
-		}
-		msr = setMeasures(data, config, ctx, height, width, "nihil", [""], true, true, true, true, true, "StackedBar");
-		valueBounds = getValueBounds();
-		if(valueBounds.minValue<=0)config.logarithmic=false;
-		if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) {
-			if (config.logarithmic !== false) {
-				if (valueBounds.minValue <= 0) {
-					config.logarithmic = false;
-				}
-			}
-			//Check and set the scale
-			labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : "";
-			if (!config.scaleOverride) {
-				calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString);
-				msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, true, true, true, true, "HorizontalBar");
-			} else {
-				var scaleStartValue= setOptionValue("SCALESTARTVALUE",ctx,data,statData,undefined,config.scaleStartValue,-1,-1,{nullValue : true} );
-				var scaleSteps =setOptionValue("SCALESTEPS",ctx,data,statData,undefined,config.scaleSteps,-1,-1,{nullValue : true} );
-				var scaleStepWidth = setOptionValue("SCALESTEPWIDTH",ctx,data,statData,undefined,config.scaleStepWidth,-1,-1,{nullValue : true} );
-
-				calculatedScale = {
-					steps: scaleSteps,
-					stepValue: scaleStepWidth,
-					graphMin: scaleStartValue,
-					graphMax: scaleStartValue + scaleSteps * scaleStepWidth,
-					labels: []
-				}
-				populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, scaleStartValue, calculatedScale.graphMax, scaleStepWidth);
-				msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, true, true, true, true, "HorizontalBar");
-			}
-			msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop;
-			msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight;
-			scaleHop = Math.floor(msr.availableHeight / data.labels.length);
-			valueHop = Math.floor(msr.availableWidth / (calculatedScale.steps));
-			if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / calculatedScale.steps);
-			msr.clrwidth = msr.clrwidth - (msr.availableWidth - (calculatedScale.steps * valueHop));
-			msr.availableWidth = (calculatedScale.steps) * valueHop;
-			msr.availableHeight = (data.labels.length) * scaleHop;
-			yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft;
-			xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop;
-			barWidth = (scaleHop - config.scaleGridLineWidth * 2 - (config.barValueSpacing * 2) - (config.barDatasetSpacing * data.datasets.length - 1) - ((config.barStrokeWidth / 2) * data.datasets.length - 1)) / data.datasets.length;
-			if(barWidth>=0 && barWidth<=1)barWidth=1;
-			if(barWidth<0 && barWidth>=-1)barWidth=-1;
-			var zeroY = 0;
-			if (valueBounds.minValue < 0) {
-				var zeroY = calculateOffset(config.logarithmic, 0, calculatedScale, valueHop);
-			}
-			drawLabels();
-			initPassVariableData_part2(statData,data,config,ctx,{ 
-				yAxisPosX : yAxisPosX,
-				xAxisPosY : xAxisPosY,
-				barWidth : barWidth,
-				zeroY : zeroY,
-				scaleHop : scaleHop,
-				valueHop : valueHop,
-				calculatedScale : calculatedScale
-			});
-			animationLoop(config, drawScale, drawBars, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data);
-		} else {
-			testRedraw(ctx,data,config);
-		}
-
-		function drawBars(animPc) {
-			for (var i = 0; i < data.datasets.length; i++) {
-				for (var j = 0; j < data.datasets[i].data.length; j++) {
-					ctx.lineWidth = config.barStrokeWidth;
-					var currentAnimPc = animationCorrection(animPc, data, config, i, j, 1).animVal;
-					if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1;
-					var barHeight = currentAnimPc * statData[i][j].barWidth + (config.barStrokeWidth / 2);
-					ctx.fillStyle=setOptionValue("COLOR",ctx,data,statData,data.datasets[i].fillColor,config.defaultFillColor,i,j,{animationValue: currentAnimPc, xPosLeft : statData[i][j].xPosLeft, yPosBottom : statData[i][j].yPosBottom, xPosRight : statData[i][j].xPosLeft+barHeight, yPosTop : statData[i][j].yPosBottom} );
-					ctx.strokeStyle=setOptionValue("STROKECOLOR",ctx,data,statData,data.datasets[i].strokeColor,config.defaultStrokeColor,i,j,{nullvalue : null} );
-
-					if (!(typeof(data.datasets[i].data[j]) == 'undefined')) {
-						roundRect(ctx, statData[i][j].yPosTop, statData[i][j].xPosLeft , barWidth, barHeight, config.barShowStroke, config.barBorderRadius, 0);
-					}
-				}
-			}
-			if (animPc >= config.animationStopValue) {
-				for (var i = 0; i < data.datasets.length; i++) {
-					for (var j = 0; j < data.datasets[i].data.length; j++) {
-						if (typeof(data.datasets[i].data[j]) == 'undefined') continue;
-						if(setOptionValue("ANNOTATEDISPLAY",ctx,data,statData,undefined,config.annotateDisplay,i,j,{nullValue : true})) {
-							jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", i ,j ,statData];
-                       				}
-                       				if(setOptionValue("INGRAPHDATASHOW",ctx,data,statData,undefined,config.inGraphDataShow,i,j,{nullValue : true}))  {
-							ctx.save();
-							ctx.textAlign = setOptionValue("INGRAPHDATAALIGN",ctx,data,statData,undefined,config.inGraphDataAlign,i,j,{nullValue: true  });
-							ctx.textBaseline = setOptionValue("INGRAPHDATAVALIGN",ctx,data,statData,undefined,config.inGraphDataVAlign,i,j,{nullValue : true} );
-							ctx.font = setOptionValue("INGRAPHDATAFONTSTYLE",ctx,data,statData,undefined,config.inGraphDataFontStyle,i,j,{nullValue : true} ) + ' ' + setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,j,{nullValue : true} ) + 'px ' + setOptionValue("INGRAPHDATAFONTFAMILY",ctx,data,statData,undefined,config.inGraphDataFontFamily,i,j,{nullValue : true} );
-							ctx.fillStyle = setOptionValue("INGRAPHDATAFONTCOLOR",ctx,data,statData,undefined,config.inGraphDataFontColor,i,j,{nullValue : true} );
-							ctx.beginPath();
-							var yPos = 0,
-								xPos = 0;
-							if (setOptionValue("INGRAPHDATAYPOSITION",ctx,data,statData,undefined,config.inGraphDataYPosition,i,j,{nullValue : true} ) == 1) {
-								yPos = statData[i][j].yPosTop - setOptionValue("INGRAPHDATAPADDINGY",ctx,data,statData,undefined,config.inGraphDataPaddingY,i,j,{nullValue : true} ) + barWidth;
-							} else if (setOptionValue("INGRAPHDATAYPOSITION",ctx,data,statData,undefined,config.inGraphDataYPosition,i,j,{nullValue : true} ) == 2) {
-								yPos = statData[i][j].yPosTop + barWidth / 2 - setOptionValue("INGRAPHDATAPADDINGY",ctx,data,statData,undefined,config.inGraphDataPaddingY,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAYPOSITION",ctx,data,statData,undefined,config.inGraphDataYPosition,i,j,{nullValue : true} ) == 3) {
-								yPos = statData[i][j].yPosTop - setOptionValue("INGRAPHDATAPADDINGY",ctx,data,statData,undefined,config.inGraphDataPaddingY,i,j,{nullValue : true} );
-							}
-							if (setOptionValue("INGRAPHDATAXPOSITION",ctx,data,statData,undefined,config.inGraphDataXPosition,i,j,{nullValue : true} ) == 1) {
-								xPos = statData[i][j].xPosLeft + setOptionValue("INGRAPHDATAPADDINGX",ctx,data,statData,undefined,config.inGraphDataPaddingX,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAXPOSITION",ctx,data,statData,undefined,config.inGraphDataXPosition,i,j,{nullValue : true} ) == 2) {
-								xPos = (statData[i][j].xPosLeft+statData[i][j].xPosRight)/2 + setOptionValue("INGRAPHDATAPADDINGX",ctx,data,statData,undefined,config.inGraphDataPaddingX,i,j,{nullValue : true} );
-							} else if (setOptionValue("INGRAPHDATAXPOSITION",ctx,data,statData,undefined,config.inGraphDataXPosition,i,j,{nullValue : true} ) == 3) {
-								xPos = statData[i][j].xPosRight + setOptionValue("INGRAPHDATAPADDINGX",ctx,data,statData,undefined,config.inGraphDataPaddingX,i,j,{nullValue : true} );
-							}
-							ctx.translate(xPos, yPos);
-							var dispString = tmplbis(setOptionValue("INGRAPHDATATMPL",ctx,data,statData,undefined,config.inGraphDataTmpl,i,j,{nullValue : true} ), statData[i][j]);
-							ctx.rotate(setOptionValue("INGRAPHDATAROTATE",ctx,data,statData,undefined,config.inGraphDataRotate,i,j,{nullValue : true} ) * (Math.PI / 180));
-							ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, setOptionValue("INGRAPHDATAFONTSIZE",ctx,data,statData,undefined,config.inGraphDataFontSize,i,j,{nullValue : true} ),true);
-							ctx.restore();
-						}
-					}
-				}
-			}
-			if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"HorizontalBar");
-		};
-
-		function roundRect(ctx, x, y, w, h, stroke, radius, zeroY) {
-			ctx.beginPath();
-			ctx.moveTo(y + zeroY, x + radius);
-			ctx.lineTo(y + zeroY, x + w - radius);
-			ctx.quadraticCurveTo(y + zeroY, x + w, y + zeroY, x + w);
-			ctx.lineTo(y + h - radius, x + w);
-			ctx.quadraticCurveTo(y + h, x + w, y + h, x + w - radius);
-			ctx.lineTo(y + h, x + radius);
-			ctx.quadraticCurveTo(y + h, x, y + h - radius, x);
-			ctx.lineTo(y + zeroY, x);
-			ctx.quadraticCurveTo(y + zeroY, x, y + zeroY, x + radius);
-			if (stroke) ctx.stroke();
-			ctx.closePath();
-			ctx.fill();
-		};
-
-		function drawScale() {
-			//X axis line                                                          
-			ctx.lineWidth = config.scaleLineWidth;
-			ctx.strokeStyle = config.scaleLineColor;
-			ctx.beginPath();
-			ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY);
-			ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY);
-			ctx.stroke();
-			for (var i = ((config.showYAxisMin) ? -1 : 0); i < calculatedScale.steps; i++) {
-				if (i >= 0) {
-					ctx.beginPath();
-					ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom);
-					ctx.lineWidth = config.scaleGridLineWidth;
-					ctx.strokeStyle = config.scaleGridLineColor;
-					//Check i isnt 0, so we dont go over the Y axis twice.
-					if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) {
-						ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
-					} else {
-						ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY);
-					}
-					ctx.stroke();
-				}
-			}
-			//Y axis
-			ctx.lineWidth = config.scaleLineWidth;
-			ctx.strokeStyle = config.scaleLineColor;
-			ctx.beginPath();
-			ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom);
-			ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop);
-			ctx.stroke();
-			for (var j = 0; j < data.labels.length; j++) {
-				ctx.beginPath();
-				ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop));
-				ctx.lineWidth = config.scaleGridLineWidth;
-				ctx.strokeStyle = config.scaleGridLineColor;
-				if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) {
-					ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY - ((j + 1) * scaleHop));
-				} else {
-					ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop));
-				}
-				ctx.stroke();
-			}
-		};
-
-		function drawLabels() {
-			ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
-			//X axis line                                                          
-			if (config.scaleShowLabels && (config.xAxisTop || config.xAxisBottom)) {
-				ctx.textBaseline = "top";
-				if (msr.rotateLabels > 90) {
-					ctx.save();
-					ctx.textAlign = "left";
-				} else if (msr.rotateLabels > 0) {
-					ctx.save();
-					ctx.textAlign = "right";
-				} else {
-					ctx.textAlign = "center";
-				}
-				ctx.fillStyle = config.scaleFontColor;
-				if (config.xAxisBottom) {
-					for (var i = ((config.showYAxisMin) ? -1 : 0); i < calculatedScale.steps; i++) {
-						ctx.save();
-						if (msr.rotateLabels > 0) {
-							ctx.translate(yAxisPosX + (i + 1) * valueHop - msr.highestXLabel / 2, msr.xLabelPos);
-							ctx.rotate(-(msr.rotateLabels * (Math.PI / 180)));
-							ctx.fillTextMultiLine(calculatedScale.labels[i + 1], 0, 0, ctx.textBaseline, config.scaleFontSize,true);
-						} else {
-							ctx.fillTextMultiLine(calculatedScale.labels[i + 1], yAxisPosX + (i + 1) * valueHop, msr.xLabelPos, ctx.textBaseline, config.scaleFontSize,true);
-						}
-						ctx.restore();
-					}
-				}
-			}
-			//Y axis
-			ctx.textAlign = "right";
-			ctx.textBaseline = "middle";
-			for (var j = 0; j < data.labels.length; j++) {
-				if (config.yAxisLeft) {
-					ctx.textAlign = "right";
-					ctx.fillTextMultiLine(fmtChartJS(config, data.labels[j], config.fmtXLabel), yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - (j * scaleHop) - scaleHop / 2, ctx.textBaseline, config.scaleFontSize,true);
-				}
-				if (config.yAxisRight) {
-					ctx.textAlign = "left";
-					ctx.fillTextMultiLine(fmtChartJS(config, data.labels[j], config.fmtXLabel), yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - (j * scaleHop) - scaleHop / 2, ctx.textBaseline, config.scaleFontSize,true);
-				}
-			}
-		};
-
-		function getValueBounds() {
-			var upperValue = -Number.MAX_VALUE;
-			var lowerValue = Number.MAX_VALUE;
-			for (var i = 0; i < data.datasets.length; i++) {
-				for (var j = 0; j < data.datasets[i].data.length; j++) {
-					if(typeof data.datasets[i].data[j]=="undefined")continue;
-					if (1 * data.datasets[i].data[j] > upperValue) {
-						upperValue = 1 * data.datasets[i].data[j]
-					};
-					if (1 * data.datasets[i].data[j] < lowerValue) {
-						lowerValue = 1 * data.datasets[i].data[j]
-					};
-				}
-			};
-			if(upperValue<lowerValue){upperValue=0;lowerValue=0;}
-			if (Math.abs(upperValue - lowerValue) < config.zeroValue) {
-				if(Math.abs(upperValue)< config.zeroValue) upperValue = .9;
-				if(upperValue>0) {
-					upperValue=upperValue*1.1;
-					lowerValue=lowerValue*0.9;
-				} else {
-					upperValue=upperValue*0.9;
-					lowerValue=lowerValue*1.1;
-				}
-			}
-			// AJOUT CHANGEMENT
-			if(typeof config.graphMin=="function")lowerValue= setOptionValue("GRAPHMIN",ctx,data,statData,undefined,config.graphMin,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMin)) lowerValue = config.graphMin;
-			if(typeof config.graphMax=="function") upperValue= setOptionValue("GRAPHMAX",ctx,data,statData,undefined,config.graphMax,-1,-1,{nullValue : true})
-			else if (!isNaN(config.graphMax)) upperValue = config.graphMax;
-
-			labelHeight = config.scaleFontSize;
-			scaleHeight = msr.availableHeight;
-
-			var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66)));
-			var minSteps = Math.floor((scaleHeight / labelHeight * 0.5));
-			return {
-				maxValue: upperValue,
-				minValue: lowerValue,
-				maxSteps: maxSteps,
-				minSteps: minSteps
-			};
-		};
-	};
-
-	function calculateOffset(logarithmic, val, calculatedScale, scaleHop) {
-		if (!logarithmic) { // no logarithmic scale
-			var outerValue = calculatedScale.steps * calculatedScale.stepValue;
-			var adjustedValue = val - calculatedScale.graphMin;
-			var scalingFactor = CapValue(adjustedValue / outerValue, 1, 0);
-			return (scaleHop * calculatedScale.steps) * scalingFactor;
-		} else { // logarithmic scale
-			return CapValue(log10(val) * scaleHop - calculateOrderOfMagnitude(calculatedScale.graphMin) * scaleHop, undefined, 0);
-		}
-	};
-
-	function animationLoop(config, drawScale, drawData, ctx, clrx, clry, clrwidth, clrheight, midPosX, midPosY, borderX, borderY, data) {
-		var cntiter = 0;
-		var animationCount = 1;
-		var multAnim = 1;
-		if (config.animationStartValue < 0 || config.animationStartValue > 1) config.animation.StartValue = 0;
-		if (config.animationStopValue < 0 || config.animationStopValue > 1) config.animation.StopValue = 1;
-		if (config.animationStopValue < config.animationStartValue) config.animationStopValue = config.animationStartValue;
-		if (isIE() < 9 && isIE() != false) config.animation = false;
-		var animFrameAmount = (config.animation) ? 1 / CapValue(config.animationSteps, Number.MAX_VALUE, 1) : 1,
-			easingFunction = animationOptions[config.animationEasing],
-			percentAnimComplete = (config.animation) ? 0 : 1;
-		if (config.animation && config.animationStartValue > 0 && config.animationStartValue <= 1) {
-			while (percentAnimComplete < config.animationStartValue) {
-				cntiter++;
-				percentAnimComplete += animFrameAmount;
-			}
-		}
-		var beginAnim = cntiter;
-		var beginAnimPct = percentAnimComplete;
-		if (typeof drawScale !== "function") drawScale = function() {};
-		if (config.clearRect) requestAnimFrame(animLoop);
-		else animLoop();
-
-		function animateFrame() {
-			var easeAdjustedAnimationPercent = (config.animation) ? CapValue(easingFunction(percentAnimComplete), null, 0) : 1;
-			if (1 * cntiter >= 1 * CapValue(config.animationSteps, Number.MAX_VALUE, 1) || config.animation == false || ctx.firstPass==3 || ctx.firstPass==4 || ctx.firstPass==8 || ctx.firstPass==9) easeAdjustedAnimationPercent = 1;
-			else if (easeAdjustedAnimationPercent >= 1) easeAdjustedAnimationPercent = 0.9999;
-			if (config.animation && !(isIE() < 9 && isIE() != false) && config.clearRect) ctx.clearRect(clrx, clry, clrwidth, clrheight);
-			dispCrossImage(ctx, config, midPosX, midPosY, borderX, borderY, false, data, easeAdjustedAnimationPercent, cntiter);
-			dispCrossText(ctx, config, midPosX, midPosY, borderX, borderY, false, data, easeAdjustedAnimationPercent, cntiter);
-			if (config.scaleOverlay) {
-				drawData(easeAdjustedAnimationPercent);
-				drawScale();
-			} else {
-				drawScale();
-				drawData(easeAdjustedAnimationPercent);
-			}
-			dispCrossImage(ctx, config, midPosX, midPosY, borderX, borderY, true, data, easeAdjustedAnimationPercent, cntiter);
-			dispCrossText(ctx, config, midPosX, midPosY, borderX, borderY, true, data, easeAdjustedAnimationPercent, cntiter);
-		};
-
-		function animLoop() {
-			//We need to check if the animation is incomplete (less than 1), or complete (1).
-			cntiter += multAnim;
-			percentAnimComplete += multAnim * animFrameAmount;
-			if (cntiter == config.animationSteps || config.animation == false || ctx.firstPass==3 || ctx.firstPass==4 || ctx.firstPass==8 || ctx.firstPass==9) percentAnimComplete = 1;
-			else if (percentAnimComplete >= 1) percentAnimComplete = 0.999;
-			animateFrame();
-			//Stop the loop continuing forever
-			if (multAnim == -1 && cntiter <= beginAnim) {
-				if (typeof config.onAnimationComplete == "function" && ctx.runanimationcompletefunction==true) config.onAnimationComplete(ctx, config, data, 0, animationCount + 1);
-				multAnim = 1;
-				requestAnimFrame(animLoop);
-			} else if (percentAnimComplete < config.animationStopValue) {
-				requestAnimFrame(animLoop);
-			} else {
-				if ((animationCount < config.animationCount || config.animationCount == 0) && (ctx.firstPass ==1 || ctx.firstPass!=2)) {
-					animationCount++;
-					if (config.animationBackward && multAnim == 1) {
-						percentAnimComplete -= animFrameAmount;
-						multAnim = -1;
-					} else {
-						multAnim = 1;
-						cntiter = beginAnim - 1;
-						percentAnimComplete = beginAnimPct - animFrameAmount;
-					}
-					window.setTimeout(animLoop, config.animationPauseTime*1000);
-				} else {
-					if(!testRedraw(ctx,data,config) ) {
-						if (typeof config.onAnimationComplete == "function" && ctx.runanimationcompletefunction==true) {
-							config.onAnimationComplete(ctx, config, data, 1, animationCount + 1);
-							ctx.runanimationcompletefunction=false;
-						}
-					}
-				}
-				
-			}
-		};
-	};
-	//Declare global functions to be called within this namespace here.
-	// shim layer with setTimeout fallback
-	var requestAnimFrame = (function() {
-		return window.requestAnimationFrame ||
-			window.webkitRequestAnimationFrame ||
-			window.mozRequestAnimationFrame ||
-			window.oRequestAnimationFrame ||
-			window.msRequestAnimationFrame ||
-			function(callback) {
-				window.setTimeout(callback, 1000 / 60);
-			};
-	})();
-
-	function calculateScale(axis, config, maxSteps, minSteps, maxValue, minValue, labelTemplateString) {
-		var graphMin, graphMax, graphRange, stepValue, numberOfSteps, valueRange, rangeOrderOfMagnitude, decimalNum;
-		var logarithmic, yAxisMinimumInterval;
-		if (axis == 2) {
-			logarithmic = config.logarithmic2;
-			yAxisMinimumInterval = config.yAxisMinimumInterval2;
-		} else {
-			logarithmic = config.logarithmic;
-			yAxisMinimumInterval = config.yAxisMinimumInterval;
-		}
-
-		if (!logarithmic) { // no logarithmic scale
-			valueRange = maxValue - minValue;
-			rangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange);
-			if(Math.abs(minValue)>config.zeroValue)graphMin = Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude);
-			else graphMin=0;
-			if(Math.abs(maxValue)>config.zeroValue)graphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude);
-			else graphMax=0;
-			if (typeof yAxisMinimumInterval == "number") {
-				if(graphMax>=0) {
-					graphMin = graphMin - (graphMin % yAxisMinimumInterval);
-					while (graphMin > minValue) graphMin = graphMin - yAxisMinimumInterval;
-					if (graphMax % yAxisMinimumInterval > config.zeroValue && graphMax % yAxisMinimumInterval < yAxisMinimumInterval - config.zeroValue) {
-						graphMax = roundScale(config, (1 + Math.floor(graphMax / yAxisMinimumInterval)) * yAxisMinimumInterval);
-					}
-					while (graphMax < maxValue) graphMax = graphMax + yAxisMinimumInterval;
-				}
-			}
-		} else { // logarithmic scale
-			if(minValue==maxValue)maxValue=maxValue+1;
-			if(minValue==0)minValue=0.01;
-			var minMag = calculateOrderOfMagnitude(minValue);
-			var maxMag = calculateOrderOfMagnitude(maxValue) + 1;
-			graphMin = Math.pow(10, minMag);
-			graphMax = Math.pow(10, maxMag);
-			rangeOrderOfMagnitude = maxMag - minMag;
-		}
-		graphRange = graphMax - graphMin;
-		stepValue = Math.pow(10, rangeOrderOfMagnitude);
-		numberOfSteps = Math.round(graphRange / stepValue);
-		if (!logarithmic) { // no logarithmic scale
-			//Compare number of steps to the max and min for that size graph, and add in half steps if need be.
-			var stopLoop = false;
-			while (!stopLoop && (numberOfSteps < minSteps || numberOfSteps > maxSteps)) {
-				if (numberOfSteps < minSteps) {
-					if (typeof yAxisMinimumInterval == "number") {
-						if (stepValue / 2 < yAxisMinimumInterval) stopLoop = true;
-					}
-					if (!stopLoop) {
-						stepValue /= 2;
-						numberOfSteps = Math.round(graphRange / stepValue);
-					}
-				} else {
-					stepValue *= 2;
-					numberOfSteps = Math.round(graphRange / stepValue);
-				}
-			}
-
-			if (typeof yAxisMinimumInterval == "number") {
-				if (stepValue < yAxisMinimumInterval) {
-					stepValue = yAxisMinimumInterval;
-					numberOfSteps = Math.round(graphRange / stepValue);
-				}
-				if (stepValue % yAxisMinimumInterval > config.zeroValue && stepValue % yAxisMinimumInterval < yAxisMinimumInterval - config.zeroValue) {
-					if ((2 * stepValue) % yAxisMinimumInterval < config.zeroValue || (2 * stepValue) % yAxisMinimumInterval > yAxisMinimumInterval - config.zeroValue) {
-						stepValue = 2 * stepValue;
-						numberOfSteps = Math.round(graphRange / stepValue);
-					} else {
-						stepValue = roundScale(config, (1 + Math.floor(stepValue / yAxisMinimumInterval)) * yAxisMinimumInterval);
-						numberOfSteps = Math.round(graphRange / stepValue);
-					}
-				}
-			}
-		} else { // logarithmic scale
-			numberOfSteps = rangeOrderOfMagnitude; // so scale is 10,100,1000,...
-		}
-		var labels = [];
-		populateLabels(1, config, labelTemplateString, labels, numberOfSteps, graphMin, graphMax, stepValue);
-		return {
-			steps: numberOfSteps,
-			stepValue: stepValue,
-			graphMin: graphMin,
-			labels: labels,
-			maxValue: maxValue
-		}
-	};
-
-	function roundScale(config, value) {
-		var scldec = 0;
-		var sscl = "" + config.yAxisMinimumInterval;
-		if (sscl.indexOf(".") > 0) {
-			scldec = sscl.substr(sscl.indexOf(".")).length;
-		}
-		return (Math.round(value * Math.pow(10, scldec)) / Math.pow(10, scldec));
-	} ;
-
-	function calculateOrderOfMagnitude(val) {
-		if (val==0)return 0;
-		return Math.floor(Math.log(val) / Math.LN10);
-	};
-	//Populate an array of all the labels by interpolating the string.
-	function populateLabels(axis, config, labelTemplateString, labels, numberOfSteps, graphMin, graphMax, stepValue) {
-		var logarithmic;
-		if (axis == 2) {
-			logarithmic = config.logarithmic2;
-			fmtYLabel = config.fmtYLabel2;
-		} else {
-			logarithmic = config.logarithmic;
-			fmtYLabel = config.fmtYLabel;
-		}
-		if (labelTemplateString) {
-			//Fix floating point errors by setting to fixed the on the same decimal as the stepValue.
-			if (!logarithmic) { // no logarithmic scale
-				for (var i = 0; i < numberOfSteps + 1; i++) {
-					labels.push(tmpl(labelTemplateString, {
-						value: fmtChartJS(config, 1 * ((graphMin + (stepValue * i)).toFixed(getDecimalPlaces(stepValue))), fmtYLabel)
-					}));
-				}
-			} else { // logarithmic scale 10,100,1000,...
-				var value = graphMin;
-				for (var i = 0; i < numberOfSteps + 1; i++) {
-					labels.push(tmpl(labelTemplateString, {
-						value: fmtChartJS(config, 1 * value.toFixed(getDecimalPlaces(value)), fmtYLabel)
-					}));
-					value *= 10;
-				}
-			}
-		}
-	};
-	//Max value from array
-	function Max(array) {
-		return Math.max.apply(Math, array);
-	};
-	//Min value from array
-	function Min(array) {
-		return Math.min.apply(Math, array);
-	};
-	//Default if undefined
-	function Default(userDeclared, valueIfFalse) {
-		if (!userDeclared) {
-			return valueIfFalse;
-		} else {
-			return userDeclared;
-		}
-	};
-	//Apply cap a value at a high or low number
-	function CapValue(valueToCap, maxValue, minValue) {
-		if (isNumber(maxValue)) {
-			if (valueToCap > maxValue) {
-				return maxValue;
-			}
-		}
-		if (isNumber(minValue)) {
-			if (valueToCap < minValue) {
-				return minValue;
-			}
-		}
-		return valueToCap;
-	};
-
-	function getDecimalPlaces(num) {
-		var match = (''+num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
-		if (!match) { 
-			return 0;
-		}
-		return Math.max(
-			0,
-			(match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0)
-		);
-	};
-
-	function mergeChartConfig(defaults, userDefined) {
-		var returnObj = {};
-		for (var attrname in defaults) {
-			returnObj[attrname] = defaults[attrname];
-		}
-		for (var attrname in userDefined) {
-			returnObj[attrname] = userDefined[attrname];
-		}
-		return returnObj;
-	};
-	//Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/
-	var cache = {};
-
-	function tmpl(str, data) {
-		// Figure out if we're getting a template, or if we need to
-		// load the template - and be sure to cache the result.
-		var fn = !/\W/.test(str) ?
-			cache[str] = cache[str] ||
-			tmpl(document.getElementById(str).innerHTML) :
-			// Generate a reusable function that will serve as a template
-			// generator (and which will be cached).
-			new Function("obj",
-				"var p=[],print=function(){p.push.apply(p,arguments);};" +
-				// Introduce the data as local variables using with(){}
-				"with(obj){p.push('" +
-				// Convert the template into pure JavaScript
-				str
-				.replace(/[\r\t\n]/g, " ")
-				.split("<%").join("\t")
-				.replace(/((^|%>)[^\t]*)'/g, "$1\r")
-				.replace(/\t=(.*?)%>/g, "',$1,'")
-				.split("\t").join("');")
-				.split("%>").join("p.push('")
-				.split("\r").join("\\'") + "');}return p.join('');");
-		// Provide some basic currying to the user
-		return data ? fn(data) : fn;
-	};
-
-	function dispCrossText(ctx, config, posX, posY, borderX, borderY, overlay, data, animPC, cntiter) {
-		var i, disptxt, txtposx, txtposy, textAlign, textBaseline;
-		for (i = 0; i < config.crossText.length; i++) {
-			if (config.crossText[i] != "" && config.crossTextOverlay[Min([i, config.crossTextOverlay.length - 1])] == overlay && ((cntiter == 1 && config.crossTextIter[Min([i, config.crossTextIter.length - 1])] == "first") || config.crossTextIter[Min([i, config.crossTextIter.length - 1])] == cntiter || config.crossTextIter[Min([i, config.crossTextIter.length - 1])] == "all" || (animPC == 1 && config.crossTextIter[Min([i, config.crossTextIter.length - 1])] == "last"))) {
-				ctx.save();
-				ctx.beginPath();
-				ctx.font = config.crossTextFontStyle[Min([i, config.crossTextFontStyle.length - 1])] + " " + config.crossTextFontSize[Min([i, config.crossTextFontSize.length - 1])] + "px " + config.crossTextFontFamily[Min([i, config.crossTextFontFamily.length - 1])];
-				ctx.fillStyle = config.crossTextFontColor[Min([i, config.crossTextFontColor.length - 1])];
-				textAlign = config.crossTextAlign[Min([i, config.crossTextAlign.length - 1])];
-				textBaseline = config.crossTextBaseline[Min([i, config.crossTextBaseline.length - 1])];
-				txtposx = 1 * config.crossTextPosX[Min([i, config.crossTextPosX.length - 1])];
-				txtposy = 1 * config.crossTextPosY[Min([i, config.crossTextPosY.length - 1])];
-				switch (1 * config.crossTextRelativePosX[Min([i, config.crossTextRelativePosX.length - 1])]) {
-					case 0:
-						if (textAlign == "default") textAlign = "left";
-						break;
-					case 1:
-						txtposx += borderX;
-						if (textAlign == "default") textAlign = "right";
-						break;
-					case 2:
-						txtposx += posX;
-						if (textAlign == "default") textAlign = "center";
-						break;
-					case -2:
-						txtposx += context.canvas.width / 2;
-						if (textAlign == "default") textAlign = "center";
-						break;
-					case 3:
-						txtposx += txtposx + 2 * posX - borderX;
-						if (textAlign == "default") textAlign = "left";
-						break;
-					case 4:
-						txtposx += context.canvas.width;
-						if (textAlign == "default") textAlign = "right";
-						break;
-					default:
-						txtposx += posX;
-						if (textAlign == "default") textAlign = "center";
-						break;
-				}
-				switch (1 * config.crossTextRelativePosY[Min([i, config.crossTextRelativePosY.length - 1])]) {
-					case 0:
-						if (textBaseline == "default") textBaseline = "top";
-						break;
-					case 3:
-						txtposy += borderY;
-						if (textBaseline == "default") textBaseline = "top";
-						break;
-					case 2:
-						txtposy += posY;
-						if (textBaseline == "default") textBaseline = "middle";
-						break;
-					case -2:
-						txtposy += context.canvas.height / 2;
-						if (textBaseline == "default") textBaseline = "middle";
-						break;
-					case 1:
-						txtposy += txtposy + 2 * posY - borderY;
-						if (textBaseline == "default") textBaseline = "bottom";
-						break;
-					case 4:
-						txtposy += context.canvas.height;
-						if (textBaseline == "default") textBaseline = "bottom";
-						break;
-					default:
-						txtposy += posY;
-						if (textBaseline == "default") textBaseline = "middle";
-						break;
-				}
-				ctx.textAlign = textAlign;
-				ctx.textBaseline = textBaseline;
-				ctx.translate(1 * txtposx, 1 * txtposy);
-				ctx.rotate(Math.PI * config.crossTextAngle[Min([i, config.crossTextAngle.length - 1])] / 180);
-				if (config.crossText[i].substring(0, 1) == "%") {
-					if (typeof config.crossTextFunction == "function") disptxt = config.crossTextFunction(i, config.crossText[i], ctx, config, posX, posY, borderX, borderY, overlay, data, animPC);
-				} else disptxt = config.crossText[i];
-				ctx.fillTextMultiLine(disptxt, 0, 0, ctx.textBaseline, config.crossTextFontSize[Min([i, config.crossTextFontSize.length - 1])],true);
-				ctx.stroke();
-				ctx.restore();
-			}
-		}
-	};
-
-	function dispCrossImage(ctx, config, posX, posY, borderX, borderY, overlay, data, animPC, cntiter) {
-		var i, disptxt, imageposx, imageposy, imageAlign, imageBaseline;
-		for (i = 0; i < config.crossImage.length; i++) {
-			if (typeof config.crossImage[i] != "undefined" && config.crossImageOverlay[Min([i, config.crossImageOverlay.length - 1])] == overlay && ((cntiter == -1 && config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == "background") || (cntiter == 1 && config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == "first") || config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == cntiter || (cntiter != -1 && config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == "all") || (animPC == 1 && config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == "last"))) {
-				ctx.save();
-				ctx.beginPath();
-				imageAlign = config.crossImageAlign[Min([i, config.crossImageAlign.length - 1])];
-				imageBaseline = config.crossImageBaseline[Min([i, config.crossImageBaseline.length - 1])];
-				imageposx = 1 * config.crossImagePosX[Min([i, config.crossImagePosX.length - 1])];
-				imageposy = 1 * config.crossImagePosY[Min([i, config.crossImagePosY.length - 1])];
-				switch (1 * config.crossImageRelativePosX[Min([i, config.crossImageRelativePosX.length - 1])]) {
-					case 0:
-						if (imageAlign == "default") imageAlign = "left";
-						break;
-					case 1:
-						imageposx += borderX;
-						if (imageAlign == "default") imageAlign = "right";
-						break;
-					case 2:
-						imageposx += posX;
-						if (imageAlign == "default") imageAlign = "center";
-						break;
-					case -2:
-						imageposx += context.canvas.width / 2;
-						if (imageAlign == "default") imageAlign = "center";
-						break;
-					case 3:
-						imageposx += imageposx + 2 * posX - borderX;
-						if (imageAlign == "default") imageAlign = "left";
-						break;
-					case 4:
-						imageposx += context.canvas.width;
-						if (imageAlign == "default") imageAlign = "right";
-						break;
-					default:
-						imageposx += posX;
-						if (imageAlign == "default") imageAlign = "center";
-						break;
-				}
-				switch (1 * config.crossImageRelativePosY[Min([i, config.crossImageRelativePosY.length - 1])]) {
-					case 0:
-						if (imageBaseline == "default") imageBaseline = "top";
-						break;
-					case 3:
-						imageposy += borderY;
-						if (imageBaseline == "default") imageBaseline = "top";
-						break;
-					case 2:
-						imageposy += posY;
-						if (imageBaseline == "default") imageBaseline = "middle";
-						break;
-					case -2:
-						imageposy += context.canvas.height / 2;
-						if (imageBaseline == "default") imageBaseline = "middle";
-						break;
-					case 1:
-						imageposy += imageposy + 2 * posY - borderY;
-						if (imageBaseline == "default") imageBaseline = "bottom";
-						break;
-					case 4:
-						imageposy += context.canvas.height;
-						if (imageBaseline == "default") imageBaseline = "bottom";
-						break;
-					default:
-						imageposy += posY;
-						if (imageBaseline == "default") imageBaseline = "middle";
-						break;
-				}
-				var imageWidth = config.crossImage[i].width;
-				switch (imageAlign) {
-					case "left":
-						break;
-					case "right":
-						imageposx -= imageWidth;
-						break;
-					case "center":
-						imageposx -= (imageWidth / 2);
-						break;
-					default:
-						break;
-				}
-				var imageHeight = config.crossImage[i].height;
-				switch (imageBaseline) {
-					case "top":
-						break;
-					case "bottom":
-						imageposy -= imageHeight;
-						break;
-					case "middle":
-						imageposy -= (imageHeight / 2);
-						break;
-					default:
-						break;
-				}
-				ctx.translate(1 * imageposx, 1 * imageposy);
-				ctx.rotate(Math.PI * config.crossImageAngle[Min([i, config.crossImageAngle.length - 1])] / 180);
-				ctx.drawImage(config.crossImage[i], 0, 0);
-				ctx.restore();
-			}
-		}
-	};
-	//****************************************************************************************
-	function setMeasures(data, config, ctx, height, width, ylabels, ylabels2, reverseLegend, reverseAxis, drawAxis, drawLegendOnData, legendBox, typegraph) {
-		if (config.canvasBackgroundColor != "none") ctx.canvas.style.background = config.canvasBackgroundColor;
-		var borderWidth = 0;
-		var xAxisLabelPos = 0;
-		var graphTitleHeight = 0;
-		var graphTitlePosY = 0;
-		var graphSubTitleHeight = 0;
-		var graphSubTitlePosY = 0;
-		var footNoteHeight = 0;
-		var footNotePosY = 0;
-		var yAxisUnitHeight = 0;
-		var yAxisUnitPosY = 0;
-		var widestLegend = 0;
-		var nbeltLegend = 0;
-		var nbLegendLines = 0;
-		var nbLegendCols = 0;
-		var spaceLegendHeight = 0;
-		var xFirstLegendTextPos = 0;
-		var yFirstLegendTextPos = 0;
-		var xLegendBorderPos = 0;
-		var yLegendBorderPos = 0;
-		var yAxisLabelWidth = 0;
-		var yAxisLabelPosLeft = 0;
-		var yAxisLabelPosRight = 0;
-		var xAxisLabelHeight = 0;
-		var xLabelHeight = 0;
-		var widestXLabel = 1;
-		var highestXLabel = 1;
-		var widestYLabel = 0;
-		var highestYLabel = 1;
-		var widestYLabel2 = 0;
-		var highestYLabel2 = 1;
-		var leftNotUsableSize = 0;
-		var rightNotUsableSize = 0;
-		var rotateLabels = 0;
-		var xLabelPos = 0;
-		var legendBorderWidth = 0;
-		var legendBorderHeight = 0;
-		
-		ctx.widthAtSetMeasures=width;
-		ctx.heightAtSetMeasures=height;
-		
-		// Borders
-		if (config.canvasBorders) borderWidth = config.canvasBordersWidth;
-		// compute widest X label
-		if (drawAxis) {
-			ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
-			for (var i = 0; i < data.labels.length; i++) {
-				var textMsr = ctx.measureTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), config.scaleFontSize);
-				//If the text length is longer - make that equal to longest text!
-				widestXLabel = (textMsr.textWidth > widestXLabel) ? textMsr.textWidth : widestXLabel;
-				highestXLabel = (textMsr.textHeight > highestXLabel) ? textMsr.textHeight : highestXLabel;
-			}
-			if (widestXLabel < config.xScaleLabelsMinimumWidth) {
-				widestXLabel = config.xScaleLabelsMinimumWidth;
-			}
-		}
-		// compute Y Label Width
-		if (drawAxis) {
-			widestYLabel = 1;
-			if (ylabels != null && ylabels != "nihil") {
-				ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
-				for (var i = ylabels.length - 1; i >= 0; i--) {
-					if (typeof(ylabels[i]) == "string") {
-						if (ylabels[i].trim() != "") {
-							var textMsr = ctx.measureTextMultiLine(fmtChartJS(config, ylabels[i], config.fmtYLabel), config.scaleFontSize);
-							//If the text length is longer - make that equal to longest text!
-							widestYLabel = (textMsr.textWidth > widestYLabel) ? textMsr.textWidth : widestYLabel;
-							highestYLabel = (textMsr.textHeight > highestYLabel) ? textMsr.textHeight : highestYLabel;
-						}
-					}
-				}
-			}
-			if (widestYLabel < config.yScaleLabelsMinimumWidth) {
-				widestYLabel = config.yScaleLabelsMinimumWidth;
-			}
-			widestYLabel2 = 1;
-			if (ylabels2 != null && config.yAxisRight) {
-				ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily;
-				for (var i = ylabels2.length - 1; i >= 0; i--) {
-					if (typeof(ylabels2[i]) == "string") {
-						if (ylabels2[i].trim() != "") {
-							var textMsr = ctx.measureTextMultiLine(fmtChartJS(config, ylabels2[i], config.fmtYLabel2), config.scaleFontSize);
-							//If the text length is longer - make that equal to longest text!
-							widestYLabel2 = (textMsr.textWidth > widestYLabel2) ? textMsr.textWidth : widestYLabel2;
-							highestYLabel2 = (textMsr.textHeight > highestYLabel2) ? textMsr.textHeight : highestYLabel2;
-						}
-					}
-				}
-			} else {
-				widestYLabel2 = widestYLabel;
-			}
-			if (widestYLabel2 < config.yScaleLabelsMinimumWidth) {
-				widestYLabel2 = config.yScaleLabelsMinimumWidth;
-			}
-		}
-		// yAxisLabel
-		leftNotUsableSize = borderWidth + config.spaceLeft
-		rightNotUsableSize = borderWidth + config.spaceRight;
-		if (drawAxis) {
-			if (typeof(config.yAxisLabel) != "undefined") {
-				if (config.yAxisLabel.trim() != "") {
-					yAxisLabelWidth = config.yAxisFontSize * (config.yAxisLabel.split("\n").length || 1) + config.yAxisLabelSpaceLeft + config.yAxisLabelSpaceRight;
-					yAxisLabelPosLeft = borderWidth + config.spaceLeft + config.yAxisLabelSpaceLeft + config.yAxisFontSize;
-					yAxisLabelPosRight = width - borderWidth - config.spaceRight - config.yAxisLabelSpaceLeft - config.yAxisFontSize;
-				}
-			}
-			if (config.yAxisLeft) {
-				if (reverseAxis == false) leftNotUsableSize = borderWidth + config.spaceLeft + yAxisLabelWidth + widestYLabel + config.yAxisSpaceLeft + config.yAxisSpaceRight;
-				else leftNotUsableSize = borderWidth + config.spaceLeft + yAxisLabelWidth + widestXLabel + config.yAxisSpaceLeft + config.yAxisSpaceRight;
-			}
-			if (config.yAxisRight) {
-				if (reverseAxis == false) rightNotUsableSize = borderWidth + config.spaceRight + yAxisLabelWidth + widestYLabel2 + config.yAxisSpaceLeft + config.yAxisSpaceRight;
-				else rightNotUsableSize = borderWidth + config.spaceRight + yAxisLabelWidth + widestXLabel + config.yAxisSpaceLeft + config.yAxisSpaceRight;
-			}
-		}
-		availableWidth = width - leftNotUsableSize - rightNotUsableSize;
-		// Title
-		if (config.graphTitle.trim() != "") {
-			graphTitleHeight = config.graphTitleFontSize * (config.graphTitle.split("\n").length || 1) + config.graphTitleSpaceBefore + config.graphTitleSpaceAfter;
-			graphTitlePosY = borderWidth + config.spaceTop + graphTitleHeight - config.graphTitleSpaceAfter;
-		}
-		// subTitle
-		if (config.graphSubTitle.trim() != "") {
-			graphSubTitleHeight = config.graphSubTitleFontSize * (config.graphSubTitle.split("\n").length || 1) + config.graphSubTitleSpaceBefore + config.graphSubTitleSpaceAfter;
-			graphSubTitlePosY = borderWidth + config.spaceTop + graphTitleHeight + graphSubTitleHeight - config.graphSubTitleSpaceAfter;
-		}
-		// yAxisUnit
-		if (drawAxis) {
-			if (config.yAxisUnit.trim() != "") {
-				yAxisUnitHeight = config.yAxisUnitFontSize * (config.yAxisUnit.split("\n").length || 1) + config.yAxisUnitSpaceBefore + config.yAxisUnitSpaceAfter;
-				yAxisUnitPosY = borderWidth + config.spaceTop + graphTitleHeight + graphSubTitleHeight + yAxisUnitHeight - config.yAxisUnitSpaceAfter;
-			}
-		}
-		topNotUsableSize = borderWidth + config.spaceTop + graphTitleHeight + graphSubTitleHeight + yAxisUnitHeight + config.graphSpaceBefore;
-		// footNote
-		if (typeof(config.footNote) != "undefined") {
-			if (config.footNote.trim() != "") {
-				footNoteHeight = config.footNoteFontSize * (config.footNote.split("\n").length || 1) + config.footNoteSpaceBefore + config.footNoteSpaceAfter;
-				footNotePosY = height - config.spaceBottom - borderWidth - config.footNoteSpaceAfter;
-			}
-		}
-		
-		// xAxisLabel
-		if (drawAxis) {
-			if (typeof(config.xAxisLabel) != "undefined") {
-				if (config.xAxisLabel.trim() != "") {
-					xAxisLabelHeight = config.xAxisFontSize * (config.xAxisLabel.split("\n").length || 1) + config.xAxisLabelSpaceBefore + config.xAxisLabelSpaceAfter;
-					xAxisLabelPos = height - borderWidth - config.spaceBottom - footNoteHeight - config.xAxisLabelSpaceAfter;
-				}
-			}
-		}
-
-		bottomNotUsableHeightWithoutXLabels = borderWidth + config.spaceBottom + footNoteHeight + xAxisLabelHeight + config.graphSpaceAfter;
-
-		// compute space for Legend
-		if (typeof(config.legend) != "undefined") {
-			if (config.legend == true) {
-				ctx.font = config.legendFontStyle + " " + config.legendFontSize + "px " + config.legendFontFamily;
-				if (drawLegendOnData) {
-					for (var i = data.datasets.length - 1; i >= 0; i--) {
-						if (typeof(data.datasets[i].title) == "string") {
-							if (data.datasets[i].title.trim() != "") {
-								nbeltLegend++;
-								var textLength = ctx.measureText(fmtChartJS(config, data.datasets[i].title, config.fmtLegend)).width;
-								//If the text length is longer - make that equal to longest text!
-								widestLegend = (textLength > widestLegend) ? textLength : widestLegend;
-							}
-						}
-					}
-				} else {
-					for (var i = data.length - 1; i >= 0; i--) {
-						if (typeof(data[i].title) == "string") {
-							if (data[i].title.trim() != "") {
-								nbeltLegend++;
-								var textLength = ctx.measureText(fmtChartJS(config, data[i].title, config.fmtLegend)).width;
-								//If the text length is longer - make that equal to longest text!
-								widestLegend = (textLength > widestLegend) ? textLength : widestLegend;
-							}
-						}
-					}
-				}
-				if (nbeltLegend > 1 || (nbeltLegend == 1 && config.showSingleLegend)) {
-					widestLegend += config.legendBlockSize + config.legendSpaceBetweenBoxAndText;
-					if(config.legendPosY==1 || config.legendPosY==2 || config.legendPosY==3) {
-						availableLegendWidth = availableWidth- config.legendSpaceLeftText - config.legendSpaceRightText;
-					} else {
-						availableLegendWidth = width - config.spaceLeft - config.spaceRight - 2 * (borderWidth) - config.legendSpaceLeftText - config.legendSpaceRightText;
-					}
-					if (config.legendBorders == true) availableLegendWidth -= 2 * (config.legendBordersWidth) - config.legendBordersSpaceLeft - config.legendBordersSpaceRight;
-					maxLegendOnLine = Min([Math.floor((availableLegendWidth + config.legendSpaceBetweenTextHorizontal) / (widestLegend + config.legendSpaceBetweenTextHorizontal)),config.maxLegendCols]);
-					nbLegendLines = Math.ceil(nbeltLegend / maxLegendOnLine);
-					nbLegendCols = Math.ceil(nbeltLegend / nbLegendLines);
-				
-					var legendHeight = nbLegendLines * (config.legendFontSize + config.legendSpaceBetweenTextVertical) - config.legendSpaceBetweenTextVertical + config.legendSpaceBeforeText + config.legendSpaceAfterText;
-
-					switch (config.legendPosY) {
-						case 0:
-							xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
-							spaceLegendHeight = legendHeight;
-							if (config.legendBorders == true) {
-								yLegendBorderPos = topNotUsableSize + config.legendBordersSpaceBefore + (config.legendBordersWidth/2);
-								yFirstLegendTextPos = yLegendBorderPos  + (config.legendBordersWidth/2) + config.legendSpaceBeforeText+config.legendFontSize;
-								spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
-								xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
-								legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
-								legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
-							} else {
-								yFirstLegendTextPos = topNotUsableSize + config.legendBordersSpaceBefore + (config.legendBordersWidth/2);
-							}
-							if(yAxisUnitHeight>0) {
-								yAxisUnitPosY+=spaceLegendHeight;
-								if(config.legendBorders==true)yLegendBorderPos-=yAxisUnitHeight;
-								yFirstLegendTextPos-=yAxisUnitHeight;
-							}
-							topNotUsableSize += spaceLegendHeight;
-							break;
-						case 1:
-							spaceLegendHeight = legendHeight;
-							xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
-							yFirstLegendTextPos = topNotUsableSize + config.legendSpaceBeforeText+config.legendFontSize;
-							if (config.legendBorders == true) {
-								yFirstLegendTextPos += config.legendBordersSpaceBefore+config.legendBordersWidth;
-								yLegendBorderPos = yFirstLegendTextPos - config.legendSpaceBeforeText - config.legendFontSize - (config.legendBordersWidth /2 );
-								spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
-								xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
-								legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
-								legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
-							}
-							break;
-						case 2:
-							spaceLegendHeight = legendHeight;
-							xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
-							yFirstLegendTextPos = topNotUsableSize + (height - topNotUsableSize - bottomNotUsableHeightWithoutXLabels - spaceLegendHeight) /2 + config.legendSpaceBeforeText+config.legendFontSize;
-							if (config.legendBorders == true) {
-								yFirstLegendTextPos += config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
-								yLegendBorderPos = yFirstLegendTextPos - config.legendSpaceBeforeText - config.legendFontSize - (config.legendBordersWidth /2 );
-								spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
-								xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
-								legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
-								legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
-							}
-							break;
-						case -2:
-							spaceLegendHeight = legendHeight;
-							xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
-							yFirstLegendTextPos = (height - spaceLegendHeight) /2 + config.legendSpaceBeforeText+config.legendFontSize;
-							if (config.legendBorders == true) {
-								yFirstLegendTextPos += config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
-								yLegendBorderPos = yFirstLegendTextPos - config.legendSpaceBeforeText - config.legendFontSize - (config.legendBordersWidth /2 );
-								spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
-								xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
-								legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
-								legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
-							}
-							break;
-						case 3:
-							spaceLegendHeight = legendHeight;
-							xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
-							availableHeight = height - topNotUsableSize - bottomNotUsableHeightWithoutXLabels;
-							yFirstLegendTextPos = topNotUsableSize + availableHeight - spaceLegendHeight + config.legendSpaceBeforeText+config.legendFontSize;
-							if (config.legendBorders == true) {
-								yFirstLegendTextPos -= (config.legendBordersSpaceAfter+config.legendBordersWidth);
-								yLegendBorderPos = yFirstLegendTextPos - config.legendSpaceBeforeText - config.legendFontSize - (config.legendBordersWidth /2 );
-								spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
-								xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
-								legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
-								legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
-							}
-							break;
-						default:
-							spaceLegendHeight = legendHeight;
-							yFirstLegendTextPos = height - borderWidth - config.spaceBottom - footNoteHeight - spaceLegendHeight + config.legendSpaceBeforeText + config.legendFontSize;
-							xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2;
-							if (config.legendBorders == true) {
-								spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter;
-								yFirstLegendTextPos -= (config.legendBordersWidth + config.legendBordersSpaceAfter);
-								yLegendBorderPos = Math.floor(height - borderWidth - config.spaceBottom - footNoteHeight - spaceLegendHeight + (config.legendBordersWidth / 2) + config.legendBordersSpaceBefore);
-								xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2));
-								legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter;
-								legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText;
-							} 
-							xAxisLabelPos -= spaceLegendHeight;
-							bottomNotUsableHeightWithoutXLabels +=spaceLegendHeight;
-							break;
-					}		
-					var fullLegendWidth=config.legendSpaceRightText + nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) - config.legendSpaceBetweenTextHorizontal +config.legendSpaceLeftText;
-					if (config.legendBorders == true) {
-						fullLegendWidth+=2*config.legendBordersWidth+config.legendBordersSpaceLeft+config.legendBordersSpaceRight;
-					}
-
-					switch (config.legendPosX) {
-						case 0:
-							xFirstLegendTextPos = config.spaceLeft + config.canvasBorders * config.canvasBordersWidth + config.legendSpaceLeftText;  
-							if (config.legendBorders == true) {
-								xFirstLegendTextPos += (config.legendBordersWidth/2)+config.legendBordersSpaceLeft;
-								xLegendBorderPos = config.spaceLeft + config.canvasBorders * config.canvasBordersWidth + config.legendBordersSpaceLeft;
-							}
-							if((config.legendPosY>=1 && config.legendPosY <=3) || config.legendPosY==-2) {
-								leftNotUsableSize+=fullLegendWidth;
-								yAxisLabelPosLeft+=fullLegendWidth;
-							}
-							break;
-						case 1:
-							xFirstLegendTextPos = leftNotUsableSize + config.legendSpaceLeftText;  
-							if (config.legendBorders == true) {
-								xLegendBorderPos = xFirstLegendTextPos;
-								xFirstLegendTextPos += (config.legendBordersWidth/2) +config.legendBordersSpaceLeft;
-							}
-							break;
-						case 2:
-							xFirstLegendTextPos = leftNotUsableSize + (width - rightNotUsableSize - leftNotUsableSize)/2 - (config.legendSpaceLeftText-config.legendSpaceRightText) - (nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) - config.legendSpaceBetweenTextHorizontal) / 2;  
-							if (config.legendBorders == true) {
-								xFirstLegendTextPos -= ((config.legendBordersWidth/2) + config.legendBordersSpaceRight);
-								xLegendBorderPos = xFirstLegendTextPos - config.legendBordersWidth/2 - config.legendSpaceLeftText ;
-							}
-							break;
-						case 3:
-							
-							xFirstLegendTextPos = width - rightNotUsableSize - config.legendSpaceRightText - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal / 2;  
-							if (config.legendBorders == true) {
-								xFirstLegendTextPos -= ((config.legendBordersWidth/2) + config.legendBordersSpaceRight);
-								xLegendBorderPos = xFirstLegendTextPos - config.legendBordersWidth/2 - config.legendSpaceLeftText ;
-							}
-							break;
-						case 4:
-							xFirstLegendTextPos = width - config.spaceRight - config.canvasBorders * config.canvasBordersWidth - config.legendSpaceRightText - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal / 2;  
-							if (config.legendBorders == true) {
-								xFirstLegendTextPos -= ((config.legendBordersWidth/2)+config.legendBordersSpaceRight);
-								xLegendBorderPos = xFirstLegendTextPos - config.legendBordersSpaceLeft - config.legendBordersWidth/2;
-							}
-							if((config.legendPosY>=1 && config.legendPosY <=3) || config.legendPosY==-2) {
-								rightNotUsableSize+=fullLegendWidth;
-								yAxisLabelPosRight-=fullLegendWidth;
-							}
-							break;
-							
-						default:
-							break;
-					}
-					if(config.legendBorders==true) {
-						yLegendBorderPos+=config.legendYPadding;
-						xLegendBorderPos+=config.legendXPadding;
-						
-					}
-					yFirstLegendTextPos+=config.legendYPadding;	
-					xFirstLegendTextPos+=config.legendXPadding;	
-					
-				}
-			}
-		}
-		xLabelWidth = 0;
-		bottomNotUsableHeightWithXLabels = bottomNotUsableHeightWithoutXLabels;
-		if (drawAxis && (config.xAxisBottom || config.xAxisTop)) {
-			if (reverseAxis == false) {
-				var widestLabel = widestXLabel;
-				var highestLabel = highestXLabel;
-				nblab = data.labels.length;
-			} else {
-				var widestLabel = widestYLabel;
-				var highestLabel = highestYLabel;
-				nblab = ylabels.length;
-			}
-			if (config.rotateLabels == "smart") {
-				rotateLabels = 0;
-				if ((availableWidth + config.xAxisSpaceBetweenLabels) / nblab < (widestLabel + config.xAxisSpaceBetweenLabels)) {
-					rotateLabels = 45;
-					if (availableWidth / nblab < Math.abs(Math.cos(rotateLabels * Math.PI / 180) * widestLabel)) {
-						rotateLabels = 90;
-					}
-				}
-			} else {
-				rotateLabels = config.rotateLabels
-				if (rotateLabels < 0) rotateLabels = 0;
-				if (rotateLabels > 180) rotateLabels = 180;
-			}
-			if (rotateLabels > 90) rotateLabels += 180;
-			xLabelHeight = Math.abs(Math.sin(rotateLabels * Math.PI / 180) * widestLabel) + Math.abs(Math.sin((rotateLabels + 90) * Math.PI / 180) * highestLabel) + config.xAxisSpaceBefore + config.xAxisSpaceAfter;
-			xLabelPos = height - borderWidth - config.spaceBottom - footNoteHeight - xAxisLabelHeight - (xLabelHeight - config.xAxisSpaceBefore) - config.graphSpaceAfter;
-			xLabelWidth = Math.abs(Math.cos(rotateLabels * Math.PI / 180) * widestLabel) + Math.abs(Math.cos((rotateLabels + 90) * Math.PI / 180) * highestLabel);
-			leftNotUsableSize = Max([leftNotUsableSize, borderWidth + config.spaceLeft + xLabelWidth / 2]);
-			rightNotUsableSize = Max([rightNotUsableSize, borderWidth + config.spaceRight + xLabelWidth / 2]);
-			availableWidth = width - leftNotUsableSize - rightNotUsableSize;
-			if (config.legend && config.xAxisBottom && config.legendPosY==4) {
-				xLabelPos-=spaceLegendHeight;
-			} 
-			bottomNotUsableHeightWithXLabels = bottomNotUsableHeightWithoutXLabels + xLabelHeight ;
-		}  else {
-			availableWidth = width - leftNotUsableSize - rightNotUsableSize;
-		}
-
-		availableHeight = height - topNotUsableSize - bottomNotUsableHeightWithXLabels;
-
-		// ----------------------- DRAW EXTERNAL ELEMENTS -------------------------------------------------
-		dispCrossImage(ctx, config, width / 2, height / 2, width / 2, height / 2, false, data, -1, -1);
- 		if (ylabels != "nihil") {
-			// Draw Borders
-			if (borderWidth > 0) {
-				ctx.save();
-				ctx.beginPath();
-				ctx.lineWidth = 2 * borderWidth;
-				ctx.strokeStyle = config.canvasBordersColor;
-				ctx.moveTo(0, 0);
-				ctx.lineTo(0, height);
-				ctx.lineTo(width, height);
-				ctx.lineTo(width, 0);
-				ctx.lineTo(0, 0);
-				ctx.stroke();
-				ctx.restore();
-			}
-			// Draw Graph Title
-			if (graphTitleHeight > 0) {
-				ctx.save();
-				ctx.beginPath();
-				ctx.font = config.graphTitleFontStyle + " " + config.graphTitleFontSize + "px " + config.graphTitleFontFamily;
-				ctx.fillStyle = config.graphTitleFontColor;
-				ctx.textAlign = "center";
-				ctx.textBaseline = "bottom";
-				ctx.translate(config.spaceLeft + (width - config.spaceLeft - config.spaceRight) / 2, graphTitlePosY);
-				ctx.fillTextMultiLine(config.graphTitle, 0, 0, ctx.textBaseline, config.graphTitleFontSize,true);
-				ctx.stroke();
-				ctx.restore();
-			}
-			// Draw Graph Sub-Title
-			if (graphSubTitleHeight > 0) {
-				ctx.save();
-				ctx.beginPath();
-				ctx.font = config.graphSubTitleFontStyle + " " + config.graphSubTitleFontSize + "px " + config.graphSubTitleFontFamily;
-				ctx.fillStyle = config.graphSubTitleFontColor;
-				ctx.textAlign = "center";
-				ctx.textBaseline = "bottom";
-				ctx.translate(config.spaceLeft + (width - config.spaceLeft - config.spaceRight) / 2, graphSubTitlePosY);
-				ctx.fillTextMultiLine(config.graphSubTitle, 0, 0, ctx.textBaseline, config.graphSubTitleFontSize,true);
-				ctx.stroke();
-				ctx.restore();
-			}
-			// Draw Y Axis Unit
-			if (yAxisUnitHeight > 0) {
-				if (config.yAxisLeft) {
-					ctx.save();
-					ctx.beginPath();
-					ctx.font = config.yAxisUnitFontStyle + " " + config.yAxisUnitFontSize + "px " + config.yAxisUnitFontFamily;
-					ctx.fillStyle = config.yAxisUnitFontColor;
-					ctx.textAlign = "center";
-					ctx.textBaseline = "bottom";
-					ctx.translate(leftNotUsableSize, yAxisUnitPosY);
-					ctx.fillTextMultiLine(config.yAxisUnit, 0, 0, ctx.textBaseline, config.yAxisUnitFontSize,true);
-					ctx.stroke();
-					ctx.restore();
-				}
-				if (config.yAxisRight) {
-					if (config.yAxisUnit2 == '') config.yAxisUnit2 = config.yAxisUnit;
-					ctx.save();
-					ctx.beginPath();
-					ctx.font = config.yAxisUnitFontStyle + " " + config.yAxisUnitFontSize + "px " + config.yAxisUnitFontFamily;
-					ctx.fillStyle = config.yAxisUnitFontColor;
-					ctx.textAlign = "center";
-					ctx.textBaseline = "bottom";
-					ctx.translate(width - rightNotUsableSize, yAxisUnitPosY);
-					ctx.fillTextMultiLine(config.yAxisUnit2, 0, 0, ctx.textBaseline, config.yAxisUnitFontSize,true);
-					ctx.stroke();
-					ctx.restore();
-				}
-			}
-			// Draw Y Axis Label
-			if (yAxisLabelWidth > 0) {
-				if (config.yAxisLeft) {
-					ctx.save();
-					ctx.beginPath();
-					ctx.font = config.yAxisFontStyle + " " + config.yAxisFontSize + "px " + config.yAxisFontFamily;
-					ctx.fillStyle = config.yAxisFontColor;
-					ctx.textAlign = "center";
-					ctx.textBaseline = "bottom";
-					ctx.translate(yAxisLabelPosLeft, topNotUsableSize + (availableHeight / 2));
-					ctx.rotate(-(90 * (Math.PI / 180)));
-					ctx.fillTextMultiLine(config.yAxisLabel, 0, 0, ctx.textBaseline, config.yAxisFontSize,false);
-					ctx.stroke();
-					ctx.restore();
-				}
-				if (config.yAxisRight) {
-					if (config.yAxisLabel2 == '') config.yAxisLabel2 = config.yAxisLabel;
-					ctx.save();
-					ctx.beginPath();
-					ctx.font = config.yAxisFontStyle + " " + config.yAxisFontSize + "px " + config.yAxisFontFamily;
-					ctx.fillStyle = config.yAxisFontColor;
-					ctx.textAlign = "center";
-					ctx.textBaseline = "bottom";
-					ctx.translate(yAxisLabelPosRight, topNotUsableSize + (availableHeight / 2));
-					ctx.rotate(+(90 * (Math.PI / 180)));
-					ctx.fillTextMultiLine(config.yAxisLabel2, 0, 0, ctx.textBaseline, config.yAxisFontSize,false);
-					ctx.stroke();
-					ctx.restore();
-				}
-			}
-			// Draw X Axis Label
-			if (xAxisLabelHeight > 0) {
-				if (config.xAxisBottom) {
-					ctx.save();
-					ctx.beginPath();
-					ctx.font = config.xAxisFontStyle + " " + config.xAxisFontSize + "px " + config.xAxisFontFamily;
-					ctx.fillStyle = config.xAxisFontColor;
-					ctx.textAlign = "center";
-					ctx.textBaseline = "bottom";
-					ctx.translate(leftNotUsableSize + (availableWidth / 2), xAxisLabelPos);