admin@web.or.kr 5 meses atrás
pai
commit
28e5ef2e41
100 arquivos alterados com 32975 adições e 0 exclusões
  1. 7 0
      public/plugin/c3-0.7.20/.bmp.yml
  2. 85 0
      public/plugin/c3-0.7.20/.circleci/config.yml
  3. 22 0
      public/plugin/c3-0.7.20/.editorconfig
  4. 21 0
      public/plugin/c3-0.7.20/.github/ISSUE_TEMPLATE.md
  5. 10 0
      public/plugin/c3-0.7.20/.github/PULL_REQUEST_TEMPLATE.md
  6. 35 0
      public/plugin/c3-0.7.20/.gitignore
  7. 27 0
      public/plugin/c3-0.7.20/.jshintrc
  8. 5 0
      public/plugin/c3-0.7.20/.prettierrc.json
  9. 19 0
      public/plugin/c3-0.7.20/.travis.yml
  10. 71 0
      public/plugin/c3-0.7.20/CONTRIBUTING.md
  11. 15 0
      public/plugin/c3-0.7.20/Gemfile
  12. 285 0
      public/plugin/c3-0.7.20/Gemfile.lock
  13. 20 0
      public/plugin/c3-0.7.20/LICENSE
  14. 33 0
      public/plugin/c3-0.7.20/MAINTAINANCE.md
  15. 61 0
      public/plugin/c3-0.7.20/README.md
  16. 23 0
      public/plugin/c3-0.7.20/bower.json
  17. 241 0
      public/plugin/c3-0.7.20/c3.css
  18. 14027 0
      public/plugin/c3-0.7.20/c3.esm.js
  19. 11320 0
      public/plugin/c3-0.7.20/c3.js
  20. 0 0
      public/plugin/c3-0.7.20/c3.min.css
  21. 1 0
      public/plugin/c3-0.7.20/c3.min.js
  22. 2 0
      public/plugin/c3-0.7.20/codecov.yml
  23. 15 0
      public/plugin/c3-0.7.20/component.json
  24. 33 0
      public/plugin/c3-0.7.20/config.rb
  25. 327 0
      public/plugin/c3-0.7.20/data/samples.yml
  26. BIN
      public/plugin/c3-0.7.20/design/c3-logo.sketch
  27. 157 0
      public/plugin/c3-0.7.20/docs/404.html
  28. 1 0
      public/plugin/c3-0.7.20/docs/CNAME
  29. 3 0
      public/plugin/c3-0.7.20/docs/_footer.haml
  30. 4 0
      public/plugin/c3-0.7.20/docs/_index_item.haml
  31. 4 0
      public/plugin/c3-0.7.20/docs/_index_item_title.haml
  32. 3 0
      public/plugin/c3-0.7.20/docs/_reference_item_link.haml
  33. 5 0
      public/plugin/c3-0.7.20/docs/_reference_menu_item.haml
  34. 34 0
      public/plugin/c3-0.7.20/docs/_sample.haml
  35. 36 0
      public/plugin/c3-0.7.20/docs/_sample_editor.haml
  36. 17 0
      public/plugin/c3-0.7.20/docs/_samples_header.haml
  37. 8 0
      public/plugin/c3-0.7.20/docs/_script.haml
  38. 22 0
      public/plugin/c3-0.7.20/docs/_script_scroll.haml
  39. 2 0
      public/plugin/c3-0.7.20/docs/_sidemenu_item.haml
  40. BIN
      public/plugin/c3-0.7.20/docs/apple-touch-icon-114x114-precomposed.png
  41. BIN
      public/plugin/c3-0.7.20/docs/apple-touch-icon-144x144-precomposed.png
  42. BIN
      public/plugin/c3-0.7.20/docs/apple-touch-icon-57x57-precomposed.png
  43. BIN
      public/plugin/c3-0.7.20/docs/apple-touch-icon-72x72-precomposed.png
  44. BIN
      public/plugin/c3-0.7.20/docs/apple-touch-icon-precomposed.png
  45. BIN
      public/plugin/c3-0.7.20/docs/apple-touch-icon.png
  46. 15 0
      public/plugin/c3-0.7.20/docs/crossdomain.xml
  47. 7 0
      public/plugin/c3-0.7.20/docs/css/bootstrap.min.css
  48. 241 0
      public/plugin/c3-0.7.20/docs/css/c3.css
  49. 0 0
      public/plugin/c3-0.7.20/docs/css/c3.min.css
  50. 0 0
      public/plugin/c3-0.7.20/docs/css/examples.css
  51. 5264 0
      public/plugin/c3-0.7.20/docs/css/foundation.css
  52. 0 0
      public/plugin/c3-0.7.20/docs/css/foundation.min.css
  53. 3 0
      public/plugin/c3-0.7.20/docs/css/gettingstarted.css
  54. 0 0
      public/plugin/c3-0.7.20/docs/css/index.css
  55. 423 0
      public/plugin/c3-0.7.20/docs/css/normalize.css
  56. 21 0
      public/plugin/c3-0.7.20/docs/css/reference.css
  57. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/api_axis_label.css
  58. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/api_axis_range.css
  59. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/api_data_color.css
  60. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/api_data_name.css
  61. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/api_flow.css
  62. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/api_grid_x.css
  63. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/api_resize.css
  64. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_label.css
  65. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_label_position.css
  66. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_rotated.css
  67. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_x_localtime.css
  68. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_x_tick_count.css
  69. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_x_tick_culling.css
  70. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_x_tick_fit.css
  71. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_x_tick_format.css
  72. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_x_tick_rotate.css
  73. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_x_tick_values.css
  74. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_y2.css
  75. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_y_padding.css
  76. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_y_range.css
  77. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/axes_y_tick_format.css
  78. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/categorized.css
  79. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/chart_area.css
  80. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/chart_area_stacked.css
  81. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/chart_bar.css
  82. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/chart_bar_negative.css
  83. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/chart_bar_stacked.css
  84. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/chart_combination.css
  85. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/chart_donut.css
  86. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/chart_gauge.css
  87. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/chart_pie.css
  88. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/chart_scatter.css
  89. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/chart_spline.css
  90. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/chart_stanford.css
  91. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/chart_step.css
  92. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/data_color.css
  93. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/data_columned.css
  94. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/data_json.css
  95. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/data_label.css
  96. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/data_label_format.css
  97. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/data_load.css
  98. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/data_name.css
  99. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/data_order.css
  100. 0 0
      public/plugin/c3-0.7.20/docs/css/samples/data_rowed.css

+ 7 - 0
public/plugin/c3-0.7.20/.bmp.yml

@@ -0,0 +1,7 @@
+---
+version: 0.7.20
+commit: 'chore(version): bump to v%.%.%'
+files:
+  src/core.ts: 'version: ''%.%.%'''
+  package.json: '"version": "%.%.%"'
+  component.json: '"version": "%.%.%"'

+ 85 - 0
public/plugin/c3-0.7.20/.circleci/config.yml

@@ -0,0 +1,85 @@
+version: 2
+
+node12: &node12
+  working_directory: ~/c3
+  docker:
+    - image: circleci/node:12-browsers
+
+node14: &node14
+  working_directory: ~/c3
+  docker:
+    - image: circleci/node:14-browsers
+
+restore_modules_cache: &restore_modules_cache
+  restore_cache:
+    keys:
+    - npm-4-{{ checksum "package.json" }}
+    # fallback to using the latest cache if no exact match is found
+    - npm-4-
+
+save_modules_cache: &save_modules_cache
+  save_cache:
+    key: npm-4-{{ checksum "package.json" }}
+    paths: ./node_modules
+
+install_and_test: &install_and_test
+  steps:
+    - checkout
+    - run:
+        name: Display versions
+        command: |
+          echo "node $(node -v)"
+          echo "npm v$(npm --version)"
+          echo "$(google-chrome --version)"
+    - *restore_modules_cache
+    - run:
+        name: Installing Dependencies
+        command: yarn
+    - *save_modules_cache
+    - run: yarn test
+    - run: yarn codecov
+    - store_artifacts:
+        path: htdocs
+        destination: htdocs
+    - run: npx status-back -s -c circleci/htdocs -r c3js/c3 "preview build succes!" "https://${CIRCLE_BUILD_NUM}-11496279-gh.circle-artifacts.com/0/htdocs/index.html"
+
+jobs:
+  test_on_node12:
+    <<: *node12
+    <<: *install_and_test
+
+  test_on_node14:
+    <<: *node14
+    <<: *install_and_test
+
+  docs:
+    docker:
+      - image: circleci/ruby:2.4-node
+        env:
+          BUNDLE_PATH: vendor/bundle
+    steps:
+      - checkout
+      - restore_cache:
+          key: deps-bundle-{{ checksum "Gemfile.lock" }}
+      - run: bundle install
+      - save_cache:
+          key: deps-bundle-{{ checksum "Gemfile.lock" }}
+          paths:
+            - vendor/bundle
+      - *restore_modules_cache
+      - run: yarn
+      - *save_modules_cache
+      - run: yarn build
+      - run: yarn copy-to-docs
+      - run: yarn build:docs
+      - store_artifacts:
+          path: build
+          destination: docs
+
+workflows:
+  version: 2
+  test:
+    jobs:
+      - test_on_node12
+      - test_on_node14
+      - docs

+ 22 - 0
public/plugin/c3-0.7.20/.editorconfig

@@ -0,0 +1,22 @@
+# editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.yml]
+indent_size = 2
+
+[*.json]
+indent_size = 2
+
+[*.haml]
+indent_size = 2
+
+[*.html]
+indent_size = 2

+ 21 - 0
public/plugin/c3-0.7.20/.github/ISSUE_TEMPLATE.md

@@ -0,0 +1,21 @@
+<!--
+
+This is not a catch-all support forum, for general support enquiries, please use the Google Group at https://groups.google.com/forum/#!forum/c3js.
+ 
+Thank you for reporting an issue.
+
+Please fill in as much of the template below as you're able.
+
+C3 version: The c3 version number which is available from `c3.version`.
+D3 version: The d3 version number.
+Browser: The browser version.
+OS: The operating system.
+
+If possible, please provide codepen or jsfiddle example that demonstrates the problem, keeping it as
+simple and free of external dependencies as you are able.
+-->
+
+* **C3 version**:
+* **D3 version**:
+* **Browser**:
+* **OS**:

+ 10 - 0
public/plugin/c3-0.7.20/.github/PULL_REQUEST_TEMPLATE.md

@@ -0,0 +1,10 @@
+<!--
+
+Thank you for contributing!
+
+Please make sure to:
+ 
+- provide tests with your code changes to ensure they are working as expected.
+- not commit any of the distribution file (`c3.js`, `c3.css`, `c3.min.js`, `c3.min.css`).
+
+-->

+ 35 - 0
public/plugin/c3-0.7.20/.gitignore

@@ -0,0 +1,35 @@
+# npm modules
+node_modules
+bower_components
+d3.js
+d3.min.js
+components
+package-lock.json
+
+# build
+/htdocs/js/c3.js
+/htdocs/js/c3.min.js
+/htdocs/js/c3.esm.js
+/htdocs/css/c3.css
+/htdocs/css/c3.min.css
+/build
+
+# sass
+.sass-cache
+
+# jetbrains
+.idea/
+
+# coverage report
+/coverage
+
+# OS related
+.DS_Store
+
+# IDE related
+.idea
+.iml
+
+# bundle
+.bundle/config
+vendor/bundle

+ 27 - 0
public/plugin/c3-0.7.20/.jshintrc

@@ -0,0 +1,27 @@
+{
+    "esversion": 6,
+    "eqeqeq": true,
+    "curly": true,
+    "strict": false,
+    "trailing": true,
+    "white": true,
+    "maxlen": 210,
+    "undef": true,
+    "unused": true,
+    "indent": 2,
+    "eqnull": true,
+    "expr": true,
+    "newcap": false,
+    "loopfunc": true,
+    "bitwise": false,
+    "asi": true,
+    "laxbreak": true,
+
+    "browser": true,
+    "jasmine": true,
+
+    "globals": {
+        "d3": false,
+        "require": false
+    }
+}

+ 5 - 0
public/plugin/c3-0.7.20/.prettierrc.json

@@ -0,0 +1,5 @@
+{
+  "tabWidth": 2,
+  "semi": false,
+  "singleQuote": true
+}

+ 19 - 0
public/plugin/c3-0.7.20/.travis.yml

@@ -0,0 +1,19 @@
+language: ruby
+rvm:
+  - 2.4
+
+branches:
+  only:
+    - master
+
+script:
+  - bundle exec middleman build
+
+deploy:
+  provider: pages
+  skip-cleanup: true
+  local-dir: build
+  github-token: $GITHUB_TOKEN
+  keep-history: true
+  on:
+    branch: master

+ 71 - 0
public/plugin/c3-0.7.20/CONTRIBUTING.md

@@ -0,0 +1,71 @@
+## Filing an issue
+
+Before filing an issue, please [search the queue](https://github.com/c3js/c3/issues) to make sure it hasn't already been reported.
+
+If a bug, please include the following —
+
+1. What version of C3?
+1. What browsers have you confirmed it in?
+1. Can you isolate the issue by providing a jsFiddle demonstrating it in a minimalist capacity?
+
+Please *do not* ask for support using the issue queue. For support, please ask [on chat](https://gitter.im/c3js/c3) or [the mailing list](groups.google.com/forum/#!forum/c3js).
+
+## Setup
+ 1. **Clone the repo from GitHub**
+
+        git clone https://github.com/c3js/c3.git
+        cd c3
+
+ 2. **Acquire build dependencies.** Make sure you have [Node.js](http://nodejs.org/) installed on your workstation. This is only needed to _build_ C3 from sources. C3 itself has no dependency on Node.js once it is built. Now run:
+
+        npm install -g grunt-cli
+        npm install
+
+    The first `npm` command sets up the popular [Grunt](http://gruntjs.com/) build tool. You might need to run this command with `sudo` if you're on Linux or Mac OS X, or in an Administrator command prompt on Windows. The second `npm` command fetches the remaining build dependencies.
+
+## Building C3 from sources
+    npm run build
+
+
+## Distribution
+    npm run dist
+
+Now you'll find the built files in `c3.js`, `c3.min.js`, `c3.css` & `c3.min.css`.
+
+## Running the tests
+    npm run test
+
+This command will automatically run the specification suite and report its results.
+
+If you want to see specs running live in browser (e.g., for debugging), simply open `http://localhost:9876/` in your browser when phantomjs starts.
+
+## Building the document site (c3js.org)
+
+First you need ruby and [bundler][] to build the documentation site.
+
+**Note:** Currently the site doesn't build with ruby 2.5.x, so you need ruby 2.4.4 or below. ([rbenv][] is useful for switching between ruby versions.)
+
+```console
+$ gem install bundler
+```
+
+Then you need to install bundler dependencies.
+
+```console
+$ bundle install
+```
+
+Then hit the following command to build the site.
+
+```console
+$ npm run watch:docs
+```
+
+Then access `http://0.0.0.0:4567`.
+
+## Contributing your changes
+
+Add something about PRs here, indicate that PRs should not bump the version number & the build output files (`c3.js`, `c3.min.js`, `c3.css` & `c3.min.css`) should be excluded
+
+[bundler]: https://bundler.io
+[rbenv]: https://github.com/rbenv/rbenv

+ 15 - 0
public/plugin/c3-0.7.20/Gemfile

@@ -0,0 +1,15 @@
+# If you have OpenSSL installed, we recommend updating
+# the following line to use "https"
+source 'http://rubygems.org'
+
+gem "middleman", "~>3.2.2"
+
+# Live-reloading plugin
+gem "middleman-livereload", "~> 3.1.0"
+
+# Sync plugin
+gem 'middleman-sync', '3.0.12'
+gem 'unf'
+
+# For faster file watcher updates on Windows:
+gem "wdm", "~> 0.1.0", :platforms => [:mswin, :mingw]

+ 285 - 0
public/plugin/c3-0.7.20/Gemfile.lock

@@ -0,0 +1,285 @@
+GEM
+  remote: http://rubygems.org/
+  specs:
+    CFPropertyList (2.3.5)
+    activemodel (3.2.22.5)
+      activesupport (= 3.2.22.5)
+      builder (~> 3.0.0)
+    activesupport (3.2.22.5)
+      i18n (~> 0.6, >= 0.6.4)
+      multi_json (~> 1.0)
+    asset_sync (1.0.0)
+      activemodel
+      fog (>= 1.8.0)
+    builder (3.0.4)
+    chunky_png (1.3.8)
+    coffee-script (2.2.0)
+      coffee-script-source
+      execjs
+    coffee-script-source (1.12.2)
+    compass (1.0.3)
+      chunky_png (~> 1.2)
+      compass-core (~> 1.0.2)
+      compass-import-once (~> 1.0.5)
+      rb-fsevent (>= 0.9.3)
+      rb-inotify (>= 0.9)
+      sass (>= 3.3.13, < 3.5)
+    compass-core (1.0.3)
+      multi_json (~> 1.0)
+      sass (>= 3.3.0, < 3.5)
+    compass-import-once (1.0.5)
+      sass (>= 3.2, < 3.5)
+    em-websocket (0.5.1)
+      eventmachine (>= 0.12.9)
+      http_parser.rb (~> 0.6.0)
+    eventmachine (1.2.3)
+    eventmachine (1.2.3-x86-mingw32)
+    excon (0.71.0)
+    execjs (1.4.1)
+      multi_json (~> 1.0)
+    ffi (1.11.1)
+    ffi (1.11.1-x86-mingw32)
+    fission (0.5.0)
+      CFPropertyList (~> 2.2)
+    fog (1.40.0)
+      fog-aliyun (>= 0.1.0)
+      fog-atmos
+      fog-aws (>= 0.6.0)
+      fog-brightbox (~> 0.4)
+      fog-cloudatcost (~> 0.1.0)
+      fog-core (~> 1.43)
+      fog-digitalocean (>= 0.3.0)
+      fog-dnsimple (~> 1.0)
+      fog-dynect (~> 0.0.2)
+      fog-ecloud (~> 0.1)
+      fog-google (<= 0.1.0)
+      fog-json
+      fog-local
+      fog-openstack
+      fog-powerdns (>= 0.1.1)
+      fog-profitbricks
+      fog-rackspace
+      fog-radosgw (>= 0.0.2)
+      fog-riakcs
+      fog-sakuracloud (>= 0.0.4)
+      fog-serverlove
+      fog-softlayer
+      fog-storm_on_demand
+      fog-terremark
+      fog-vmfusion
+      fog-voxel
+      fog-vsphere (>= 0.4.0)
+      fog-xenserver
+      fog-xml (~> 0.1.1)
+      ipaddress (~> 0.5)
+      json (>= 1.8, < 2.0)
+    fog-aliyun (0.1.0)
+      fog-core (~> 1.27)
+      fog-json (~> 1.0)
+      ipaddress (~> 0.8)
+      xml-simple (~> 1.1)
+    fog-atmos (0.1.0)
+      fog-core
+      fog-xml
+    fog-aws (1.3.0)
+      fog-core (~> 1.38)
+      fog-json (~> 1.0)
+      fog-xml (~> 0.1)
+      ipaddress (~> 0.8)
+    fog-brightbox (0.11.0)
+      fog-core (~> 1.22)
+      fog-json
+      inflecto (~> 0.0.2)
+    fog-cloudatcost (0.1.2)
+      fog-core (~> 1.36)
+      fog-json (~> 1.0)
+      fog-xml (~> 0.1)
+      ipaddress (~> 0.8)
+    fog-core (1.44.3)
+      builder
+      excon (~> 0.49)
+      formatador (~> 0.2)
+    fog-digitalocean (0.3.0)
+      fog-core (~> 1.42)
+      fog-json (>= 1.0)
+      fog-xml (>= 0.1)
+      ipaddress (>= 0.5)
+    fog-dnsimple (1.0.0)
+      fog-core (~> 1.38)
+      fog-json (~> 1.0)
+    fog-dynect (0.0.3)
+      fog-core
+      fog-json
+      fog-xml
+    fog-ecloud (0.3.0)
+      fog-core
+      fog-xml
+    fog-google (0.1.0)
+      fog-core
+      fog-json
+      fog-xml
+    fog-json (1.0.2)
+      fog-core (~> 1.0)
+      multi_json (~> 1.10)
+    fog-local (0.3.1)
+      fog-core (~> 1.27)
+    fog-openstack (0.1.20)
+      fog-core (>= 1.40)
+      fog-json (>= 1.0)
+      ipaddress (>= 0.8)
+    fog-powerdns (0.1.1)
+      fog-core (~> 1.27)
+      fog-json (~> 1.0)
+      fog-xml (~> 0.1)
+    fog-profitbricks (3.0.0)
+      fog-core (~> 1.42)
+      fog-json (~> 1.0)
+    fog-rackspace (0.1.5)
+      fog-core (>= 1.35)
+      fog-json (>= 1.0)
+      fog-xml (>= 0.1)
+      ipaddress (>= 0.8)
+    fog-radosgw (0.0.5)
+      fog-core (>= 1.21.0)
+      fog-json
+      fog-xml (>= 0.0.1)
+    fog-riakcs (0.1.0)
+      fog-core
+      fog-json
+      fog-xml
+    fog-sakuracloud (1.7.5)
+      fog-core
+      fog-json
+    fog-serverlove (0.1.2)
+      fog-core
+      fog-json
+    fog-softlayer (1.1.4)
+      fog-core
+      fog-json
+    fog-storm_on_demand (0.1.1)
+      fog-core
+      fog-json
+    fog-terremark (0.1.0)
+      fog-core
+      fog-xml
+    fog-vmfusion (0.1.0)
+      fission
+      fog-core
+    fog-voxel (0.1.0)
+      fog-core
+      fog-xml
+    fog-vsphere (1.10.0)
+      fog-core
+      rbvmomi (~> 1.9)
+    fog-xenserver (0.3.0)
+      fog-core
+      fog-xml
+    fog-xml (0.1.3)
+      fog-core
+      nokogiri (>= 1.5.11, < 2.0.0)
+    formatador (0.2.5)
+    haml (5.0.1)
+      temple (>= 0.8.0)
+      tilt
+    hike (1.2.3)
+    http_parser.rb (0.6.0)
+    i18n (0.6.11)
+    inflecto (0.0.2)
+    ipaddress (0.8.3)
+    json (1.8.6)
+    kramdown (1.13.2)
+    listen (1.3.1)
+      rb-fsevent (>= 0.9.3)
+      rb-inotify (>= 0.9)
+      rb-kqueue (>= 0.2)
+    middleman (3.2.2)
+      coffee-script (~> 2.2.0)
+      compass (>= 0.12.2)
+      execjs (~> 1.4.0)
+      haml (>= 3.1.6)
+      kramdown (~> 1.2)
+      middleman-core (= 3.2.2)
+      middleman-sprockets (>= 3.1.2)
+      sass (>= 3.1.20)
+      uglifier (~> 2.4.0)
+    middleman-core (3.2.2)
+      activesupport (~> 3.2.6)
+      bundler (~> 1.1)
+      i18n (~> 0.6.9)
+      listen (~> 1.1)
+      rack (>= 1.4.5)
+      rack-test (~> 0.6.1)
+      thor (>= 0.15.2, < 2.0)
+      tilt (~> 1.4.1)
+    middleman-livereload (3.1.1)
+      em-websocket (>= 0.2.0)
+      middleman-core (>= 3.0.2)
+      multi_json (~> 1.0)
+      rack-livereload
+    middleman-sprockets (3.3.3)
+      middleman-core (>= 3.2)
+      sprockets (~> 2.2)
+      sprockets-helpers (~> 1.1.0)
+      sprockets-sass (~> 1.1.0)
+    middleman-sync (3.0.12)
+      asset_sync (~> 1.0.0)
+      middleman-core (>= 3.0.0)
+    mini_portile2 (2.4.0)
+    multi_json (1.13.1)
+    nokogiri (1.10.8)
+      mini_portile2 (~> 2.4.0)
+    nokogiri (1.10.8-x86-mingw32)
+      mini_portile2 (~> 2.4.0)
+    rack (1.6.12)
+    rack-livereload (0.3.16)
+      rack
+    rack-test (0.6.3)
+      rack (>= 1.0)
+    rb-fsevent (0.9.8)
+    rb-inotify (0.9.8)
+      ffi (>= 0.5.0)
+    rb-kqueue (0.2.5)
+      ffi (>= 0.5.0)
+    rbvmomi (1.11.2)
+      builder (~> 3.0)
+      json (>= 1.8)
+      nokogiri (~> 1.5)
+      trollop (~> 2.1)
+    sass (3.4.24)
+    sprockets (2.12.5)
+      hike (~> 1.2)
+      multi_json (~> 1.0)
+      rack (~> 1.0)
+      tilt (~> 1.1, != 1.3.0)
+    sprockets-helpers (1.1.0)
+      sprockets (~> 2.0)
+    sprockets-sass (1.1.0)
+      sprockets (~> 2.0)
+      tilt (~> 1.1)
+    temple (0.8.0)
+    thor (0.19.4)
+    tilt (1.4.1)
+    trollop (2.1.2)
+    uglifier (2.4.0)
+      execjs (>= 0.3.0)
+      json (>= 1.8.0)
+    unf (0.1.4)
+      unf_ext
+    unf_ext (0.0.7.4)
+    unf_ext (0.0.7.4-x86-mingw32)
+    wdm (0.1.1)
+    xml-simple (1.1.5)
+
+PLATFORMS
+  ruby
+  x86-mingw32
+
+DEPENDENCIES
+  middleman (~> 3.2.2)
+  middleman-livereload (~> 3.1.0)
+  middleman-sync (= 3.0.12)
+  unf
+  wdm (~> 0.1.0)
+
+BUNDLED WITH
+   1.17.3

+ 20 - 0
public/plugin/c3-0.7.20/LICENSE

@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Masayuki Tanaka
+
+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.

+ 33 - 0
public/plugin/c3-0.7.20/MAINTAINANCE.md

@@ -0,0 +1,33 @@
+# Release process
+
+If you don't have `bmp` command installed, first install `bmp` ruby gem:
+
+    gem install bmp
+
+When master is ready for the next release, hit the command:
+
+    bmp -p
+
+This automatically updates all the version numbers with a new one in the repository.
+
+Then hit the command:
+
+    npm run dist
+
+This builds the scripts and stylesheets. Then hit:
+
+    bmp -c
+
+This commits all the changes (including the built assets) and git-tags a new version (like v0.4.16):
+
+Then publish it to the npm registry (you need admin access to c3 module):
+
+    npm publish
+
+At this point, the new version is available through npm.
+
+Then push master and the tag to github:
+
+    git push origin master vX.Y.Z
+
+That's all.

+ 61 - 0
public/plugin/c3-0.7.20/README.md

@@ -0,0 +1,61 @@
+# c3
+
+[![CircleCI](https://circleci.com/gh/c3js/c3.svg?style=shield)](https://circleci.com/gh/c3js/c3)
+[![license](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](https://github.com/c3js/c3/blob/master/LICENSE)
+[![codecov.io](https://codecov.io/github/c3js/c3/coverage.svg?branch=master)](https://codecov.io/github/c3js/c3?branch=master)
+
+[![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/c3/badge?style=rounded)](https://www.jsdelivr.com/package/npm/c3)
+
+> c3 is a D3-based reusable chart library that enables deeper integration of charts into web applications.
+
+Follow the link for more information: [http://c3js.org](http://c3js.org/)
+
+## Documentation
+
++ [Getting Started](http://c3js.org/gettingstarted.html)
++ [Examples](http://c3js.org/examples.html)
++ [Full API Reference](https://c3js.org/reference.html)
+
+Additional samples can be found in this repository:
++ [https://github.com/c3js/c3/tree/master/htdocs/samples](https://github.com/c3js/c3/tree/master/htdocs/samples)
+
+You can run these samples as:
+```
+$ npm run serve-static
+```
+
+## Google Group
+For general C3.js-related discussion, please visit our [Google Group at https://groups.google.com/forum/#!forum/c3js](https://groups.google.com/forum/#!forum/c3js).
+
+## Gitter
+[![Join the chat at https://gitter.im/c3js/c3](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/c3js/c3?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+## Using the issue queue
+The [issue queue](https://github.com/c3js/c3/issues) is to be used for reporting defects and problems with C3.js, in addition to feature requests and ideas. It is **not** a catch-all support forum. **For general support enquiries, please use the [Google Group](https://groups.google.com/forum/#!forum/c3js) at https://groups.google.com/forum/#!forum/c3js.** All questions involving the interplay between C3.js and any other library (such as AngularJS) should be posted there first!
+
+Before reporting an issue, please do the following:
+
+1. [Search for existing issues](https://github.com/c3js/c3/issues) to ensure you're not posting a duplicate.
+
+1.  [Search the Google Group](https://groups.google.com/forum/#!forum/c3js) to ensure it hasn't been addressed there already.
+
+1. Create a JSFiddle or Plunkr highlighting the issue. Please don't include any unnecessary dependencies so we can isolate that the issue is in fact with C3. *Please be advised that custom CSS can modify C3.js output!*
+
+1. When posting the issue, please use a descriptive title and include the version of C3 (or, if cloning from Git, the commit hash — C3 is under active development and the master branch contains the latest dev commits!), along with any platform/browser/OS information that may be relevant.
+
+## Pull requests
+Pull requests are welcome, though please post an issue first to see whether such a change is desirable.
+If you choose to submit a pull request, please do not bump the version number unless asked to, and please include test cases for any new features. Squash all your commits as well, please.
+
+## Playground
+Please fork this fiddle:
+
++ http://jsfiddle.net/7kYJu/4742/
+
+## Dependency
+
++ [D3.js](https://github.com/mbostock/d3) `^5.0.0`
+
+## License
+
+MIT

+ 23 - 0
public/plugin/c3-0.7.20/bower.json

@@ -0,0 +1,23 @@
+{
+  "name": "c3",
+  "main": ["c3.css", "c3.js"],
+  "homepage": "https://github.com/c3js/c3",
+  "authors": ["Masayuki Tanaka <masayuki0812@mac.com>"],
+  "description": "D3-based reusable chart library",
+  "keywords": ["chart", "d3"],
+  "license": "MIT",
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "bower_components",
+    "htdocs",
+    "spec",
+    "src/**/*.js",
+    "package.json",
+    "component.json",
+    "Gruntfile.*"
+  ],
+  "dependencies": {
+    "d3": "^5.0.0"
+  }
+}

+ 241 - 0
public/plugin/c3-0.7.20/c3.css

@@ -0,0 +1,241 @@
+/*-- Chart --*/
+.c3 svg {
+  font: 10px sans-serif;
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+
+.c3 path, .c3 line {
+  fill: none;
+  stroke: #000;
+}
+
+.c3 text {
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  user-select: none;
+}
+
+.c3-legend-item-tile,
+.c3-xgrid-focus,
+.c3-ygrid,
+.c3-event-rect,
+.c3-bars path {
+  shape-rendering: crispEdges;
+}
+
+.c3-chart-arc path {
+  stroke: #fff;
+}
+
+.c3-chart-arc rect {
+  stroke: white;
+  stroke-width: 1;
+}
+
+.c3-chart-arc text {
+  fill: #fff;
+  font-size: 13px;
+}
+
+/*-- Axis --*/
+/*-- Grid --*/
+.c3-grid line {
+  stroke: #aaa;
+}
+
+.c3-grid text {
+  fill: #aaa;
+}
+
+.c3-xgrid, .c3-ygrid {
+  stroke-dasharray: 3 3;
+}
+
+/*-- Text on Chart --*/
+.c3-text.c3-empty {
+  fill: #808080;
+  font-size: 2em;
+}
+
+/*-- Line --*/
+.c3-line {
+  stroke-width: 1px;
+}
+
+/*-- Point --*/
+.c3-circle {
+  fill: currentColor;
+}
+
+.c3-circle._expanded_ {
+  stroke-width: 1px;
+  stroke: white;
+}
+
+.c3-selected-circle {
+  fill: white;
+  stroke-width: 2px;
+}
+
+/*-- Bar --*/
+.c3-bar {
+  stroke-width: 0;
+}
+
+.c3-bar._expanded_ {
+  fill-opacity: 1;
+  fill-opacity: 0.75;
+}
+
+/*-- Focus --*/
+.c3-target.c3-focused {
+  opacity: 1;
+}
+
+.c3-target.c3-focused path.c3-line, .c3-target.c3-focused path.c3-step {
+  stroke-width: 2px;
+}
+
+.c3-target.c3-defocused {
+  opacity: 0.3 !important;
+}
+
+/*-- Region --*/
+.c3-region {
+  fill: steelblue;
+  fill-opacity: 0.1;
+}
+.c3-region text {
+  fill-opacity: 1;
+}
+
+/*-- Brush --*/
+.c3-brush .extent {
+  fill-opacity: 0.1;
+}
+
+/*-- Select - Drag --*/
+/*-- Legend --*/
+.c3-legend-item {
+  font-size: 12px;
+}
+
+.c3-legend-item-hidden {
+  opacity: 0.15;
+}
+
+.c3-legend-background {
+  opacity: 0.75;
+  fill: white;
+  stroke: lightgray;
+  stroke-width: 1;
+}
+
+/*-- Title --*/
+.c3-title {
+  font: 14px sans-serif;
+}
+
+/*-- Tooltip --*/
+.c3-tooltip-container {
+  z-index: 10;
+}
+
+.c3-tooltip {
+  border-collapse: collapse;
+  border-spacing: 0;
+  background-color: #fff;
+  empty-cells: show;
+  -webkit-box-shadow: 7px 7px 12px -9px #777777;
+  -moz-box-shadow: 7px 7px 12px -9px #777777;
+  box-shadow: 7px 7px 12px -9px #777777;
+  opacity: 0.9;
+}
+
+.c3-tooltip tr {
+  border: 1px solid #CCC;
+}
+
+.c3-tooltip th {
+  background-color: #aaa;
+  font-size: 14px;
+  padding: 2px 5px;
+  text-align: left;
+  color: #FFF;
+}
+
+.c3-tooltip td {
+  font-size: 13px;
+  padding: 3px 6px;
+  background-color: #fff;
+  border-left: 1px dotted #999;
+}
+
+.c3-tooltip td > span {
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  margin-right: 6px;
+}
+
+.c3-tooltip .value {
+  text-align: right;
+}
+
+/*-- Area --*/
+.c3-area {
+  stroke-width: 0;
+  opacity: 0.2;
+}
+
+/*-- Arc --*/
+.c3-chart-arcs-title {
+  dominant-baseline: middle;
+  font-size: 1.3em;
+}
+
+.c3-chart-arcs .c3-chart-arcs-background {
+  fill: #e0e0e0;
+  stroke: #FFF;
+}
+
+.c3-chart-arcs .c3-chart-arcs-gauge-unit {
+  fill: #000;
+  font-size: 16px;
+}
+
+.c3-chart-arcs .c3-chart-arcs-gauge-max {
+  fill: #777;
+}
+
+.c3-chart-arcs .c3-chart-arcs-gauge-min {
+  fill: #777;
+}
+
+.c3-chart-arc .c3-gauge-value {
+  fill: #000;
+  /*  font-size: 28px !important;*/
+}
+
+.c3-chart-arc.c3-target g path {
+  opacity: 1;
+}
+
+.c3-chart-arc.c3-target.c3-focused g path {
+  opacity: 1;
+}
+
+/*-- Zoom --*/
+.c3-drag-zoom.enabled {
+  pointer-events: all !important;
+  visibility: visible;
+}
+
+.c3-drag-zoom.disabled {
+  pointer-events: none !important;
+  visibility: hidden;
+}
+
+.c3-drag-zoom .extent {
+  fill-opacity: 0.1;
+}

+ 14027 - 0
public/plugin/c3-0.7.20/c3.esm.js

@@ -0,0 +1,14027 @@
+/* @license C3.js v0.7.18 | (c) C3 Team and other contributors | http://c3js.org/ */
+import * as d3 from 'd3';
+
+function ChartInternal(api) {
+  var $$ = this;
+  // Note: This part will be replaced by rollup-plugin-modify
+  // When bundling esm output. Beware of changing this line.
+  // TODO: Maybe we should check that the modification by rollup-plugin-modify
+  // is valid during unit tests.
+  $$.d3 = window.d3
+    ? window.d3
+    : typeof require !== 'undefined'
+    ? require('d3')
+    : undefined;
+  $$.api = api;
+  $$.config = $$.getDefaultConfig();
+  $$.data = {};
+  $$.cache = {};
+  $$.axes = {};
+}
+
+/**
+ * The Chart class
+ *
+ * The methods of this class is the public APIs of the chart object.
+ */
+function Chart(config) {
+  this.internal = new ChartInternal(this);
+  this.internal.loadConfig(config);
+
+  this.internal.beforeInit(config);
+  this.internal.init();
+  this.internal.afterInit(config)
+
+  // bind "this" to nested API
+  ;(function bindThis(fn, target, argThis) {
+    Object.keys(fn).forEach(function(key) {
+      target[key] = fn[key].bind(argThis);
+      if (Object.keys(fn[key]).length > 0) {
+        bindThis(fn[key], target[key], argThis);
+      }
+    });
+  })(Chart.prototype, this, this);
+}
+
+var asHalfPixel = function(n) {
+  return Math.ceil(n) + 0.5
+};
+var ceil10 = function(v) {
+  return Math.ceil(v / 10) * 10
+};
+var diffDomain = function(d) {
+  return d[1] - d[0]
+};
+var getOption = function(options, key, defaultValue) {
+  return isDefined(options[key]) ? options[key] : defaultValue
+};
+var getPathBox = function(path) {
+  var box = getBBox(path),
+    items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)],
+    minX = items[0].x,
+    minY = Math.min(items[0].y, items[1].y);
+  return { x: minX, y: minY, width: box.width, height: box.height }
+};
+var getBBox = function(element) {
+  try {
+    return element.getBBox()
+  } catch (ignore) {
+    // Firefox will throw an exception if getBBox() is called whereas the
+    // element is rendered with display:none
+    // See https://github.com/c3js/c3/issues/2692
+
+    // The previous code was using `getBoundingClientRect` which was returning
+    // everything at 0 in this case so let's reproduce this behavior here.
+
+    return { x: 0, y: 0, width: 0, height: 0 }
+  }
+};
+var hasValue = function(dict, value) {
+  var found = false;
+  Object.keys(dict).forEach(function(key) {
+    if (dict[key] === value) {
+      found = true;
+    }
+  });
+  return found
+};
+var isArray = function(o) {
+  return Array.isArray(o)
+};
+var isDefined = function(v) {
+  return typeof v !== 'undefined'
+};
+var isEmpty = function(o) {
+  return (
+    typeof o === 'undefined' ||
+    o === null ||
+    (isString(o) && o.length === 0) ||
+    (typeof o === 'object' && Object.keys(o).length === 0)
+  )
+};
+var isFunction = function(o) {
+  return typeof o === 'function'
+};
+var isNumber = function(o) {
+  return typeof o === 'number'
+};
+var isString = function(o) {
+  return typeof o === 'string'
+};
+var isUndefined = function(v) {
+  return typeof v === 'undefined'
+};
+var isValue = function(v) {
+  return v || v === 0
+};
+var notEmpty = function(o) {
+  return !isEmpty(o)
+};
+var sanitise = function(str) {
+  return typeof str === 'string'
+    ? str.replace(/</g, '&lt;').replace(/>/g, '&gt;')
+    : str
+};
+var flattenArray = function(arr) {
+  return Array.isArray(arr) ? [].concat(...arr) : []
+};
+/**
+ * Returns whether the point is within the given box.
+ *
+ * @param {Array} point An [x,y] coordinate
+ * @param {Object} box An object with {x, y, width, height} keys
+ * @param {Number} sensitivity An offset to ease check on very small boxes
+ */
+var isWithinBox = function(point, box, sensitivity = 0) {
+  const xStart = box.x - sensitivity;
+  const xEnd = box.x + box.width + sensitivity;
+  const yStart = box.y + box.height + sensitivity;
+  const yEnd = box.y - sensitivity;
+
+  return (
+    xStart < point[0] && point[0] < xEnd && yEnd < point[1] && point[1] < yStart
+  )
+};
+
+/**
+ * Returns Internet Explorer version number (or false if no Internet Explorer used).
+ *
+ * @param string agent Optional parameter to specify user agent
+ */
+var getIEVersion = function(agent) {
+  // https://stackoverflow.com/questions/19999388/check-if-user-is-using-ie
+  if (typeof agent === 'undefined') {
+    agent = window.navigator.userAgent;
+  }
+
+  let pos = agent.indexOf('MSIE '); // up to IE10
+  if (pos > 0) {
+    return parseInt(agent.substring(pos + 5, agent.indexOf('.', pos)), 10)
+  }
+
+  pos = agent.indexOf('Trident/'); // IE11
+  if (pos > 0) {
+    pos = agent.indexOf('rv:');
+    return parseInt(agent.substring(pos + 3, agent.indexOf('.', pos)), 10)
+  }
+
+  return false
+};
+
+/**
+ * Returns whether the used browser is Internet Explorer.
+ *
+ * @param {Number} version Optional parameter to specify IE version
+ */
+var isIE = function(version) {
+  const ver = getIEVersion();
+
+  if (typeof version === 'undefined') {
+    return !!ver
+  }
+
+  return version === ver
+};
+
+function AxisInternal(component, params) {
+  var internal = this;
+  internal.component = component;
+  internal.params = params || {};
+
+  internal.d3 = component.d3;
+  internal.scale = internal.d3.scaleLinear();
+  internal.range;
+  internal.orient = 'bottom';
+  internal.innerTickSize = 6;
+  internal.outerTickSize = this.params.withOuterTick ? 6 : 0;
+  internal.tickPadding = 3;
+  internal.tickValues = null;
+  internal.tickFormat;
+  internal.tickArguments;
+
+  internal.tickOffset = 0;
+  internal.tickCulling = true;
+  internal.tickCentered;
+  internal.tickTextCharSize;
+  internal.tickTextRotate = internal.params.tickTextRotate;
+  internal.tickLength;
+
+  internal.axis = internal.generateAxis();
+}
+
+AxisInternal.prototype.axisX = function(selection, x, tickOffset) {
+  selection.attr('transform', function(d) {
+    return 'translate(' + Math.ceil(x(d) + tickOffset) + ', 0)'
+  });
+};
+AxisInternal.prototype.axisY = function(selection, y) {
+  selection.attr('transform', function(d) {
+    return 'translate(0,' + Math.ceil(y(d)) + ')'
+  });
+};
+AxisInternal.prototype.scaleExtent = function(domain) {
+  var start = domain[0],
+    stop = domain[domain.length - 1];
+  return start < stop ? [start, stop] : [stop, start]
+};
+AxisInternal.prototype.generateTicks = function(scale) {
+  var internal = this;
+  var i,
+    domain,
+    ticks = [];
+  if (scale.ticks) {
+    return scale.ticks.apply(scale, internal.tickArguments)
+  }
+  domain = scale.domain();
+  for (i = Math.ceil(domain[0]); i < domain[1]; i++) {
+    ticks.push(i);
+  }
+  if (ticks.length > 0 && ticks[0] > 0) {
+    ticks.unshift(ticks[0] - (ticks[1] - ticks[0]));
+  }
+  return ticks
+};
+AxisInternal.prototype.copyScale = function() {
+  var internal = this;
+  var newScale = internal.scale.copy(),
+    domain;
+  if (internal.params.isCategory) {
+    domain = internal.scale.domain();
+    newScale.domain([domain[0], domain[1] - 1]);
+  }
+  return newScale
+};
+AxisInternal.prototype.textFormatted = function(v) {
+  var internal = this,
+    formatted = internal.tickFormat ? internal.tickFormat(v) : v;
+  return typeof formatted !== 'undefined' ? formatted : ''
+};
+AxisInternal.prototype.updateRange = function() {
+  var internal = this;
+  internal.range = internal.scale.rangeExtent
+    ? internal.scale.rangeExtent()
+    : internal.scaleExtent(internal.scale.range());
+  return internal.range
+};
+AxisInternal.prototype.updateTickTextCharSize = function(tick) {
+  var internal = this;
+  if (internal.tickTextCharSize) {
+    return internal.tickTextCharSize
+  }
+  var size = {
+    h: 11.5,
+    w: 5.5
+  };
+  tick
+    .select('text')
+    .text(function(d) {
+      return internal.textFormatted(d)
+    })
+    .each(function(d) {
+      var box = getBBox(this),
+        text = internal.textFormatted(d),
+        h = box.height,
+        w = text ? box.width / text.length : undefined;
+      if (h && w) {
+        size.h = h;
+        size.w = w;
+      }
+    })
+    .text('');
+  internal.tickTextCharSize = size;
+  return size
+};
+AxisInternal.prototype.isVertical = function() {
+  return this.orient === 'left' || this.orient === 'right'
+};
+AxisInternal.prototype.tspanData = function(d, i, scale) {
+  var internal = this;
+  var splitted = internal.params.tickMultiline
+    ? internal.splitTickText(d, scale)
+    : [].concat(internal.textFormatted(d));
+
+  if (internal.params.tickMultiline && internal.params.tickMultilineMax > 0) {
+    splitted = internal.ellipsify(splitted, internal.params.tickMultilineMax);
+  }
+
+  return splitted.map(function(s) {
+    return { index: i, splitted: s, length: splitted.length }
+  })
+};
+AxisInternal.prototype.splitTickText = function(d, scale) {
+  var internal = this,
+    tickText = internal.textFormatted(d),
+    maxWidth = internal.params.tickWidth,
+    subtext,
+    spaceIndex,
+    textWidth,
+    splitted = [];
+
+  if (Object.prototype.toString.call(tickText) === '[object Array]') {
+    return tickText
+  }
+
+  if (!maxWidth || maxWidth <= 0) {
+    maxWidth = internal.isVertical()
+      ? 95
+      : internal.params.isCategory
+      ? Math.ceil(scale(1) - scale(0)) - 12
+      : 110;
+  }
+
+  function split(splitted, text) {
+    spaceIndex = undefined;
+    for (var i = 1; i < text.length; i++) {
+      if (text.charAt(i) === ' ') {
+        spaceIndex = i;
+      }
+      subtext = text.substr(0, i + 1);
+      textWidth = internal.tickTextCharSize.w * subtext.length;
+      // if text width gets over tick width, split by space index or crrent index
+      if (maxWidth < textWidth) {
+        return split(
+          splitted.concat(text.substr(0, spaceIndex ? spaceIndex : i)),
+          text.slice(spaceIndex ? spaceIndex + 1 : i)
+        )
+      }
+    }
+    return splitted.concat(text)
+  }
+
+  return split(splitted, tickText + '')
+};
+AxisInternal.prototype.ellipsify = function(splitted, max) {
+  if (splitted.length <= max) {
+    return splitted
+  }
+
+  var ellipsified = splitted.slice(0, max);
+  var remaining = 3;
+  for (var i = max - 1; i >= 0; i--) {
+    var available = ellipsified[i].length;
+
+    ellipsified[i] = ellipsified[i]
+      .substr(0, available - remaining)
+      .padEnd(available, '.');
+
+    remaining -= available;
+
+    if (remaining <= 0) {
+      break
+    }
+  }
+
+  return ellipsified
+};
+AxisInternal.prototype.updateTickLength = function() {
+  var internal = this;
+  internal.tickLength =
+    Math.max(internal.innerTickSize, 0) + internal.tickPadding;
+};
+AxisInternal.prototype.lineY2 = function(d) {
+  var internal = this,
+    tickPosition =
+      internal.scale(d) + (internal.tickCentered ? 0 : internal.tickOffset);
+  return internal.range[0] < tickPosition && tickPosition < internal.range[1]
+    ? internal.innerTickSize
+    : 0
+};
+AxisInternal.prototype.textY = function() {
+  var internal = this,
+    rotate = internal.tickTextRotate;
+  return rotate
+    ? 11.5 - 2.5 * (rotate / 15) * (rotate > 0 ? 1 : -1)
+    : internal.tickLength
+};
+AxisInternal.prototype.textTransform = function() {
+  var internal = this,
+    rotate = internal.tickTextRotate;
+  return rotate ? 'rotate(' + rotate + ')' : ''
+};
+AxisInternal.prototype.textTextAnchor = function() {
+  var internal = this,
+    rotate = internal.tickTextRotate;
+  return rotate ? (rotate > 0 ? 'start' : 'end') : 'middle'
+};
+AxisInternal.prototype.tspanDx = function() {
+  var internal = this,
+    rotate = internal.tickTextRotate;
+  return rotate ? 8 * Math.sin(Math.PI * (rotate / 180)) : 0
+};
+AxisInternal.prototype.tspanDy = function(d, i) {
+  var internal = this,
+    dy = internal.tickTextCharSize.h;
+  if (i === 0) {
+    if (internal.isVertical()) {
+      dy = -((d.length - 1) * (internal.tickTextCharSize.h / 2) - 3);
+    } else {
+      dy = '.71em';
+    }
+  }
+  return dy
+};
+
+AxisInternal.prototype.generateAxis = function() {
+  var internal = this,
+    d3 = internal.d3,
+    params = internal.params;
+  function axis(g, transition) {
+    var self;
+    g.each(function() {
+      var g = (axis.g = d3.select(this));
+
+      var scale0 = this.__chart__ || internal.scale,
+        scale1 = (this.__chart__ = internal.copyScale());
+
+      var ticksValues = internal.tickValues
+          ? internal.tickValues
+          : internal.generateTicks(scale1),
+        ticks = g.selectAll('.tick').data(ticksValues, scale1),
+        tickEnter = ticks
+          .enter()
+          .insert('g', '.domain')
+          .attr('class', 'tick')
+          .style('opacity', 1e-6),
+        // MEMO: No exit transition. The reason is this transition affects max tick width calculation because old tick will be included in the ticks.
+        tickExit = ticks.exit().remove(),
+        tickUpdate = ticks.merge(tickEnter),
+        tickTransform,
+        tickX,
+        tickY;
+
+      if (params.isCategory) {
+        internal.tickOffset = Math.ceil((scale1(1) - scale1(0)) / 2);
+        tickX = internal.tickCentered ? 0 : internal.tickOffset;
+        tickY = internal.tickCentered ? internal.tickOffset : 0;
+      } else {
+        internal.tickOffset = tickX = 0;
+      }
+
+      internal.updateRange();
+      internal.updateTickLength();
+      internal.updateTickTextCharSize(g.select('.tick'));
+
+      var lineUpdate = tickUpdate
+          .select('line')
+          .merge(tickEnter.append('line')),
+        textUpdate = tickUpdate.select('text').merge(tickEnter.append('text'));
+
+      var tspans = tickUpdate
+          .selectAll('text')
+          .selectAll('tspan')
+          .data(function(d, i) {
+            return internal.tspanData(d, i, scale1)
+          }),
+        tspanEnter = tspans.enter().append('tspan'),
+        tspanUpdate = tspanEnter.merge(tspans).text(function(d) {
+          return d.splitted
+        });
+      tspans.exit().remove();
+
+      var path = g.selectAll('.domain').data([0]),
+        pathUpdate = path
+          .enter()
+          .append('path')
+          .merge(path)
+          .attr('class', 'domain');
+
+      // TODO: each attr should be one function and change its behavior by internal.orient, probably
+      switch (internal.orient) {
+        case 'bottom': {
+          tickTransform = internal.axisX;
+          lineUpdate
+            .attr('x1', tickX)
+            .attr('x2', tickX)
+            .attr('y2', function(d, i) {
+              return internal.lineY2(d, i)
+            });
+          textUpdate
+            .attr('x', 0)
+            .attr('y', function(d, i) {
+              return internal.textY(d, i)
+            })
+            .attr('transform', function(d, i) {
+              return internal.textTransform(d, i)
+            })
+            .style('text-anchor', function(d, i) {
+              return internal.textTextAnchor(d, i)
+            });
+          tspanUpdate
+            .attr('x', 0)
+            .attr('dy', function(d, i) {
+              return internal.tspanDy(d, i)
+            })
+            .attr('dx', function(d, i) {
+              return internal.tspanDx(d, i)
+            });
+          pathUpdate.attr(
+            'd',
+            'M' +
+              internal.range[0] +
+              ',' +
+              internal.outerTickSize +
+              'V0H' +
+              internal.range[1] +
+              'V' +
+              internal.outerTickSize
+          );
+          break
+        }
+        case 'top': {
+          // TODO: rotated tick text
+          tickTransform = internal.axisX;
+          lineUpdate
+            .attr('x1', tickX)
+            .attr('x2', tickX)
+            .attr('y2', function(d, i) {
+              return -1 * internal.lineY2(d, i)
+            });
+          textUpdate
+            .attr('x', 0)
+            .attr('y', function(d, i) {
+              return (
+                -1 * internal.textY(d, i) -
+                (params.isCategory ? 2 : internal.tickLength - 2)
+              )
+            })
+            .attr('transform', function(d, i) {
+              return internal.textTransform(d, i)
+            })
+            .style('text-anchor', function(d, i) {
+              return internal.textTextAnchor(d, i)
+            });
+          tspanUpdate
+            .attr('x', 0)
+            .attr('dy', function(d, i) {
+              return internal.tspanDy(d, i)
+            })
+            .attr('dx', function(d, i) {
+              return internal.tspanDx(d, i)
+            });
+          pathUpdate.attr(
+            'd',
+            'M' +
+              internal.range[0] +
+              ',' +
+              -internal.outerTickSize +
+              'V0H' +
+              internal.range[1] +
+              'V' +
+              -internal.outerTickSize
+          );
+          break
+        }
+        case 'left': {
+          tickTransform = internal.axisY;
+          lineUpdate
+            .attr('x2', -internal.innerTickSize)
+            .attr('y1', tickY)
+            .attr('y2', tickY);
+          textUpdate
+            .attr('x', -internal.tickLength)
+            .attr('y', internal.tickOffset)
+            .style('text-anchor', 'end');
+          tspanUpdate
+            .attr('x', -internal.tickLength)
+            .attr('dy', function(d, i) {
+              return internal.tspanDy(d, i)
+            });
+          pathUpdate.attr(
+            'd',
+            'M' +
+              -internal.outerTickSize +
+              ',' +
+              internal.range[0] +
+              'H0V' +
+              internal.range[1] +
+              'H' +
+              -internal.outerTickSize
+          );
+          break
+        }
+        case 'right': {
+          tickTransform = internal.axisY;
+          lineUpdate
+            .attr('x2', internal.innerTickSize)
+            .attr('y1', tickY)
+            .attr('y2', tickY);
+          textUpdate
+            .attr('x', internal.tickLength)
+            .attr('y', internal.tickOffset)
+            .style('text-anchor', 'start');
+          tspanUpdate.attr('x', internal.tickLength).attr('dy', function(d, i) {
+            return internal.tspanDy(d, i)
+          });
+          pathUpdate.attr(
+            'd',
+            'M' +
+              internal.outerTickSize +
+              ',' +
+              internal.range[0] +
+              'H0V' +
+              internal.range[1] +
+              'H' +
+              internal.outerTickSize
+          );
+          break
+        }
+      }
+      if (scale1.rangeBand) {
+        var x = scale1,
+          dx = x.rangeBand() / 2;
+        scale0 = scale1 = function(d) {
+          return x(d) + dx
+        };
+      } else if (scale0.rangeBand) {
+        scale0 = scale1;
+      } else {
+        tickExit.call(tickTransform, scale1, internal.tickOffset);
+      }
+      tickEnter.call(tickTransform, scale0, internal.tickOffset);
+      self = (transition ? tickUpdate.transition(transition) : tickUpdate)
+        .style('opacity', 1)
+        .call(tickTransform, scale1, internal.tickOffset);
+    });
+    return self
+  }
+  axis.scale = function(x) {
+    if (!arguments.length) {
+      return internal.scale
+    }
+    internal.scale = x;
+    return axis
+  };
+  axis.orient = function(x) {
+    if (!arguments.length) {
+      return internal.orient
+    }
+    internal.orient =
+      x in { top: 1, right: 1, bottom: 1, left: 1 } ? x + '' : 'bottom';
+    return axis
+  };
+  axis.tickFormat = function(format) {
+    if (!arguments.length) {
+      return internal.tickFormat
+    }
+    internal.tickFormat = format;
+    return axis
+  };
+  axis.tickCentered = function(isCentered) {
+    if (!arguments.length) {
+      return internal.tickCentered
+    }
+    internal.tickCentered = isCentered;
+    return axis
+  };
+  axis.tickOffset = function() {
+    return internal.tickOffset
+  };
+  axis.tickInterval = function() {
+    var interval, length;
+    if (params.isCategory) {
+      interval = internal.tickOffset * 2;
+    } else {
+      length =
+        axis.g
+          .select('path.domain')
+          .node()
+          .getTotalLength() -
+        internal.outerTickSize * 2;
+      interval = length / axis.g.selectAll('line').size();
+    }
+    return interval === Infinity ? 0 : interval
+  };
+  axis.ticks = function() {
+    if (!arguments.length) {
+      return internal.tickArguments
+    }
+    internal.tickArguments = arguments;
+    return axis
+  };
+  axis.tickCulling = function(culling) {
+    if (!arguments.length) {
+      return internal.tickCulling
+    }
+    internal.tickCulling = culling;
+    return axis
+  };
+  axis.tickValues = function(x) {
+    if (typeof x === 'function') {
+      internal.tickValues = function() {
+        return x(internal.scale.domain())
+      };
+    } else {
+      if (!arguments.length) {
+        return internal.tickValues
+      }
+      internal.tickValues = x;
+    }
+    return axis
+  };
+  return axis
+};
+
+var CLASS = {
+  target: 'c3-target',
+  chart: 'c3-chart',
+  chartLine: 'c3-chart-line',
+  chartLines: 'c3-chart-lines',
+  chartBar: 'c3-chart-bar',
+  chartBars: 'c3-chart-bars',
+  chartText: 'c3-chart-text',
+  chartTexts: 'c3-chart-texts',
+  chartArc: 'c3-chart-arc',
+  chartArcs: 'c3-chart-arcs',
+  chartArcsTitle: 'c3-chart-arcs-title',
+  chartArcsBackground: 'c3-chart-arcs-background',
+  chartArcsGaugeUnit: 'c3-chart-arcs-gauge-unit',
+  chartArcsGaugeMax: 'c3-chart-arcs-gauge-max',
+  chartArcsGaugeMin: 'c3-chart-arcs-gauge-min',
+  selectedCircle: 'c3-selected-circle',
+  selectedCircles: 'c3-selected-circles',
+  eventRect: 'c3-event-rect',
+  eventRects: 'c3-event-rects',
+  eventRectsSingle: 'c3-event-rects-single',
+  eventRectsMultiple: 'c3-event-rects-multiple',
+  zoomRect: 'c3-zoom-rect',
+  brush: 'c3-brush',
+  dragZoom: 'c3-drag-zoom',
+  focused: 'c3-focused',
+  defocused: 'c3-defocused',
+  region: 'c3-region',
+  regions: 'c3-regions',
+  title: 'c3-title',
+  tooltipContainer: 'c3-tooltip-container',
+  tooltip: 'c3-tooltip',
+  tooltipName: 'c3-tooltip-name',
+  shape: 'c3-shape',
+  shapes: 'c3-shapes',
+  line: 'c3-line',
+  lines: 'c3-lines',
+  bar: 'c3-bar',
+  bars: 'c3-bars',
+  circle: 'c3-circle',
+  circles: 'c3-circles',
+  arc: 'c3-arc',
+  arcLabelLine: 'c3-arc-label-line',
+  arcs: 'c3-arcs',
+  area: 'c3-area',
+  areas: 'c3-areas',
+  empty: 'c3-empty',
+  text: 'c3-text',
+  texts: 'c3-texts',
+  gaugeValue: 'c3-gauge-value',
+  grid: 'c3-grid',
+  gridLines: 'c3-grid-lines',
+  xgrid: 'c3-xgrid',
+  xgrids: 'c3-xgrids',
+  xgridLine: 'c3-xgrid-line',
+  xgridLines: 'c3-xgrid-lines',
+  xgridFocus: 'c3-xgrid-focus',
+  ygrid: 'c3-ygrid',
+  ygrids: 'c3-ygrids',
+  ygridLine: 'c3-ygrid-line',
+  ygridLines: 'c3-ygrid-lines',
+  colorScale: 'c3-colorscale',
+  stanfordElements: 'c3-stanford-elements',
+  stanfordLine: 'c3-stanford-line',
+  stanfordLines: 'c3-stanford-lines',
+  stanfordRegion: 'c3-stanford-region',
+  stanfordRegions: 'c3-stanford-regions',
+  stanfordText: 'c3-stanford-text',
+  stanfordTexts: 'c3-stanford-texts',
+  axis: 'c3-axis',
+  axisX: 'c3-axis-x',
+  axisXLabel: 'c3-axis-x-label',
+  axisY: 'c3-axis-y',
+  axisYLabel: 'c3-axis-y-label',
+  axisY2: 'c3-axis-y2',
+  axisY2Label: 'c3-axis-y2-label',
+  legendBackground: 'c3-legend-background',
+  legendItem: 'c3-legend-item',
+  legendItemEvent: 'c3-legend-item-event',
+  legendItemTile: 'c3-legend-item-tile',
+  legendItemHidden: 'c3-legend-item-hidden',
+  legendItemFocused: 'c3-legend-item-focused',
+  dragarea: 'c3-dragarea',
+  EXPANDED: '_expanded_',
+  SELECTED: '_selected_',
+  INCLUDED: '_included_'
+};
+
+class Axis {
+  constructor(owner) {
+    this.owner = owner;
+    this.d3 = owner.d3;
+    this.internal = AxisInternal;
+  }
+}
+Axis.prototype.init = function init() {
+  var $$ = this.owner,
+    config = $$.config,
+    main = $$.main;
+  $$.axes.x = main
+    .append('g')
+    .attr('class', CLASS.axis + ' ' + CLASS.axisX)
+    .attr('clip-path', config.axis_x_inner ? '' : $$.clipPathForXAxis)
+    .attr('transform', $$.getTranslate('x'))
+    .style('visibility', config.axis_x_show ? 'visible' : 'hidden');
+  $$.axes.x
+    .append('text')
+    .attr('class', CLASS.axisXLabel)
+    .attr('transform', config.axis_rotated ? 'rotate(-90)' : '')
+    .style('text-anchor', this.textAnchorForXAxisLabel.bind(this));
+  $$.axes.y = main
+    .append('g')
+    .attr('class', CLASS.axis + ' ' + CLASS.axisY)
+    .attr('clip-path', config.axis_y_inner ? '' : $$.clipPathForYAxis)
+    .attr('transform', $$.getTranslate('y'))
+    .style('visibility', config.axis_y_show ? 'visible' : 'hidden');
+  $$.axes.y
+    .append('text')
+    .attr('class', CLASS.axisYLabel)
+    .attr('transform', config.axis_rotated ? '' : 'rotate(-90)')
+    .style('text-anchor', this.textAnchorForYAxisLabel.bind(this));
+
+  $$.axes.y2 = main
+    .append('g')
+    .attr('class', CLASS.axis + ' ' + CLASS.axisY2)
+    // clip-path?
+    .attr('transform', $$.getTranslate('y2'))
+    .style('visibility', config.axis_y2_show ? 'visible' : 'hidden');
+  $$.axes.y2
+    .append('text')
+    .attr('class', CLASS.axisY2Label)
+    .attr('transform', config.axis_rotated ? '' : 'rotate(-90)')
+    .style('text-anchor', this.textAnchorForY2AxisLabel.bind(this));
+};
+Axis.prototype.getXAxis = function getXAxis(
+  scale,
+  orient,
+  tickFormat,
+  tickValues,
+  withOuterTick,
+  withoutTransition,
+  withoutRotateTickText
+) {
+  var $$ = this.owner,
+    config = $$.config,
+    axisParams = {
+      isCategory: $$.isCategorized(),
+      withOuterTick: withOuterTick,
+      tickMultiline: config.axis_x_tick_multiline,
+      tickMultilineMax: config.axis_x_tick_multiline
+        ? Number(config.axis_x_tick_multilineMax)
+        : 0,
+      tickWidth: config.axis_x_tick_width,
+      tickTextRotate: withoutRotateTickText ? 0 : config.axis_x_tick_rotate,
+      withoutTransition: withoutTransition
+    },
+    axis = new this.internal(this, axisParams).axis.scale(scale).orient(orient);
+
+  if ($$.isTimeSeries() && tickValues && typeof tickValues !== 'function') {
+    tickValues = tickValues.map(function(v) {
+      return $$.parseDate(v)
+    });
+  }
+
+  // Set tick
+  axis.tickFormat(tickFormat).tickValues(tickValues);
+  if ($$.isCategorized()) {
+    axis.tickCentered(config.axis_x_tick_centered);
+    if (isEmpty(config.axis_x_tick_culling)) {
+      config.axis_x_tick_culling = false;
+    }
+  }
+
+  return axis
+};
+Axis.prototype.updateXAxisTickValues = function updateXAxisTickValues(
+  targets,
+  axis
+) {
+  var $$ = this.owner,
+    config = $$.config,
+    tickValues;
+  if (config.axis_x_tick_fit || config.axis_x_tick_count) {
+    tickValues = this.generateTickValues(
+      $$.mapTargetsToUniqueXs(targets),
+      config.axis_x_tick_count,
+      $$.isTimeSeries()
+    );
+  }
+  if (axis) {
+    axis.tickValues(tickValues);
+  } else {
+    $$.xAxis.tickValues(tickValues);
+    $$.subXAxis.tickValues(tickValues);
+  }
+  return tickValues
+};
+Axis.prototype.getYAxis = function getYAxis(
+  axisId,
+  scale,
+  orient,
+  tickValues,
+  withOuterTick,
+  withoutTransition,
+  withoutRotateTickText
+) {
+  const $$ = this.owner;
+  const config = $$.config;
+
+  let tickFormat = config[`axis_${axisId}_tick_format`];
+  if (!tickFormat && $$.isAxisNormalized(axisId)) {
+    tickFormat = x => `${x}%`;
+  }
+
+  const axis = new this.internal(this, {
+    withOuterTick: withOuterTick,
+    withoutTransition: withoutTransition,
+    tickTextRotate: withoutRotateTickText ? 0 : config.axis_y_tick_rotate
+  }).axis
+    .scale(scale)
+    .orient(orient);
+
+  if (tickFormat) {
+    axis.tickFormat(tickFormat);
+  }
+
+  if ($$.isTimeSeriesY()) {
+    axis.ticks(config.axis_y_tick_time_type, config.axis_y_tick_time_interval);
+  } else {
+    axis.tickValues(tickValues);
+  }
+  return axis
+};
+Axis.prototype.getId = function getId(id) {
+  var config = this.owner.config;
+  return id in config.data_axes ? config.data_axes[id] : 'y'
+};
+Axis.prototype.getXAxisTickFormat = function getXAxisTickFormat() {
+  // #2251 previously set any negative values to a whole number,
+  // however both should be truncated according to the users format specification
+  var $$ = this.owner,
+    config = $$.config;
+  let format = $$.isTimeSeries()
+    ? $$.defaultAxisTimeFormat
+    : $$.isCategorized()
+    ? $$.categoryName
+    : function(v) {
+        return v
+      };
+
+  if (config.axis_x_tick_format) {
+    if (isFunction(config.axis_x_tick_format)) {
+      format = config.axis_x_tick_format;
+    } else if ($$.isTimeSeries()) {
+      format = function(date) {
+        return date ? $$.axisTimeFormat(config.axis_x_tick_format)(date) : ''
+      };
+    }
+  }
+  return isFunction(format)
+    ? function(v) {
+        return format.call($$, v)
+      }
+    : format
+};
+Axis.prototype.getTickValues = function getTickValues(tickValues, axis) {
+  return tickValues ? tickValues : axis ? axis.tickValues() : undefined
+};
+Axis.prototype.getXAxisTickValues = function getXAxisTickValues() {
+  return this.getTickValues(
+    this.owner.config.axis_x_tick_values,
+    this.owner.xAxis
+  )
+};
+Axis.prototype.getYAxisTickValues = function getYAxisTickValues() {
+  return this.getTickValues(
+    this.owner.config.axis_y_tick_values,
+    this.owner.yAxis
+  )
+};
+Axis.prototype.getY2AxisTickValues = function getY2AxisTickValues() {
+  return this.getTickValues(
+    this.owner.config.axis_y2_tick_values,
+    this.owner.y2Axis
+  )
+};
+Axis.prototype.getLabelOptionByAxisId = function getLabelOptionByAxisId(
+  axisId
+) {
+  var $$ = this.owner,
+    config = $$.config,
+    option;
+  if (axisId === 'y') {
+    option = config.axis_y_label;
+  } else if (axisId === 'y2') {
+    option = config.axis_y2_label;
+  } else if (axisId === 'x') {
+    option = config.axis_x_label;
+  }
+  return option
+};
+Axis.prototype.getLabelText = function getLabelText(axisId) {
+  var option = this.getLabelOptionByAxisId(axisId);
+  return isString(option) ? option : option ? option.text : null
+};
+Axis.prototype.setLabelText = function setLabelText(axisId, text) {
+  var $$ = this.owner,
+    config = $$.config,
+    option = this.getLabelOptionByAxisId(axisId);
+  if (isString(option)) {
+    if (axisId === 'y') {
+      config.axis_y_label = text;
+    } else if (axisId === 'y2') {
+      config.axis_y2_label = text;
+    } else if (axisId === 'x') {
+      config.axis_x_label = text;
+    }
+  } else if (option) {
+    option.text = text;
+  }
+};
+Axis.prototype.getLabelPosition = function getLabelPosition(
+  axisId,
+  defaultPosition
+) {
+  var option = this.getLabelOptionByAxisId(axisId),
+    position =
+      option && typeof option === 'object' && option.position
+        ? option.position
+        : defaultPosition;
+  return {
+    isInner: position.indexOf('inner') >= 0,
+    isOuter: position.indexOf('outer') >= 0,
+    isLeft: position.indexOf('left') >= 0,
+    isCenter: position.indexOf('center') >= 0,
+    isRight: position.indexOf('right') >= 0,
+    isTop: position.indexOf('top') >= 0,
+    isMiddle: position.indexOf('middle') >= 0,
+    isBottom: position.indexOf('bottom') >= 0
+  }
+};
+Axis.prototype.getXAxisLabelPosition = function getXAxisLabelPosition() {
+  return this.getLabelPosition(
+    'x',
+    this.owner.config.axis_rotated ? 'inner-top' : 'inner-right'
+  )
+};
+Axis.prototype.getYAxisLabelPosition = function getYAxisLabelPosition() {
+  return this.getLabelPosition(
+    'y',
+    this.owner.config.axis_rotated ? 'inner-right' : 'inner-top'
+  )
+};
+Axis.prototype.getY2AxisLabelPosition = function getY2AxisLabelPosition() {
+  return this.getLabelPosition(
+    'y2',
+    this.owner.config.axis_rotated ? 'inner-right' : 'inner-top'
+  )
+};
+Axis.prototype.getLabelPositionById = function getLabelPositionById(id) {
+  return id === 'y2'
+    ? this.getY2AxisLabelPosition()
+    : id === 'y'
+    ? this.getYAxisLabelPosition()
+    : this.getXAxisLabelPosition()
+};
+Axis.prototype.textForXAxisLabel = function textForXAxisLabel() {
+  return this.getLabelText('x')
+};
+Axis.prototype.textForYAxisLabel = function textForYAxisLabel() {
+  return this.getLabelText('y')
+};
+Axis.prototype.textForY2AxisLabel = function textForY2AxisLabel() {
+  return this.getLabelText('y2')
+};
+Axis.prototype.xForAxisLabel = function xForAxisLabel(forHorizontal, position) {
+  var $$ = this.owner;
+  if (forHorizontal) {
+    return position.isLeft ? 0 : position.isCenter ? $$.width / 2 : $$.width
+  } else {
+    return position.isBottom
+      ? -$$.height
+      : position.isMiddle
+      ? -$$.height / 2
+      : 0
+  }
+};
+Axis.prototype.dxForAxisLabel = function dxForAxisLabel(
+  forHorizontal,
+  position
+) {
+  if (forHorizontal) {
+    return position.isLeft ? '0.5em' : position.isRight ? '-0.5em' : '0'
+  } else {
+    return position.isTop ? '-0.5em' : position.isBottom ? '0.5em' : '0'
+  }
+};
+Axis.prototype.textAnchorForAxisLabel = function textAnchorForAxisLabel(
+  forHorizontal,
+  position
+) {
+  if (forHorizontal) {
+    return position.isLeft ? 'start' : position.isCenter ? 'middle' : 'end'
+  } else {
+    return position.isBottom ? 'start' : position.isMiddle ? 'middle' : 'end'
+  }
+};
+Axis.prototype.xForXAxisLabel = function xForXAxisLabel() {
+  return this.xForAxisLabel(
+    !this.owner.config.axis_rotated,
+    this.getXAxisLabelPosition()
+  )
+};
+Axis.prototype.xForYAxisLabel = function xForYAxisLabel() {
+  return this.xForAxisLabel(
+    this.owner.config.axis_rotated,
+    this.getYAxisLabelPosition()
+  )
+};
+Axis.prototype.xForY2AxisLabel = function xForY2AxisLabel() {
+  return this.xForAxisLabel(
+    this.owner.config.axis_rotated,
+    this.getY2AxisLabelPosition()
+  )
+};
+Axis.prototype.dxForXAxisLabel = function dxForXAxisLabel() {
+  return this.dxForAxisLabel(
+    !this.owner.config.axis_rotated,
+    this.getXAxisLabelPosition()
+  )
+};
+Axis.prototype.dxForYAxisLabel = function dxForYAxisLabel() {
+  return this.dxForAxisLabel(
+    this.owner.config.axis_rotated,
+    this.getYAxisLabelPosition()
+  )
+};
+Axis.prototype.dxForY2AxisLabel = function dxForY2AxisLabel() {
+  return this.dxForAxisLabel(
+    this.owner.config.axis_rotated,
+    this.getY2AxisLabelPosition()
+  )
+};
+Axis.prototype.dyForXAxisLabel = function dyForXAxisLabel() {
+  var $$ = this.owner,
+    config = $$.config,
+    position = this.getXAxisLabelPosition();
+  if (config.axis_rotated) {
+    return position.isInner
+      ? '1.2em'
+      : -25 - ($$.config.axis_x_inner ? 0 : this.getMaxTickWidth('x'))
+  } else {
+    return position.isInner ? '-0.5em' : $$.getHorizontalAxisHeight('x') - 10
+  }
+};
+Axis.prototype.dyForYAxisLabel = function dyForYAxisLabel() {
+  var $$ = this.owner,
+    position = this.getYAxisLabelPosition();
+  if ($$.config.axis_rotated) {
+    return position.isInner ? '-0.5em' : '3em'
+  } else {
+    return position.isInner
+      ? '1.2em'
+      : -10 - ($$.config.axis_y_inner ? 0 : this.getMaxTickWidth('y') + 10)
+  }
+};
+Axis.prototype.dyForY2AxisLabel = function dyForY2AxisLabel() {
+  var $$ = this.owner,
+    position = this.getY2AxisLabelPosition();
+  if ($$.config.axis_rotated) {
+    return position.isInner ? '1.2em' : '-2.2em'
+  } else {
+    return position.isInner
+      ? '-0.5em'
+      : 15 + ($$.config.axis_y2_inner ? 0 : this.getMaxTickWidth('y2') + 15)
+  }
+};
+Axis.prototype.textAnchorForXAxisLabel = function textAnchorForXAxisLabel() {
+  var $$ = this.owner;
+  return this.textAnchorForAxisLabel(
+    !$$.config.axis_rotated,
+    this.getXAxisLabelPosition()
+  )
+};
+Axis.prototype.textAnchorForYAxisLabel = function textAnchorForYAxisLabel() {
+  var $$ = this.owner;
+  return this.textAnchorForAxisLabel(
+    $$.config.axis_rotated,
+    this.getYAxisLabelPosition()
+  )
+};
+Axis.prototype.textAnchorForY2AxisLabel = function textAnchorForY2AxisLabel() {
+  var $$ = this.owner;
+  return this.textAnchorForAxisLabel(
+    $$.config.axis_rotated,
+    this.getY2AxisLabelPosition()
+  )
+};
+Axis.prototype.getMaxTickWidth = function getMaxTickWidth(
+  id,
+  withoutRecompute
+) {
+  var $$ = this.owner,
+    maxWidth = 0,
+    targetsToShow,
+    scale,
+    axis,
+    dummy,
+    svg;
+  if (withoutRecompute && $$.currentMaxTickWidths[id]) {
+    return $$.currentMaxTickWidths[id]
+  }
+  if ($$.svg) {
+    targetsToShow = $$.filterTargetsToShow($$.data.targets);
+    if (id === 'y') {
+      scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y'));
+      axis = this.getYAxis(
+        id,
+        scale,
+        $$.yOrient,
+        $$.yAxisTickValues,
+        false,
+        true,
+        true
+      );
+    } else if (id === 'y2') {
+      scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2'));
+      axis = this.getYAxis(
+        id,
+        scale,
+        $$.y2Orient,
+        $$.y2AxisTickValues,
+        false,
+        true,
+        true
+      );
+    } else {
+      scale = $$.x.copy().domain($$.getXDomain(targetsToShow));
+      axis = this.getXAxis(
+        scale,
+        $$.xOrient,
+        $$.xAxisTickFormat,
+        $$.xAxisTickValues,
+        false,
+        true,
+        true
+      );
+      this.updateXAxisTickValues(targetsToShow, axis);
+    }
+    dummy = $$.d3
+      .select('body')
+      .append('div')
+      .classed('c3', true)
+    ;(svg = dummy
+      .append('svg')
+      .style('visibility', 'hidden')
+      .style('position', 'fixed')
+      .style('top', 0)
+      .style('left', 0)),
+      svg
+        .append('g')
+        .call(axis)
+        .each(function() {
+          $$.d3
+            .select(this)
+            .selectAll('text')
+            .each(function() {
+              var box = getBBox(this);
+              if (maxWidth < box.width) {
+                maxWidth = box.width;
+              }
+            });
+          dummy.remove();
+        });
+  }
+  $$.currentMaxTickWidths[id] =
+    maxWidth <= 0 ? $$.currentMaxTickWidths[id] : maxWidth;
+  return $$.currentMaxTickWidths[id]
+};
+
+Axis.prototype.updateLabels = function updateLabels(withTransition) {
+  var $$ = this.owner;
+  var axisXLabel = $$.main.select('.' + CLASS.axisX + ' .' + CLASS.axisXLabel),
+    axisYLabel = $$.main.select('.' + CLASS.axisY + ' .' + CLASS.axisYLabel),
+    axisY2Label = $$.main.select('.' + CLASS.axisY2 + ' .' + CLASS.axisY2Label)
+  ;(withTransition ? axisXLabel.transition() : axisXLabel)
+    .attr('x', this.xForXAxisLabel.bind(this))
+    .attr('dx', this.dxForXAxisLabel.bind(this))
+    .attr('dy', this.dyForXAxisLabel.bind(this))
+    .text(this.textForXAxisLabel.bind(this))
+  ;(withTransition ? axisYLabel.transition() : axisYLabel)
+    .attr('x', this.xForYAxisLabel.bind(this))
+    .attr('dx', this.dxForYAxisLabel.bind(this))
+    .attr('dy', this.dyForYAxisLabel.bind(this))
+    .text(this.textForYAxisLabel.bind(this))
+  ;(withTransition ? axisY2Label.transition() : axisY2Label)
+    .attr('x', this.xForY2AxisLabel.bind(this))
+    .attr('dx', this.dxForY2AxisLabel.bind(this))
+    .attr('dy', this.dyForY2AxisLabel.bind(this))
+    .text(this.textForY2AxisLabel.bind(this));
+};
+Axis.prototype.getPadding = function getPadding(
+  padding,
+  key,
+  defaultValue,
+  domainLength
+) {
+  var p = typeof padding === 'number' ? padding : padding[key];
+  if (!isValue(p)) {
+    return defaultValue
+  }
+  if (padding.unit === 'ratio') {
+    return padding[key] * domainLength
+  }
+  // assume padding is pixels if unit is not specified
+  return this.convertPixelsToAxisPadding(p, domainLength)
+};
+Axis.prototype.convertPixelsToAxisPadding = function convertPixelsToAxisPadding(
+  pixels,
+  domainLength
+) {
+  var $$ = this.owner,
+    length = $$.config.axis_rotated ? $$.width : $$.height;
+  return domainLength * (pixels / length)
+};
+Axis.prototype.generateTickValues = function generateTickValues(
+  values,
+  tickCount,
+  forTimeSeries
+) {
+  var tickValues = values,
+    targetCount,
+    start,
+    end,
+    count,
+    interval,
+    i,
+    tickValue;
+  if (tickCount) {
+    targetCount = isFunction(tickCount) ? tickCount() : tickCount;
+    // compute ticks according to tickCount
+    if (targetCount === 1) {
+      tickValues = [values[0]];
+    } else if (targetCount === 2) {
+      tickValues = [values[0], values[values.length - 1]];
+    } else if (targetCount > 2) {
+      count = targetCount - 2;
+      start = values[0];
+      end = values[values.length - 1];
+      interval = (end - start) / (count + 1);
+      // re-construct unique values
+      tickValues = [start];
+      for (i = 0; i < count; i++) {
+        tickValue = +start + interval * (i + 1);
+        tickValues.push(forTimeSeries ? new Date(tickValue) : tickValue);
+      }
+      tickValues.push(end);
+    }
+  }
+  if (!forTimeSeries) {
+    tickValues = tickValues.sort(function(a, b) {
+      return a - b
+    });
+  }
+  return tickValues
+};
+Axis.prototype.generateTransitions = function generateTransitions(duration) {
+  var $$ = this.owner,
+    axes = $$.axes;
+  return {
+    axisX: duration ? axes.x.transition().duration(duration) : axes.x,
+    axisY: duration ? axes.y.transition().duration(duration) : axes.y,
+    axisY2: duration ? axes.y2.transition().duration(duration) : axes.y2,
+    axisSubX: duration ? axes.subx.transition().duration(duration) : axes.subx
+  }
+};
+Axis.prototype.redraw = function redraw(duration, isHidden) {
+  var $$ = this.owner,
+    transition = duration ? $$.d3.transition().duration(duration) : null;
+  $$.axes.x.style('opacity', isHidden ? 0 : 1).call($$.xAxis, transition);
+  $$.axes.y.style('opacity', isHidden ? 0 : 1).call($$.yAxis, transition);
+  $$.axes.y2.style('opacity', isHidden ? 0 : 1).call($$.y2Axis, transition);
+  $$.axes.subx.style('opacity', isHidden ? 0 : 1).call($$.subXAxis, transition);
+};
+
+var c3 = {
+  version: '0.7.18',
+  chart: {
+    fn: Chart.prototype,
+    internal: {
+      fn: ChartInternal.prototype,
+      axis: {
+        fn: Axis.prototype,
+        internal: {
+          fn: AxisInternal.prototype
+        }
+      }
+    }
+  },
+  generate: function(config) {
+    return new Chart(config)
+  }
+};
+
+ChartInternal.prototype.beforeInit = function() {
+  // can do something
+};
+ChartInternal.prototype.afterInit = function() {
+  // can do something
+};
+ChartInternal.prototype.init = function() {
+  var $$ = this,
+    config = $$.config;
+
+  $$.initParams();
+
+  if (config.data_url) {
+    $$.convertUrlToData(
+      config.data_url,
+      config.data_mimeType,
+      config.data_headers,
+      config.data_keys,
+      $$.initWithData
+    );
+  } else if (config.data_json) {
+    $$.initWithData($$.convertJsonToData(config.data_json, config.data_keys));
+  } else if (config.data_rows) {
+    $$.initWithData($$.convertRowsToData(config.data_rows));
+  } else if (config.data_columns) {
+    $$.initWithData($$.convertColumnsToData(config.data_columns));
+  } else {
+    throw Error('url or json or rows or columns is required.')
+  }
+};
+
+ChartInternal.prototype.initParams = function() {
+  var $$ = this,
+    d3 = $$.d3,
+    config = $$.config;
+
+  // MEMO: clipId needs to be unique because it conflicts when multiple charts exist
+  $$.clipId = 'c3-' + new Date().valueOf() + '-clip';
+  $$.clipIdForXAxis = $$.clipId + '-xaxis';
+  $$.clipIdForYAxis = $$.clipId + '-yaxis';
+  $$.clipIdForGrid = $$.clipId + '-grid';
+  $$.clipIdForSubchart = $$.clipId + '-subchart';
+  $$.clipPath = $$.getClipPath($$.clipId);
+  $$.clipPathForXAxis = $$.getClipPath($$.clipIdForXAxis);
+  $$.clipPathForYAxis = $$.getClipPath($$.clipIdForYAxis);
+  $$.clipPathForGrid = $$.getClipPath($$.clipIdForGrid);
+  $$.clipPathForSubchart = $$.getClipPath($$.clipIdForSubchart);
+
+  $$.dragStart = null;
+  $$.dragging = false;
+  $$.flowing = false;
+  $$.cancelClick = false;
+  $$.mouseover = undefined;
+  $$.transiting = false;
+
+  $$.color = $$.generateColor();
+  $$.levelColor = $$.generateLevelColor();
+
+  $$.dataTimeParse = (config.data_xLocaltime ? d3.timeParse : d3.utcParse)(
+    $$.config.data_xFormat
+  );
+  $$.axisTimeFormat = config.axis_x_localtime ? d3.timeFormat : d3.utcFormat;
+  $$.defaultAxisTimeFormat = function(date) {
+    if (date.getMilliseconds()) {
+      return d3.timeFormat('.%L')(date)
+    }
+    if (date.getSeconds()) {
+      return d3.timeFormat(':%S')(date)
+    }
+    if (date.getMinutes()) {
+      return d3.timeFormat('%I:%M')(date)
+    }
+    if (date.getHours()) {
+      return d3.timeFormat('%I %p')(date)
+    }
+    if (date.getDay() && date.getDate() !== 1) {
+      return d3.timeFormat('%-m/%-d')(date)
+    }
+    if (date.getDate() !== 1) {
+      return d3.timeFormat('%-m/%-d')(date)
+    }
+    if (date.getMonth()) {
+      return d3.timeFormat('%-m/%-d')(date)
+    }
+    return d3.timeFormat('%Y/%-m/%-d')(date)
+  };
+  $$.hiddenTargetIds = [];
+  $$.hiddenLegendIds = [];
+  $$.focusedTargetIds = [];
+  $$.defocusedTargetIds = [];
+
+  $$.xOrient = config.axis_rotated
+    ? config.axis_x_inner
+      ? 'right'
+      : 'left'
+    : config.axis_x_inner
+    ? 'top'
+    : 'bottom';
+  $$.yOrient = config.axis_rotated
+    ? config.axis_y_inner
+      ? 'top'
+      : 'bottom'
+    : config.axis_y_inner
+    ? 'right'
+    : 'left';
+  $$.y2Orient = config.axis_rotated
+    ? config.axis_y2_inner
+      ? 'bottom'
+      : 'top'
+    : config.axis_y2_inner
+    ? 'left'
+    : 'right';
+  $$.subXOrient = config.axis_rotated ? 'left' : 'bottom';
+
+  $$.isLegendRight = config.legend_position === 'right';
+  $$.isLegendInset = config.legend_position === 'inset';
+  $$.isLegendTop =
+    config.legend_inset_anchor === 'top-left' ||
+    config.legend_inset_anchor === 'top-right';
+  $$.isLegendLeft =
+    config.legend_inset_anchor === 'top-left' ||
+    config.legend_inset_anchor === 'bottom-left';
+  $$.legendStep = 0;
+  $$.legendItemWidth = 0;
+  $$.legendItemHeight = 0;
+
+  $$.currentMaxTickWidths = {
+    x: 0,
+    y: 0,
+    y2: 0
+  };
+
+  $$.rotated_padding_left = 30;
+  $$.rotated_padding_right = config.axis_rotated && !config.axis_x_show ? 0 : 30;
+  $$.rotated_padding_top = 5;
+
+  $$.withoutFadeIn = {};
+
+  $$.intervalForObserveInserted = undefined;
+
+  $$.axes.subx = d3.selectAll([]); // needs when excluding subchart.js
+};
+
+ChartInternal.prototype.initChartElements = function() {
+  if (this.initBar) {
+    this.initBar();
+  }
+  if (this.initLine) {
+    this.initLine();
+  }
+  if (this.initArc) {
+    this.initArc();
+  }
+  if (this.initGauge) {
+    this.initGauge();
+  }
+  if (this.initText) {
+    this.initText();
+  }
+};
+
+ChartInternal.prototype.initWithData = function(data) {
+  var $$ = this,
+    d3 = $$.d3,
+    config = $$.config;
+  var defs,
+    main,
+    binding = true;
+
+  $$.axis = new Axis($$);
+
+  if (!config.bindto) {
+    $$.selectChart = d3.selectAll([]);
+  } else if (typeof config.bindto.node === 'function') {
+    $$.selectChart = config.bindto;
+  } else {
+    $$.selectChart = d3.select(config.bindto);
+  }
+  if ($$.selectChart.empty()) {
+    $$.selectChart = d3
+      .select(document.createElement('div'))
+      .style('opacity', 0);
+    $$.observeInserted($$.selectChart);
+    binding = false;
+  }
+  $$.selectChart.html('').classed('c3', true);
+
+  // Init data as targets
+  $$.data.xs = {};
+  $$.data.targets = $$.convertDataToTargets(data);
+
+  if (config.data_filter) {
+    $$.data.targets = $$.data.targets.filter(config.data_filter);
+  }
+
+  // Set targets to hide if needed
+  if (config.data_hide) {
+    $$.addHiddenTargetIds(
+      config.data_hide === true
+        ? $$.mapToIds($$.data.targets)
+        : config.data_hide
+    );
+  }
+  if (config.legend_hide) {
+    $$.addHiddenLegendIds(
+      config.legend_hide === true
+        ? $$.mapToIds($$.data.targets)
+        : config.legend_hide
+    );
+  }
+
+  if ($$.isStanfordGraphType()) {
+    $$.initStanfordData();
+  }
+
+  // Init sizes and scales
+  $$.updateSizes();
+  $$.updateScales();
+
+  // Set domains for each scale
+  $$.x.domain(d3.extent($$.getXDomain($$.data.targets)));
+  $$.y.domain($$.getYDomain($$.data.targets, 'y'));
+  $$.y2.domain($$.getYDomain($$.data.targets, 'y2'));
+  $$.subX.domain($$.x.domain());
+  $$.subY.domain($$.y.domain());
+  $$.subY2.domain($$.y2.domain());
+
+  // Save original x domain for zoom update
+  $$.orgXDomain = $$.x.domain();
+
+  /*-- Basic Elements --*/
+
+  // Define svgs
+  $$.svg = $$.selectChart
+    .append('svg')
+    .style('overflow', 'hidden')
+    .on('mouseenter', function() {
+      return config.onmouseover.call($$)
+    })
+    .on('mouseleave', function() {
+      return config.onmouseout.call($$)
+    });
+
+  if ($$.config.svg_classname) {
+    $$.svg.attr('class', $$.config.svg_classname);
+  }
+
+  // Define defs
+  defs = $$.svg.append('defs');
+  $$.clipChart = $$.appendClip(defs, $$.clipId);
+  $$.clipXAxis = $$.appendClip(defs, $$.clipIdForXAxis);
+  $$.clipYAxis = $$.appendClip(defs, $$.clipIdForYAxis);
+  $$.clipGrid = $$.appendClip(defs, $$.clipIdForGrid);
+  $$.clipSubchart = $$.appendClip(defs, $$.clipIdForSubchart);
+  $$.updateSvgSize();
+
+  // Define regions
+  main = $$.main = $$.svg.append('g').attr('transform', $$.getTranslate('main'));
+
+  if ($$.initPie) {
+    $$.initPie();
+  }
+  if ($$.initDragZoom) {
+    $$.initDragZoom();
+  }
+  if (config.subchart_show && $$.initSubchart) {
+    $$.initSubchart();
+  }
+  if ($$.initTooltip) {
+    $$.initTooltip();
+  }
+  if ($$.initLegend) {
+    $$.initLegend();
+  }
+  if ($$.initTitle) {
+    $$.initTitle();
+  }
+  if ($$.initZoom) {
+    $$.initZoom();
+  }
+  if ($$.isStanfordGraphType()) {
+    $$.drawColorScale();
+  }
+
+  // Update selection based on size and scale
+  // TODO: currently this must be called after initLegend because of update of sizes, but it should be done in initSubchart.
+  if (config.subchart_show && $$.initSubchartBrush) {
+    $$.initSubchartBrush();
+  }
+
+  /*-- Main Region --*/
+
+  // text when empty
+  main
+    .append('text')
+    .attr('class', CLASS.text + ' ' + CLASS.empty)
+    .attr('text-anchor', 'middle') // horizontal centering of text at x position in all browsers.
+    .attr('dominant-baseline', 'middle'); // vertical centering of text at y position in all browsers, except IE.
+
+  // Regions
+  $$.initRegion();
+
+  // Grids
+  $$.initGrid();
+
+  // Define g for chart area
+  main
+    .append('g')
+    .attr('clip-path', $$.clipPath)
+    .attr('class', CLASS.chart);
+
+  // Grid lines
+  if (config.grid_lines_front) {
+    $$.initGridLines();
+  }
+
+  $$.initStanfordElements();
+
+  // Cover whole with rects for events
+  $$.initEventRect();
+
+  // Define g for chart
+  $$.initChartElements();
+
+  // Add Axis
+  $$.axis.init();
+
+  // Set targets
+  $$.updateTargets($$.data.targets);
+
+  // Set default extent if defined
+  if (config.axis_x_selection) {
+    $$.brush.selectionAsValue($$.getDefaultSelection());
+  }
+
+  // Draw with targets
+  if (binding) {
+    $$.updateDimension();
+    $$.config.oninit.call($$);
+    $$.redraw({
+      withTransition: false,
+      withTransform: true,
+      withUpdateXDomain: true,
+      withUpdateOrgXDomain: true,
+      withTransitionForAxis: false
+    });
+  }
+
+  // Bind to resize event
+  $$.bindResize();
+
+  // Bind to window focus event
+  $$.bindWindowFocus();
+
+  // export element of the chart
+  $$.api.element = $$.selectChart.node();
+};
+
+ChartInternal.prototype.smoothLines = function(el, type) {
+  var $$ = this;
+  if (type === 'grid') {
+    el.each(function() {
+      var g = $$.d3.select(this),
+        x1 = g.attr('x1'),
+        x2 = g.attr('x2'),
+        y1 = g.attr('y1'),
+        y2 = g.attr('y2');
+      g.attr({
+        x1: Math.ceil(x1),
+        x2: Math.ceil(x2),
+        y1: Math.ceil(y1),
+        y2: Math.ceil(y2)
+      });
+    });
+  }
+};
+
+ChartInternal.prototype.updateSizes = function() {
+  var $$ = this,
+    config = $$.config;
+  var legendHeight = $$.legend ? $$.getLegendHeight() : 0,
+    legendWidth = $$.legend ? $$.getLegendWidth() : 0,
+    legendHeightForBottom =
+      $$.isLegendRight || $$.isLegendInset ? 0 : legendHeight,
+    hasArc = $$.hasArcType(),
+    xAxisHeight =
+      config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight('x'),
+    subchartHeight =
+      config.subchart_show && !hasArc
+        ? config.subchart_size_height + xAxisHeight
+        : 0;
+
+  $$.currentWidth = $$.getCurrentWidth();
+  $$.currentHeight = $$.getCurrentHeight();
+
+  // for main
+  $$.margin = config.axis_rotated
+    ? {
+        top: $$.getHorizontalAxisHeight('y2') + $$.getCurrentPaddingTop(),
+        right: hasArc ? 0 : $$.getCurrentPaddingRight(),
+        bottom:
+          $$.getHorizontalAxisHeight('y') +
+          legendHeightForBottom +
+          $$.getCurrentPaddingBottom(),
+        left: subchartHeight + (hasArc ? 0 : $$.getCurrentPaddingLeft())
+      }
+    : {
+        top: 4 + $$.getCurrentPaddingTop(), // for top tick text
+        right: hasArc ? 0 : $$.getCurrentPaddingRight(),
+        bottom:
+          xAxisHeight +
+          subchartHeight +
+          legendHeightForBottom +
+          $$.getCurrentPaddingBottom(),
+        left: hasArc ? 0 : $$.getCurrentPaddingLeft()
+      };
+
+  // for subchart
+  $$.margin2 = config.axis_rotated
+    ? {
+        top: $$.margin.top,
+        right: NaN,
+        bottom: 20 + legendHeightForBottom,
+        left: $$.rotated_padding_left
+      }
+    : {
+        top: $$.currentHeight - subchartHeight - legendHeightForBottom,
+        right: NaN,
+        bottom: xAxisHeight + legendHeightForBottom,
+        left: $$.margin.left
+      };
+
+  // for legend
+  $$.margin3 = {
+    top: 0,
+    right: NaN,
+    bottom: 0,
+    left: 0
+  };
+  if ($$.updateSizeForLegend) {
+    $$.updateSizeForLegend(legendHeight, legendWidth);
+  }
+
+  $$.width = $$.currentWidth - $$.margin.left - $$.margin.right;
+  $$.height = $$.currentHeight - $$.margin.top - $$.margin.bottom;
+  if ($$.width < 0) {
+    $$.width = 0;
+  }
+  if ($$.height < 0) {
+    $$.height = 0;
+  }
+
+  $$.width2 = config.axis_rotated
+    ? $$.margin.left - $$.rotated_padding_left - $$.rotated_padding_right
+    : $$.width;
+  $$.height2 = config.axis_rotated
+    ? $$.height
+    : $$.currentHeight - $$.margin2.top - $$.margin2.bottom;
+  if ($$.width2 < 0) {
+    $$.width2 = 0;
+  }
+  if ($$.height2 < 0) {
+    $$.height2 = 0;
+  }
+
+  // for arc
+  $$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0);
+  $$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10);
+  if ($$.hasType('gauge') && !config.gauge_fullCircle) {
+    $$.arcHeight += $$.height - $$.getGaugeLabelHeight();
+  }
+  if ($$.updateRadius) {
+    $$.updateRadius();
+  }
+
+  if ($$.isLegendRight && hasArc) {
+    $$.margin3.left = $$.arcWidth / 2 + $$.radiusExpanded * 1.1;
+  }
+};
+
+ChartInternal.prototype.updateTargets = function(targets) {
+  var $$ = this,
+    config = $$.config;
+
+  /*-- Main --*/
+
+  //-- Text --//
+  $$.updateTargetsForText(targets);
+
+  //-- Bar --//
+  $$.updateTargetsForBar(targets);
+
+  //-- Line --//
+  $$.updateTargetsForLine(targets);
+
+  //-- Arc --//
+  if ($$.hasArcType() && $$.updateTargetsForArc) {
+    $$.updateTargetsForArc(targets);
+  }
+
+  /*-- Sub --*/
+
+  if (config.subchart_show && $$.updateTargetsForSubchart) {
+    $$.updateTargetsForSubchart(targets);
+  }
+
+  // Fade-in each chart
+  $$.showTargets();
+};
+ChartInternal.prototype.showTargets = function() {
+  var $$ = this;
+  $$.svg
+    .selectAll('.' + CLASS.target)
+    .filter(function(d) {
+      return $$.isTargetToShow(d.id)
+    })
+    .transition()
+    .duration($$.config.transition_duration)
+    .style('opacity', 1);
+};
+
+ChartInternal.prototype.redraw = function(options, transitions) {
+  var $$ = this,
+    main = $$.main,
+    d3 = $$.d3,
+    config = $$.config;
+  var areaIndices = $$.getShapeIndices($$.isAreaType),
+    barIndices = $$.getShapeIndices($$.isBarType),
+    lineIndices = $$.getShapeIndices($$.isLineType);
+  var withY,
+    withSubchart,
+    withTransition,
+    withTransitionForExit,
+    withTransitionForAxis,
+    withTransform,
+    withUpdateXDomain,
+    withUpdateOrgXDomain,
+    withTrimXDomain,
+    withLegend,
+    withEventRect,
+    withDimension,
+    withUpdateXAxis;
+  var hideAxis = $$.hasArcType();
+  var drawArea, drawBar, drawLine, xForText, yForText;
+  var duration, durationForExit, durationForAxis;
+  var transitionsToWait, waitForDraw, flow, transition;
+  var targetsToShow = $$.filterTargetsToShow($$.data.targets),
+    tickValues,
+    i,
+    intervalForCulling,
+    xDomainForZoom;
+  var xv = $$.xv.bind($$),
+    cx,
+    cy;
+
+  options = options || {};
+  withY = getOption(options, 'withY', true);
+  withSubchart = getOption(options, 'withSubchart', true);
+  withTransition = getOption(options, 'withTransition', true);
+  withTransform = getOption(options, 'withTransform', false);
+  withUpdateXDomain = getOption(options, 'withUpdateXDomain', false);
+  withUpdateOrgXDomain = getOption(options, 'withUpdateOrgXDomain', false);
+  withTrimXDomain = getOption(options, 'withTrimXDomain', true);
+  withUpdateXAxis = getOption(options, 'withUpdateXAxis', withUpdateXDomain);
+  withLegend = getOption(options, 'withLegend', false);
+  withEventRect = getOption(options, 'withEventRect', true);
+  withDimension = getOption(options, 'withDimension', true);
+  withTransitionForExit = getOption(
+    options,
+    'withTransitionForExit',
+    withTransition
+  );
+  withTransitionForAxis = getOption(
+    options,
+    'withTransitionForAxis',
+    withTransition
+  );
+
+  duration = withTransition ? config.transition_duration : 0;
+  durationForExit = withTransitionForExit ? duration : 0;
+  durationForAxis = withTransitionForAxis ? duration : 0;
+
+  transitions = transitions || $$.axis.generateTransitions(durationForAxis);
+
+  // update legend and transform each g
+  if (withLegend && config.legend_show) {
+    $$.updateLegend($$.mapToIds($$.data.targets), options, transitions);
+  } else if (withDimension) {
+    // need to update dimension (e.g. axis.y.tick.values) because y tick values should change
+    // no need to update axis in it because they will be updated in redraw()
+    $$.updateDimension(true);
+  }
+
+  // MEMO: needed for grids calculation
+  if ($$.isCategorized() && targetsToShow.length === 0) {
+    $$.x.domain([0, $$.axes.x.selectAll('.tick').size()]);
+  }
+
+  if (targetsToShow.length) {
+    $$.updateXDomain(
+      targetsToShow,
+      withUpdateXDomain,
+      withUpdateOrgXDomain,
+      withTrimXDomain
+    );
+    if (!config.axis_x_tick_values) {
+      tickValues = $$.axis.updateXAxisTickValues(targetsToShow);
+    }
+  } else {
+    $$.xAxis.tickValues([]);
+    $$.subXAxis.tickValues([]);
+  }
+
+  if (config.zoom_rescale && !options.flow) {
+    xDomainForZoom = $$.x.orgDomain();
+  }
+
+  $$.y.domain($$.getYDomain(targetsToShow, 'y', xDomainForZoom));
+  $$.y2.domain($$.getYDomain(targetsToShow, 'y2', xDomainForZoom));
+
+  if (!config.axis_y_tick_values && config.axis_y_tick_count) {
+    $$.yAxis.tickValues(
+      $$.axis.generateTickValues($$.y.domain(), config.axis_y_tick_count)
+    );
+  }
+  if (!config.axis_y2_tick_values && config.axis_y2_tick_count) {
+    $$.y2Axis.tickValues(
+      $$.axis.generateTickValues($$.y2.domain(), config.axis_y2_tick_count)
+    );
+  }
+
+  // axes
+  $$.axis.redraw(durationForAxis, hideAxis);
+
+  // Update axis label
+  $$.axis.updateLabels(withTransition);
+
+  // show/hide if manual culling needed
+  if ((withUpdateXDomain || withUpdateXAxis) && targetsToShow.length) {
+    if (config.axis_x_tick_culling && tickValues) {
+      for (i = 1; i < tickValues.length; i++) {
+        if (tickValues.length / i < config.axis_x_tick_culling_max) {
+          intervalForCulling = i;
+          break
+        }
+      }
+      $$.svg.selectAll('.' + CLASS.axisX + ' .tick text').each(function(e) {
+        var index = tickValues.indexOf(e);
+        if (index >= 0) {
+          d3.select(this).style(
+            'display',
+            index % intervalForCulling ? 'none' : 'block'
+          );
+        }
+      });
+    } else {
+      $$.svg
+        .selectAll('.' + CLASS.axisX + ' .tick text')
+        .style('display', 'block');
+    }
+  }
+
+  // setup drawer - MEMO: these must be called after axis updated
+  drawArea = $$.generateDrawArea
+    ? $$.generateDrawArea(areaIndices, false)
+    : undefined;
+  drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices) : undefined;
+  drawLine = $$.generateDrawLine
+    ? $$.generateDrawLine(lineIndices, false)
+    : undefined;
+  xForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, true);
+  yForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, false);
+
+  // update circleY based on updated parameters
+  $$.updateCircleY();
+  // generate circle x/y functions depending on updated params
+  cx = ($$.config.axis_rotated ? $$.circleY : $$.circleX).bind($$);
+  cy = ($$.config.axis_rotated ? $$.circleX : $$.circleY).bind($$);
+
+  // Update sub domain
+  if (withY) {
+    $$.subY.domain($$.getYDomain(targetsToShow, 'y'));
+    $$.subY2.domain($$.getYDomain(targetsToShow, 'y2'));
+  }
+
+  // xgrid focus
+  $$.updateXgridFocus();
+
+  // Data empty label positioning and text.
+  main
+    .select('text.' + CLASS.text + '.' + CLASS.empty)
+    .attr('x', $$.width / 2)
+    .attr('y', $$.height / 2)
+    .text(config.data_empty_label_text)
+    .transition()
+    .style('opacity', targetsToShow.length ? 0 : 1);
+
+  // event rect
+  if (withEventRect) {
+    $$.redrawEventRect();
+  }
+
+  // grid
+  $$.updateGrid(duration);
+
+  $$.updateStanfordElements(duration);
+
+  // rect for regions
+  $$.updateRegion(duration);
+
+  // bars
+  $$.updateBar(durationForExit);
+
+  // lines, areas and circles
+  $$.updateLine(durationForExit);
+  $$.updateArea(durationForExit);
+  $$.updateCircle(cx, cy);
+
+  // text
+  if ($$.hasDataLabel()) {
+    $$.updateText(xForText, yForText, durationForExit);
+  }
+
+  // title
+  if ($$.redrawTitle) {
+    $$.redrawTitle();
+  }
+
+  // arc
+  if ($$.redrawArc) {
+    $$.redrawArc(duration, durationForExit, withTransform);
+  }
+
+  // subchart
+  if (config.subchart_show && $$.redrawSubchart) {
+    $$.redrawSubchart(
+      withSubchart,
+      transitions,
+      duration,
+      durationForExit,
+      areaIndices,
+      barIndices,
+      lineIndices
+    );
+  }
+
+  if ($$.isStanfordGraphType()) {
+    $$.drawColorScale();
+  }
+
+  // circles for select
+  main
+    .selectAll('.' + CLASS.selectedCircles)
+    .filter($$.isBarType.bind($$))
+    .selectAll('circle')
+    .remove();
+
+  if (options.flow) {
+    flow = $$.generateFlow({
+      targets: targetsToShow,
+      flow: options.flow,
+      duration: options.flow.duration,
+      drawBar: drawBar,
+      drawLine: drawLine,
+      drawArea: drawArea,
+      cx: cx,
+      cy: cy,
+      xv: xv,
+      xForText: xForText,
+      yForText: yForText
+    });
+  }
+
+  if (duration && $$.isTabVisible()) {
+    // Only use transition if tab visible. See #938.
+    // transition should be derived from one transition
+    transition = d3.transition().duration(duration);
+    transitionsToWait = []
+    ;[
+      $$.redrawBar(drawBar, true, transition),
+      $$.redrawLine(drawLine, true, transition),
+      $$.redrawArea(drawArea, true, transition),
+      $$.redrawCircle(cx, cy, true, transition),
+      $$.redrawText(xForText, yForText, options.flow, true, transition),
+      $$.redrawRegion(true, transition),
+      $$.redrawGrid(true, transition)
+    ].forEach(function(transitions) {
+      transitions.forEach(function(transition) {
+        transitionsToWait.push(transition);
+      });
+    });
+    // Wait for end of transitions to call flow and onrendered callback
+    waitForDraw = $$.generateWait();
+    transitionsToWait.forEach(function(t) {
+      waitForDraw.add(t);
+    });
+    waitForDraw(function() {
+      if (flow) {
+        flow();
+      }
+      if (config.onrendered) {
+        config.onrendered.call($$);
+      }
+    });
+  } else {
+    $$.redrawBar(drawBar);
+    $$.redrawLine(drawLine);
+    $$.redrawArea(drawArea);
+    $$.redrawCircle(cx, cy);
+    $$.redrawText(xForText, yForText, options.flow);
+    $$.redrawRegion();
+    $$.redrawGrid();
+    if (flow) {
+      flow();
+    }
+    if (config.onrendered) {
+      config.onrendered.call($$);
+    }
+  }
+
+  // update fadein condition
+  $$.mapToIds($$.data.targets).forEach(function(id) {
+    $$.withoutFadeIn[id] = true;
+  });
+};
+
+ChartInternal.prototype.updateAndRedraw = function(options) {
+  var $$ = this,
+    config = $$.config,
+    transitions;
+  options = options || {};
+  // same with redraw
+  options.withTransition = getOption(options, 'withTransition', true);
+  options.withTransform = getOption(options, 'withTransform', false);
+  options.withLegend = getOption(options, 'withLegend', false);
+  // NOT same with redraw
+  options.withUpdateXDomain = getOption(options, 'withUpdateXDomain', true);
+  options.withUpdateOrgXDomain = getOption(
+    options,
+    'withUpdateOrgXDomain',
+    true
+  );
+  options.withTransitionForExit = false;
+  options.withTransitionForTransform = getOption(
+    options,
+    'withTransitionForTransform',
+    options.withTransition
+  );
+  // MEMO: this needs to be called before updateLegend and it means this ALWAYS needs to be called)
+  $$.updateSizes();
+  // MEMO: called in updateLegend in redraw if withLegend
+  if (!(options.withLegend && config.legend_show)) {
+    transitions = $$.axis.generateTransitions(
+      options.withTransitionForAxis ? config.transition_duration : 0
+    );
+    // Update scales
+    $$.updateScales();
+    $$.updateSvgSize();
+    // Update g positions
+    $$.transformAll(options.withTransitionForTransform, transitions);
+  }
+  // Draw with new sizes & scales
+  $$.redraw(options, transitions);
+};
+ChartInternal.prototype.redrawWithoutRescale = function() {
+  this.redraw({
+    withY: false,
+    withSubchart: false,
+    withEventRect: false,
+    withTransitionForAxis: false
+  });
+};
+
+ChartInternal.prototype.isTimeSeries = function() {
+  return this.config.axis_x_type === 'timeseries'
+};
+ChartInternal.prototype.isCategorized = function() {
+  return this.config.axis_x_type.indexOf('categor') >= 0
+};
+ChartInternal.prototype.isCustomX = function() {
+  var $$ = this,
+    config = $$.config;
+  return !$$.isTimeSeries() && (config.data_x || notEmpty(config.data_xs))
+};
+
+ChartInternal.prototype.isTimeSeriesY = function() {
+  return this.config.axis_y_type === 'timeseries'
+};
+
+ChartInternal.prototype.getTranslate = function(target) {
+  var $$ = this,
+    config = $$.config,
+    x,
+    y;
+  if (target === 'main') {
+    x = asHalfPixel($$.margin.left);
+    y = asHalfPixel($$.margin.top);
+  } else if (target === 'context') {
+    x = asHalfPixel($$.margin2.left);
+    y = asHalfPixel($$.margin2.top);
+  } else if (target === 'legend') {
+    x = $$.margin3.left;
+    y = $$.margin3.top;
+  } else if (target === 'x') {
+    x = 0;
+    y = config.axis_rotated ? 0 : $$.height;
+  } else if (target === 'y') {
+    x = 0;
+    y = config.axis_rotated ? $$.height : 0;
+  } else if (target === 'y2') {
+    x = config.axis_rotated ? 0 : $$.width;
+    y = config.axis_rotated ? 1 : 0;
+  } else if (target === 'subx') {
+    x = 0;
+    y = config.axis_rotated ? 0 : $$.height2;
+  } else if (target === 'arc') {
+    x = $$.arcWidth / 2;
+    y = $$.arcHeight / 2 - ($$.hasType('gauge') ? 6 : 0); // to prevent wrong display of min and max label
+  }
+  return 'translate(' + x + ',' + y + ')'
+};
+ChartInternal.prototype.initialOpacity = function(d) {
+  return d.value !== null && this.withoutFadeIn[d.id] ? 1 : 0
+};
+ChartInternal.prototype.initialOpacityForCircle = function(d) {
+  return d.value !== null && this.withoutFadeIn[d.id]
+    ? this.opacityForCircle(d)
+    : 0
+};
+ChartInternal.prototype.opacityForCircle = function(d) {
+  var isPointShouldBeShown = isFunction(this.config.point_show)
+    ? this.config.point_show(d)
+    : this.config.point_show;
+  var opacity = isPointShouldBeShown || this.isStanfordType(d) ? 1 : 0;
+  return isValue(d.value) ? (this.isScatterType(d) ? 0.5 : opacity) : 0
+};
+ChartInternal.prototype.opacityForText = function() {
+  return this.hasDataLabel() ? 1 : 0
+};
+ChartInternal.prototype.xx = function(d) {
+  return d ? this.x(d.x) : null
+};
+ChartInternal.prototype.xvCustom = function(d, xyValue) {
+  var $$ = this,
+    value = xyValue ? d[xyValue] : d.value;
+  if ($$.isTimeSeries()) {
+    value = $$.parseDate(d.value);
+  } else if ($$.isCategorized() && typeof d.value === 'string') {
+    value = $$.config.axis_x_categories.indexOf(d.value);
+  }
+  return Math.ceil($$.x(value))
+};
+ChartInternal.prototype.yvCustom = function(d, xyValue) {
+  var $$ = this,
+    yScale = d.axis && d.axis === 'y2' ? $$.y2 : $$.y,
+    value = xyValue ? d[xyValue] : d.value;
+  return Math.ceil(yScale(value))
+};
+ChartInternal.prototype.xv = function(d) {
+  var $$ = this,
+    value = d.value;
+  if ($$.isTimeSeries()) {
+    value = $$.parseDate(d.value);
+  } else if ($$.isCategorized() && typeof d.value === 'string') {
+    value = $$.config.axis_x_categories.indexOf(d.value);
+  }
+  return Math.ceil($$.x(value))
+};
+ChartInternal.prototype.yv = function(d) {
+  var $$ = this,
+    yScale = d.axis && d.axis === 'y2' ? $$.y2 : $$.y;
+  return Math.ceil(yScale(d.value))
+};
+ChartInternal.prototype.subxx = function(d) {
+  return d ? this.subX(d.x) : null
+};
+
+ChartInternal.prototype.transformMain = function(withTransition, transitions) {
+  var $$ = this,
+    xAxis,
+    yAxis,
+    y2Axis;
+  if (transitions && transitions.axisX) {
+    xAxis = transitions.axisX;
+  } else {
+    xAxis = $$.main.select('.' + CLASS.axisX);
+    if (withTransition) {
+      xAxis = xAxis.transition();
+    }
+  }
+  if (transitions && transitions.axisY) {
+    yAxis = transitions.axisY;
+  } else {
+    yAxis = $$.main.select('.' + CLASS.axisY);
+    if (withTransition) {
+      yAxis = yAxis.transition();
+    }
+  }
+  if (transitions && transitions.axisY2) {
+    y2Axis = transitions.axisY2;
+  } else {
+    y2Axis = $$.main.select('.' + CLASS.axisY2);
+    if (withTransition) {
+      y2Axis = y2Axis.transition();
+    }
+  }
+(withTransition ? $$.main.transition() : $$.main).attr(
+    'transform',
+    $$.getTranslate('main')
+  );
+  xAxis.attr('transform', $$.getTranslate('x'));
+  yAxis.attr('transform', $$.getTranslate('y'));
+  y2Axis.attr('transform', $$.getTranslate('y2'));
+  $$.main
+    .select('.' + CLASS.chartArcs)
+    .attr('transform', $$.getTranslate('arc'));
+};
+ChartInternal.prototype.transformAll = function(withTransition, transitions) {
+  var $$ = this;
+  $$.transformMain(withTransition, transitions);
+  if ($$.config.subchart_show) {
+    $$.transformContext(withTransition, transitions);
+  }
+  if ($$.legend) {
+    $$.transformLegend(withTransition);
+  }
+};
+
+ChartInternal.prototype.updateSvgSize = function() {
+  var $$ = this,
+    brush = $$.svg.select(`.${CLASS.brush} .overlay`);
+  $$.svg.attr('width', $$.currentWidth).attr('height', $$.currentHeight);
+  $$.svg
+    .selectAll(['#' + $$.clipId, '#' + $$.clipIdForGrid])
+    .select('rect')
+    .attr('width', $$.width)
+    .attr('height', $$.height);
+  $$.svg
+    .select('#' + $$.clipIdForXAxis)
+    .select('rect')
+    .attr('x', $$.getXAxisClipX.bind($$))
+    .attr('y', $$.getXAxisClipY.bind($$))
+    .attr('width', $$.getXAxisClipWidth.bind($$))
+    .attr('height', $$.getXAxisClipHeight.bind($$));
+  $$.svg
+    .select('#' + $$.clipIdForYAxis)
+    .select('rect')
+    .attr('x', $$.getYAxisClipX.bind($$))
+    .attr('y', $$.getYAxisClipY.bind($$))
+    .attr('width', $$.getYAxisClipWidth.bind($$))
+    .attr('height', $$.getYAxisClipHeight.bind($$));
+  $$.svg
+    .select('#' + $$.clipIdForSubchart)
+    .select('rect')
+    .attr('width', $$.width)
+    .attr('height', (brush.size() && brush.attr('height')) || 0);
+  // MEMO: parent div's height will be bigger than svg when <!DOCTYPE html>
+  $$.selectChart.style('max-height', $$.currentHeight + 'px');
+};
+
+ChartInternal.prototype.updateDimension = function(withoutAxis) {
+  var $$ = this;
+  if (!withoutAxis) {
+    if ($$.config.axis_rotated) {
+      $$.axes.x.call($$.xAxis);
+      $$.axes.subx.call($$.subXAxis);
+    } else {
+      $$.axes.y.call($$.yAxis);
+      $$.axes.y2.call($$.y2Axis);
+    }
+  }
+  $$.updateSizes();
+  $$.updateScales();
+  $$.updateSvgSize();
+  $$.transformAll(false);
+};
+
+ChartInternal.prototype.observeInserted = function(selection) {
+  var $$ = this,
+    observer;
+  if (typeof MutationObserver === 'undefined') {
+    window.console.error('MutationObserver not defined.');
+    return
+  }
+  observer = new MutationObserver(function(mutations) {
+    mutations.forEach(function(mutation) {
+      if (mutation.type === 'childList' && mutation.previousSibling) {
+        observer.disconnect();
+        // need to wait for completion of load because size calculation requires the actual sizes determined after that completion
+        $$.intervalForObserveInserted = window.setInterval(function() {
+          // parentNode will NOT be null when completed
+          if (selection.node().parentNode) {
+            window.clearInterval($$.intervalForObserveInserted);
+            $$.updateDimension();
+            if ($$.brush) {
+              $$.brush.update();
+            }
+            $$.config.oninit.call($$);
+            $$.redraw({
+              withTransform: true,
+              withUpdateXDomain: true,
+              withUpdateOrgXDomain: true,
+              withTransition: false,
+              withTransitionForTransform: false,
+              withLegend: true
+            });
+            selection.transition().style('opacity', 1);
+          }
+        }, 10);
+      }
+    });
+  });
+  observer.observe(selection.node(), {
+    attributes: true,
+    childList: true,
+    characterData: true
+  });
+};
+
+/**
+ * Binds handlers to the window resize event.
+ */
+ChartInternal.prototype.bindResize = function() {
+  var $$ = this,
+    config = $$.config;
+
+  $$.resizeFunction = $$.generateResize(); // need to call .remove
+
+  $$.resizeFunction.add(function() {
+    config.onresize.call($$);
+  });
+  if (config.resize_auto) {
+    $$.resizeFunction.add(function() {
+      if ($$.resizeTimeout !== undefined) {
+        window.clearTimeout($$.resizeTimeout);
+      }
+      $$.resizeTimeout = window.setTimeout(function() {
+        delete $$.resizeTimeout;
+        $$.updateAndRedraw({
+          withUpdateXDomain: false,
+          withUpdateOrgXDomain: false,
+          withTransition: false,
+          withTransitionForTransform: false,
+          withLegend: true
+        });
+        if ($$.brush) {
+          $$.brush.update();
+        }
+      }, 100);
+    });
+  }
+  $$.resizeFunction.add(function() {
+    config.onresized.call($$);
+  });
+
+  $$.resizeIfElementDisplayed = function() {
+    // if element not displayed skip it
+    if ($$.api == null || !$$.api.element.offsetParent) {
+      return
+    }
+
+    $$.resizeFunction();
+  };
+
+  if (window.attachEvent) {
+    window.attachEvent('onresize', $$.resizeIfElementDisplayed);
+  } else if (window.addEventListener) {
+    window.addEventListener('resize', $$.resizeIfElementDisplayed, false);
+  } else {
+    // fallback to this, if this is a very old browser
+    var wrapper = window.onresize;
+    if (!wrapper) {
+      // create a wrapper that will call all charts
+      wrapper = $$.generateResize();
+    } else if (!wrapper.add || !wrapper.remove) {
+      // there is already a handler registered, make sure we call it too
+      wrapper = $$.generateResize();
+      wrapper.add(window.onresize);
+    }
+    // add this graph to the wrapper, we will be removed if the user calls destroy
+    wrapper.add($$.resizeFunction);
+    window.onresize = function() {
+      // if element not displayed skip it
+      if (!$$.api.element.offsetParent) {
+        return
+      }
+
+      wrapper();
+    };
+  }
+};
+
+/**
+ * Binds handlers to the window focus event.
+ */
+ChartInternal.prototype.bindWindowFocus = function() {
+  if (this.windowFocusHandler) {
+    // The handler is already set
+    return
+  }
+
+  this.windowFocusHandler = () => {
+    this.redraw();
+  };
+
+  window.addEventListener('focus', this.windowFocusHandler);
+};
+
+/**
+ * Unbinds from the window focus event.
+ */
+ChartInternal.prototype.unbindWindowFocus = function() {
+  window.removeEventListener('focus', this.windowFocusHandler);
+  delete this.windowFocusHandler;
+};
+
+ChartInternal.prototype.generateResize = function() {
+  var resizeFunctions = [];
+
+  function callResizeFunctions() {
+    resizeFunctions.forEach(function(f) {
+      f();
+    });
+  }
+  callResizeFunctions.add = function(f) {
+    resizeFunctions.push(f);
+  };
+  callResizeFunctions.remove = function(f) {
+    for (var i = 0; i < resizeFunctions.length; i++) {
+      if (resizeFunctions[i] === f) {
+        resizeFunctions.splice(i, 1);
+        break
+      }
+    }
+  };
+  return callResizeFunctions
+};
+
+ChartInternal.prototype.endall = function(transition, callback) {
+  var n = 0;
+  transition
+    .each(function() {
+      ++n;
+    })
+    .on('end', function() {
+      if (!--n) {
+        callback.apply(this, arguments);
+      }
+    });
+};
+ChartInternal.prototype.generateWait = function() {
+  var $$ = this;
+  var transitionsToWait = [],
+    f = function(callback) {
+      var timer = setInterval(function() {
+        if (!$$.isTabVisible()) {
+          return
+        }
+
+        var done = 0;
+        transitionsToWait.forEach(function(t) {
+          if (t.empty()) {
+            done += 1;
+            return
+          }
+          try {
+            t.transition();
+          } catch (e) {
+            done += 1;
+          }
+        });
+        if (done === transitionsToWait.length) {
+          clearInterval(timer);
+          if (callback) {
+            callback();
+          }
+        }
+      }, 50);
+    };
+  f.add = function(transition) {
+    transitionsToWait.push(transition);
+  };
+  return f
+};
+
+ChartInternal.prototype.parseDate = function(date) {
+  var $$ = this,
+    parsedDate;
+  if (date instanceof Date) {
+    parsedDate = date;
+  } else if (typeof date === 'string') {
+    parsedDate = $$.dataTimeParse(date);
+  } else if (typeof date === 'object') {
+    parsedDate = new Date(+date);
+  } else if (typeof date === 'number' && !isNaN(date)) {
+    parsedDate = new Date(+date);
+  }
+  if (!parsedDate || isNaN(+parsedDate)) {
+    window.console.error("Failed to parse x '" + date + "' to Date object");
+  }
+  return parsedDate
+};
+
+ChartInternal.prototype.isTabVisible = function() {
+  return !document.hidden
+};
+
+ChartInternal.prototype.getPathBox = getPathBox;
+ChartInternal.prototype.CLASS = CLASS;
+
+/* jshint ignore:start */
+(function() {
+  if (!('SVGPathSeg' in window)) {
+    // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg
+    window.SVGPathSeg = function(type, typeAsLetter, owningPathSegList) {
+      this.pathSegType = type;
+      this.pathSegTypeAsLetter = typeAsLetter;
+      this._owningPathSegList = owningPathSegList;
+    };
+
+    window.SVGPathSeg.prototype.classname = 'SVGPathSeg';
+
+    window.SVGPathSeg.PATHSEG_UNKNOWN = 0;
+    window.SVGPathSeg.PATHSEG_CLOSEPATH = 1;
+    window.SVGPathSeg.PATHSEG_MOVETO_ABS = 2;
+    window.SVGPathSeg.PATHSEG_MOVETO_REL = 3;
+    window.SVGPathSeg.PATHSEG_LINETO_ABS = 4;
+    window.SVGPathSeg.PATHSEG_LINETO_REL = 5;
+    window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;
+    window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;
+    window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;
+    window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;
+    window.SVGPathSeg.PATHSEG_ARC_ABS = 10;
+    window.SVGPathSeg.PATHSEG_ARC_REL = 11;
+    window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;
+    window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;
+    window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;
+    window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;
+    window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
+    window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
+    window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
+    window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
+
+    // Notify owning PathSegList on any changes so they can be synchronized back to the path element.
+    window.SVGPathSeg.prototype._segmentChanged = function() {
+      if (this._owningPathSegList) this._owningPathSegList.segmentChanged(this);
+    };
+
+    window.SVGPathSegClosePath = function(owningPathSegList) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_CLOSEPATH,
+        'z',
+        owningPathSegList
+      );
+    };
+    window.SVGPathSegClosePath.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegClosePath.prototype.toString = function() {
+      return '[object SVGPathSegClosePath]'
+    };
+    window.SVGPathSegClosePath.prototype._asPathString = function() {
+      return this.pathSegTypeAsLetter
+    };
+    window.SVGPathSegClosePath.prototype.clone = function() {
+      return new window.SVGPathSegClosePath(undefined)
+    };
+
+    window.SVGPathSegMovetoAbs = function(owningPathSegList, x, y) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_MOVETO_ABS,
+        'M',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+    };
+    window.SVGPathSegMovetoAbs.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegMovetoAbs.prototype.toString = function() {
+      return '[object SVGPathSegMovetoAbs]'
+    };
+    window.SVGPathSegMovetoAbs.prototype._asPathString = function() {
+      return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y
+    };
+    window.SVGPathSegMovetoAbs.prototype.clone = function() {
+      return new window.SVGPathSegMovetoAbs(undefined, this._x, this._y)
+    };
+    Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, 'x', {
+      get: function() {
+        return this._x
+      },
+      set: function(x) {
+        this._x = x;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, 'y', {
+      get: function() {
+        return this._y
+      },
+      set: function(y) {
+        this._y = y;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+
+    window.SVGPathSegMovetoRel = function(owningPathSegList, x, y) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_MOVETO_REL,
+        'm',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+    };
+    window.SVGPathSegMovetoRel.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegMovetoRel.prototype.toString = function() {
+      return '[object SVGPathSegMovetoRel]'
+    };
+    window.SVGPathSegMovetoRel.prototype._asPathString = function() {
+      return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y
+    };
+    window.SVGPathSegMovetoRel.prototype.clone = function() {
+      return new window.SVGPathSegMovetoRel(undefined, this._x, this._y)
+    };
+    Object.defineProperty(window.SVGPathSegMovetoRel.prototype, 'x', {
+      get: function() {
+        return this._x
+      },
+      set: function(x) {
+        this._x = x;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegMovetoRel.prototype, 'y', {
+      get: function() {
+        return this._y
+      },
+      set: function(y) {
+        this._y = y;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+
+    window.SVGPathSegLinetoAbs = function(owningPathSegList, x, y) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_LINETO_ABS,
+        'L',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+    };
+    window.SVGPathSegLinetoAbs.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegLinetoAbs.prototype.toString = function() {
+      return '[object SVGPathSegLinetoAbs]'
+    };
+    window.SVGPathSegLinetoAbs.prototype._asPathString = function() {
+      return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y
+    };
+    window.SVGPathSegLinetoAbs.prototype.clone = function() {
+      return new window.SVGPathSegLinetoAbs(undefined, this._x, this._y)
+    };
+    Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, 'x', {
+      get: function() {
+        return this._x
+      },
+      set: function(x) {
+        this._x = x;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, 'y', {
+      get: function() {
+        return this._y
+      },
+      set: function(y) {
+        this._y = y;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+
+    window.SVGPathSegLinetoRel = function(owningPathSegList, x, y) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_LINETO_REL,
+        'l',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+    };
+    window.SVGPathSegLinetoRel.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegLinetoRel.prototype.toString = function() {
+      return '[object SVGPathSegLinetoRel]'
+    };
+    window.SVGPathSegLinetoRel.prototype._asPathString = function() {
+      return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y
+    };
+    window.SVGPathSegLinetoRel.prototype.clone = function() {
+      return new window.SVGPathSegLinetoRel(undefined, this._x, this._y)
+    };
+    Object.defineProperty(window.SVGPathSegLinetoRel.prototype, 'x', {
+      get: function() {
+        return this._x
+      },
+      set: function(x) {
+        this._x = x;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegLinetoRel.prototype, 'y', {
+      get: function() {
+        return this._y
+      },
+      set: function(y) {
+        this._y = y;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+
+    window.SVGPathSegCurvetoCubicAbs = function(
+      owningPathSegList,
+      x,
+      y,
+      x1,
+      y1,
+      x2,
+      y2
+    ) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS,
+        'C',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+      this._x1 = x1;
+      this._y1 = y1;
+      this._x2 = x2;
+      this._y2 = y2;
+    };
+    window.SVGPathSegCurvetoCubicAbs.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegCurvetoCubicAbs.prototype.toString = function() {
+      return '[object SVGPathSegCurvetoCubicAbs]'
+    };
+    window.SVGPathSegCurvetoCubicAbs.prototype._asPathString = function() {
+      return (
+        this.pathSegTypeAsLetter +
+        ' ' +
+        this._x1 +
+        ' ' +
+        this._y1 +
+        ' ' +
+        this._x2 +
+        ' ' +
+        this._y2 +
+        ' ' +
+        this._x +
+        ' ' +
+        this._y
+      )
+    };
+    window.SVGPathSegCurvetoCubicAbs.prototype.clone = function() {
+      return new window.SVGPathSegCurvetoCubicAbs(
+        undefined,
+        this._x,
+        this._y,
+        this._x1,
+        this._y1,
+        this._x2,
+        this._y2
+      )
+    };
+    Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'x', {
+      get: function() {
+        return this._x
+      },
+      set: function(x) {
+        this._x = x;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'y', {
+      get: function() {
+        return this._y
+      },
+      set: function(y) {
+        this._y = y;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'x1', {
+      get: function() {
+        return this._x1
+      },
+      set: function(x1) {
+        this._x1 = x1;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'y1', {
+      get: function() {
+        return this._y1
+      },
+      set: function(y1) {
+        this._y1 = y1;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'x2', {
+      get: function() {
+        return this._x2
+      },
+      set: function(x2) {
+        this._x2 = x2;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'y2', {
+      get: function() {
+        return this._y2
+      },
+      set: function(y2) {
+        this._y2 = y2;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+
+    window.SVGPathSegCurvetoCubicRel = function(
+      owningPathSegList,
+      x,
+      y,
+      x1,
+      y1,
+      x2,
+      y2
+    ) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL,
+        'c',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+      this._x1 = x1;
+      this._y1 = y1;
+      this._x2 = x2;
+      this._y2 = y2;
+    };
+    window.SVGPathSegCurvetoCubicRel.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegCurvetoCubicRel.prototype.toString = function() {
+      return '[object SVGPathSegCurvetoCubicRel]'
+    };
+    window.SVGPathSegCurvetoCubicRel.prototype._asPathString = function() {
+      return (
+        this.pathSegTypeAsLetter +
+        ' ' +
+        this._x1 +
+        ' ' +
+        this._y1 +
+        ' ' +
+        this._x2 +
+        ' ' +
+        this._y2 +
+        ' ' +
+        this._x +
+        ' ' +
+        this._y
+      )
+    };
+    window.SVGPathSegCurvetoCubicRel.prototype.clone = function() {
+      return new window.SVGPathSegCurvetoCubicRel(
+        undefined,
+        this._x,
+        this._y,
+        this._x1,
+        this._y1,
+        this._x2,
+        this._y2
+      )
+    };
+    Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'x', {
+      get: function() {
+        return this._x
+      },
+      set: function(x) {
+        this._x = x;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'y', {
+      get: function() {
+        return this._y
+      },
+      set: function(y) {
+        this._y = y;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'x1', {
+      get: function() {
+        return this._x1
+      },
+      set: function(x1) {
+        this._x1 = x1;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'y1', {
+      get: function() {
+        return this._y1
+      },
+      set: function(y1) {
+        this._y1 = y1;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'x2', {
+      get: function() {
+        return this._x2
+      },
+      set: function(x2) {
+        this._x2 = x2;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'y2', {
+      get: function() {
+        return this._y2
+      },
+      set: function(y2) {
+        this._y2 = y2;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+
+    window.SVGPathSegCurvetoQuadraticAbs = function(
+      owningPathSegList,
+      x,
+      y,
+      x1,
+      y1
+    ) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS,
+        'Q',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+      this._x1 = x1;
+      this._y1 = y1;
+    };
+    window.SVGPathSegCurvetoQuadraticAbs.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegCurvetoQuadraticAbs.prototype.toString = function() {
+      return '[object SVGPathSegCurvetoQuadraticAbs]'
+    };
+    window.SVGPathSegCurvetoQuadraticAbs.prototype._asPathString = function() {
+      return (
+        this.pathSegTypeAsLetter +
+        ' ' +
+        this._x1 +
+        ' ' +
+        this._y1 +
+        ' ' +
+        this._x +
+        ' ' +
+        this._y
+      )
+    };
+    window.SVGPathSegCurvetoQuadraticAbs.prototype.clone = function() {
+      return new window.SVGPathSegCurvetoQuadraticAbs(
+        undefined,
+        this._x,
+        this._y,
+        this._x1,
+        this._y1
+      )
+    };
+    Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'x', {
+      get: function() {
+        return this._x
+      },
+      set: function(x) {
+        this._x = x;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'y', {
+      get: function() {
+        return this._y
+      },
+      set: function(y) {
+        this._y = y;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(
+      window.SVGPathSegCurvetoQuadraticAbs.prototype,
+      'x1',
+      {
+        get: function() {
+          return this._x1
+        },
+        set: function(x1) {
+          this._x1 = x1;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+    Object.defineProperty(
+      window.SVGPathSegCurvetoQuadraticAbs.prototype,
+      'y1',
+      {
+        get: function() {
+          return this._y1
+        },
+        set: function(y1) {
+          this._y1 = y1;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+
+    window.SVGPathSegCurvetoQuadraticRel = function(
+      owningPathSegList,
+      x,
+      y,
+      x1,
+      y1
+    ) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL,
+        'q',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+      this._x1 = x1;
+      this._y1 = y1;
+    };
+    window.SVGPathSegCurvetoQuadraticRel.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegCurvetoQuadraticRel.prototype.toString = function() {
+      return '[object SVGPathSegCurvetoQuadraticRel]'
+    };
+    window.SVGPathSegCurvetoQuadraticRel.prototype._asPathString = function() {
+      return (
+        this.pathSegTypeAsLetter +
+        ' ' +
+        this._x1 +
+        ' ' +
+        this._y1 +
+        ' ' +
+        this._x +
+        ' ' +
+        this._y
+      )
+    };
+    window.SVGPathSegCurvetoQuadraticRel.prototype.clone = function() {
+      return new window.SVGPathSegCurvetoQuadraticRel(
+        undefined,
+        this._x,
+        this._y,
+        this._x1,
+        this._y1
+      )
+    };
+    Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'x', {
+      get: function() {
+        return this._x
+      },
+      set: function(x) {
+        this._x = x;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'y', {
+      get: function() {
+        return this._y
+      },
+      set: function(y) {
+        this._y = y;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(
+      window.SVGPathSegCurvetoQuadraticRel.prototype,
+      'x1',
+      {
+        get: function() {
+          return this._x1
+        },
+        set: function(x1) {
+          this._x1 = x1;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+    Object.defineProperty(
+      window.SVGPathSegCurvetoQuadraticRel.prototype,
+      'y1',
+      {
+        get: function() {
+          return this._y1
+        },
+        set: function(y1) {
+          this._y1 = y1;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+
+    window.SVGPathSegArcAbs = function(
+      owningPathSegList,
+      x,
+      y,
+      r1,
+      r2,
+      angle,
+      largeArcFlag,
+      sweepFlag
+    ) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_ARC_ABS,
+        'A',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+      this._r1 = r1;
+      this._r2 = r2;
+      this._angle = angle;
+      this._largeArcFlag = largeArcFlag;
+      this._sweepFlag = sweepFlag;
+    };
+    window.SVGPathSegArcAbs.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegArcAbs.prototype.toString = function() {
+      return '[object SVGPathSegArcAbs]'
+    };
+    window.SVGPathSegArcAbs.prototype._asPathString = function() {
+      return (
+        this.pathSegTypeAsLetter +
+        ' ' +
+        this._r1 +
+        ' ' +
+        this._r2 +
+        ' ' +
+        this._angle +
+        ' ' +
+        (this._largeArcFlag ? '1' : '0') +
+        ' ' +
+        (this._sweepFlag ? '1' : '0') +
+        ' ' +
+        this._x +
+        ' ' +
+        this._y
+      )
+    };
+    window.SVGPathSegArcAbs.prototype.clone = function() {
+      return new window.SVGPathSegArcAbs(
+        undefined,
+        this._x,
+        this._y,
+        this._r1,
+        this._r2,
+        this._angle,
+        this._largeArcFlag,
+        this._sweepFlag
+      )
+    };
+    Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'x', {
+      get: function() {
+        return this._x
+      },
+      set: function(x) {
+        this._x = x;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'y', {
+      get: function() {
+        return this._y
+      },
+      set: function(y) {
+        this._y = y;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'r1', {
+      get: function() {
+        return this._r1
+      },
+      set: function(r1) {
+        this._r1 = r1;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'r2', {
+      get: function() {
+        return this._r2
+      },
+      set: function(r2) {
+        this._r2 = r2;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'angle', {
+      get: function() {
+        return this._angle
+      },
+      set: function(angle) {
+        this._angle = angle;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'largeArcFlag', {
+      get: function() {
+        return this._largeArcFlag
+      },
+      set: function(largeArcFlag) {
+        this._largeArcFlag = largeArcFlag;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'sweepFlag', {
+      get: function() {
+        return this._sweepFlag
+      },
+      set: function(sweepFlag) {
+        this._sweepFlag = sweepFlag;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+
+    window.SVGPathSegArcRel = function(
+      owningPathSegList,
+      x,
+      y,
+      r1,
+      r2,
+      angle,
+      largeArcFlag,
+      sweepFlag
+    ) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_ARC_REL,
+        'a',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+      this._r1 = r1;
+      this._r2 = r2;
+      this._angle = angle;
+      this._largeArcFlag = largeArcFlag;
+      this._sweepFlag = sweepFlag;
+    };
+    window.SVGPathSegArcRel.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegArcRel.prototype.toString = function() {
+      return '[object SVGPathSegArcRel]'
+    };
+    window.SVGPathSegArcRel.prototype._asPathString = function() {
+      return (
+        this.pathSegTypeAsLetter +
+        ' ' +
+        this._r1 +
+        ' ' +
+        this._r2 +
+        ' ' +
+        this._angle +
+        ' ' +
+        (this._largeArcFlag ? '1' : '0') +
+        ' ' +
+        (this._sweepFlag ? '1' : '0') +
+        ' ' +
+        this._x +
+        ' ' +
+        this._y
+      )
+    };
+    window.SVGPathSegArcRel.prototype.clone = function() {
+      return new window.SVGPathSegArcRel(
+        undefined,
+        this._x,
+        this._y,
+        this._r1,
+        this._r2,
+        this._angle,
+        this._largeArcFlag,
+        this._sweepFlag
+      )
+    };
+    Object.defineProperty(window.SVGPathSegArcRel.prototype, 'x', {
+      get: function() {
+        return this._x
+      },
+      set: function(x) {
+        this._x = x;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegArcRel.prototype, 'y', {
+      get: function() {
+        return this._y
+      },
+      set: function(y) {
+        this._y = y;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegArcRel.prototype, 'r1', {
+      get: function() {
+        return this._r1
+      },
+      set: function(r1) {
+        this._r1 = r1;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegArcRel.prototype, 'r2', {
+      get: function() {
+        return this._r2
+      },
+      set: function(r2) {
+        this._r2 = r2;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegArcRel.prototype, 'angle', {
+      get: function() {
+        return this._angle
+      },
+      set: function(angle) {
+        this._angle = angle;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegArcRel.prototype, 'largeArcFlag', {
+      get: function() {
+        return this._largeArcFlag
+      },
+      set: function(largeArcFlag) {
+        this._largeArcFlag = largeArcFlag;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+    Object.defineProperty(window.SVGPathSegArcRel.prototype, 'sweepFlag', {
+      get: function() {
+        return this._sweepFlag
+      },
+      set: function(sweepFlag) {
+        this._sweepFlag = sweepFlag;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+
+    window.SVGPathSegLinetoHorizontalAbs = function(owningPathSegList, x) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS,
+        'H',
+        owningPathSegList
+      );
+      this._x = x;
+    };
+    window.SVGPathSegLinetoHorizontalAbs.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegLinetoHorizontalAbs.prototype.toString = function() {
+      return '[object SVGPathSegLinetoHorizontalAbs]'
+    };
+    window.SVGPathSegLinetoHorizontalAbs.prototype._asPathString = function() {
+      return this.pathSegTypeAsLetter + ' ' + this._x
+    };
+    window.SVGPathSegLinetoHorizontalAbs.prototype.clone = function() {
+      return new window.SVGPathSegLinetoHorizontalAbs(undefined, this._x)
+    };
+    Object.defineProperty(window.SVGPathSegLinetoHorizontalAbs.prototype, 'x', {
+      get: function() {
+        return this._x
+      },
+      set: function(x) {
+        this._x = x;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+
+    window.SVGPathSegLinetoHorizontalRel = function(owningPathSegList, x) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL,
+        'h',
+        owningPathSegList
+      );
+      this._x = x;
+    };
+    window.SVGPathSegLinetoHorizontalRel.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegLinetoHorizontalRel.prototype.toString = function() {
+      return '[object SVGPathSegLinetoHorizontalRel]'
+    };
+    window.SVGPathSegLinetoHorizontalRel.prototype._asPathString = function() {
+      return this.pathSegTypeAsLetter + ' ' + this._x
+    };
+    window.SVGPathSegLinetoHorizontalRel.prototype.clone = function() {
+      return new window.SVGPathSegLinetoHorizontalRel(undefined, this._x)
+    };
+    Object.defineProperty(window.SVGPathSegLinetoHorizontalRel.prototype, 'x', {
+      get: function() {
+        return this._x
+      },
+      set: function(x) {
+        this._x = x;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+
+    window.SVGPathSegLinetoVerticalAbs = function(owningPathSegList, y) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS,
+        'V',
+        owningPathSegList
+      );
+      this._y = y;
+    };
+    window.SVGPathSegLinetoVerticalAbs.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegLinetoVerticalAbs.prototype.toString = function() {
+      return '[object SVGPathSegLinetoVerticalAbs]'
+    };
+    window.SVGPathSegLinetoVerticalAbs.prototype._asPathString = function() {
+      return this.pathSegTypeAsLetter + ' ' + this._y
+    };
+    window.SVGPathSegLinetoVerticalAbs.prototype.clone = function() {
+      return new window.SVGPathSegLinetoVerticalAbs(undefined, this._y)
+    };
+    Object.defineProperty(window.SVGPathSegLinetoVerticalAbs.prototype, 'y', {
+      get: function() {
+        return this._y
+      },
+      set: function(y) {
+        this._y = y;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+
+    window.SVGPathSegLinetoVerticalRel = function(owningPathSegList, y) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL,
+        'v',
+        owningPathSegList
+      );
+      this._y = y;
+    };
+    window.SVGPathSegLinetoVerticalRel.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegLinetoVerticalRel.prototype.toString = function() {
+      return '[object SVGPathSegLinetoVerticalRel]'
+    };
+    window.SVGPathSegLinetoVerticalRel.prototype._asPathString = function() {
+      return this.pathSegTypeAsLetter + ' ' + this._y
+    };
+    window.SVGPathSegLinetoVerticalRel.prototype.clone = function() {
+      return new window.SVGPathSegLinetoVerticalRel(undefined, this._y)
+    };
+    Object.defineProperty(window.SVGPathSegLinetoVerticalRel.prototype, 'y', {
+      get: function() {
+        return this._y
+      },
+      set: function(y) {
+        this._y = y;
+        this._segmentChanged();
+      },
+      enumerable: true
+    });
+
+    window.SVGPathSegCurvetoCubicSmoothAbs = function(
+      owningPathSegList,
+      x,
+      y,
+      x2,
+      y2
+    ) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS,
+        'S',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+      this._x2 = x2;
+      this._y2 = y2;
+    };
+    window.SVGPathSegCurvetoCubicSmoothAbs.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegCurvetoCubicSmoothAbs.prototype.toString = function() {
+      return '[object SVGPathSegCurvetoCubicSmoothAbs]'
+    };
+    window.SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString = function() {
+      return (
+        this.pathSegTypeAsLetter +
+        ' ' +
+        this._x2 +
+        ' ' +
+        this._y2 +
+        ' ' +
+        this._x +
+        ' ' +
+        this._y
+      )
+    };
+    window.SVGPathSegCurvetoCubicSmoothAbs.prototype.clone = function() {
+      return new window.SVGPathSegCurvetoCubicSmoothAbs(
+        undefined,
+        this._x,
+        this._y,
+        this._x2,
+        this._y2
+      )
+    };
+    Object.defineProperty(
+      window.SVGPathSegCurvetoCubicSmoothAbs.prototype,
+      'x',
+      {
+        get: function() {
+          return this._x
+        },
+        set: function(x) {
+          this._x = x;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+    Object.defineProperty(
+      window.SVGPathSegCurvetoCubicSmoothAbs.prototype,
+      'y',
+      {
+        get: function() {
+          return this._y
+        },
+        set: function(y) {
+          this._y = y;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+    Object.defineProperty(
+      window.SVGPathSegCurvetoCubicSmoothAbs.prototype,
+      'x2',
+      {
+        get: function() {
+          return this._x2
+        },
+        set: function(x2) {
+          this._x2 = x2;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+    Object.defineProperty(
+      window.SVGPathSegCurvetoCubicSmoothAbs.prototype,
+      'y2',
+      {
+        get: function() {
+          return this._y2
+        },
+        set: function(y2) {
+          this._y2 = y2;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+
+    window.SVGPathSegCurvetoCubicSmoothRel = function(
+      owningPathSegList,
+      x,
+      y,
+      x2,
+      y2
+    ) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL,
+        's',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+      this._x2 = x2;
+      this._y2 = y2;
+    };
+    window.SVGPathSegCurvetoCubicSmoothRel.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegCurvetoCubicSmoothRel.prototype.toString = function() {
+      return '[object SVGPathSegCurvetoCubicSmoothRel]'
+    };
+    window.SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString = function() {
+      return (
+        this.pathSegTypeAsLetter +
+        ' ' +
+        this._x2 +
+        ' ' +
+        this._y2 +
+        ' ' +
+        this._x +
+        ' ' +
+        this._y
+      )
+    };
+    window.SVGPathSegCurvetoCubicSmoothRel.prototype.clone = function() {
+      return new window.SVGPathSegCurvetoCubicSmoothRel(
+        undefined,
+        this._x,
+        this._y,
+        this._x2,
+        this._y2
+      )
+    };
+    Object.defineProperty(
+      window.SVGPathSegCurvetoCubicSmoothRel.prototype,
+      'x',
+      {
+        get: function() {
+          return this._x
+        },
+        set: function(x) {
+          this._x = x;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+    Object.defineProperty(
+      window.SVGPathSegCurvetoCubicSmoothRel.prototype,
+      'y',
+      {
+        get: function() {
+          return this._y
+        },
+        set: function(y) {
+          this._y = y;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+    Object.defineProperty(
+      window.SVGPathSegCurvetoCubicSmoothRel.prototype,
+      'x2',
+      {
+        get: function() {
+          return this._x2
+        },
+        set: function(x2) {
+          this._x2 = x2;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+    Object.defineProperty(
+      window.SVGPathSegCurvetoCubicSmoothRel.prototype,
+      'y2',
+      {
+        get: function() {
+          return this._y2
+        },
+        set: function(y2) {
+          this._y2 = y2;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+
+    window.SVGPathSegCurvetoQuadraticSmoothAbs = function(
+      owningPathSegList,
+      x,
+      y
+    ) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS,
+        'T',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+    };
+    window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString = function() {
+      return '[object SVGPathSegCurvetoQuadraticSmoothAbs]'
+    };
+    window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString = function() {
+      return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y
+    };
+    window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone = function() {
+      return new window.SVGPathSegCurvetoQuadraticSmoothAbs(
+        undefined,
+        this._x,
+        this._y
+      )
+    };
+    Object.defineProperty(
+      window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype,
+      'x',
+      {
+        get: function() {
+          return this._x
+        },
+        set: function(x) {
+          this._x = x;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+    Object.defineProperty(
+      window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype,
+      'y',
+      {
+        get: function() {
+          return this._y
+        },
+        set: function(y) {
+          this._y = y;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+
+    window.SVGPathSegCurvetoQuadraticSmoothRel = function(
+      owningPathSegList,
+      x,
+      y
+    ) {
+      window.SVGPathSeg.call(
+        this,
+        window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL,
+        't',
+        owningPathSegList
+      );
+      this._x = x;
+      this._y = y;
+    };
+    window.SVGPathSegCurvetoQuadraticSmoothRel.prototype = Object.create(
+      window.SVGPathSeg.prototype
+    );
+    window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString = function() {
+      return '[object SVGPathSegCurvetoQuadraticSmoothRel]'
+    };
+    window.SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString = function() {
+      return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y
+    };
+    window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone = function() {
+      return new window.SVGPathSegCurvetoQuadraticSmoothRel(
+        undefined,
+        this._x,
+        this._y
+      )
+    };
+    Object.defineProperty(
+      window.SVGPathSegCurvetoQuadraticSmoothRel.prototype,
+      'x',
+      {
+        get: function() {
+          return this._x
+        },
+        set: function(x) {
+          this._x = x;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+    Object.defineProperty(
+      window.SVGPathSegCurvetoQuadraticSmoothRel.prototype,
+      'y',
+      {
+        get: function() {
+          return this._y
+        },
+        set: function(y) {
+          this._y = y;
+          this._segmentChanged();
+        },
+        enumerable: true
+      }
+    );
+
+    // Add createSVGPathSeg* functions to window.SVGPathElement.
+    // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-Interfacewindow.SVGPathElement.
+    window.SVGPathElement.prototype.createSVGPathSegClosePath = function() {
+      return new window.SVGPathSegClosePath(undefined)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegMovetoAbs = function(x, y) {
+      return new window.SVGPathSegMovetoAbs(undefined, x, y)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegMovetoRel = function(x, y) {
+      return new window.SVGPathSegMovetoRel(undefined, x, y)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegLinetoAbs = function(x, y) {
+      return new window.SVGPathSegLinetoAbs(undefined, x, y)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegLinetoRel = function(x, y) {
+      return new window.SVGPathSegLinetoRel(undefined, x, y)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function(
+      x,
+      y,
+      x1,
+      y1,
+      x2,
+      y2
+    ) {
+      return new window.SVGPathSegCurvetoCubicAbs(
+        undefined,
+        x,
+        y,
+        x1,
+        y1,
+        x2,
+        y2
+      )
+    };
+    window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function(
+      x,
+      y,
+      x1,
+      y1,
+      x2,
+      y2
+    ) {
+      return new window.SVGPathSegCurvetoCubicRel(
+        undefined,
+        x,
+        y,
+        x1,
+        y1,
+        x2,
+        y2
+      )
+    };
+    window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function(
+      x,
+      y,
+      x1,
+      y1
+    ) {
+      return new window.SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function(
+      x,
+      y,
+      x1,
+      y1
+    ) {
+      return new window.SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegArcAbs = function(
+      x,
+      y,
+      r1,
+      r2,
+      angle,
+      largeArcFlag,
+      sweepFlag
+    ) {
+      return new window.SVGPathSegArcAbs(
+        undefined,
+        x,
+        y,
+        r1,
+        r2,
+        angle,
+        largeArcFlag,
+        sweepFlag
+      )
+    };
+    window.SVGPathElement.prototype.createSVGPathSegArcRel = function(
+      x,
+      y,
+      r1,
+      r2,
+      angle,
+      largeArcFlag,
+      sweepFlag
+    ) {
+      return new window.SVGPathSegArcRel(
+        undefined,
+        x,
+        y,
+        r1,
+        r2,
+        angle,
+        largeArcFlag,
+        sweepFlag
+      )
+    };
+    window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function(
+      x
+    ) {
+      return new window.SVGPathSegLinetoHorizontalAbs(undefined, x)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function(
+      x
+    ) {
+      return new window.SVGPathSegLinetoHorizontalRel(undefined, x)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function(
+      y
+    ) {
+      return new window.SVGPathSegLinetoVerticalAbs(undefined, y)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function(
+      y
+    ) {
+      return new window.SVGPathSegLinetoVerticalRel(undefined, y)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function(
+      x,
+      y,
+      x2,
+      y2
+    ) {
+      return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function(
+      x,
+      y,
+      x2,
+      y2
+    ) {
+      return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function(
+      x,
+      y
+    ) {
+      return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y)
+    };
+    window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function(
+      x,
+      y
+    ) {
+      return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y)
+    };
+
+    if (!('getPathSegAtLength' in window.SVGPathElement.prototype)) {
+      // Add getPathSegAtLength to SVGPathElement.
+      // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-__svg__SVGPathElement__getPathSegAtLength
+      // This polyfill requires SVGPathElement.getTotalLength to implement the distance-along-a-path algorithm.
+      window.SVGPathElement.prototype.getPathSegAtLength = function(distance) {
+        if (distance === undefined || !isFinite(distance))
+          throw 'Invalid arguments.'
+
+        var measurementElement = document.createElementNS(
+          'http://www.w3.org/2000/svg',
+          'path'
+        );
+        measurementElement.setAttribute('d', this.getAttribute('d'));
+        var lastPathSegment = measurementElement.pathSegList.numberOfItems - 1;
+
+        // If the path is empty, return 0.
+        if (lastPathSegment <= 0) return 0
+
+        do {
+          measurementElement.pathSegList.removeItem(lastPathSegment);
+          if (distance > measurementElement.getTotalLength()) break
+          lastPathSegment--;
+        } while (lastPathSegment > 0)
+        return lastPathSegment
+      };
+    }
+  }
+
+  if (!('SVGPathSegList' in window)) {
+    // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList
+    window.SVGPathSegList = function(pathElement) {
+      this._pathElement = pathElement;
+      this._list = this._parsePath(this._pathElement.getAttribute('d'));
+
+      // Use a MutationObserver to catch changes to the path's "d" attribute.
+      this._mutationObserverConfig = {
+        attributes: true,
+        attributeFilter: ['d']
+      };
+      this._pathElementMutationObserver = new MutationObserver(
+        this._updateListFromPathMutations.bind(this)
+      );
+      this._pathElementMutationObserver.observe(
+        this._pathElement,
+        this._mutationObserverConfig
+      );
+    };
+
+    window.SVGPathSegList.prototype.classname = 'SVGPathSegList';
+
+    Object.defineProperty(window.SVGPathSegList.prototype, 'numberOfItems', {
+      get: function() {
+        this._checkPathSynchronizedToList();
+        return this._list.length
+      },
+      enumerable: true
+    });
+
+    // Add the pathSegList accessors to window.SVGPathElement.
+    // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData
+    Object.defineProperty(window.SVGPathElement.prototype, 'pathSegList', {
+      get: function() {
+        if (!this._pathSegList)
+          this._pathSegList = new window.SVGPathSegList(this);
+        return this._pathSegList
+      },
+      enumerable: true
+    });
+    // FIXME: The following are not implemented and simply return window.SVGPathElement.pathSegList.
+    Object.defineProperty(
+      window.SVGPathElement.prototype,
+      'normalizedPathSegList',
+      {
+        get: function() {
+          return this.pathSegList
+        },
+        enumerable: true
+      }
+    );
+    Object.defineProperty(
+      window.SVGPathElement.prototype,
+      'animatedPathSegList',
+      {
+        get: function() {
+          return this.pathSegList
+        },
+        enumerable: true
+      }
+    );
+    Object.defineProperty(
+      window.SVGPathElement.prototype,
+      'animatedNormalizedPathSegList',
+      {
+        get: function() {
+          return this.pathSegList
+        },
+        enumerable: true
+      }
+    );
+
+    // Process any pending mutations to the path element and update the list as needed.
+    // This should be the first call of all public functions and is needed because
+    // MutationObservers are not synchronous so we can have pending asynchronous mutations.
+    window.SVGPathSegList.prototype._checkPathSynchronizedToList = function() {
+      this._updateListFromPathMutations(
+        this._pathElementMutationObserver.takeRecords()
+      );
+    };
+
+    window.SVGPathSegList.prototype._updateListFromPathMutations = function(
+      mutationRecords
+    ) {
+      if (!this._pathElement) return
+      var hasPathMutations = false;
+      mutationRecords.forEach(function(record) {
+        if (record.attributeName == 'd') hasPathMutations = true;
+      });
+      if (hasPathMutations)
+        this._list = this._parsePath(this._pathElement.getAttribute('d'));
+    };
+
+    // Serialize the list and update the path's 'd' attribute.
+    window.SVGPathSegList.prototype._writeListToPath = function() {
+      this._pathElementMutationObserver.disconnect();
+      this._pathElement.setAttribute(
+        'd',
+        window.SVGPathSegList._pathSegArrayAsString(this._list)
+      );
+      this._pathElementMutationObserver.observe(
+        this._pathElement,
+        this._mutationObserverConfig
+      );
+    };
+
+    // When a path segment changes the list needs to be synchronized back to the path element.
+    window.SVGPathSegList.prototype.segmentChanged = function(pathSeg) {
+      this._writeListToPath();
+    };
+
+    window.SVGPathSegList.prototype.clear = function() {
+      this._checkPathSynchronizedToList();
+
+      this._list.forEach(function(pathSeg) {
+        pathSeg._owningPathSegList = null;
+      });
+      this._list = [];
+      this._writeListToPath();
+    };
+
+    window.SVGPathSegList.prototype.initialize = function(newItem) {
+      this._checkPathSynchronizedToList();
+
+      this._list = [newItem];
+      newItem._owningPathSegList = this;
+      this._writeListToPath();
+      return newItem
+    };
+
+    window.SVGPathSegList.prototype._checkValidIndex = function(index) {
+      if (isNaN(index) || index < 0 || index >= this.numberOfItems)
+        throw 'INDEX_SIZE_ERR'
+    };
+
+    window.SVGPathSegList.prototype.getItem = function(index) {
+      this._checkPathSynchronizedToList();
+
+      this._checkValidIndex(index);
+      return this._list[index]
+    };
+
+    window.SVGPathSegList.prototype.insertItemBefore = function(
+      newItem,
+      index
+    ) {
+      this._checkPathSynchronizedToList();
+
+      // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
+      if (index > this.numberOfItems) index = this.numberOfItems;
+      if (newItem._owningPathSegList) {
+        // SVG2 spec says to make a copy.
+        newItem = newItem.clone();
+      }
+      this._list.splice(index, 0, newItem);
+      newItem._owningPathSegList = this;
+      this._writeListToPath();
+      return newItem
+    };
+
+    window.SVGPathSegList.prototype.replaceItem = function(newItem, index) {
+      this._checkPathSynchronizedToList();
+
+      if (newItem._owningPathSegList) {
+        // SVG2 spec says to make a copy.
+        newItem = newItem.clone();
+      }
+      this._checkValidIndex(index);
+      this._list[index] = newItem;
+      newItem._owningPathSegList = this;
+      this._writeListToPath();
+      return newItem
+    };
+
+    window.SVGPathSegList.prototype.removeItem = function(index) {
+      this._checkPathSynchronizedToList();
+
+      this._checkValidIndex(index);
+      var item = this._list[index];
+      this._list.splice(index, 1);
+      this._writeListToPath();
+      return item
+    };
+
+    window.SVGPathSegList.prototype.appendItem = function(newItem) {
+      this._checkPathSynchronizedToList();
+
+      if (newItem._owningPathSegList) {
+        // SVG2 spec says to make a copy.
+        newItem = newItem.clone();
+      }
+      this._list.push(newItem);
+      newItem._owningPathSegList = this;
+      // TODO: Optimize this to just append to the existing attribute.
+      this._writeListToPath();
+      return newItem
+    };
+
+    window.SVGPathSegList._pathSegArrayAsString = function(pathSegArray) {
+      var string = '';
+      var first = true;
+      pathSegArray.forEach(function(pathSeg) {
+        if (first) {
+          first = false;
+          string += pathSeg._asPathString();
+        } else {
+          string += ' ' + pathSeg._asPathString();
+        }
+      });
+      return string
+    };
+
+    // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp.
+    window.SVGPathSegList.prototype._parsePath = function(string) {
+      if (!string || string.length == 0) return []
+
+      var owningPathSegList = this;
+
+      var Builder = function() {
+        this.pathSegList = [];
+      };
+
+      Builder.prototype.appendSegment = function(pathSeg) {
+        this.pathSegList.push(pathSeg);
+      };
+
+      var Source = function(string) {
+        this._string = string;
+        this._currentIndex = 0;
+        this._endIndex = this._string.length;
+        this._previousCommand = window.SVGPathSeg.PATHSEG_UNKNOWN;
+
+        this._skipOptionalSpaces();
+      };
+
+      Source.prototype._isCurrentSpace = function() {
+        var character = this._string[this._currentIndex];
+        return (
+          character <= ' ' &&
+          (character == ' ' ||
+            character == '\n' ||
+            character == '\t' ||
+            character == '\r' ||
+            character == '\f')
+        )
+      };
+
+      Source.prototype._skipOptionalSpaces = function() {
+        while (this._currentIndex < this._endIndex && this._isCurrentSpace())
+          this._currentIndex++;
+        return this._currentIndex < this._endIndex
+      };
+
+      Source.prototype._skipOptionalSpacesOrDelimiter = function() {
+        if (
+          this._currentIndex < this._endIndex &&
+          !this._isCurrentSpace() &&
+          this._string.charAt(this._currentIndex) != ','
+        )
+          return false
+        if (this._skipOptionalSpaces()) {
+          if (
+            this._currentIndex < this._endIndex &&
+            this._string.charAt(this._currentIndex) == ','
+          ) {
+            this._currentIndex++;
+            this._skipOptionalSpaces();
+          }
+        }
+        return this._currentIndex < this._endIndex
+      };
+
+      Source.prototype.hasMoreData = function() {
+        return this._currentIndex < this._endIndex
+      };
+
+      Source.prototype.peekSegmentType = function() {
+        var lookahead = this._string[this._currentIndex];
+        return this._pathSegTypeFromChar(lookahead)
+      };
+
+      Source.prototype._pathSegTypeFromChar = function(lookahead) {
+        switch (lookahead) {
+          case 'Z':
+          case 'z':
+            return window.SVGPathSeg.PATHSEG_CLOSEPATH
+          case 'M':
+            return window.SVGPathSeg.PATHSEG_MOVETO_ABS
+          case 'm':
+            return window.SVGPathSeg.PATHSEG_MOVETO_REL
+          case 'L':
+            return window.SVGPathSeg.PATHSEG_LINETO_ABS
+          case 'l':
+            return window.SVGPathSeg.PATHSEG_LINETO_REL
+          case 'C':
+            return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS
+          case 'c':
+            return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL
+          case 'Q':
+            return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS
+          case 'q':
+            return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL
+          case 'A':
+            return window.SVGPathSeg.PATHSEG_ARC_ABS
+          case 'a':
+            return window.SVGPathSeg.PATHSEG_ARC_REL
+          case 'H':
+            return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS
+          case 'h':
+            return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL
+          case 'V':
+            return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS
+          case 'v':
+            return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL
+          case 'S':
+            return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS
+          case 's':
+            return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL
+          case 'T':
+            return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS
+          case 't':
+            return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL
+          default:
+            return window.SVGPathSeg.PATHSEG_UNKNOWN
+        }
+      };
+
+      Source.prototype._nextCommandHelper = function(
+        lookahead,
+        previousCommand
+      ) {
+        // Check for remaining coordinates in the current command.
+        if (
+          (lookahead == '+' ||
+            lookahead == '-' ||
+            lookahead == '.' ||
+            (lookahead >= '0' && lookahead <= '9')) &&
+          previousCommand != window.SVGPathSeg.PATHSEG_CLOSEPATH
+        ) {
+          if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_ABS)
+            return window.SVGPathSeg.PATHSEG_LINETO_ABS
+          if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_REL)
+            return window.SVGPathSeg.PATHSEG_LINETO_REL
+          return previousCommand
+        }
+        return window.SVGPathSeg.PATHSEG_UNKNOWN
+      };
+
+      Source.prototype.initialCommandIsMoveTo = function() {
+        // If the path is empty it is still valid, so return true.
+        if (!this.hasMoreData()) return true
+        var command = this.peekSegmentType();
+        // Path must start with moveTo.
+        return (
+          command == window.SVGPathSeg.PATHSEG_MOVETO_ABS ||
+          command == window.SVGPathSeg.PATHSEG_MOVETO_REL
+        )
+      };
+
+      // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp.
+      // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
+      Source.prototype._parseNumber = function() {
+        var exponent = 0;
+        var integer = 0;
+        var frac = 1;
+        var decimal = 0;
+        var sign = 1;
+        var expsign = 1;
+
+        var startIndex = this._currentIndex;
+
+        this._skipOptionalSpaces();
+
+        // Read the sign.
+        if (
+          this._currentIndex < this._endIndex &&
+          this._string.charAt(this._currentIndex) == '+'
+        )
+          this._currentIndex++;
+        else if (
+          this._currentIndex < this._endIndex &&
+          this._string.charAt(this._currentIndex) == '-'
+        ) {
+          this._currentIndex++;
+          sign = -1;
+        }
+
+        if (
+          this._currentIndex == this._endIndex ||
+          ((this._string.charAt(this._currentIndex) < '0' ||
+            this._string.charAt(this._currentIndex) > '9') &&
+            this._string.charAt(this._currentIndex) != '.')
+        )
+          // The first character of a number must be one of [0-9+-.].
+          return undefined
+
+        // Read the integer part, build right-to-left.
+        var startIntPartIndex = this._currentIndex;
+        while (
+          this._currentIndex < this._endIndex &&
+          this._string.charAt(this._currentIndex) >= '0' &&
+          this._string.charAt(this._currentIndex) <= '9'
+        )
+          this._currentIndex++; // Advance to first non-digit.
+
+        if (this._currentIndex != startIntPartIndex) {
+          var scanIntPartIndex = this._currentIndex - 1;
+          var multiplier = 1;
+          while (scanIntPartIndex >= startIntPartIndex) {
+            integer +=
+              multiplier * (this._string.charAt(scanIntPartIndex--) - '0');
+            multiplier *= 10;
+          }
+        }
+
+        // Read the decimals.
+        if (
+          this._currentIndex < this._endIndex &&
+          this._string.charAt(this._currentIndex) == '.'
+        ) {
+          this._currentIndex++;
+
+          // There must be a least one digit following the .
+          if (
+            this._currentIndex >= this._endIndex ||
+            this._string.charAt(this._currentIndex) < '0' ||
+            this._string.charAt(this._currentIndex) > '9'
+          )
+            return undefined
+          while (
+            this._currentIndex < this._endIndex &&
+            this._string.charAt(this._currentIndex) >= '0' &&
+            this._string.charAt(this._currentIndex) <= '9'
+          ) {
+            frac *= 10;
+            decimal += (this._string.charAt(this._currentIndex) - '0') / frac;
+            this._currentIndex += 1;
+          }
+        }
+
+        // Read the exponent part.
+        if (
+          this._currentIndex != startIndex &&
+          this._currentIndex + 1 < this._endIndex &&
+          (this._string.charAt(this._currentIndex) == 'e' ||
+            this._string.charAt(this._currentIndex) == 'E') &&
+          this._string.charAt(this._currentIndex + 1) != 'x' &&
+          this._string.charAt(this._currentIndex + 1) != 'm'
+        ) {
+          this._currentIndex++;
+
+          // Read the sign of the exponent.
+          if (this._string.charAt(this._currentIndex) == '+') {
+            this._currentIndex++;
+          } else if (this._string.charAt(this._currentIndex) == '-') {
+            this._currentIndex++;
+            expsign = -1;
+          }
+
+          // There must be an exponent.
+          if (
+            this._currentIndex >= this._endIndex ||
+            this._string.charAt(this._currentIndex) < '0' ||
+            this._string.charAt(this._currentIndex) > '9'
+          )
+            return undefined
+
+          while (
+            this._currentIndex < this._endIndex &&
+            this._string.charAt(this._currentIndex) >= '0' &&
+            this._string.charAt(this._currentIndex) <= '9'
+          ) {
+            exponent *= 10;
+            exponent += this._string.charAt(this._currentIndex) - '0';
+            this._currentIndex++;
+          }
+        }
+
+        var number = integer + decimal;
+        number *= sign;
+
+        if (exponent) number *= Math.pow(10, expsign * exponent);
+
+        if (startIndex == this._currentIndex) return undefined
+
+        this._skipOptionalSpacesOrDelimiter();
+
+        return number
+      };
+
+      Source.prototype._parseArcFlag = function() {
+        if (this._currentIndex >= this._endIndex) return undefined
+        var flag = false;
+        var flagChar = this._string.charAt(this._currentIndex++);
+        if (flagChar == '0') flag = false;
+        else if (flagChar == '1') flag = true;
+        else return undefined
+
+        this._skipOptionalSpacesOrDelimiter();
+        return flag
+      };
+
+      Source.prototype.parseSegment = function() {
+        var lookahead = this._string[this._currentIndex];
+        var command = this._pathSegTypeFromChar(lookahead);
+        if (command == window.SVGPathSeg.PATHSEG_UNKNOWN) {
+          // Possibly an implicit command. Not allowed if this is the first command.
+          if (this._previousCommand == window.SVGPathSeg.PATHSEG_UNKNOWN)
+            return null
+          command = this._nextCommandHelper(lookahead, this._previousCommand);
+          if (command == window.SVGPathSeg.PATHSEG_UNKNOWN) return null
+        } else {
+          this._currentIndex++;
+        }
+
+        this._previousCommand = command;
+
+        switch (command) {
+          case window.SVGPathSeg.PATHSEG_MOVETO_REL:
+            return new window.SVGPathSegMovetoRel(
+              owningPathSegList,
+              this._parseNumber(),
+              this._parseNumber()
+            )
+          case window.SVGPathSeg.PATHSEG_MOVETO_ABS:
+            return new window.SVGPathSegMovetoAbs(
+              owningPathSegList,
+              this._parseNumber(),
+              this._parseNumber()
+            )
+          case window.SVGPathSeg.PATHSEG_LINETO_REL:
+            return new window.SVGPathSegLinetoRel(
+              owningPathSegList,
+              this._parseNumber(),
+              this._parseNumber()
+            )
+          case window.SVGPathSeg.PATHSEG_LINETO_ABS:
+            return new window.SVGPathSegLinetoAbs(
+              owningPathSegList,
+              this._parseNumber(),
+              this._parseNumber()
+            )
+          case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
+            return new window.SVGPathSegLinetoHorizontalRel(
+              owningPathSegList,
+              this._parseNumber()
+            )
+          case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
+            return new window.SVGPathSegLinetoHorizontalAbs(
+              owningPathSegList,
+              this._parseNumber()
+            )
+          case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
+            return new window.SVGPathSegLinetoVerticalRel(
+              owningPathSegList,
+              this._parseNumber()
+            )
+          case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
+            return new window.SVGPathSegLinetoVerticalAbs(
+              owningPathSegList,
+              this._parseNumber()
+            )
+          case window.SVGPathSeg.PATHSEG_CLOSEPATH:
+            this._skipOptionalSpaces();
+            return new window.SVGPathSegClosePath(owningPathSegList)
+          case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
+            var points = {
+              x1: this._parseNumber(),
+              y1: this._parseNumber(),
+              x2: this._parseNumber(),
+              y2: this._parseNumber(),
+              x: this._parseNumber(),
+              y: this._parseNumber()
+            };
+            return new window.SVGPathSegCurvetoCubicRel(
+              owningPathSegList,
+              points.x,
+              points.y,
+              points.x1,
+              points.y1,
+              points.x2,
+              points.y2
+            )
+          case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
+            var points = {
+              x1: this._parseNumber(),
+              y1: this._parseNumber(),
+              x2: this._parseNumber(),
+              y2: this._parseNumber(),
+              x: this._parseNumber(),
+              y: this._parseNumber()
+            };
+            return new window.SVGPathSegCurvetoCubicAbs(
+              owningPathSegList,
+              points.x,
+              points.y,
+              points.x1,
+              points.y1,
+              points.x2,
+              points.y2
+            )
+          case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
+            var points = {
+              x2: this._parseNumber(),
+              y2: this._parseNumber(),
+              x: this._parseNumber(),
+              y: this._parseNumber()
+            };
+            return new window.SVGPathSegCurvetoCubicSmoothRel(
+              owningPathSegList,
+              points.x,
+              points.y,
+              points.x2,
+              points.y2
+            )
+          case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
+            var points = {
+              x2: this._parseNumber(),
+              y2: this._parseNumber(),
+              x: this._parseNumber(),
+              y: this._parseNumber()
+            };
+            return new window.SVGPathSegCurvetoCubicSmoothAbs(
+              owningPathSegList,
+              points.x,
+              points.y,
+              points.x2,
+              points.y2
+            )
+          case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
+            var points = {
+              x1: this._parseNumber(),
+              y1: this._parseNumber(),
+              x: this._parseNumber(),
+              y: this._parseNumber()
+            };
+            return new window.SVGPathSegCurvetoQuadraticRel(
+              owningPathSegList,
+              points.x,
+              points.y,
+              points.x1,
+              points.y1
+            )
+          case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
+            var points = {
+              x1: this._parseNumber(),
+              y1: this._parseNumber(),
+              x: this._parseNumber(),
+              y: this._parseNumber()
+            };
+            return new window.SVGPathSegCurvetoQuadraticAbs(
+              owningPathSegList,
+              points.x,
+              points.y,
+              points.x1,
+              points.y1
+            )
+          case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
+            return new window.SVGPathSegCurvetoQuadraticSmoothRel(
+              owningPathSegList,
+              this._parseNumber(),
+              this._parseNumber()
+            )
+          case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
+            return new window.SVGPathSegCurvetoQuadraticSmoothAbs(
+              owningPathSegList,
+              this._parseNumber(),
+              this._parseNumber()
+            )
+          case window.SVGPathSeg.PATHSEG_ARC_REL:
+            var points = {
+              x1: this._parseNumber(),
+              y1: this._parseNumber(),
+              arcAngle: this._parseNumber(),
+              arcLarge: this._parseArcFlag(),
+              arcSweep: this._parseArcFlag(),
+              x: this._parseNumber(),
+              y: this._parseNumber()
+            };
+            return new window.SVGPathSegArcRel(
+              owningPathSegList,
+              points.x,
+              points.y,
+              points.x1,
+              points.y1,
+              points.arcAngle,
+              points.arcLarge,
+              points.arcSweep
+            )
+          case window.SVGPathSeg.PATHSEG_ARC_ABS:
+            var points = {
+              x1: this._parseNumber(),
+              y1: this._parseNumber(),
+              arcAngle: this._parseNumber(),
+              arcLarge: this._parseArcFlag(),
+              arcSweep: this._parseArcFlag(),
+              x: this._parseNumber(),
+              y: this._parseNumber()
+            };
+            return new window.SVGPathSegArcAbs(
+              owningPathSegList,
+              points.x,
+              points.y,
+              points.x1,
+              points.y1,
+              points.arcAngle,
+              points.arcLarge,
+              points.arcSweep
+            )
+          default:
+            throw 'Unknown path seg type.'
+        }
+      };
+
+      var builder = new Builder();
+      var source = new Source(string);
+
+      if (!source.initialCommandIsMoveTo()) return []
+      while (source.hasMoreData()) {
+        var pathSeg = source.parseSegment();
+        if (!pathSeg) return []
+        builder.appendSegment(pathSeg);
+      }
+
+      return builder.pathSegList
+    };
+  }
+})();
+
+// String.padEnd polyfill for IE11
+//
+// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
+if (!String.prototype.padEnd) {
+  String.prototype.padEnd = function padEnd(targetLength, padString) {
+    targetLength = targetLength >> 0; //floor if number or convert non-number to 0;
+    padString = String(typeof padString !== 'undefined' ? padString : ' ');
+    if (this.length > targetLength) {
+      return String(this)
+    } else {
+      targetLength = targetLength - this.length;
+      if (targetLength > padString.length) {
+        padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
+      }
+      return String(this) + padString.slice(0, targetLength)
+    }
+  };
+}
+
+// Object.assign polyfill for IE11
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill
+if (typeof Object.assign !== 'function') {
+  // Must be writable: true, enumerable: false, configurable: true
+  Object.defineProperty(Object, 'assign', {
+    value: function assign(target, varArgs) {
+      if (target === null || target === undefined) {
+        throw new TypeError('Cannot convert undefined or null to object')
+      }
+
+      var to = Object(target);
+
+      for (var index = 1; index < arguments.length; index++) {
+        var nextSource = arguments[index];
+
+        if (nextSource !== null && nextSource !== undefined) {
+          for (var nextKey in nextSource) {
+            // Avoid bugs when hasOwnProperty is shadowed
+            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
+              to[nextKey] = nextSource[nextKey];
+            }
+          }
+        }
+      }
+      return to
+    },
+    writable: true,
+    configurable: true
+  });
+}
+
+/* jshint ignore:end */
+
+Chart.prototype.axis = function() {};
+Chart.prototype.axis.labels = function(labels) {
+  var $$ = this.internal;
+  if (arguments.length) {
+    Object.keys(labels).forEach(function(axisId) {
+      $$.axis.setLabelText(axisId, labels[axisId]);
+    });
+    $$.axis.updateLabels();
+  }
+  // TODO: return some values?
+};
+Chart.prototype.axis.max = function(max) {
+  var $$ = this.internal,
+    config = $$.config;
+  if (arguments.length) {
+    if (typeof max === 'object') {
+      if (isValue(max.x)) {
+        config.axis_x_max = max.x;
+      }
+      if (isValue(max.y)) {
+        config.axis_y_max = max.y;
+      }
+      if (isValue(max.y2)) {
+        config.axis_y2_max = max.y2;
+      }
+    } else {
+      config.axis_y_max = config.axis_y2_max = max;
+    }
+    $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true });
+  } else {
+    return {
+      x: config.axis_x_max,
+      y: config.axis_y_max,
+      y2: config.axis_y2_max
+    }
+  }
+};
+Chart.prototype.axis.min = function(min) {
+  var $$ = this.internal,
+    config = $$.config;
+  if (arguments.length) {
+    if (typeof min === 'object') {
+      if (isValue(min.x)) {
+        config.axis_x_min = min.x;
+      }
+      if (isValue(min.y)) {
+        config.axis_y_min = min.y;
+      }
+      if (isValue(min.y2)) {
+        config.axis_y2_min = min.y2;
+      }
+    } else {
+      config.axis_y_min = config.axis_y2_min = min;
+    }
+    $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true });
+  } else {
+    return {
+      x: config.axis_x_min,
+      y: config.axis_y_min,
+      y2: config.axis_y2_min
+    }
+  }
+};
+Chart.prototype.axis.range = function(range) {
+  if (arguments.length) {
+    if (isDefined(range.max)) {
+      this.axis.max(range.max);
+    }
+    if (isDefined(range.min)) {
+      this.axis.min(range.min);
+    }
+  } else {
+    return {
+      max: this.axis.max(),
+      min: this.axis.min()
+    }
+  }
+};
+
+Chart.prototype.axis.types = function(types) {
+  const $$ = this.internal;
+  if (types === undefined) {
+    return {
+      y: $$.config.axis_y_type,
+      y2: $$.config.axis_y2_type
+    }
+  } else {
+    if (isDefined(types.y)) {
+      $$.config.axis_y_type = types.y;
+    }
+
+    if (isDefined(types.y2)) {
+      $$.config.axis_y2_type = types.y2;
+    }
+
+    $$.updateScales();
+    $$.redraw();
+  }
+};
+
+Chart.prototype.category = function(i, category) {
+  var $$ = this.internal,
+    config = $$.config;
+  if (arguments.length > 1) {
+    config.axis_x_categories[i] = category;
+    $$.redraw();
+  }
+  return config.axis_x_categories[i]
+};
+Chart.prototype.categories = function(categories) {
+  var $$ = this.internal,
+    config = $$.config;
+  if (!arguments.length) {
+    return config.axis_x_categories
+  }
+  config.axis_x_categories = categories;
+  $$.redraw();
+  return config.axis_x_categories
+};
+
+Chart.prototype.resize = function(size) {
+  var $$ = this.internal,
+    config = $$.config;
+  config.size_width = size ? size.width : null;
+  config.size_height = size ? size.height : null;
+  this.flush();
+};
+
+Chart.prototype.flush = function() {
+  var $$ = this.internal;
+  $$.updateAndRedraw({
+    withLegend: true,
+    withTransition: false,
+    withTransitionForTransform: false
+  });
+};
+
+Chart.prototype.destroy = function() {
+  var $$ = this.internal;
+
+  window.clearInterval($$.intervalForObserveInserted);
+
+  if ($$.resizeTimeout !== undefined) {
+    window.clearTimeout($$.resizeTimeout);
+  }
+
+  if (window.detachEvent) {
+    window.detachEvent('onresize', $$.resizeIfElementDisplayed);
+  } else if (window.removeEventListener) {
+    window.removeEventListener('resize', $$.resizeIfElementDisplayed);
+  } else {
+    var wrapper = window.onresize;
+    // check if no one else removed our wrapper and remove our resizeFunction from it
+    if (wrapper && wrapper.add && wrapper.remove) {
+      wrapper.remove($$.resizeFunction);
+    }
+  }
+
+  // Removes the inner resize functions
+  $$.resizeFunction.remove();
+
+  // Unbinds from the window focus event
+  $$.unbindWindowFocus();
+
+  $$.selectChart.classed('c3', false).html('');
+
+  // MEMO: this is needed because the reference of some elements will not be released, then memory leak will happen.
+  Object.keys($$).forEach(function(key) {
+    $$[key] = null;
+  });
+
+  return null
+};
+
+// TODO: fix
+Chart.prototype.color = function(id) {
+  var $$ = this.internal;
+  return $$.color(id) // more patterns
+};
+
+Chart.prototype.data = function(targetIds) {
+  var targets = this.internal.data.targets;
+  return typeof targetIds === 'undefined'
+    ? targets
+    : targets.filter(function(t) {
+        return [].concat(targetIds).indexOf(t.id) >= 0
+      })
+};
+Chart.prototype.data.shown = function(targetIds) {
+  return this.internal.filterTargetsToShow(this.data(targetIds))
+};
+
+/**
+ * Get values of the data loaded in the chart.
+ *
+ * @param {String|Array} targetId This API returns the value of specified target.
+ * @param flat
+ * @return {Array} Data values
+ */
+Chart.prototype.data.values = function(targetId, flat = true) {
+  let values = null;
+
+  if (targetId) {
+    const targets = this.data(targetId);
+    if (targets && isArray(targets)) {
+      values = targets.reduce((ret, v) => {
+        const dataValue = v.values.map(d => d.value);
+        if (flat) {
+          ret = ret.concat(dataValue);
+        } else {
+          ret.push(dataValue);
+        }
+        return ret
+      }, []);
+    }
+  }
+
+  return values
+};
+Chart.prototype.data.names = function(names) {
+  this.internal.clearLegendItemTextBoxCache();
+  return this.internal.updateDataAttributes('names', names)
+};
+Chart.prototype.data.colors = function(colors) {
+  return this.internal.updateDataAttributes('colors', colors)
+};
+Chart.prototype.data.axes = function(axes) {
+  return this.internal.updateDataAttributes('axes', axes)
+};
+
+Chart.prototype.data.stackNormalized = function(normalized) {
+  if (normalized === undefined) {
+    return this.internal.isStackNormalized()
+  }
+
+  this.internal.config.data_stack_normalize = !!normalized;
+  this.internal.redraw();
+};
+
+Chart.prototype.donut = function() {};
+
+Chart.prototype.donut.padAngle = function(padAngle) {
+  if (padAngle === undefined) {
+    return this.internal.config.donut_padAngle
+  }
+  this.internal.config.donut_padAngle = padAngle;
+  this.flush();
+};
+
+Chart.prototype.flow = function(args) {
+  var $$ = this.internal,
+    targets,
+    data,
+    notfoundIds = [],
+    orgDataCount = $$.getMaxDataCount(),
+    dataCount,
+    domain,
+    baseTarget,
+    baseValue,
+    length = 0,
+    tail = 0,
+    diff,
+    to;
+
+  if (args.json) {
+    data = $$.convertJsonToData(args.json, args.keys);
+  } else if (args.rows) {
+    data = $$.convertRowsToData(args.rows);
+  } else if (args.columns) {
+    data = $$.convertColumnsToData(args.columns);
+  } else {
+    return
+  }
+  targets = $$.convertDataToTargets(data, true);
+
+  // Update/Add data
+  $$.data.targets.forEach(function(t) {
+    var found = false,
+      i,
+      j;
+    for (i = 0; i < targets.length; i++) {
+      if (t.id === targets[i].id) {
+        found = true;
+
+        if (t.values[t.values.length - 1]) {
+          tail = t.values[t.values.length - 1].index + 1;
+        }
+        length = targets[i].values.length;
+
+        for (j = 0; j < length; j++) {
+          targets[i].values[j].index = tail + j;
+          if (!$$.isTimeSeries()) {
+            targets[i].values[j].x = tail + j;
+          }
+        }
+        t.values = t.values.concat(targets[i].values);
+
+        targets.splice(i, 1);
+        break
+      }
+    }
+    if (!found) {
+      notfoundIds.push(t.id);
+    }
+  });
+
+  // Append null for not found targets
+  $$.data.targets.forEach(function(t) {
+    var i, j;
+    for (i = 0; i < notfoundIds.length; i++) {
+      if (t.id === notfoundIds[i]) {
+        tail = t.values[t.values.length - 1].index + 1;
+        for (j = 0; j < length; j++) {
+          t.values.push({
+            id: t.id,
+            index: tail + j,
+            x: $$.isTimeSeries() ? $$.getOtherTargetX(tail + j) : tail + j,
+            value: null
+          });
+        }
+      }
+    }
+  });
+
+  // Generate null values for new target
+  if ($$.data.targets.length) {
+    targets.forEach(function(t) {
+      var i,
+        missing = [];
+      for (i = $$.data.targets[0].values[0].index; i < tail; i++) {
+        missing.push({
+          id: t.id,
+          index: i,
+          x: $$.isTimeSeries() ? $$.getOtherTargetX(i) : i,
+          value: null
+        });
+      }
+      t.values.forEach(function(v) {
+        v.index += tail;
+        if (!$$.isTimeSeries()) {
+          v.x += tail;
+        }
+      });
+      t.values = missing.concat(t.values);
+    });
+  }
+  $$.data.targets = $$.data.targets.concat(targets); // add remained
+
+  // check data count because behavior needs to change when it's only one
+  dataCount = $$.getMaxDataCount();
+  baseTarget = $$.data.targets[0];
+  baseValue = baseTarget.values[0];
+
+  // Update length to flow if needed
+  if (isDefined(args.to)) {
+    length = 0;
+    to = $$.isTimeSeries() ? $$.parseDate(args.to) : args.to;
+    baseTarget.values.forEach(function(v) {
+      if (v.x < to) {
+        length++;
+      }
+    });
+  } else if (isDefined(args.length)) {
+    length = args.length;
+  }
+
+  // If only one data, update the domain to flow from left edge of the chart
+  if (!orgDataCount) {
+    if ($$.isTimeSeries()) {
+      if (baseTarget.values.length > 1) {
+        diff = baseTarget.values[baseTarget.values.length - 1].x - baseValue.x;
+      } else {
+        diff = baseValue.x - $$.getXDomain($$.data.targets)[0];
+      }
+    } else {
+      diff = 1;
+    }
+    domain = [baseValue.x - diff, baseValue.x];
+    $$.updateXDomain(null, true, true, false, domain);
+  } else if (orgDataCount === 1) {
+    if ($$.isTimeSeries()) {
+      diff =
+        (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2;
+      domain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)];
+      $$.updateXDomain(null, true, true, false, domain);
+    }
+  }
+
+  // Set targets
+  $$.updateTargets($$.data.targets);
+
+  // Redraw with new targets
+  $$.redraw({
+    flow: {
+      index: baseValue.index,
+      length: length,
+      duration: isValue(args.duration)
+        ? args.duration
+        : $$.config.transition_duration,
+      done: args.done,
+      orgDataCount: orgDataCount
+    },
+    withLegend: true,
+    withTransition: orgDataCount > 1,
+    withTrimXDomain: false,
+    withUpdateXAxis: true
+  });
+};
+
+ChartInternal.prototype.generateFlow = function(args) {
+  var $$ = this,
+    config = $$.config,
+    d3 = $$.d3;
+
+  return function() {
+    var targets = args.targets,
+      flow = args.flow,
+      drawBar = args.drawBar,
+      drawLine = args.drawLine,
+      drawArea = args.drawArea,
+      cx = args.cx,
+      cy = args.cy,
+      xv = args.xv,
+      xForText = args.xForText,
+      yForText = args.yForText,
+      duration = args.duration;
+
+    var translateX,
+      scaleX = 1,
+      transform,
+      flowIndex = flow.index,
+      flowLength = flow.length,
+      flowStart = $$.getValueOnIndex($$.data.targets[0].values, flowIndex),
+      flowEnd = $$.getValueOnIndex(
+        $$.data.targets[0].values,
+        flowIndex + flowLength
+      ),
+      orgDomain = $$.x.domain(),
+      domain,
+      durationForFlow = flow.duration || duration,
+      done = flow.done || function() {},
+      wait = $$.generateWait();
+
+    var xgrid,
+      xgridLines,
+      mainRegion,
+      mainText,
+      mainBar,
+      mainLine,
+      mainArea,
+      mainCircle;
+
+    // set flag
+    $$.flowing = true;
+
+    // remove head data after rendered
+    $$.data.targets.forEach(function(d) {
+      d.values.splice(0, flowLength);
+    });
+
+    // update x domain to generate axis elements for flow
+    domain = $$.updateXDomain(targets, true, true);
+    // update elements related to x scale
+    if ($$.updateXGrid) {
+      $$.updateXGrid(true);
+    }
+
+    xgrid = $$.xgrid || d3.selectAll([]); // xgrid needs to be obtained after updateXGrid
+    xgridLines = $$.xgridLines || d3.selectAll([]);
+    mainRegion = $$.mainRegion || d3.selectAll([]);
+    mainText = $$.mainText || d3.selectAll([]);
+    mainBar = $$.mainBar || d3.selectAll([]);
+    mainLine = $$.mainLine || d3.selectAll([]);
+    mainArea = $$.mainArea || d3.selectAll([]);
+    mainCircle = $$.mainCircle || d3.selectAll([]);
+
+    // generate transform to flow
+    if (!flow.orgDataCount) {
+      // if empty
+      if ($$.data.targets[0].values.length !== 1) {
+        translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
+      } else {
+        if ($$.isTimeSeries()) {
+          flowStart = $$.getValueOnIndex($$.data.targets[0].values, 0);
+          flowEnd = $$.getValueOnIndex(
+            $$.data.targets[0].values,
+            $$.data.targets[0].values.length - 1
+          );
+          translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);
+        } else {
+          translateX = diffDomain(domain) / 2;
+        }
+      }
+    } else if (
+      flow.orgDataCount === 1 ||
+      (flowStart && flowStart.x) === (flowEnd && flowEnd.x)
+    ) {
+      translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
+    } else {
+      if ($$.isTimeSeries()) {
+        translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
+      } else {
+        translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);
+      }
+    }
+    scaleX = diffDomain(orgDomain) / diffDomain(domain);
+    transform = 'translate(' + translateX + ',0) scale(' + scaleX + ',1)';
+
+    $$.hideXGridFocus();
+
+    var flowTransition = d3
+      .transition()
+      .ease(d3.easeLinear)
+      .duration(durationForFlow);
+    wait.add($$.xAxis($$.axes.x, flowTransition));
+    wait.add(mainBar.transition(flowTransition).attr('transform', transform));
+    wait.add(mainLine.transition(flowTransition).attr('transform', transform));
+    wait.add(mainArea.transition(flowTransition).attr('transform', transform));
+    wait.add(mainCircle.transition(flowTransition).attr('transform', transform));
+    wait.add(mainText.transition(flowTransition).attr('transform', transform));
+    wait.add(
+      mainRegion
+        .filter($$.isRegionOnX)
+        .transition(flowTransition)
+        .attr('transform', transform)
+    );
+    wait.add(xgrid.transition(flowTransition).attr('transform', transform));
+    wait.add(xgridLines.transition(flowTransition).attr('transform', transform));
+    wait(function() {
+      var i,
+        shapes = [],
+        texts = [];
+
+      // remove flowed elements
+      if (flowLength) {
+        for (i = 0; i < flowLength; i++) {
+          shapes.push('.' + CLASS.shape + '-' + (flowIndex + i));
+          texts.push('.' + CLASS.text + '-' + (flowIndex + i));
+        }
+        $$.svg
+          .selectAll('.' + CLASS.shapes)
+          .selectAll(shapes)
+          .remove();
+        $$.svg
+          .selectAll('.' + CLASS.texts)
+          .selectAll(texts)
+          .remove();
+        $$.svg.select('.' + CLASS.xgrid).remove();
+      }
+
+      // draw again for removing flowed elements and reverting attr
+      xgrid
+        .attr('transform', null)
+        .attr('x1', $$.xgridAttr.x1)
+        .attr('x2', $$.xgridAttr.x2)
+        .attr('y1', $$.xgridAttr.y1)
+        .attr('y2', $$.xgridAttr.y2)
+        .style('opacity', $$.xgridAttr.opacity);
+      xgridLines.attr('transform', null);
+      xgridLines
+        .select('line')
+        .attr('x1', config.axis_rotated ? 0 : xv)
+        .attr('x2', config.axis_rotated ? $$.width : xv);
+      xgridLines
+        .select('text')
+        .attr('x', config.axis_rotated ? $$.width : 0)
+        .attr('y', xv);
+      mainBar.attr('transform', null).attr('d', drawBar);
+      mainLine.attr('transform', null).attr('d', drawLine);
+      mainArea.attr('transform', null).attr('d', drawArea);
+      mainCircle
+        .attr('transform', null)
+        .attr('cx', cx)
+        .attr('cy', cy);
+      mainText
+        .attr('transform', null)
+        .attr('x', xForText)
+        .attr('y', yForText)
+        .style('fill-opacity', $$.opacityForText.bind($$));
+      mainRegion.attr('transform', null);
+      mainRegion
+        .filter($$.isRegionOnX)
+        .attr('x', $$.regionX.bind($$))
+        .attr('width', $$.regionWidth.bind($$));
+
+      // callback for end of flow
+      done();
+
+      $$.flowing = false;
+    });
+  }
+};
+
+Chart.prototype.focus = function(targetIds) {
+  var $$ = this.internal,
+    candidates;
+
+  targetIds = $$.mapToTargetIds(targetIds)
+  ;(candidates = $$.svg.selectAll(
+    $$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))
+  )),
+    this.revert();
+  this.defocus();
+  candidates.classed(CLASS.focused, true).classed(CLASS.defocused, false);
+  if ($$.hasArcType()) {
+    $$.expandArc(targetIds);
+  }
+  $$.toggleFocusLegend(targetIds, true);
+
+  $$.focusedTargetIds = targetIds;
+  $$.defocusedTargetIds = $$.defocusedTargetIds.filter(function(id) {
+    return targetIds.indexOf(id) < 0
+  });
+};
+
+Chart.prototype.defocus = function(targetIds) {
+  var $$ = this.internal,
+    candidates;
+
+  targetIds = $$.mapToTargetIds(targetIds)
+  ;(candidates = $$.svg.selectAll(
+    $$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))
+  )),
+    candidates.classed(CLASS.focused, false).classed(CLASS.defocused, true);
+  if ($$.hasArcType()) {
+    $$.unexpandArc(targetIds);
+  }
+  $$.toggleFocusLegend(targetIds, false);
+
+  $$.focusedTargetIds = $$.focusedTargetIds.filter(function(id) {
+    return targetIds.indexOf(id) < 0
+  });
+  $$.defocusedTargetIds = targetIds;
+};
+
+Chart.prototype.revert = function(targetIds) {
+  var $$ = this.internal,
+    candidates;
+
+  targetIds = $$.mapToTargetIds(targetIds);
+  candidates = $$.svg.selectAll($$.selectorTargets(targetIds)); // should be for all targets
+
+  candidates.classed(CLASS.focused, false).classed(CLASS.defocused, false);
+  if ($$.hasArcType()) {
+    $$.unexpandArc(targetIds);
+  }
+  if ($$.config.legend_show) {
+    $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$)));
+    $$.legend
+      .selectAll($$.selectorLegends(targetIds))
+      .filter(function() {
+        return $$.d3.select(this).classed(CLASS.legendItemFocused)
+      })
+      .classed(CLASS.legendItemFocused, false);
+  }
+
+  $$.focusedTargetIds = [];
+  $$.defocusedTargetIds = [];
+};
+
+Chart.prototype.xgrids = function(grids) {
+  var $$ = this.internal,
+    config = $$.config;
+  if (!grids) {
+    return config.grid_x_lines
+  }
+  config.grid_x_lines = grids;
+  $$.redrawWithoutRescale();
+  return config.grid_x_lines
+};
+Chart.prototype.xgrids.add = function(grids) {
+  var $$ = this.internal;
+  return this.xgrids($$.config.grid_x_lines.concat(grids ? grids : []))
+};
+Chart.prototype.xgrids.remove = function(params) {
+  // TODO: multiple
+  var $$ = this.internal;
+  $$.removeGridLines(params, true);
+};
+
+Chart.prototype.ygrids = function(grids) {
+  var $$ = this.internal,
+    config = $$.config;
+  if (!grids) {
+    return config.grid_y_lines
+  }
+  config.grid_y_lines = grids;
+  $$.redrawWithoutRescale();
+  return config.grid_y_lines
+};
+Chart.prototype.ygrids.add = function(grids) {
+  var $$ = this.internal;
+  return this.ygrids($$.config.grid_y_lines.concat(grids ? grids : []))
+};
+Chart.prototype.ygrids.remove = function(params) {
+  // TODO: multiple
+  var $$ = this.internal;
+  $$.removeGridLines(params, false);
+};
+
+Chart.prototype.groups = function(groups) {
+  var $$ = this.internal,
+    config = $$.config;
+  if (isUndefined(groups)) {
+    return config.data_groups
+  }
+  config.data_groups = groups;
+  $$.redraw();
+  return config.data_groups
+};
+
+Chart.prototype.legend = function() {};
+Chart.prototype.legend.show = function(targetIds) {
+  var $$ = this.internal;
+  $$.showLegend($$.mapToTargetIds(targetIds));
+  $$.updateAndRedraw({ withLegend: true });
+};
+Chart.prototype.legend.hide = function(targetIds) {
+  var $$ = this.internal;
+  $$.hideLegend($$.mapToTargetIds(targetIds));
+  $$.updateAndRedraw({ withLegend: false });
+};
+
+Chart.prototype.load = function(args) {
+  var $$ = this.internal,
+    config = $$.config;
+  // update xs if specified
+  if (args.xs) {
+    $$.addXs(args.xs);
+  }
+  // update names if exists
+  if ('names' in args) {
+    Chart.prototype.data.names.bind(this)(args.names);
+  }
+  // update classes if exists
+  if ('classes' in args) {
+    Object.keys(args.classes).forEach(function(id) {
+      config.data_classes[id] = args.classes[id];
+    });
+  }
+  // update categories if exists
+  if ('categories' in args && $$.isCategorized()) {
+    config.axis_x_categories = args.categories;
+  }
+  // update axes if exists
+  if ('axes' in args) {
+    Object.keys(args.axes).forEach(function(id) {
+      config.data_axes[id] = args.axes[id];
+    });
+  }
+  // update colors if exists
+  if ('colors' in args) {
+    Object.keys(args.colors).forEach(function(id) {
+      config.data_colors[id] = args.colors[id];
+    });
+  }
+  // use cache if exists
+  if ('cacheIds' in args && $$.hasCaches(args.cacheIds)) {
+    $$.load($$.getCaches(args.cacheIds), args.done);
+    return
+  }
+  // unload if needed
+  if (args.unload) {
+    // TODO: do not unload if target will load (included in url/rows/columns)
+    $$.unload(
+      $$.mapToTargetIds(args.unload === true ? null : args.unload),
+      function() {
+        $$.loadFromArgs(args);
+      }
+    );
+  } else {
+    $$.loadFromArgs(args);
+  }
+};
+
+Chart.prototype.unload = function(args) {
+  var $$ = this.internal;
+  args = args || {};
+  if (args instanceof Array) {
+    args = { ids: args };
+  } else if (typeof args === 'string') {
+    args = { ids: [args] };
+  }
+  $$.unload($$.mapToTargetIds(args.ids), function() {
+    $$.redraw({
+      withUpdateOrgXDomain: true,
+      withUpdateXDomain: true,
+      withLegend: true
+    });
+    if (args.done) {
+      args.done();
+    }
+  });
+};
+
+Chart.prototype.pie = function() {};
+
+Chart.prototype.pie.padAngle = function(padAngle) {
+  if (padAngle === undefined) {
+    return this.internal.config.pie_padAngle
+  }
+  this.internal.config.pie_padAngle = padAngle;
+  this.flush();
+};
+
+Chart.prototype.regions = function(regions) {
+  var $$ = this.internal,
+    config = $$.config;
+  if (!regions) {
+    return config.regions
+  }
+  config.regions = regions;
+  $$.redrawWithoutRescale();
+  return config.regions
+};
+Chart.prototype.regions.add = function(regions) {
+  var $$ = this.internal,
+    config = $$.config;
+  if (!regions) {
+    return config.regions
+  }
+  config.regions = config.regions.concat(regions);
+  $$.redrawWithoutRescale();
+  return config.regions
+};
+Chart.prototype.regions.remove = function(options) {
+  var $$ = this.internal,
+    config = $$.config,
+    duration,
+    classes,
+    regions;
+
+  options = options || {};
+  duration = getOption(options, 'duration', config.transition_duration);
+  classes = getOption(options, 'classes', [CLASS.region]);
+
+  regions = $$.main.select('.' + CLASS.regions).selectAll(
+    classes.map(function(c) {
+      return '.' + c
+    })
+  )
+  ;(duration ? regions.transition().duration(duration) : regions)
+    .style('opacity', 0)
+    .remove();
+
+  config.regions = config.regions.filter(function(region) {
+    var found = false;
+    if (!region['class']) {
+      return true
+    }
+    region['class'].split(' ').forEach(function(c) {
+      if (classes.indexOf(c) >= 0) {
+        found = true;
+      }
+    });
+    return !found
+  });
+
+  return config.regions
+};
+
+Chart.prototype.selected = function(targetId) {
+  var $$ = this.internal,
+    d3 = $$.d3;
+  return $$.main
+    .selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(targetId))
+    .selectAll('.' + CLASS.shape)
+    .filter(function() {
+      return d3.select(this).classed(CLASS.SELECTED)
+    })
+    .nodes()
+    .map(function(d) {
+      var data = d.__data__;
+      return data.data ? data.data : data
+    })
+};
+Chart.prototype.select = function(ids, indices, resetOther) {
+  var $$ = this.internal,
+    d3 = $$.d3,
+    config = $$.config;
+  if (!config.data_selection_enabled) {
+    return
+  }
+  $$.main
+    .selectAll('.' + CLASS.shapes)
+    .selectAll('.' + CLASS.shape)
+    .each(function(d, i) {
+      var shape = d3.select(this),
+        id = d.data ? d.data.id : d.id,
+        toggle = $$.getToggle(this, d).bind($$),
+        isTargetId =
+          config.data_selection_grouped || !ids || ids.indexOf(id) >= 0,
+        isTargetIndex = !indices || indices.indexOf(i) >= 0,
+        isSelected = shape.classed(CLASS.SELECTED);
+      // line/area selection not supported yet
+      if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
+        return
+      }
+      if (isTargetId && isTargetIndex) {
+        if (config.data_selection_isselectable(d) && !isSelected) {
+          toggle(true, shape.classed(CLASS.SELECTED, true), d, i);
+        }
+      } else if (isDefined(resetOther) && resetOther) {
+        if (isSelected) {
+          toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
+        }
+      }
+    });
+};
+Chart.prototype.unselect = function(ids, indices) {
+  var $$ = this.internal,
+    d3 = $$.d3,
+    config = $$.config;
+  if (!config.data_selection_enabled) {
+    return
+  }
+  $$.main
+    .selectAll('.' + CLASS.shapes)
+    .selectAll('.' + CLASS.shape)
+    .each(function(d, i) {
+      var shape = d3.select(this),
+        id = d.data ? d.data.id : d.id,
+        toggle = $$.getToggle(this, d).bind($$),
+        isTargetId =
+          config.data_selection_grouped || !ids || ids.indexOf(id) >= 0,
+        isTargetIndex = !indices || indices.indexOf(i) >= 0,
+        isSelected = shape.classed(CLASS.SELECTED);
+      // line/area selection not supported yet
+      if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
+        return
+      }
+      if (isTargetId && isTargetIndex) {
+        if (config.data_selection_isselectable(d)) {
+          if (isSelected) {
+            toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
+          }
+        }
+      }
+    });
+};
+
+Chart.prototype.show = function(targetIds, options) {
+  var $$ = this.internal,
+    targets;
+
+  targetIds = $$.mapToTargetIds(targetIds);
+  options = options || {};
+
+  $$.removeHiddenTargetIds(targetIds);
+  targets = $$.svg.selectAll($$.selectorTargets(targetIds));
+
+  targets
+    .transition()
+    .style('display', isIE() ? 'block' : 'initial', 'important')
+    .style('opacity', 1, 'important')
+    .call($$.endall, function() {
+      targets.style('opacity', null).style('opacity', 1);
+    });
+
+  if (options.withLegend) {
+    $$.showLegend(targetIds);
+  }
+
+  $$.redraw({
+    withUpdateOrgXDomain: true,
+    withUpdateXDomain: true,
+    withLegend: true
+  });
+};
+
+Chart.prototype.hide = function(targetIds, options) {
+  var $$ = this.internal,
+    targets;
+
+  targetIds = $$.mapToTargetIds(targetIds);
+  options = options || {};
+
+  $$.addHiddenTargetIds(targetIds);
+  targets = $$.svg.selectAll($$.selectorTargets(targetIds));
+
+  targets
+    .transition()
+    .style('opacity', 0, 'important')
+    .call($$.endall, function() {
+      targets.style('opacity', null).style('opacity', 0);
+      targets.style('display', 'none');
+    });
+
+  if (options.withLegend) {
+    $$.hideLegend(targetIds);
+  }
+
+  $$.redraw({
+    withUpdateOrgXDomain: true,
+    withUpdateXDomain: true,
+    withLegend: true
+  });
+};
+
+Chart.prototype.toggle = function(targetIds, options) {
+  var that = this,
+    $$ = this.internal;
+  $$.mapToTargetIds(targetIds).forEach(function(targetId) {
+    $$.isTargetToShow(targetId)
+      ? that.hide(targetId, options)
+      : that.show(targetId, options);
+  });
+};
+
+Chart.prototype.subchart = function() {};
+
+Chart.prototype.subchart.isShown = function() {
+  const $$ = this.internal;
+
+  return $$.config.subchart_show
+};
+
+Chart.prototype.subchart.show = function() {
+  const $$ = this.internal;
+
+  if ($$.config.subchart_show) {
+    return
+  }
+
+  $$.config.subchart_show = true;
+
+  // insert DOM
+  $$.initSubchart();
+
+  // update dimensions with sub chart now visible
+  $$.updateDimension();
+
+  // insert brush (depends on sizes previously updated)
+  $$.initSubchartBrush();
+
+  // attach data
+  $$.updateTargetsForSubchart($$.getTargets());
+
+  // reset fade-in state
+  $$.mapToIds($$.data.targets).forEach(function(id) {
+    $$.withoutFadeIn[id] = false;
+  });
+
+  // redraw chart !
+  $$.updateAndRedraw();
+
+  // update visible targets !
+  $$.showTargets();
+};
+
+Chart.prototype.subchart.hide = function() {
+  const $$ = this.internal;
+
+  if (!$$.config.subchart_show) {
+    return
+  }
+
+  $$.config.subchart_show = false;
+
+  // remove DOM
+  $$.removeSubchart();
+
+  // re-render chart
+  $$.redraw();
+};
+
+Chart.prototype.tooltip = function() {};
+Chart.prototype.tooltip.show = function(args) {
+  var $$ = this.internal,
+    targets,
+    data,
+    mouse = {};
+
+  // determine mouse position on the chart
+  if (args.mouse) {
+    mouse = args.mouse;
+  } else {
+    // determine focus data
+    if (args.data) {
+      data = args.data;
+    } else if (typeof args.x !== 'undefined') {
+      if (args.id) {
+        targets = $$.data.targets.filter(function(t) {
+          return t.id === args.id
+        });
+      } else {
+        targets = $$.data.targets;
+      }
+      data = $$.filterByX(targets, args.x).slice(0, 1)[0];
+    }
+    mouse = data ? $$.getMousePosition(data) : null;
+  }
+
+  // emulate mouse events to show
+  $$.dispatchEvent('mousemove', mouse);
+
+  $$.config.tooltip_onshow.call($$, data);
+};
+Chart.prototype.tooltip.hide = function() {
+  // TODO: get target data by checking the state of focus
+  this.internal.dispatchEvent('mouseout', 0);
+
+  this.internal.config.tooltip_onhide.call(this);
+};
+
+Chart.prototype.transform = function(type, targetIds) {
+  var $$ = this.internal,
+    options =
+      ['pie', 'donut'].indexOf(type) >= 0 ? { withTransform: true } : null;
+  $$.transformTo(targetIds, type, options);
+};
+
+ChartInternal.prototype.transformTo = function(
+  targetIds,
+  type,
+  optionsForRedraw
+) {
+  var $$ = this,
+    withTransitionForAxis = !$$.hasArcType(),
+    options = optionsForRedraw || {
+      withTransitionForAxis: withTransitionForAxis
+    };
+  options.withTransitionForTransform = false;
+  $$.transiting = false;
+  $$.setTargetType(targetIds, type);
+  $$.updateTargets($$.data.targets); // this is needed when transforming to arc
+  $$.updateAndRedraw(options);
+};
+
+Chart.prototype.x = function(x) {
+  var $$ = this.internal;
+  if (arguments.length) {
+    $$.updateTargetX($$.data.targets, x);
+    $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true });
+  }
+  return $$.data.xs
+};
+Chart.prototype.xs = function(xs) {
+  var $$ = this.internal;
+  if (arguments.length) {
+    $$.updateTargetXs($$.data.targets, xs);
+    $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true });
+  }
+  return $$.data.xs
+};
+
+Chart.prototype.zoom = function(domain) {
+  var $$ = this.internal;
+  if (domain) {
+    if ($$.isTimeSeries()) {
+      domain = domain.map(function(x) {
+        return $$.parseDate(x)
+      });
+    }
+    if ($$.config.subchart_show) {
+      $$.brush.selectionAsValue(domain, true);
+    } else {
+      $$.updateXDomain(null, true, false, false, domain);
+      $$.redraw({ withY: $$.config.zoom_rescale, withSubchart: false });
+    }
+    $$.config.zoom_onzoom.call(this, $$.x.orgDomain());
+    return domain
+  } else {
+    return $$.x.domain()
+  }
+};
+Chart.prototype.zoom.enable = function(enabled) {
+  var $$ = this.internal;
+  $$.config.zoom_enabled = enabled;
+  $$.updateAndRedraw();
+};
+Chart.prototype.unzoom = function() {
+  var $$ = this.internal;
+  if ($$.config.subchart_show) {
+    $$.brush.clear();
+  } else {
+    $$.updateXDomain(null, true, false, false, $$.subX.domain());
+    $$.redraw({ withY: $$.config.zoom_rescale, withSubchart: false });
+  }
+};
+
+Chart.prototype.zoom.max = function(max) {
+  var $$ = this.internal,
+    config = $$.config,
+    d3 = $$.d3;
+  if (max === 0 || max) {
+    config.zoom_x_max = d3.max([$$.orgXDomain[1], max]);
+  } else {
+    return config.zoom_x_max
+  }
+};
+
+Chart.prototype.zoom.min = function(min) {
+  var $$ = this.internal,
+    config = $$.config,
+    d3 = $$.d3;
+  if (min === 0 || min) {
+    config.zoom_x_min = d3.min([$$.orgXDomain[0], min]);
+  } else {
+    return config.zoom_x_min
+  }
+};
+
+Chart.prototype.zoom.range = function(range) {
+  if (arguments.length) {
+    if (isDefined(range.max)) {
+      this.domain.max(range.max);
+    }
+    if (isDefined(range.min)) {
+      this.domain.min(range.min);
+    }
+  } else {
+    return {
+      max: this.domain.max(),
+      min: this.domain.min()
+    }
+  }
+};
+
+ChartInternal.prototype.initPie = function() {
+  var $$ = this,
+    d3 = $$.d3;
+  $$.pie = d3
+    .pie()
+    .padAngle(this.getPadAngle.bind(this))
+    .value(function(d) {
+      return d.values.reduce(function(a, b) {
+        return a + b.value
+      }, 0)
+    });
+
+  let orderFct = $$.getOrderFunction();
+
+  // we need to reverse the returned order if asc or desc to have the slice in expected order.
+  if (orderFct && ($$.isOrderAsc() || $$.isOrderDesc())) {
+    let defaultSort = orderFct;
+    orderFct = (t1, t2) => defaultSort(t1, t2) * -1;
+  }
+
+  $$.pie.sort(orderFct || null);
+};
+
+ChartInternal.prototype.updateRadius = function() {
+  var $$ = this,
+    config = $$.config,
+    w = config.gauge_width || config.donut_width,
+    gaugeArcWidth =
+      $$.filterTargetsToShow($$.data.targets).length *
+      $$.config.gauge_arcs_minWidth;
+  $$.radiusExpanded =
+    (Math.min($$.arcWidth, $$.arcHeight) / 2) * ($$.hasType('gauge') ? 0.85 : 1);
+  $$.radius = $$.radiusExpanded * 0.95;
+  $$.innerRadiusRatio = w ? ($$.radius - w) / $$.radius : 0.6;
+  $$.innerRadius =
+    $$.hasType('donut') || $$.hasType('gauge')
+      ? $$.radius * $$.innerRadiusRatio
+      : 0;
+  $$.gaugeArcWidth = w
+    ? w
+    : gaugeArcWidth <= $$.radius - $$.innerRadius
+    ? $$.radius - $$.innerRadius
+    : gaugeArcWidth <= $$.radius
+    ? gaugeArcWidth
+    : $$.radius;
+};
+
+ChartInternal.prototype.getPadAngle = function() {
+  if (this.hasType('pie')) {
+    return this.config.pie_padAngle || 0
+  } else if (this.hasType('donut')) {
+    return this.config.donut_padAngle || 0
+  } else {
+    return 0
+  }
+};
+
+ChartInternal.prototype.updateArc = function() {
+  var $$ = this;
+  $$.svgArc = $$.getSvgArc();
+  $$.svgArcExpanded = $$.getSvgArcExpanded();
+  $$.svgArcExpandedSub = $$.getSvgArcExpanded(0.98);
+};
+
+ChartInternal.prototype.updateAngle = function(d) {
+  var $$ = this,
+    config = $$.config,
+    found = false,
+    index = 0,
+    gMin,
+    gMax,
+    gTic,
+    gValue;
+
+  if (!config) {
+    return null
+  }
+
+  $$.pie($$.filterTargetsToShow($$.data.targets)).forEach(function(t) {
+    if (!found && t.data.id === d.data.id) {
+      found = true;
+      d = t;
+      d.index = index;
+    }
+    index++;
+  });
+  if (isNaN(d.startAngle)) {
+    d.startAngle = 0;
+  }
+  if (isNaN(d.endAngle)) {
+    d.endAngle = d.startAngle;
+  }
+  if ($$.isGaugeType(d.data)) {
+    gMin = config.gauge_min;
+    gMax = config.gauge_max;
+    gTic = (Math.PI * (config.gauge_fullCircle ? 2 : 1)) / (gMax - gMin);
+    gValue = d.value < gMin ? 0 : d.value < gMax ? d.value - gMin : gMax - gMin;
+    d.startAngle = config.gauge_startingAngle;
+    d.endAngle = d.startAngle + gTic * gValue;
+  }
+  return found ? d : null
+};
+
+ChartInternal.prototype.getSvgArc = function() {
+  var $$ = this,
+    hasGaugeType = $$.hasType('gauge'),
+    singleArcWidth =
+      $$.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length,
+    arc = $$.d3
+      .arc()
+      .outerRadius(function(d) {
+        return hasGaugeType ? $$.radius - singleArcWidth * d.index : $$.radius
+      })
+      .innerRadius(function(d) {
+        return hasGaugeType
+          ? $$.radius - singleArcWidth * (d.index + 1)
+          : $$.innerRadius
+      }),
+    newArc = function(d, withoutUpdate) {
+      var updated;
+      if (withoutUpdate) {
+        return arc(d)
+      } // for interpolate
+      updated = $$.updateAngle(d);
+      return updated ? arc(updated) : 'M 0 0'
+    };
+  // TODO: extends all function
+  newArc.centroid = arc.centroid;
+  return newArc
+};
+
+ChartInternal.prototype.getSvgArcExpanded = function(rate) {
+  rate = rate || 1;
+  var $$ = this,
+    hasGaugeType = $$.hasType('gauge'),
+    singleArcWidth =
+      $$.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length,
+    expandWidth = Math.min(
+      $$.radiusExpanded * rate - $$.radius,
+      singleArcWidth * 0.8 - (1 - rate) * 100
+    ),
+    arc = $$.d3
+      .arc()
+      .outerRadius(function(d) {
+        return hasGaugeType
+          ? $$.radius - singleArcWidth * d.index + expandWidth
+          : $$.radiusExpanded * rate
+      })
+      .innerRadius(function(d) {
+        return hasGaugeType
+          ? $$.radius - singleArcWidth * (d.index + 1)
+          : $$.innerRadius
+      });
+  return function(d) {
+    var updated = $$.updateAngle(d);
+    return updated ? arc(updated) : 'M 0 0'
+  }
+};
+
+ChartInternal.prototype.getArc = function(d, withoutUpdate, force) {
+  return force || this.isArcType(d.data)
+    ? this.svgArc(d, withoutUpdate)
+    : 'M 0 0'
+};
+
+ChartInternal.prototype.transformForArcLabel = function(d) {
+  var $$ = this,
+    config = $$.config,
+    updated = $$.updateAngle(d),
+    c,
+    x,
+    y,
+    h,
+    ratio,
+    translate = '',
+    hasGauge = $$.hasType('gauge');
+  if (updated && !hasGauge) {
+    c = this.svgArc.centroid(updated);
+    x = isNaN(c[0]) ? 0 : c[0];
+    y = isNaN(c[1]) ? 0 : c[1];
+    h = Math.sqrt(x * x + y * y);
+    if ($$.hasType('donut') && config.donut_label_ratio) {
+      ratio = isFunction(config.donut_label_ratio)
+        ? config.donut_label_ratio(d, $$.radius, h)
+        : config.donut_label_ratio;
+    } else if ($$.hasType('pie') && config.pie_label_ratio) {
+      ratio = isFunction(config.pie_label_ratio)
+        ? config.pie_label_ratio(d, $$.radius, h)
+        : config.pie_label_ratio;
+    } else {
+      ratio =
+        $$.radius && h
+          ? ((36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) *
+              $$.radius) /
+            h
+          : 0;
+    }
+    translate = 'translate(' + x * ratio + ',' + y * ratio + ')';
+  } else if (
+    updated &&
+    hasGauge &&
+    $$.filterTargetsToShow($$.data.targets).length > 1
+  ) {
+    var y1 = Math.sin(updated.endAngle - Math.PI / 2);
+    x = Math.cos(updated.endAngle - Math.PI / 2) * ($$.radiusExpanded + 25);
+    y = y1 * ($$.radiusExpanded + 15 - Math.abs(y1 * 10)) + 3;
+    translate = 'translate(' + x + ',' + y + ')';
+  }
+  return translate
+};
+
+/**
+ * @deprecated Use `getRatio('arc', d)` instead.
+ */
+ChartInternal.prototype.getArcRatio = function(d) {
+  return this.getRatio('arc', d)
+};
+
+ChartInternal.prototype.convertToArcData = function(d) {
+  return this.addName({
+    id: d.data.id,
+    value: d.value,
+    ratio: this.getRatio('arc', d),
+    index: d.index
+  })
+};
+
+ChartInternal.prototype.textForArcLabel = function(d) {
+  var $$ = this,
+    updated,
+    value,
+    ratio,
+    id,
+    format;
+  if (!$$.shouldShowArcLabel()) {
+    return ''
+  }
+  updated = $$.updateAngle(d);
+  value = updated ? updated.value : null;
+  ratio = $$.getRatio('arc', updated);
+  id = d.data.id;
+  if (!$$.hasType('gauge') && !$$.meetsArcLabelThreshold(ratio)) {
+    return ''
+  }
+  format = $$.getArcLabelFormat();
+  return format
+    ? format(value, ratio, id)
+    : $$.defaultArcValueFormat(value, ratio)
+};
+
+ChartInternal.prototype.textForGaugeMinMax = function(value, isMax) {
+  var $$ = this,
+    format = $$.getGaugeLabelExtents();
+
+  return format ? format(value, isMax) : value
+};
+
+ChartInternal.prototype.expandArc = function(targetIds) {
+  var $$ = this,
+    interval;
+
+  // MEMO: avoid to cancel transition
+  if ($$.transiting) {
+    interval = window.setInterval(function() {
+      if (!$$.transiting) {
+        window.clearInterval(interval);
+        if ($$.legend.selectAll('.c3-legend-item-focused').size() > 0) {
+          $$.expandArc(targetIds);
+        }
+      }
+    }, 10);
+    return
+  }
+
+  targetIds = $$.mapToTargetIds(targetIds);
+
+  $$.svg
+    .selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc))
+    .each(function(d) {
+      if (!$$.shouldExpand(d.data.id)) {
+        return
+      }
+      $$.d3
+        .select(this)
+        .selectAll('path')
+        .transition()
+        .duration($$.expandDuration(d.data.id))
+        .attr('d', $$.svgArcExpanded)
+        .transition()
+        .duration($$.expandDuration(d.data.id) * 2)
+        .attr('d', $$.svgArcExpandedSub)
+        .each(function(d) {
+          if ($$.isDonutType(d.data)) ;
+        });
+    });
+};
+
+ChartInternal.prototype.unexpandArc = function(targetIds) {
+  var $$ = this;
+
+  if ($$.transiting) {
+    return
+  }
+
+  targetIds = $$.mapToTargetIds(targetIds);
+
+  $$.svg
+    .selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc))
+    .selectAll('path')
+    .transition()
+    .duration(function(d) {
+      return $$.expandDuration(d.data.id)
+    })
+    .attr('d', $$.svgArc);
+  $$.svg.selectAll('.' + CLASS.arc);
+};
+
+ChartInternal.prototype.expandDuration = function(id) {
+  var $$ = this,
+    config = $$.config;
+
+  if ($$.isDonutType(id)) {
+    return config.donut_expand_duration
+  } else if ($$.isGaugeType(id)) {
+    return config.gauge_expand_duration
+  } else if ($$.isPieType(id)) {
+    return config.pie_expand_duration
+  } else {
+    return 50
+  }
+};
+
+ChartInternal.prototype.shouldExpand = function(id) {
+  var $$ = this,
+    config = $$.config;
+  return (
+    ($$.isDonutType(id) && config.donut_expand) ||
+    ($$.isGaugeType(id) && config.gauge_expand) ||
+    ($$.isPieType(id) && config.pie_expand)
+  )
+};
+
+ChartInternal.prototype.shouldShowArcLabel = function() {
+  var $$ = this,
+    config = $$.config,
+    shouldShow = true;
+  if ($$.hasType('donut')) {
+    shouldShow = config.donut_label_show;
+  } else if ($$.hasType('pie')) {
+    shouldShow = config.pie_label_show;
+  }
+  // when gauge, always true
+  return shouldShow
+};
+
+ChartInternal.prototype.meetsArcLabelThreshold = function(ratio) {
+  var $$ = this,
+    config = $$.config,
+    threshold = $$.hasType('donut')
+      ? config.donut_label_threshold
+      : config.pie_label_threshold;
+  return ratio >= threshold
+};
+
+ChartInternal.prototype.getArcLabelFormat = function() {
+  var $$ = this,
+    config = $$.config,
+    format = config.pie_label_format;
+  if ($$.hasType('gauge')) {
+    format = config.gauge_label_format;
+  } else if ($$.hasType('donut')) {
+    format = config.donut_label_format;
+  }
+  return format
+};
+
+ChartInternal.prototype.getGaugeLabelExtents = function() {
+  var $$ = this,
+    config = $$.config;
+  return config.gauge_label_extents
+};
+
+ChartInternal.prototype.getArcTitle = function() {
+  var $$ = this;
+  return $$.hasType('donut') ? $$.config.donut_title : ''
+};
+
+ChartInternal.prototype.updateTargetsForArc = function(targets) {
+  var $$ = this,
+    main = $$.main,
+    mainPies,
+    mainPieEnter,
+    classChartArc = $$.classChartArc.bind($$),
+    classArcs = $$.classArcs.bind($$),
+    classFocus = $$.classFocus.bind($$);
+  mainPies = main
+    .select('.' + CLASS.chartArcs)
+    .selectAll('.' + CLASS.chartArc)
+    .data($$.pie(targets))
+    .attr('class', function(d) {
+      return classChartArc(d) + classFocus(d.data)
+    });
+  mainPieEnter = mainPies
+    .enter()
+    .append('g')
+    .attr('class', classChartArc);
+  mainPieEnter.append('g').attr('class', classArcs);
+  mainPieEnter
+    .append('text')
+    .attr('dy', $$.hasType('gauge') ? '-.1em' : '.35em')
+    .style('opacity', 0)
+    .style('text-anchor', 'middle')
+    .style('pointer-events', 'none');
+  // MEMO: can not keep same color..., but not bad to update color in redraw
+  //mainPieUpdate.exit().remove();
+};
+
+ChartInternal.prototype.initArc = function() {
+  var $$ = this;
+  $$.arcs = $$.main
+    .select('.' + CLASS.chart)
+    .append('g')
+    .attr('class', CLASS.chartArcs)
+    .attr('transform', $$.getTranslate('arc'));
+  $$.arcs
+    .append('text')
+    .attr('class', CLASS.chartArcsTitle)
+    .style('text-anchor', 'middle')
+    .text($$.getArcTitle());
+};
+
+ChartInternal.prototype.redrawArc = function(
+  duration,
+  durationForExit,
+  withTransform
+) {
+  var $$ = this,
+    d3 = $$.d3,
+    config = $$.config,
+    main = $$.main,
+    arcs,
+    mainArc,
+    arcLabelLines,
+    mainArcLabelLine,
+    hasGaugeType = $$.hasType('gauge');
+  arcs = main
+    .selectAll('.' + CLASS.arcs)
+    .selectAll('.' + CLASS.arc)
+    .data($$.arcData.bind($$));
+  mainArc = arcs
+    .enter()
+    .append('path')
+    .attr('class', $$.classArc.bind($$))
+    .style('fill', function(d) {
+      return $$.color(d.data)
+    })
+    .style('cursor', function(d) {
+      return config.interaction_enabled && config.data_selection_isselectable(d)
+        ? 'pointer'
+        : null
+    })
+    .each(function(d) {
+      if ($$.isGaugeType(d.data)) {
+        d.startAngle = d.endAngle = config.gauge_startingAngle;
+      }
+      this._current = d;
+    })
+    .merge(arcs);
+  if (hasGaugeType) {
+    arcLabelLines = main
+      .selectAll('.' + CLASS.arcs)
+      .selectAll('.' + CLASS.arcLabelLine)
+      .data($$.arcData.bind($$));
+    mainArcLabelLine = arcLabelLines
+      .enter()
+      .append('rect')
+      .attr('class', function(d) {
+        return (
+          CLASS.arcLabelLine +
+          ' ' +
+          CLASS.target +
+          ' ' +
+          CLASS.target +
+          '-' +
+          d.data.id
+        )
+      })
+      .merge(arcLabelLines);
+
+    if ($$.filterTargetsToShow($$.data.targets).length === 1) {
+      mainArcLabelLine.style('display', 'none');
+    } else {
+      mainArcLabelLine
+        .style('fill', function(d) {
+          return $$.levelColor
+            ? $$.levelColor(
+                d.data.values.reduce(function(total, item) {
+                  return total + item.value
+                }, 0)
+              )
+            : $$.color(d.data)
+        })
+        .style('display', config.gauge_labelLine_show ? '' : 'none')
+        .each(function(d) {
+          var lineLength = 0,
+            lineThickness = 2,
+            x = 0,
+            y = 0,
+            transform = '';
+          if ($$.hiddenTargetIds.indexOf(d.data.id) < 0) {
+            var updated = $$.updateAngle(d),
+              innerLineLength =
+                ($$.gaugeArcWidth /
+                  $$.filterTargetsToShow($$.data.targets).length) *
+                (updated.index + 1),
+              lineAngle = updated.endAngle - Math.PI / 2,
+              arcInnerRadius = $$.radius - innerLineLength,
+              linePositioningAngle =
+                lineAngle - (arcInnerRadius === 0 ? 0 : 1 / arcInnerRadius);
+            lineLength = $$.radiusExpanded - $$.radius + innerLineLength;
+            x = Math.cos(linePositioningAngle) * arcInnerRadius;
+            y = Math.sin(linePositioningAngle) * arcInnerRadius;
+            transform =
+              'rotate(' +
+              (lineAngle * 180) / Math.PI +
+              ', ' +
+              x +
+              ', ' +
+              y +
+              ')';
+          }
+          d3.select(this)
+            .attr('x', x)
+            .attr('y', y)
+            .attr('width', lineLength)
+            .attr('height', lineThickness)
+            .attr('transform', transform)
+            .style(
+              'stroke-dasharray',
+              '0, ' + (lineLength + lineThickness) + ', 0'
+            );
+        });
+    }
+  }
+  mainArc
+    .attr('transform', function(d) {
+      return !$$.isGaugeType(d.data) && withTransform ? 'scale(0)' : ''
+    })
+    .on(
+      'mouseover',
+      config.interaction_enabled
+        ? function(d) {
+            var updated, arcData;
+            if ($$.transiting) {
+              // skip while transiting
+              return
+            }
+            updated = $$.updateAngle(d);
+            if (updated) {
+              arcData = $$.convertToArcData(updated);
+              // transitions
+              $$.expandArc(updated.data.id);
+              $$.api.focus(updated.data.id);
+              $$.toggleFocusLegend(updated.data.id, true);
+              $$.config.data_onmouseover(arcData, this);
+            }
+          }
+        : null
+    )
+    .on(
+      'mousemove',
+      config.interaction_enabled
+        ? function(d) {
+            var updated = $$.updateAngle(d),
+              arcData,
+              selectedData;
+            if (updated) {
+(arcData = $$.convertToArcData(updated)),
+                (selectedData = [arcData]);
+              $$.showTooltip(selectedData, this);
+            }
+          }
+        : null
+    )
+    .on(
+      'mouseout',
+      config.interaction_enabled
+        ? function(d) {
+            var updated, arcData;
+            if ($$.transiting) {
+              // skip while transiting
+              return
+            }
+            updated = $$.updateAngle(d);
+            if (updated) {
+              arcData = $$.convertToArcData(updated);
+              // transitions
+              $$.unexpandArc(updated.data.id);
+              $$.api.revert();
+              $$.revertLegend();
+              $$.hideTooltip();
+              $$.config.data_onmouseout(arcData, this);
+            }
+          }
+        : null
+    )
+    .on(
+      'click',
+      config.interaction_enabled
+        ? function(d, i) {
+            var updated = $$.updateAngle(d),
+              arcData;
+            if (updated) {
+              arcData = $$.convertToArcData(updated);
+              if ($$.toggleShape) {
+                $$.toggleShape(this, arcData, i);
+              }
+              $$.config.data_onclick.call($$.api, arcData, this);
+            }
+          }
+        : null
+    )
+    .each(function() {
+      $$.transiting = true;
+    })
+    .transition()
+    .duration(duration)
+    .attrTween('d', function(d) {
+      var updated = $$.updateAngle(d),
+        interpolate;
+      if (!updated) {
+        return function() {
+          return 'M 0 0'
+        }
+      }
+      //                if (this._current === d) {
+      //                    this._current = {
+      //                        startAngle: Math.PI*2,
+      //                        endAngle: Math.PI*2,
+      //                    };
+      //                }
+      if (isNaN(this._current.startAngle)) {
+        this._current.startAngle = 0;
+      }
+      if (isNaN(this._current.endAngle)) {
+        this._current.endAngle = this._current.startAngle;
+      }
+      interpolate = d3.interpolate(this._current, updated);
+      this._current = interpolate(0);
+      return function(t) {
+        // prevents crashing the charts once in transition and chart.destroy() has been called
+        if ($$.config === null) {
+          return 'M 0 0'
+        }
+        var interpolated = interpolate(t);
+        interpolated.data = d.data; // data.id will be updated by interporator
+        return $$.getArc(interpolated, true)
+      }
+    })
+    .attr('transform', withTransform ? 'scale(1)' : '')
+    .style('fill', function(d) {
+      return $$.levelColor
+        ? $$.levelColor(
+            d.data.values.reduce(function(total, item) {
+              return total + item.value
+            }, 0)
+          )
+        : $$.color(d.data.id)
+    }) // Where gauge reading color would receive customization.
+    .call($$.endall, function() {
+      $$.transiting = false;
+    });
+  arcs
+    .exit()
+    .transition()
+    .duration(durationForExit)
+    .style('opacity', 0)
+    .remove();
+  main
+    .selectAll('.' + CLASS.chartArc)
+    .select('text')
+    .style('opacity', 0)
+    .attr('class', function(d) {
+      return $$.isGaugeType(d.data) ? CLASS.gaugeValue : ''
+    })
+    .text($$.textForArcLabel.bind($$))
+    .attr('transform', $$.transformForArcLabel.bind($$))
+    .style('font-size', function(d) {
+      return $$.isGaugeType(d.data) &&
+        $$.filterTargetsToShow($$.data.targets).length === 1
+        ? Math.round($$.radius / 5) + 'px'
+        : ''
+    })
+    .transition()
+    .duration(duration)
+    .style('opacity', function(d) {
+      return $$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? 1 : 0
+    });
+  main
+    .select('.' + CLASS.chartArcsTitle)
+    .style('opacity', $$.hasType('donut') || hasGaugeType ? 1 : 0);
+
+  if (hasGaugeType) {
+    let index = 0;
+    const backgroundArc = $$.arcs
+      .select('g.' + CLASS.chartArcsBackground)
+      .selectAll('path.' + CLASS.chartArcsBackground)
+      .data($$.data.targets);
+
+    backgroundArc
+      .enter()
+      .append('path')
+      .attr(
+        'class',
+        (d, i) =>
+          CLASS.chartArcsBackground + ' ' + CLASS.chartArcsBackground + '-' + i
+      )
+      .merge(backgroundArc)
+      .attr('d', d1 => {
+        if ($$.hiddenTargetIds.indexOf(d1.id) >= 0) {
+          return 'M 0 0'
+        }
+
+        var d = {
+          data: [{ value: config.gauge_max }],
+          startAngle: config.gauge_startingAngle,
+          endAngle:
+            -1 *
+            config.gauge_startingAngle *
+            (config.gauge_fullCircle ? Math.PI : 1),
+          index: index++
+        };
+        return $$.getArc(d, true, true)
+      });
+
+    backgroundArc.exit().remove();
+
+    $$.arcs
+      .select('.' + CLASS.chartArcsGaugeUnit)
+      .attr('dy', '.75em')
+      .text(config.gauge_label_show ? config.gauge_units : '');
+    $$.arcs
+      .select('.' + CLASS.chartArcsGaugeMin)
+      .attr(
+        'dx',
+        -1 *
+          ($$.innerRadius +
+            ($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2)) +
+          'px'
+      )
+      .attr('dy', '1.2em')
+      .text(
+        config.gauge_label_show
+          ? $$.textForGaugeMinMax(config.gauge_min, false)
+          : ''
+      );
+    $$.arcs
+      .select('.' + CLASS.chartArcsGaugeMax)
+      .attr(
+        'dx',
+        $$.innerRadius +
+          ($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2) +
+          'px'
+      )
+      .attr('dy', '1.2em')
+      .text(
+        config.gauge_label_show
+          ? $$.textForGaugeMinMax(config.gauge_max, true)
+          : ''
+      );
+  }
+};
+ChartInternal.prototype.initGauge = function() {
+  var arcs = this.arcs;
+  if (this.hasType('gauge')) {
+    arcs.append('g').attr('class', CLASS.chartArcsBackground);
+    arcs
+      .append('text')
+      .attr('class', CLASS.chartArcsGaugeUnit)
+      .style('text-anchor', 'middle')
+      .style('pointer-events', 'none');
+    arcs
+      .append('text')
+      .attr('class', CLASS.chartArcsGaugeMin)
+      .style('text-anchor', 'middle')
+      .style('pointer-events', 'none');
+    arcs
+      .append('text')
+      .attr('class', CLASS.chartArcsGaugeMax)
+      .style('text-anchor', 'middle')
+      .style('pointer-events', 'none');
+  }
+};
+ChartInternal.prototype.getGaugeLabelHeight = function() {
+  return this.config.gauge_label_show ? 20 : 0
+};
+
+/**
+ * Store value into cache
+ *
+ * @param key
+ * @param value
+ */
+ChartInternal.prototype.addToCache = function(key, value) {
+  this.cache[`$${key}`] = value;
+};
+
+/**
+ * Returns a cached value or undefined
+ *
+ * @param key
+ * @return {*}
+ */
+ChartInternal.prototype.getFromCache = function(key) {
+  return this.cache[`$${key}`]
+};
+
+/**
+ * Reset cached data
+ */
+ChartInternal.prototype.resetCache = function() {
+  Object.keys(this.cache)
+    .filter(key => /^\$/.test(key))
+    .forEach(key => {
+      delete this.cache[key];
+    });
+};
+
+// Old API that stores Targets
+
+ChartInternal.prototype.hasCaches = function(ids) {
+  for (var i = 0; i < ids.length; i++) {
+    if (!(ids[i] in this.cache)) {
+      return false
+    }
+  }
+  return true
+};
+ChartInternal.prototype.addCache = function(id, target) {
+  this.cache[id] = this.cloneTarget(target);
+};
+ChartInternal.prototype.getCaches = function(ids) {
+  var targets = [],
+    i;
+  for (i = 0; i < ids.length; i++) {
+    if (ids[i] in this.cache) {
+      targets.push(this.cloneTarget(this.cache[ids[i]]));
+    }
+  }
+  return targets
+};
+
+ChartInternal.prototype.categoryName = function(i) {
+  var config = this.config;
+  return i < config.axis_x_categories.length ? config.axis_x_categories[i] : i
+};
+
+ChartInternal.prototype.generateTargetClass = function(targetId) {
+  return targetId || targetId === 0 ? ('-' + targetId).replace(/\s/g, '-') : ''
+};
+ChartInternal.prototype.generateClass = function(prefix, targetId) {
+  return ' ' + prefix + ' ' + prefix + this.generateTargetClass(targetId)
+};
+ChartInternal.prototype.classText = function(d) {
+  return this.generateClass(CLASS.text, d.index)
+};
+ChartInternal.prototype.classTexts = function(d) {
+  return this.generateClass(CLASS.texts, d.id)
+};
+ChartInternal.prototype.classShape = function(d) {
+  return this.generateClass(CLASS.shape, d.index)
+};
+ChartInternal.prototype.classShapes = function(d) {
+  return this.generateClass(CLASS.shapes, d.id)
+};
+ChartInternal.prototype.classLine = function(d) {
+  return this.classShape(d) + this.generateClass(CLASS.line, d.id)
+};
+ChartInternal.prototype.classLines = function(d) {
+  return this.classShapes(d) + this.generateClass(CLASS.lines, d.id)
+};
+ChartInternal.prototype.classCircle = function(d) {
+  return this.classShape(d) + this.generateClass(CLASS.circle, d.index)
+};
+ChartInternal.prototype.classCircles = function(d) {
+  return this.classShapes(d) + this.generateClass(CLASS.circles, d.id)
+};
+ChartInternal.prototype.classBar = function(d) {
+  return this.classShape(d) + this.generateClass(CLASS.bar, d.index)
+};
+ChartInternal.prototype.classBars = function(d) {
+  return this.classShapes(d) + this.generateClass(CLASS.bars, d.id)
+};
+ChartInternal.prototype.classArc = function(d) {
+  return this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id)
+};
+ChartInternal.prototype.classArcs = function(d) {
+  return this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id)
+};
+ChartInternal.prototype.classArea = function(d) {
+  return this.classShape(d) + this.generateClass(CLASS.area, d.id)
+};
+ChartInternal.prototype.classAreas = function(d) {
+  return this.classShapes(d) + this.generateClass(CLASS.areas, d.id)
+};
+ChartInternal.prototype.classRegion = function(d, i) {
+  return (
+    this.generateClass(CLASS.region, i) + ' ' + ('class' in d ? d['class'] : '')
+  )
+};
+ChartInternal.prototype.classEvent = function(d) {
+  return this.generateClass(CLASS.eventRect, d.index)
+};
+ChartInternal.prototype.classTarget = function(id) {
+  var $$ = this;
+  var additionalClassSuffix = $$.config.data_classes[id],
+    additionalClass = '';
+  if (additionalClassSuffix) {
+    additionalClass = ' ' + CLASS.target + '-' + additionalClassSuffix;
+  }
+  return $$.generateClass(CLASS.target, id) + additionalClass
+};
+ChartInternal.prototype.classFocus = function(d) {
+  return this.classFocused(d) + this.classDefocused(d)
+};
+ChartInternal.prototype.classFocused = function(d) {
+  return ' ' + (this.focusedTargetIds.indexOf(d.id) >= 0 ? CLASS.focused : '')
+};
+ChartInternal.prototype.classDefocused = function(d) {
+  return (
+    ' ' + (this.defocusedTargetIds.indexOf(d.id) >= 0 ? CLASS.defocused : '')
+  )
+};
+ChartInternal.prototype.classChartText = function(d) {
+  return CLASS.chartText + this.classTarget(d.id)
+};
+ChartInternal.prototype.classChartLine = function(d) {
+  return CLASS.chartLine + this.classTarget(d.id)
+};
+ChartInternal.prototype.classChartBar = function(d) {
+  return CLASS.chartBar + this.classTarget(d.id)
+};
+ChartInternal.prototype.classChartArc = function(d) {
+  return CLASS.chartArc + this.classTarget(d.data.id)
+};
+ChartInternal.prototype.getTargetSelectorSuffix = function(targetId) {
+  const targetClass = this.generateTargetClass(targetId);
+  if (window.CSS && window.CSS.escape) {
+    return window.CSS.escape(targetClass)
+  }
+
+  // fallback on imperfect method for old browsers (does not handles unicode)
+  return targetClass.replace(/([?!@#$%^&*()=+,.<>'":;\[\]\/|~`{}\\])/g, '\\$1')
+};
+ChartInternal.prototype.selectorTarget = function(id, prefix) {
+  return (prefix || '') + '.' + CLASS.target + this.getTargetSelectorSuffix(id)
+};
+ChartInternal.prototype.selectorTargets = function(ids, prefix) {
+  var $$ = this;
+  ids = ids || [];
+  return ids.length
+    ? ids.map(function(id) {
+        return $$.selectorTarget(id, prefix)
+      })
+    : null
+};
+ChartInternal.prototype.selectorLegend = function(id) {
+  return '.' + CLASS.legendItem + this.getTargetSelectorSuffix(id)
+};
+ChartInternal.prototype.selectorLegends = function(ids) {
+  var $$ = this;
+  return ids && ids.length
+    ? ids.map(function(id) {
+        return $$.selectorLegend(id)
+      })
+    : null
+};
+
+ChartInternal.prototype.getClipPath = function(id) {
+  return 'url(' + (isIE(9) ? '' : document.URL.split('#')[0]) + '#' + id + ')'
+};
+ChartInternal.prototype.appendClip = function(parent, id) {
+  return parent
+    .append('clipPath')
+    .attr('id', id)
+    .append('rect')
+};
+ChartInternal.prototype.getAxisClipX = function(forHorizontal) {
+  // axis line width + padding for left
+  var left = Math.max(30, this.margin.left);
+  return forHorizontal ? -(1 + left) : -(left - 1)
+};
+ChartInternal.prototype.getAxisClipY = function(forHorizontal) {
+  return forHorizontal ? -20 : -this.margin.top
+};
+ChartInternal.prototype.getXAxisClipX = function() {
+  var $$ = this;
+  return $$.getAxisClipX(!$$.config.axis_rotated)
+};
+ChartInternal.prototype.getXAxisClipY = function() {
+  var $$ = this;
+  return $$.getAxisClipY(!$$.config.axis_rotated)
+};
+ChartInternal.prototype.getYAxisClipX = function() {
+  var $$ = this;
+  return $$.config.axis_y_inner ? -1 : $$.getAxisClipX($$.config.axis_rotated)
+};
+ChartInternal.prototype.getYAxisClipY = function() {
+  var $$ = this;
+  return $$.getAxisClipY($$.config.axis_rotated)
+};
+ChartInternal.prototype.getAxisClipWidth = function(forHorizontal) {
+  var $$ = this,
+    left = Math.max(30, $$.margin.left),
+    right = Math.max(30, $$.margin.right);
+  // width + axis line width + padding for left/right
+  return forHorizontal ? $$.width + 2 + left + right : $$.margin.left + 20
+};
+ChartInternal.prototype.getAxisClipHeight = function(forHorizontal) {
+  // less than 20 is not enough to show the axis label 'outer' without legend
+  return (
+    (forHorizontal ? this.margin.bottom : this.margin.top + this.height) + 20
+  )
+};
+ChartInternal.prototype.getXAxisClipWidth = function() {
+  var $$ = this;
+  return $$.getAxisClipWidth(!$$.config.axis_rotated)
+};
+ChartInternal.prototype.getXAxisClipHeight = function() {
+  var $$ = this;
+  return $$.getAxisClipHeight(!$$.config.axis_rotated)
+};
+ChartInternal.prototype.getYAxisClipWidth = function() {
+  var $$ = this;
+  return (
+    $$.getAxisClipWidth($$.config.axis_rotated) +
+    ($$.config.axis_y_inner ? 20 : 0)
+  )
+};
+ChartInternal.prototype.getYAxisClipHeight = function() {
+  var $$ = this;
+  return $$.getAxisClipHeight($$.config.axis_rotated)
+};
+
+ChartInternal.prototype.generateColor = function() {
+  var $$ = this,
+    config = $$.config,
+    d3 = $$.d3,
+    colors = config.data_colors,
+    pattern = notEmpty(config.color_pattern)
+      ? config.color_pattern
+      : d3.schemeCategory10,
+    callback = config.data_color,
+    ids = [];
+
+  return function(d) {
+    var id = d.id || (d.data && d.data.id) || d,
+      color;
+
+    // if callback function is provided
+    if (colors[id] instanceof Function) {
+      color = colors[id](d);
+    }
+    // if specified, choose that color
+    else if (colors[id]) {
+      color = colors[id];
+    }
+    // if not specified, choose from pattern
+    else {
+      if (ids.indexOf(id) < 0) {
+        ids.push(id);
+      }
+      color = pattern[ids.indexOf(id) % pattern.length];
+      colors[id] = color;
+    }
+    return callback instanceof Function ? callback(color, d) : color
+  }
+};
+ChartInternal.prototype.generateLevelColor = function() {
+  var $$ = this,
+    config = $$.config,
+    colors = config.color_pattern,
+    threshold = config.color_threshold,
+    asValue = threshold.unit === 'value',
+    values =
+      threshold.values && threshold.values.length ? threshold.values : [],
+    max = threshold.max || 100;
+  return notEmpty(threshold) && notEmpty(colors)
+    ? function(value) {
+        var i,
+          v,
+          color = colors[colors.length - 1];
+        for (i = 0; i < values.length; i++) {
+          v = asValue ? value : (value * 100) / max;
+          if (v < values[i]) {
+            color = colors[i];
+            break
+          }
+        }
+        return color
+      }
+    : null
+};
+
+ChartInternal.prototype.getDefaultConfig = function() {
+  var config = {
+    bindto: '#chart',
+    svg_classname: undefined,
+    size_width: undefined,
+    size_height: undefined,
+    padding_left: undefined,
+    padding_right: undefined,
+    padding_top: undefined,
+    padding_bottom: undefined,
+    resize_auto: true,
+    zoom_enabled: false,
+    zoom_initialRange: undefined,
+    zoom_type: 'scroll',
+    zoom_disableDefaultBehavior: false,
+    zoom_privileged: false,
+    zoom_rescale: false,
+    zoom_onzoom: function() {},
+    zoom_onzoomstart: function() {},
+    zoom_onzoomend: function() {},
+    zoom_x_min: undefined,
+    zoom_x_max: undefined,
+    interaction_brighten: true,
+    interaction_enabled: true,
+    onmouseover: function() {},
+    onmouseout: function() {},
+    onresize: function() {},
+    onresized: function() {},
+    oninit: function() {},
+    onrendered: function() {},
+    transition_duration: 350,
+    data_epochs: 'epochs',
+    data_x: undefined,
+    data_xs: {},
+    data_xFormat: '%Y-%m-%d',
+    data_xLocaltime: true,
+    data_xSort: true,
+    data_idConverter: function(id) {
+      return id
+    },
+    data_names: {},
+    data_classes: {},
+    data_groups: [],
+    data_axes: {},
+    data_type: undefined,
+    data_types: {},
+    data_labels: {},
+    data_order: 'desc',
+    data_regions: {},
+    data_color: undefined,
+    data_colors: {},
+    data_hide: false,
+    data_filter: undefined,
+    data_selection_enabled: false,
+    data_selection_grouped: false,
+    data_selection_isselectable: function() {
+      return true
+    },
+    data_selection_multiple: true,
+    data_selection_draggable: false,
+    data_stack_normalize: false,
+    data_onclick: function() {},
+    data_onmouseover: function() {},
+    data_onmouseout: function() {},
+    data_onselected: function() {},
+    data_onunselected: function() {},
+    data_url: undefined,
+    data_headers: undefined,
+    data_json: undefined,
+    data_rows: undefined,
+    data_columns: undefined,
+    data_mimeType: undefined,
+    data_keys: undefined,
+    // configuration for no plot-able data supplied.
+    data_empty_label_text: '',
+    // subchart
+    subchart_show: false,
+    subchart_size_height: 60,
+    subchart_axis_x_show: true,
+    subchart_onbrush: function() {},
+    // color
+    color_pattern: [],
+    color_threshold: {},
+    // legend
+    legend_show: true,
+    legend_hide: false,
+    legend_position: 'bottom',
+    legend_inset_anchor: 'top-left',
+    legend_inset_x: 10,
+    legend_inset_y: 0,
+    legend_inset_step: undefined,
+    legend_item_onclick: undefined,
+    legend_item_onmouseover: undefined,
+    legend_item_onmouseout: undefined,
+    legend_equally: false,
+    legend_padding: 0,
+    legend_item_tile_width: 10,
+    legend_item_tile_height: 10,
+    // axis
+    axis_rotated: false,
+    axis_x_show: true,
+    axis_x_type: 'indexed',
+    axis_x_localtime: true,
+    axis_x_categories: [],
+    axis_x_tick_centered: false,
+    axis_x_tick_format: undefined,
+    axis_x_tick_culling: {},
+    axis_x_tick_culling_max: 10,
+    axis_x_tick_count: undefined,
+    axis_x_tick_fit: true,
+    axis_x_tick_values: null,
+    axis_x_tick_rotate: 0,
+    axis_x_tick_outer: true,
+    axis_x_tick_multiline: true,
+    axis_x_tick_multilineMax: 0,
+    axis_x_tick_width: null,
+    axis_x_max: undefined,
+    axis_x_min: undefined,
+    axis_x_padding: {},
+    axis_x_height: undefined,
+    axis_x_selection: undefined,
+    axis_x_label: {},
+    axis_x_inner: undefined,
+    axis_y_show: true,
+    axis_y_type: 'linear',
+    axis_y_max: undefined,
+    axis_y_min: undefined,
+    axis_y_inverted: false,
+    axis_y_center: undefined,
+    axis_y_inner: undefined,
+    axis_y_label: {},
+    axis_y_tick_format: undefined,
+    axis_y_tick_outer: true,
+    axis_y_tick_values: null,
+    axis_y_tick_rotate: 0,
+    axis_y_tick_count: undefined,
+    axis_y_tick_time_type: undefined,
+    axis_y_tick_time_interval: undefined,
+    axis_y_padding: {},
+    axis_y_default: undefined,
+    axis_y2_show: false,
+    axis_y2_type: 'linear',
+    axis_y2_max: undefined,
+    axis_y2_min: undefined,
+    axis_y2_inverted: false,
+    axis_y2_center: undefined,
+    axis_y2_inner: undefined,
+    axis_y2_label: {},
+    axis_y2_tick_format: undefined,
+    axis_y2_tick_outer: true,
+    axis_y2_tick_values: null,
+    axis_y2_tick_count: undefined,
+    axis_y2_padding: {},
+    axis_y2_default: undefined,
+    // grid
+    grid_x_show: false,
+    grid_x_type: 'tick',
+    grid_x_lines: [],
+    grid_y_show: false,
+    // not used
+    // grid_y_type: 'tick',
+    grid_y_lines: [],
+    grid_y_ticks: 10,
+    grid_focus_show: true,
+    grid_lines_front: true,
+    // point - point of each data
+    point_show: true,
+    point_r: 2.5,
+    point_sensitivity: 10,
+    point_focus_expand_enabled: true,
+    point_focus_expand_r: undefined,
+    point_select_r: undefined,
+    // line
+    line_connectNull: false,
+    line_step_type: 'step',
+    // bar
+    bar_width: undefined,
+    bar_width_ratio: 0.6,
+    bar_width_max: undefined,
+    bar_zerobased: true,
+    bar_space: 0,
+    // area
+    area_zerobased: true,
+    area_above: false,
+    // pie
+    pie_label_show: true,
+    pie_label_format: undefined,
+    pie_label_threshold: 0.05,
+    pie_label_ratio: undefined,
+    pie_expand: {},
+    pie_expand_duration: 50,
+    pie_padAngle: 0,
+    // gauge
+    gauge_fullCircle: false,
+    gauge_label_show: true,
+    gauge_labelLine_show: true,
+    gauge_label_format: undefined,
+    gauge_min: 0,
+    gauge_max: 100,
+    gauge_startingAngle: (-1 * Math.PI) / 2,
+    gauge_label_extents: undefined,
+    gauge_units: undefined,
+    gauge_width: undefined,
+    gauge_arcs_minWidth: 5,
+    gauge_expand: {},
+    gauge_expand_duration: 50,
+    // donut
+    donut_label_show: true,
+    donut_label_format: undefined,
+    donut_label_threshold: 0.05,
+    donut_label_ratio: undefined,
+    donut_width: undefined,
+    donut_title: '',
+    donut_expand: {},
+    donut_expand_duration: 50,
+    donut_padAngle: 0,
+    // spline
+    spline_interpolation_type: 'cardinal',
+    // stanford
+    stanford_lines: [],
+    stanford_regions: [],
+    stanford_texts: [],
+    stanford_scaleMin: undefined,
+    stanford_scaleMax: undefined,
+    stanford_scaleWidth: undefined,
+    stanford_scaleFormat: undefined,
+    stanford_scaleValues: undefined,
+    stanford_colors: undefined,
+    stanford_padding: {
+      top: 0,
+      right: 0,
+      bottom: 0,
+      left: 0
+    },
+    // region - region to change style
+    regions: [],
+    // tooltip - show when mouseover on each data
+    tooltip_show: true,
+    tooltip_grouped: true,
+    tooltip_order: undefined,
+    tooltip_format_title: undefined,
+    tooltip_format_name: undefined,
+    tooltip_format_value: undefined,
+    tooltip_horizontal: undefined,
+    tooltip_position: undefined,
+    tooltip_contents: function(
+      d,
+      defaultTitleFormat,
+      defaultValueFormat,
+      color
+    ) {
+      return this.getTooltipContent
+        ? this.getTooltipContent(
+            d,
+            defaultTitleFormat,
+            defaultValueFormat,
+            color
+          )
+        : ''
+    },
+    tooltip_init_show: false,
+    tooltip_init_x: 0,
+    tooltip_init_position: { top: '0px', left: '50px' },
+    tooltip_onshow: function() {},
+    tooltip_onhide: function() {},
+    // title
+    title_text: undefined,
+    title_padding: {
+      top: 0,
+      right: 0,
+      bottom: 0,
+      left: 0
+    },
+    title_position: 'top-center'
+  };
+
+  Object.keys(this.additionalConfig).forEach(function(key) {
+    config[key] = this.additionalConfig[key];
+  }, this);
+
+  return config
+};
+ChartInternal.prototype.additionalConfig = {};
+
+ChartInternal.prototype.loadConfig = function(config) {
+  var this_config = this.config,
+    target,
+    keys,
+    read;
+  function find() {
+    var key = keys.shift();
+    //        console.log("key =>", key, ", target =>", target);
+    if (key && target && typeof target === 'object' && key in target) {
+      target = target[key];
+      return find()
+    } else if (!key) {
+      return target
+    } else {
+      return undefined
+    }
+  }
+  Object.keys(this_config).forEach(function(key) {
+    target = config;
+    keys = key.split('_');
+    read = find();
+    //        console.log("CONFIG : ", key, read);
+    if (isDefined(read)) {
+      this_config[key] = read;
+    }
+  });
+};
+
+ChartInternal.prototype.convertUrlToData = function(
+  url,
+  mimeType,
+  headers,
+  keys,
+  done
+) {
+  var $$ = this,
+    type = mimeType ? mimeType : 'csv',
+    f,
+    converter;
+
+  if (type === 'json') {
+    f = $$.d3.json;
+    converter = $$.convertJsonToData;
+  } else if (type === 'tsv') {
+    f = $$.d3.tsv;
+    converter = $$.convertXsvToData;
+  } else {
+    f = $$.d3.csv;
+    converter = $$.convertXsvToData;
+  }
+
+  f(url, headers)
+    .then(function(data) {
+      done.call($$, converter.call($$, data, keys));
+    })
+    .catch(function(error) {
+      throw error
+    });
+};
+ChartInternal.prototype.convertXsvToData = function(xsv) {
+  var keys = xsv.columns,
+    rows = xsv;
+  if (rows.length === 0) {
+    return {
+      keys,
+      rows: [keys.reduce((row, key) => Object.assign(row, { [key]: null }), {})]
+    }
+  } else {
+    // [].concat() is to convert result into a plain array otherwise
+    // test is not happy because rows have properties.
+    return { keys, rows: [].concat(xsv) }
+  }
+};
+ChartInternal.prototype.convertJsonToData = function(json, keys) {
+  var $$ = this,
+    new_rows = [],
+    targetKeys,
+    data;
+  if (keys) {
+    // when keys specified, json would be an array that includes objects
+    if (keys.x) {
+      targetKeys = keys.value.concat(keys.x);
+      $$.config.data_x = keys.x;
+    } else {
+      targetKeys = keys.value;
+    }
+    new_rows.push(targetKeys);
+    json.forEach(function(o) {
+      var new_row = [];
+      targetKeys.forEach(function(key) {
+        // convert undefined to null because undefined data will be removed in convertDataToTargets()
+        var v = $$.findValueInJson(o, key);
+        if (isUndefined(v)) {
+          v = null;
+        }
+        new_row.push(v);
+      });
+      new_rows.push(new_row);
+    });
+    data = $$.convertRowsToData(new_rows);
+  } else {
+    Object.keys(json).forEach(function(key) {
+      new_rows.push([key].concat(json[key]));
+    });
+    data = $$.convertColumnsToData(new_rows);
+  }
+  return data
+};
+/**
+ * Finds value from the given nested object by the given path.
+ * If it's not found, then this returns undefined.
+ * @param {Object} object the object
+ * @param {string} path the path
+ */
+ChartInternal.prototype.findValueInJson = function(object, path) {
+  if (path in object) {
+    // If object has a key that contains . or [], return the key's value
+    // instead of searching for an inner object.
+    // See https://github.com/c3js/c3/issues/1691 for details.
+    return object[path]
+  }
+
+  path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties (replace [] with .)
+  path = path.replace(/^\./, ''); // strip a leading dot
+  var pathArray = path.split('.');
+  for (var i = 0; i < pathArray.length; ++i) {
+    var k = pathArray[i];
+    if (k in object) {
+      object = object[k];
+    } else {
+      return
+    }
+  }
+  return object
+};
+
+/**
+ * Converts the rows to normalized data.
+ * @param {any[][]} rows The row data
+ * @return {Object}
+ */
+ChartInternal.prototype.convertRowsToData = rows => {
+  const newRows = [];
+  const keys = rows[0];
+
+  for (let i = 1; i < rows.length; i++) {
+    const newRow = {};
+    for (let j = 0; j < rows[i].length; j++) {
+      if (isUndefined(rows[i][j])) {
+        throw new Error(
+          'Source data is missing a component at (' + i + ',' + j + ')!'
+        )
+      }
+      newRow[keys[j]] = rows[i][j];
+    }
+    newRows.push(newRow);
+  }
+  return { keys, rows: newRows }
+};
+
+/**
+ * Converts the columns to normalized data.
+ * @param {any[][]} columns The column data
+ * @return {Object}
+ */
+ChartInternal.prototype.convertColumnsToData = columns => {
+  const newRows = [];
+  const keys = [];
+
+  for (let i = 0; i < columns.length; i++) {
+    const key = columns[i][0];
+    for (let j = 1; j < columns[i].length; j++) {
+      if (isUndefined(newRows[j - 1])) {
+        newRows[j - 1] = {};
+      }
+      if (isUndefined(columns[i][j])) {
+        throw new Error(
+          'Source data is missing a component at (' + i + ',' + j + ')!'
+        )
+      }
+      newRows[j - 1][key] = columns[i][j];
+    }
+    keys.push(key);
+  }
+
+  return { keys, rows: newRows }
+};
+
+/**
+ * Converts the data format into the target format.
+ * @param {!Object} data
+ * @param {!Array} data.keys Ordered list of target IDs.
+ * @param {!Array} data.rows Rows of data to convert.
+ * @param {boolean} appendXs True to append to $$.data.xs, False to replace.
+ * @return {!Array}
+ */
+ChartInternal.prototype.convertDataToTargets = function(data, appendXs) {
+  var $$ = this,
+    config = $$.config,
+    targets,
+    ids,
+    xs,
+    keys,
+    epochs;
+
+  // handles format where keys are not orderly provided
+  if (isArray(data)) {
+    keys = Object.keys(data[0]);
+  } else {
+    keys = data.keys;
+    data = data.rows;
+  }
+
+  xs = keys.filter($$.isX, $$);
+
+  if (!$$.isStanfordGraphType()) {
+    ids = keys.filter($$.isNotX, $$);
+  } else {
+    epochs = keys.filter($$.isEpochs, $$);
+    ids = keys.filter($$.isNotXAndNotEpochs, $$);
+
+    if (xs.length !== 1 || epochs.length !== 1 || ids.length !== 1) {
+      throw new Error(
+        "You must define the 'x' key name and the 'epochs' for Stanford Diagrams"
+      )
+    }
+  }
+
+  // save x for update data by load when custom x and c3.x API
+  ids.forEach(function(id) {
+    var xKey = $$.getXKey(id);
+
+    if ($$.isCustomX() || $$.isTimeSeries()) {
+      // if included in input data
+      if (xs.indexOf(xKey) >= 0) {
+        $$.data.xs[id] = (appendXs && $$.data.xs[id]
+          ? $$.data.xs[id]
+          : []
+        ).concat(
+          data
+            .map(function(d) {
+              return d[xKey]
+            })
+            .filter(isValue)
+            .map(function(rawX, i) {
+              return $$.generateTargetX(rawX, id, i)
+            })
+        );
+      }
+      // if not included in input data, find from preloaded data of other id's x
+      else if (config.data_x) {
+        $$.data.xs[id] = $$.getOtherTargetXs();
+      }
+      // if not included in input data, find from preloaded data
+      else if (notEmpty(config.data_xs)) {
+        $$.data.xs[id] = $$.getXValuesOfXKey(xKey, $$.data.targets);
+      }
+      // MEMO: if no x included, use same x of current will be used
+    } else {
+      $$.data.xs[id] = data.map(function(d, i) {
+        return i
+      });
+    }
+  });
+
+  // check x is defined
+  ids.forEach(function(id) {
+    if (!$$.data.xs[id]) {
+      throw new Error('x is not defined for id = "' + id + '".')
+    }
+  });
+
+  // convert to target
+  targets = ids.map(function(id, index) {
+    var convertedId = config.data_idConverter(id);
+    return {
+      id: convertedId,
+      id_org: id,
+      values: data
+        .map(function(d, i) {
+          var xKey = $$.getXKey(id),
+            rawX = d[xKey],
+            value = d[id] !== null && !isNaN(d[id]) ? +d[id] : null,
+            x,
+            returnData;
+          // use x as categories if custom x and categorized
+          if ($$.isCustomX() && $$.isCategorized() && !isUndefined(rawX)) {
+            if (index === 0 && i === 0) {
+              config.axis_x_categories = [];
+            }
+            x = config.axis_x_categories.indexOf(rawX);
+            if (x === -1) {
+              x = config.axis_x_categories.length;
+              config.axis_x_categories.push(rawX);
+            }
+          } else {
+            x = $$.generateTargetX(rawX, id, i);
+          }
+          // mark as x = undefined if value is undefined and filter to remove after mapped
+          if (isUndefined(d[id]) || $$.data.xs[id].length <= i) {
+            x = undefined;
+          }
+
+          returnData = { x: x, value: value, id: convertedId };
+
+          if ($$.isStanfordGraphType()) {
+            returnData.epochs = d[epochs];
+          }
+
+          return returnData
+        })
+        .filter(function(v) {
+          return isDefined(v.x)
+        })
+    }
+  });
+
+  // finish targets
+  targets.forEach(function(t) {
+    var i;
+    // sort values by its x
+    if (config.data_xSort) {
+      t.values = t.values.sort(function(v1, v2) {
+        var x1 = v1.x || v1.x === 0 ? v1.x : Infinity,
+          x2 = v2.x || v2.x === 0 ? v2.x : Infinity;
+        return x1 - x2
+      });
+    }
+    // indexing each value
+    i = 0;
+    t.values.forEach(function(v) {
+      v.index = i++;
+    });
+    // this needs to be sorted because its index and value.index is identical
+    $$.data.xs[t.id].sort(function(v1, v2) {
+      return v1 - v2
+    });
+  });
+
+  // cache information about values
+  $$.hasNegativeValue = $$.hasNegativeValueInTargets(targets);
+  $$.hasPositiveValue = $$.hasPositiveValueInTargets(targets);
+
+  // set target types
+  if (config.data_type) {
+    $$.setTargetType(
+      $$.mapToIds(targets).filter(function(id) {
+        return !(id in config.data_types)
+      }),
+      config.data_type
+    );
+  }
+
+  // cache as original id keyed
+  targets.forEach(function(d) {
+    $$.addCache(d.id_org, d);
+  });
+
+  return targets
+};
+
+ChartInternal.prototype.isEpochs = function(key) {
+  var $$ = this,
+    config = $$.config;
+  return config.data_epochs && key === config.data_epochs
+};
+ChartInternal.prototype.isX = function(key) {
+  var $$ = this,
+    config = $$.config;
+  return (
+    (config.data_x && key === config.data_x) ||
+    (notEmpty(config.data_xs) && hasValue(config.data_xs, key))
+  )
+};
+ChartInternal.prototype.isNotX = function(key) {
+  return !this.isX(key)
+};
+ChartInternal.prototype.isNotXAndNotEpochs = function(key) {
+  return !this.isX(key) && !this.isEpochs(key)
+};
+
+/**
+ * Returns whether the normalized stack option is enabled or not.
+ *
+ * To be enabled it must also have data.groups defined.
+ *
+ * @return {boolean}
+ */
+ChartInternal.prototype.isStackNormalized = function() {
+  return this.config.data_stack_normalize && this.config.data_groups.length > 0
+};
+
+/**
+ * Returns whether the axis is normalized or not.
+ *
+ * An axis is normalized as long as one of its associated target
+ * is normalized.
+ *
+ * @param axisId Axis ID (y or y2)
+ * @return {Boolean}
+ */
+ChartInternal.prototype.isAxisNormalized = function(axisId) {
+  const $$ = this;
+
+  if (!$$.isStackNormalized()) {
+    // shortcut
+    return false
+  }
+
+  return $$.data.targets
+    .filter(target => $$.axis.getId(target.id) === axisId)
+    .some(target => $$.isTargetNormalized(target.id))
+};
+
+/**
+ * Returns whether the values for this target ID is normalized or not.
+ *
+ * To be normalized the option needs to be enabled and target needs
+ * to be defined in `data.groups`.
+ *
+ * @param targetId ID of the target
+ * @return {Boolean} True if the target is normalized, false otherwise.
+ */
+ChartInternal.prototype.isTargetNormalized = function(targetId) {
+  const $$ = this;
+
+  return (
+    $$.isStackNormalized() &&
+    $$.config.data_groups.some(group => group.includes(targetId))
+  )
+};
+
+ChartInternal.prototype.getXKey = function(id) {
+  var $$ = this,
+    config = $$.config;
+  return config.data_x
+    ? config.data_x
+    : notEmpty(config.data_xs)
+    ? config.data_xs[id]
+    : null
+};
+
+/**
+ * Get sum of visible data per index for given axis.
+ *
+ * Expect axisId to be either 'y' or 'y2'.
+ *
+ * @private
+ * @param axisId Compute sum for data associated to given axis.
+ * @return {Array}
+ */
+ChartInternal.prototype.getTotalPerIndex = function(axisId) {
+  const $$ = this;
+
+  if (!$$.isStackNormalized()) {
+    return null
+  }
+
+  const cached = $$.getFromCache('getTotalPerIndex');
+  if (cached !== undefined) {
+    return cached[axisId]
+  }
+
+  const sum = { y: [], y2: [] };
+
+  $$.data.targets
+    // keep only target that are normalized
+    .filter(target => $$.isTargetNormalized(target.id))
+
+    // keep only target that are visible
+    .filter(target => $$.isTargetToShow(target.id))
+
+    // compute sum per axis
+    .forEach(target => {
+      const sumByAxis = sum[$$.axis.getId(target.id)];
+
+      target.values.forEach((v, i) => {
+        if (!sumByAxis[i]) {
+          sumByAxis[i] = 0;
+        }
+        sumByAxis[i] += isNumber(v.value) ? v.value : 0;
+      });
+    });
+
+  $$.addToCache('getTotalPerIndex', sum);
+
+  return sum[axisId]
+};
+
+/**
+ * Get sum of visible data.
+ *
+ * Should be used for normalised data only since all values
+ * are expected to be positive.
+ *
+ * @private
+ * @return {Number}
+ */
+ChartInternal.prototype.getTotalDataSum = function() {
+  const $$ = this;
+
+  const cached = $$.getFromCache('getTotalDataSum');
+  if (cached !== undefined) {
+    return cached
+  }
+
+  const totalDataSum = flattenArray(
+    $$.data.targets
+      .filter(target => $$.isTargetToShow(target.id))
+      .map(target => target.values)
+  )
+    .map(d => d.value)
+    .reduce((p, c) => p + c, 0);
+
+  $$.addToCache('getTotalDataSum', totalDataSum);
+
+  return totalDataSum
+};
+
+ChartInternal.prototype.getXValuesOfXKey = function(key, targets) {
+  var $$ = this,
+    xValues,
+    ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : [];
+  ids.forEach(function(id) {
+    if ($$.getXKey(id) === key) {
+      xValues = $$.data.xs[id];
+    }
+  });
+  return xValues
+};
+ChartInternal.prototype.getXValue = function(id, i) {
+  var $$ = this;
+  return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i])
+    ? $$.data.xs[id][i]
+    : i
+};
+ChartInternal.prototype.getOtherTargetXs = function() {
+  var $$ = this,
+    idsForX = Object.keys($$.data.xs);
+  return idsForX.length ? $$.data.xs[idsForX[0]] : null
+};
+ChartInternal.prototype.getOtherTargetX = function(index) {
+  var xs = this.getOtherTargetXs();
+  return xs && index < xs.length ? xs[index] : null
+};
+ChartInternal.prototype.addXs = function(xs) {
+  var $$ = this;
+  Object.keys(xs).forEach(function(id) {
+    $$.config.data_xs[id] = xs[id];
+  });
+};
+ChartInternal.prototype.addName = function(data) {
+  var $$ = this,
+    name;
+  if (data) {
+    name = $$.config.data_names[data.id];
+    data.name = name !== undefined ? name : data.id;
+  }
+  return data
+};
+ChartInternal.prototype.getValueOnIndex = function(values, index) {
+  var valueOnIndex = values.filter(function(v) {
+    return v.index === index
+  });
+  return valueOnIndex.length ? valueOnIndex[0] : null
+};
+ChartInternal.prototype.updateTargetX = function(targets, x) {
+  var $$ = this;
+  targets.forEach(function(t) {
+    t.values.forEach(function(v, i) {
+      v.x = $$.generateTargetX(x[i], t.id, i);
+    });
+    $$.data.xs[t.id] = x;
+  });
+};
+ChartInternal.prototype.updateTargetXs = function(targets, xs) {
+  var $$ = this;
+  targets.forEach(function(t) {
+    if (xs[t.id]) {
+      $$.updateTargetX([t], xs[t.id]);
+    }
+  });
+};
+ChartInternal.prototype.generateTargetX = function(rawX, id, index) {
+  var $$ = this,
+    x;
+  if ($$.isTimeSeries()) {
+    x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index));
+  } else if ($$.isCustomX() && !$$.isCategorized()) {
+    x = isValue(rawX) ? +rawX : $$.getXValue(id, index);
+  } else {
+    x = index;
+  }
+  return x
+};
+ChartInternal.prototype.cloneTarget = function(target) {
+  return {
+    id: target.id,
+    id_org: target.id_org,
+    values: target.values.map(function(d) {
+      return {
+        x: d.x,
+        value: d.value,
+        id: d.id
+      }
+    })
+  }
+};
+ChartInternal.prototype.getMaxDataCount = function() {
+  var $$ = this;
+  return $$.d3.max($$.data.targets, function(t) {
+    return t.values.length
+  })
+};
+ChartInternal.prototype.mapToIds = function(targets) {
+  return targets.map(function(d) {
+    return d.id
+  })
+};
+ChartInternal.prototype.mapToTargetIds = function(ids) {
+  var $$ = this;
+  return ids ? [].concat(ids) : $$.mapToIds($$.data.targets)
+};
+ChartInternal.prototype.hasTarget = function(targets, id) {
+  var ids = this.mapToIds(targets),
+    i;
+  for (i = 0; i < ids.length; i++) {
+    if (ids[i] === id) {
+      return true
+    }
+  }
+  return false
+};
+ChartInternal.prototype.isTargetToShow = function(targetId) {
+  return this.hiddenTargetIds.indexOf(targetId) < 0
+};
+ChartInternal.prototype.isLegendToShow = function(targetId) {
+  return this.hiddenLegendIds.indexOf(targetId) < 0
+};
+
+/**
+ * Returns only visible targets.
+ *
+ * This is the same as calling {@link filterTargetsToShow} on $$.data.targets.
+ *
+ * @return {Array}
+ */
+ChartInternal.prototype.getTargetsToShow = function() {
+  const $$ = this;
+  return $$.filterTargetsToShow($$.data.targets)
+};
+
+ChartInternal.prototype.filterTargetsToShow = function(targets) {
+  var $$ = this;
+  return targets.filter(function(t) {
+    return $$.isTargetToShow(t.id)
+  })
+};
+
+/**
+ * @return {Array} Returns all the targets attached to the chart, visible or not
+ */
+ChartInternal.prototype.getTargets = function() {
+  const $$ = this;
+  return $$.data.targets
+};
+
+ChartInternal.prototype.mapTargetsToUniqueXs = function(targets) {
+  var $$ = this;
+  var xs = $$.d3
+    .set(
+      $$.d3.merge(
+        targets.map(function(t) {
+          return t.values.map(function(v) {
+            return +v.x
+          })
+        })
+      )
+    )
+    .values();
+  xs = $$.isTimeSeries()
+    ? xs.map(function(x) {
+        return new Date(+x)
+      })
+    : xs.map(function(x) {
+        return +x
+      });
+  return xs.sort(function(a, b) {
+    return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN
+  })
+};
+ChartInternal.prototype.addHiddenTargetIds = function(targetIds) {
+  targetIds = targetIds instanceof Array ? targetIds : new Array(targetIds);
+  for (var i = 0; i < targetIds.length; i++) {
+    if (this.hiddenTargetIds.indexOf(targetIds[i]) < 0) {
+      this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds[i]);
+    }
+  }
+  this.resetCache();
+};
+ChartInternal.prototype.removeHiddenTargetIds = function(targetIds) {
+  this.hiddenTargetIds = this.hiddenTargetIds.filter(function(id) {
+    return targetIds.indexOf(id) < 0
+  });
+  this.resetCache();
+};
+ChartInternal.prototype.addHiddenLegendIds = function(targetIds) {
+  targetIds = targetIds instanceof Array ? targetIds : new Array(targetIds);
+  for (var i = 0; i < targetIds.length; i++) {
+    if (this.hiddenLegendIds.indexOf(targetIds[i]) < 0) {
+      this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds[i]);
+    }
+  }
+};
+ChartInternal.prototype.removeHiddenLegendIds = function(targetIds) {
+  this.hiddenLegendIds = this.hiddenLegendIds.filter(function(id) {
+    return targetIds.indexOf(id) < 0
+  });
+};
+ChartInternal.prototype.getValuesAsIdKeyed = function(targets) {
+  var ys = {};
+  targets.forEach(function(t) {
+    ys[t.id] = [];
+    t.values.forEach(function(v) {
+      ys[t.id].push(v.value);
+    });
+  });
+  return ys
+};
+ChartInternal.prototype.checkValueInTargets = function(targets, checker) {
+  var ids = Object.keys(targets),
+    i,
+    j,
+    values;
+  for (i = 0; i < ids.length; i++) {
+    values = targets[ids[i]].values;
+    for (j = 0; j < values.length; j++) {
+      if (checker(values[j].value)) {
+        return true
+      }
+    }
+  }
+  return false
+};
+ChartInternal.prototype.hasNegativeValueInTargets = function(targets) {
+  return this.checkValueInTargets(targets, function(v) {
+    return v < 0
+  })
+};
+ChartInternal.prototype.hasPositiveValueInTargets = function(targets) {
+  return this.checkValueInTargets(targets, function(v) {
+    return v > 0
+  })
+};
+ChartInternal.prototype.isOrderDesc = function() {
+  var config = this.config;
+  return (
+    typeof config.data_order === 'string' &&
+    config.data_order.toLowerCase() === 'desc'
+  )
+};
+ChartInternal.prototype.isOrderAsc = function() {
+  var config = this.config;
+  return (
+    typeof config.data_order === 'string' &&
+    config.data_order.toLowerCase() === 'asc'
+  )
+};
+ChartInternal.prototype.getOrderFunction = function() {
+  var $$ = this,
+    config = $$.config,
+    orderAsc = $$.isOrderAsc(),
+    orderDesc = $$.isOrderDesc();
+  if (orderAsc || orderDesc) {
+    var reducer = function(p, c) {
+      return p + Math.abs(c.value)
+    };
+    return function(t1, t2) {
+      var t1Sum = t1.values.reduce(reducer, 0),
+        t2Sum = t2.values.reduce(reducer, 0);
+      return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum
+    }
+  } else if (isFunction(config.data_order)) {
+    return config.data_order
+  } else if (isArray(config.data_order)) {
+    var order = config.data_order;
+    return function(t1, t2) {
+      return order.indexOf(t1.id) - order.indexOf(t2.id)
+    }
+  }
+};
+ChartInternal.prototype.orderTargets = function(targets) {
+  var fct = this.getOrderFunction();
+  if (fct) {
+    targets.sort(fct);
+  }
+  return targets
+};
+
+/**
+ * Returns all the values from the given targets at the given index.
+ *
+ * @param {Array} targets
+ * @param {Number} index
+ * @return {Array}
+ */
+ChartInternal.prototype.filterByIndex = function(targets, index) {
+  return this.d3.merge(
+    targets.map(t => t.values.filter(v => v.index === index))
+  )
+};
+
+ChartInternal.prototype.filterByX = function(targets, x) {
+  return this.d3
+    .merge(
+      targets.map(function(t) {
+        return t.values
+      })
+    )
+    .filter(function(v) {
+      return v.x - x === 0
+    })
+};
+ChartInternal.prototype.filterRemoveNull = function(data) {
+  return data.filter(function(d) {
+    return isValue(d.value)
+  })
+};
+ChartInternal.prototype.filterByXDomain = function(targets, xDomain) {
+  return targets.map(function(t) {
+    return {
+      id: t.id,
+      id_org: t.id_org,
+      values: t.values.filter(function(v) {
+        return xDomain[0] <= v.x && v.x <= xDomain[1]
+      })
+    }
+  })
+};
+ChartInternal.prototype.hasDataLabel = function() {
+  var config = this.config;
+  if (typeof config.data_labels === 'boolean' && config.data_labels) {
+    return true
+  } else if (
+    typeof config.data_labels === 'object' &&
+    notEmpty(config.data_labels)
+  ) {
+    return true
+  }
+  return false
+};
+ChartInternal.prototype.getDataLabelLength = function(min, max, key) {
+  var $$ = this,
+    lengths = [0, 0],
+    paddingCoef = 1.3;
+  $$.selectChart
+    .select('svg')
+    .selectAll('.dummy')
+    .data([min, max])
+    .enter()
+    .append('text')
+    .text(function(d) {
+      return $$.dataLabelFormat(d.id)(d)
+    })
+    .each(function(d, i) {
+      lengths[i] = getBBox(this)[key] * paddingCoef;
+    })
+    .remove();
+  return lengths
+};
+/**
+ * Returns true if the given data point is not arc type, otherwise false.
+ * @param {Object} d The data point
+ * @return {boolean}
+ */
+ChartInternal.prototype.isNoneArc = function(d) {
+  return this.hasTarget(this.data.targets, d.id)
+};
+
+/**
+ * Returns true if the given data point is arc type, otherwise false.
+ * @param {Object} d The data point
+ * @return {boolean}
+ */
+ChartInternal.prototype.isArc = function(d) {
+  return 'data' in d && this.hasTarget(this.data.targets, d.data.id)
+};
+
+/**
+ * Find the closest point from the given pos among the given targets or
+ * undefined if none satisfies conditions.
+ *
+ * @param {Array} targets
+ * @param {Array} pos An [x,y] coordinate
+ * @return {Object|undefined}
+ */
+ChartInternal.prototype.findClosestFromTargets = function(targets, pos) {
+  const $$ = this;
+
+  // for each target, find the closest point
+  const candidates = targets
+    .map(t =>
+      $$.findClosest(
+        t.values,
+        pos,
+        $$.config.tooltip_horizontal
+          ? $$.horizontalDistance.bind($$)
+          : $$.dist.bind($$),
+        $$.config.point_sensitivity
+      )
+    )
+    .filter(v => v);
+
+  // returns the closest of candidates
+  if (candidates.length === 0) {
+    return undefined
+  } else if (candidates.length === 1) {
+    return candidates[0]
+  } else {
+    return $$.findClosest(candidates, pos, $$.dist.bind($$))
+  }
+};
+
+/**
+ * Find the closest point from the x value or undefined if none satisfies conditions.
+ *
+ * @param {Array} targets
+ * @param {Array} x A value on X axis
+ * @return {Object|undefined}
+ */
+ChartInternal.prototype.findClosestFromTargetsByX = function(targets, x) {
+  let closest;
+  let diff;
+
+  targets.forEach(t => {
+    t.values.forEach(d => {
+      let newDiff = Math.abs(x - d.x);
+
+      if (diff === undefined || newDiff < diff) {
+        closest = d;
+        diff = newDiff;
+      }
+    });
+  });
+
+  return closest
+};
+
+/**
+ * Using given compute distance method, returns the closest data point from the
+ * given position.
+ *
+ * Giving optionally a minimum distance to satisfy.
+ *
+ * @param {Array} dataPoints List of DataPoints
+ * @param {Array} pos An [x,y] coordinate
+ * @param {Function} computeDist Function to compute distance between 2 points
+ * @param {Number} minDist Minimal distance to satisfy
+ * @return {Object|undefined} Closest data point
+ */
+ChartInternal.prototype.findClosest = function(
+  dataPoints,
+  pos,
+  computeDist,
+  minDist = Infinity
+) {
+  const $$ = this;
+
+  let closest;
+
+  // find closest bar
+  dataPoints
+    .filter(v => v && $$.isBarType(v.id))
+    .forEach(function(v) {
+      if (!closest) {
+        const shape = $$.main
+          .select(
+            '.' +
+              CLASS.bars +
+              $$.getTargetSelectorSuffix(v.id) +
+              ' .' +
+              CLASS.bar +
+              '-' +
+              v.index
+          )
+          .node();
+        if ($$.isWithinBar(pos, shape)) {
+          closest = v;
+        }
+      }
+    });
+
+  // find closest point from non-bar
+  dataPoints
+    .filter(v => v && !$$.isBarType(v.id))
+    .forEach(v => {
+      let d = computeDist(v, pos);
+      if (d < minDist) {
+        minDist = d;
+        closest = v;
+      }
+    });
+
+  return closest
+};
+ChartInternal.prototype.dist = function(data, pos) {
+  var $$ = this,
+    config = $$.config,
+    xIndex = config.axis_rotated ? 1 : 0,
+    yIndex = config.axis_rotated ? 0 : 1,
+    y = $$.circleY(data, data.index),
+    x = $$.x(data.x);
+  return Math.sqrt(Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2))
+};
+ChartInternal.prototype.horizontalDistance = function(data, pos) {
+  var $$ = this,
+    config = $$.config,
+    xIndex = config.axis_rotated ? 1 : 0,
+    x = $$.x(data.x);
+
+  return Math.abs(x - pos[xIndex])
+};
+ChartInternal.prototype.convertValuesToStep = function(values) {
+  var converted = [].concat(values),
+    i;
+
+  if (!this.isCategorized()) {
+    return values
+  }
+
+  for (i = values.length + 1; 0 < i; i--) {
+    converted[i] = converted[i - 1];
+  }
+
+  converted[0] = {
+    x: converted[0].x - 1,
+    value: converted[0].value,
+    id: converted[0].id
+  };
+  converted[values.length + 1] = {
+    x: converted[values.length].x + 1,
+    value: converted[values.length].value,
+    id: converted[values.length].id
+  };
+
+  return converted
+};
+
+/**
+ * Get ratio value
+ *
+ * @param {String} type Ratio for given type
+ * @param {Object} d Data value object
+ * @param {Boolean} asPercent Convert the return as percent or not
+ * @return {Number} Ratio value
+ * @private
+ */
+ChartInternal.prototype.getRatio = function(type, d, asPercent = false) {
+  const $$ = this;
+  const api = $$.api;
+  let ratio = 0;
+
+  if (d && api.data.shown.call(api).length) {
+    ratio = d.ratio || d.value;
+
+    if (type === 'arc') {
+      if ($$.hasType('gauge')) {
+        ratio =
+          (d.endAngle - d.startAngle) /
+          (Math.PI * ($$.config.gauge_fullCircle ? 2 : 1));
+      } else {
+        const total = $$.getTotalDataSum();
+
+        ratio = d.value / total;
+      }
+    } else if (type === 'index') {
+      const total = $$.getTotalPerIndex($$.axis.getId(d.id));
+
+      d.ratio =
+        isNumber(d.value) && total && total[d.index] > 0
+          ? d.value / total[d.index]
+          : 0;
+
+      ratio = d.ratio;
+    }
+  }
+
+  return asPercent && ratio ? ratio * 100 : ratio
+};
+
+ChartInternal.prototype.updateDataAttributes = function(name, attrs) {
+  var $$ = this,
+    config = $$.config,
+    current = config['data_' + name];
+  if (typeof attrs === 'undefined') {
+    return current
+  }
+  Object.keys(attrs).forEach(function(id) {
+    current[id] = attrs[id];
+  });
+  $$.redraw({
+    withLegend: true
+  });
+  return current
+};
+
+ChartInternal.prototype.load = function(targets, args) {
+  var $$ = this;
+  if (targets) {
+    // filter loading targets if needed
+    if (args.filter) {
+      targets = targets.filter(args.filter);
+    }
+    // set type if args.types || args.type specified
+    if (args.type || args.types) {
+      targets.forEach(function(t) {
+        var type = args.types && args.types[t.id] ? args.types[t.id] : args.type;
+        $$.setTargetType(t.id, type);
+      });
+    }
+    // Update/Add data
+    $$.data.targets.forEach(function(d) {
+      for (var i = 0; i < targets.length; i++) {
+        if (d.id === targets[i].id) {
+          d.values = targets[i].values;
+          targets.splice(i, 1);
+          break
+        }
+      }
+    });
+    $$.data.targets = $$.data.targets.concat(targets); // add remained
+  }
+
+  // Set targets
+  $$.updateTargets($$.data.targets);
+
+  // Redraw with new targets
+  $$.redraw({
+    withUpdateOrgXDomain: true,
+    withUpdateXDomain: true,
+    withLegend: true
+  });
+
+  if (args.done) {
+    args.done();
+  }
+};
+ChartInternal.prototype.loadFromArgs = function(args) {
+  var $$ = this;
+
+  $$.resetCache();
+
+  if (args.data) {
+    $$.load($$.convertDataToTargets(args.data), args);
+  } else if (args.url) {
+    $$.convertUrlToData(
+      args.url,
+      args.mimeType,
+      args.headers,
+      args.keys,
+      function(data) {
+        $$.load($$.convertDataToTargets(data), args);
+      }
+    );
+  } else if (args.json) {
+    $$.load(
+      $$.convertDataToTargets($$.convertJsonToData(args.json, args.keys)),
+      args
+    );
+  } else if (args.rows) {
+    $$.load($$.convertDataToTargets($$.convertRowsToData(args.rows)), args);
+  } else if (args.columns) {
+    $$.load(
+      $$.convertDataToTargets($$.convertColumnsToData(args.columns)),
+      args
+    );
+  } else {
+    $$.load(null, args);
+  }
+};
+ChartInternal.prototype.unload = function(targetIds, done) {
+  var $$ = this;
+
+  $$.resetCache();
+
+  if (!done) {
+    done = function() {};
+  }
+  // filter existing target
+  targetIds = targetIds.filter(function(id) {
+    return $$.hasTarget($$.data.targets, id)
+  });
+  // If no target, call done and return
+  if (!targetIds || targetIds.length === 0) {
+    done();
+    return
+  }
+  $$.svg
+    .selectAll(
+      targetIds.map(function(id) {
+        return $$.selectorTarget(id)
+      })
+    )
+    .transition()
+    .style('opacity', 0)
+    .remove()
+    .call($$.endall, done);
+  targetIds.forEach(function(id) {
+    // Reset fadein for future load
+    $$.withoutFadeIn[id] = false;
+    // Remove target's elements
+    if ($$.legend) {
+      $$.legend
+        .selectAll('.' + CLASS.legendItem + $$.getTargetSelectorSuffix(id))
+        .remove();
+    }
+    // Remove target
+    $$.data.targets = $$.data.targets.filter(function(t) {
+      return t.id !== id
+    });
+  });
+};
+
+ChartInternal.prototype.getYDomainMin = function(targets) {
+  var $$ = this,
+    config = $$.config,
+    ids = $$.mapToIds(targets),
+    ys = $$.getValuesAsIdKeyed(targets),
+    j,
+    k,
+    baseId,
+    idsInGroup,
+    id,
+    hasNegativeValue;
+  if (config.data_groups.length > 0) {
+    hasNegativeValue = $$.hasNegativeValueInTargets(targets);
+    for (j = 0; j < config.data_groups.length; j++) {
+      // Determine baseId
+      idsInGroup = config.data_groups[j].filter(function(id) {
+        return ids.indexOf(id) >= 0
+      });
+      if (idsInGroup.length === 0) {
+        continue
+      }
+      baseId = idsInGroup[0];
+      // Consider negative values
+      if (hasNegativeValue && ys[baseId]) {
+        ys[baseId].forEach(function(v, i) {
+          ys[baseId][i] = v < 0 ? v : 0;
+        });
+      }
+      // Compute min
+      for (k = 1; k < idsInGroup.length; k++) {
+        id = idsInGroup[k];
+        if (!ys[id]) {
+          continue
+        }
+        ys[id].forEach(function(v, i) {
+          if (
+            $$.axis.getId(id) === $$.axis.getId(baseId) &&
+            ys[baseId] &&
+            !(hasNegativeValue && +v > 0)
+          ) {
+            ys[baseId][i] += +v;
+          }
+        });
+      }
+    }
+  }
+  return $$.d3.min(
+    Object.keys(ys).map(function(key) {
+      return $$.d3.min(ys[key])
+    })
+  )
+};
+ChartInternal.prototype.getYDomainMax = function(targets) {
+  var $$ = this,
+    config = $$.config,
+    ids = $$.mapToIds(targets),
+    ys = $$.getValuesAsIdKeyed(targets),
+    j,
+    k,
+    baseId,
+    idsInGroup,
+    id,
+    hasPositiveValue;
+  if (config.data_groups.length > 0) {
+    hasPositiveValue = $$.hasPositiveValueInTargets(targets);
+    for (j = 0; j < config.data_groups.length; j++) {
+      // Determine baseId
+      idsInGroup = config.data_groups[j].filter(function(id) {
+        return ids.indexOf(id) >= 0
+      });
+      if (idsInGroup.length === 0) {
+        continue
+      }
+      baseId = idsInGroup[0];
+      // Consider positive values
+      if (hasPositiveValue && ys[baseId]) {
+        ys[baseId].forEach(function(v, i) {
+          ys[baseId][i] = v > 0 ? v : 0;
+        });
+      }
+      // Compute max
+      for (k = 1; k < idsInGroup.length; k++) {
+        id = idsInGroup[k];
+        if (!ys[id]) {
+          continue
+        }
+        ys[id].forEach(function(v, i) {
+          if (
+            $$.axis.getId(id) === $$.axis.getId(baseId) &&
+            ys[baseId] &&
+            !(hasPositiveValue && +v < 0)
+          ) {
+            ys[baseId][i] += +v;
+          }
+        });
+      }
+    }
+  }
+  return $$.d3.max(
+    Object.keys(ys).map(function(key) {
+      return $$.d3.max(ys[key])
+    })
+  )
+};
+ChartInternal.prototype.getYDomain = function(targets, axisId, xDomain) {
+  var $$ = this,
+    config = $$.config;
+
+  if ($$.isAxisNormalized(axisId)) {
+    return [0, 100]
+  }
+
+  var targetsByAxisId = targets.filter(function(t) {
+      return $$.axis.getId(t.id) === axisId
+    }),
+    yTargets = xDomain
+      ? $$.filterByXDomain(targetsByAxisId, xDomain)
+      : targetsByAxisId,
+    yMin = axisId === 'y2' ? config.axis_y2_min : config.axis_y_min,
+    yMax = axisId === 'y2' ? config.axis_y2_max : config.axis_y_max,
+    yDomainMin = $$.getYDomainMin(yTargets),
+    yDomainMax = $$.getYDomainMax(yTargets),
+    domain,
+    domainLength,
+    padding_top,
+    padding_bottom,
+    center = axisId === 'y2' ? config.axis_y2_center : config.axis_y_center,
+    yDomainAbs,
+    lengths,
+    diff,
+    ratio,
+    isAllPositive,
+    isAllNegative,
+    isZeroBased =
+      ($$.hasType('bar', yTargets) && config.bar_zerobased) ||
+      ($$.hasType('area', yTargets) && config.area_zerobased),
+    isInverted =
+      axisId === 'y2' ? config.axis_y2_inverted : config.axis_y_inverted,
+    showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated,
+    showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated;
+
+  // MEMO: avoid inverting domain unexpectedly
+  yDomainMin = isValue(yMin)
+    ? yMin
+    : isValue(yMax)
+    ? yDomainMin < yMax
+      ? yDomainMin
+      : yMax - 10
+    : yDomainMin;
+  yDomainMax = isValue(yMax)
+    ? yMax
+    : isValue(yMin)
+    ? yMin < yDomainMax
+      ? yDomainMax
+      : yMin + 10
+    : yDomainMax;
+
+  if (yTargets.length === 0) {
+    // use current domain if target of axisId is none
+    return axisId === 'y2' ? $$.y2.domain() : $$.y.domain()
+  }
+  if (isNaN(yDomainMin)) {
+    // set minimum to zero when not number
+    yDomainMin = 0;
+  }
+  if (isNaN(yDomainMax)) {
+    // set maximum to have same value as yDomainMin
+    yDomainMax = yDomainMin;
+  }
+  if (yDomainMin === yDomainMax) {
+    yDomainMin < 0 ? (yDomainMax = 0) : (yDomainMin = 0);
+  }
+  isAllPositive = yDomainMin >= 0 && yDomainMax >= 0;
+  isAllNegative = yDomainMin <= 0 && yDomainMax <= 0;
+
+  // Cancel zerobased if axis_*_min / axis_*_max specified
+  if ((isValue(yMin) && isAllPositive) || (isValue(yMax) && isAllNegative)) {
+    isZeroBased = false;
+  }
+
+  // Bar/Area chart should be 0-based if all positive|negative
+  if (isZeroBased) {
+    if (isAllPositive) {
+      yDomainMin = 0;
+    }
+    if (isAllNegative) {
+      yDomainMax = 0;
+    }
+  }
+
+  domainLength = Math.abs(yDomainMax - yDomainMin);
+  padding_top = padding_bottom = domainLength * 0.1;
+
+  if (typeof center !== 'undefined') {
+    yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax));
+    yDomainMax = center + yDomainAbs;
+    yDomainMin = center - yDomainAbs;
+  }
+  // add padding for data label
+  if (showHorizontalDataLabel) {
+    lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'width');
+    diff = diffDomain($$.y.range());
+    ratio = [lengths[0] / diff, lengths[1] / diff];
+    padding_top += domainLength * (ratio[1] / (1 - ratio[0] - ratio[1]));
+    padding_bottom += domainLength * (ratio[0] / (1 - ratio[0] - ratio[1]));
+  } else if (showVerticalDataLabel) {
+    lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'height');
+
+    const pixelsToAxisPadding = $$.getY(
+      config[`axis_${axisId}_type`],
+      // input domain as pixels
+      [0, config.axis_rotated ? $$.width : $$.height],
+      // output range as axis padding
+      [0, domainLength]
+    );
+
+    padding_top += pixelsToAxisPadding(lengths[1]);
+    padding_bottom += pixelsToAxisPadding(lengths[0]);
+  }
+  if (axisId === 'y' && notEmpty(config.axis_y_padding)) {
+    padding_top = $$.axis.getPadding(
+      config.axis_y_padding,
+      'top',
+      padding_top,
+      domainLength
+    );
+    padding_bottom = $$.axis.getPadding(
+      config.axis_y_padding,
+      'bottom',
+      padding_bottom,
+      domainLength
+    );
+  }
+  if (axisId === 'y2' && notEmpty(config.axis_y2_padding)) {
+    padding_top = $$.axis.getPadding(
+      config.axis_y2_padding,
+      'top',
+      padding_top,
+      domainLength
+    );
+    padding_bottom = $$.axis.getPadding(
+      config.axis_y2_padding,
+      'bottom',
+      padding_bottom,
+      domainLength
+    );
+  }
+  // Bar/Area chart should be 0-based if all positive|negative
+  if (isZeroBased) {
+    if (isAllPositive) {
+      padding_bottom = yDomainMin;
+    }
+    if (isAllNegative) {
+      padding_top = -yDomainMax;
+    }
+  }
+  domain = [yDomainMin - padding_bottom, yDomainMax + padding_top];
+  return isInverted ? domain.reverse() : domain
+};
+ChartInternal.prototype.getXDomainMin = function(targets) {
+  var $$ = this,
+    config = $$.config;
+  return isDefined(config.axis_x_min)
+    ? $$.isTimeSeries()
+      ? this.parseDate(config.axis_x_min)
+      : config.axis_x_min
+    : $$.d3.min(targets, function(t) {
+        return $$.d3.min(t.values, function(v) {
+          return v.x
+        })
+      })
+};
+ChartInternal.prototype.getXDomainMax = function(targets) {
+  var $$ = this,
+    config = $$.config;
+  return isDefined(config.axis_x_max)
+    ? $$.isTimeSeries()
+      ? this.parseDate(config.axis_x_max)
+      : config.axis_x_max
+    : $$.d3.max(targets, function(t) {
+        return $$.d3.max(t.values, function(v) {
+          return v.x
+        })
+      })
+};
+ChartInternal.prototype.getXDomainPadding = function(domain) {
+  var $$ = this,
+    config = $$.config,
+    diff = domain[1] - domain[0],
+    maxDataCount,
+    padding,
+    paddingLeft,
+    paddingRight;
+  if ($$.isCategorized()) {
+    padding = 0;
+  } else if ($$.hasType('bar')) {
+    maxDataCount = $$.getMaxDataCount();
+    padding = maxDataCount > 1 ? diff / (maxDataCount - 1) / 2 : 0.5;
+  } else {
+    padding = diff * 0.01;
+  }
+  if (
+    typeof config.axis_x_padding === 'object' &&
+    notEmpty(config.axis_x_padding)
+  ) {
+    paddingLeft = isValue(config.axis_x_padding.left)
+      ? config.axis_x_padding.left
+      : padding;
+    paddingRight = isValue(config.axis_x_padding.right)
+      ? config.axis_x_padding.right
+      : padding;
+  } else if (typeof config.axis_x_padding === 'number') {
+    paddingLeft = paddingRight = config.axis_x_padding;
+  } else {
+    paddingLeft = paddingRight = padding;
+  }
+  return { left: paddingLeft, right: paddingRight }
+};
+ChartInternal.prototype.getXDomain = function(targets) {
+  var $$ = this,
+    xDomain = [$$.getXDomainMin(targets), $$.getXDomainMax(targets)],
+    firstX = xDomain[0],
+    lastX = xDomain[1],
+    padding = $$.getXDomainPadding(xDomain),
+    min = 0,
+    max = 0;
+  // show center of x domain if min and max are the same
+  if (firstX - lastX === 0 && !$$.isCategorized()) {
+    if ($$.isTimeSeries()) {
+      firstX = new Date(firstX.getTime() * 0.5);
+      lastX = new Date(lastX.getTime() * 1.5);
+    } else {
+      firstX = firstX === 0 ? 1 : firstX * 0.5;
+      lastX = lastX === 0 ? -1 : lastX * 1.5;
+    }
+  }
+  if (firstX || firstX === 0) {
+    min = $$.isTimeSeries()
+      ? new Date(firstX.getTime() - padding.left)
+      : firstX - padding.left;
+  }
+  if (lastX || lastX === 0) {
+    max = $$.isTimeSeries()
+      ? new Date(lastX.getTime() + padding.right)
+      : lastX + padding.right;
+  }
+  return [min, max]
+};
+ChartInternal.prototype.updateXDomain = function(
+  targets,
+  withUpdateXDomain,
+  withUpdateOrgXDomain,
+  withTrim,
+  domain
+) {
+  var $$ = this,
+    config = $$.config;
+
+  if (withUpdateOrgXDomain) {
+    $$.x.domain(domain ? domain : $$.d3.extent($$.getXDomain(targets)));
+    $$.orgXDomain = $$.x.domain();
+    if (config.zoom_enabled) {
+      $$.zoom.update();
+    }
+    $$.subX.domain($$.x.domain());
+    if ($$.brush) {
+      $$.brush.updateScale($$.subX);
+    }
+  }
+  if (withUpdateXDomain) {
+    $$.x.domain(
+      domain
+        ? domain
+        : !$$.brush || $$.brush.empty()
+        ? $$.orgXDomain
+        : $$.brush.selectionAsValue()
+    );
+  }
+
+  // Trim domain when too big by zoom mousemove event
+  if (withTrim) {
+    $$.x.domain($$.trimXDomain($$.x.orgDomain()));
+  }
+
+  return $$.x.domain()
+};
+ChartInternal.prototype.trimXDomain = function(domain) {
+  var zoomDomain = this.getZoomDomain(),
+    min = zoomDomain[0],
+    max = zoomDomain[1];
+  if (domain[0] <= min) {
+    domain[1] = +domain[1] + (min - domain[0]);
+    domain[0] = min;
+  }
+  if (max <= domain[1]) {
+    domain[0] = +domain[0] - (domain[1] - max);
+    domain[1] = max;
+  }
+  return domain
+};
+
+ChartInternal.prototype.drag = function(mouse) {
+  var $$ = this,
+    config = $$.config,
+    main = $$.main,
+    d3 = $$.d3;
+  var sx, sy, mx, my, minX, maxX, minY, maxY;
+
+  if ($$.hasArcType()) {
+    return
+  }
+  if (!config.data_selection_enabled) {
+    return
+  } // do nothing if not selectable
+  if (!config.data_selection_multiple) {
+    return
+  } // skip when single selection because drag is used for multiple selection
+
+  sx = $$.dragStart[0];
+  sy = $$.dragStart[1];
+  mx = mouse[0];
+  my = mouse[1];
+  minX = Math.min(sx, mx);
+  maxX = Math.max(sx, mx);
+  minY = config.data_selection_grouped ? $$.margin.top : Math.min(sy, my);
+  maxY = config.data_selection_grouped ? $$.height : Math.max(sy, my);
+
+  main
+    .select('.' + CLASS.dragarea)
+    .attr('x', minX)
+    .attr('y', minY)
+    .attr('width', maxX - minX)
+    .attr('height', maxY - minY);
+  // TODO: binary search when multiple xs
+  main
+    .selectAll('.' + CLASS.shapes)
+    .selectAll('.' + CLASS.shape)
+    .each(function(d, i) {
+      if (!config.data_selection_isselectable(d)) {
+        return
+      }
+      var shape = d3.select(this),
+        isSelected = shape.classed(CLASS.SELECTED),
+        isIncluded = shape.classed(CLASS.INCLUDED),
+        _x,
+        _y,
+        _w,
+        _h,
+        toggle,
+        isWithin = false,
+        box;
+      if (shape.classed(CLASS.circle)) {
+        _x = shape.attr('cx') * 1;
+        _y = shape.attr('cy') * 1;
+        toggle = $$.togglePoint;
+        isWithin = minX < _x && _x < maxX && minY < _y && _y < maxY;
+      } else if (shape.classed(CLASS.bar)) {
+        box = getPathBox(this);
+        _x = box.x;
+        _y = box.y;
+        _w = box.width;
+        _h = box.height;
+        toggle = $$.togglePath;
+        isWithin =
+          !(maxX < _x || _x + _w < minX) && !(maxY < _y || _y + _h < minY);
+      } else {
+        // line/area selection not supported yet
+        return
+      }
+      if (isWithin ^ isIncluded) {
+        shape.classed(CLASS.INCLUDED, !isIncluded);
+        // TODO: included/unincluded callback here
+        shape.classed(CLASS.SELECTED, !isSelected);
+        toggle.call($$, !isSelected, shape, d, i);
+      }
+    });
+};
+
+ChartInternal.prototype.dragstart = function(mouse) {
+  var $$ = this,
+    config = $$.config;
+  if ($$.hasArcType()) {
+    return
+  }
+  if (!config.data_selection_enabled) {
+    return
+  } // do nothing if not selectable
+  $$.dragStart = mouse;
+  $$.main
+    .select('.' + CLASS.chart)
+    .append('rect')
+    .attr('class', CLASS.dragarea)
+    .style('opacity', 0.1);
+  $$.dragging = true;
+};
+
+ChartInternal.prototype.dragend = function() {
+  var $$ = this,
+    config = $$.config;
+  if ($$.hasArcType()) {
+    return
+  }
+  if (!config.data_selection_enabled) {
+    return
+  } // do nothing if not selectable
+  $$.main
+    .select('.' + CLASS.dragarea)
+    .transition()
+    .duration(100)
+    .style('opacity', 0)
+    .remove();
+  $$.main.selectAll('.' + CLASS.shape).classed(CLASS.INCLUDED, false);
+  $$.dragging = false;
+};
+
+ChartInternal.prototype.getYFormat = function(forArc) {
+  var $$ = this,
+    formatForY =
+      forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.yFormat,
+    formatForY2 =
+      forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.y2Format;
+  return function(v, ratio, id) {
+    var format = $$.axis.getId(id) === 'y2' ? formatForY2 : formatForY;
+    return format.call($$, v, ratio)
+  }
+};
+ChartInternal.prototype.yFormat = function(v) {
+  var $$ = this,
+    config = $$.config,
+    format = config.axis_y_tick_format
+      ? config.axis_y_tick_format
+      : $$.defaultValueFormat;
+  return format(v)
+};
+ChartInternal.prototype.y2Format = function(v) {
+  var $$ = this,
+    config = $$.config,
+    format = config.axis_y2_tick_format
+      ? config.axis_y2_tick_format
+      : $$.defaultValueFormat;
+  return format(v)
+};
+ChartInternal.prototype.defaultValueFormat = function(v) {
+  return isValue(v) ? +v : ''
+};
+ChartInternal.prototype.defaultArcValueFormat = function(v, ratio) {
+  return (ratio * 100).toFixed(1) + '%'
+};
+ChartInternal.prototype.dataLabelFormat = function(targetId) {
+  var $$ = this,
+    data_labels = $$.config.data_labels,
+    format,
+    defaultFormat = function(v) {
+      return isValue(v) ? +v : ''
+    };
+  // find format according to axis id
+  if (typeof data_labels.format === 'function') {
+    format = data_labels.format;
+  } else if (typeof data_labels.format === 'object') {
+    if (data_labels.format[targetId]) {
+      format =
+        data_labels.format[targetId] === true
+          ? defaultFormat
+          : data_labels.format[targetId];
+    } else {
+      format = function() {
+        return ''
+      };
+    }
+  } else {
+    format = defaultFormat;
+  }
+  return format
+};
+
+ChartInternal.prototype.initGrid = function() {
+  var $$ = this,
+    config = $$.config,
+    d3 = $$.d3;
+  $$.grid = $$.main
+    .append('g')
+    .attr('clip-path', $$.clipPathForGrid)
+    .attr('class', CLASS.grid);
+  if (config.grid_x_show) {
+    $$.grid.append('g').attr('class', CLASS.xgrids);
+  }
+  if (config.grid_y_show) {
+    $$.grid.append('g').attr('class', CLASS.ygrids);
+  }
+  if (config.grid_focus_show) {
+    $$.grid
+      .append('g')
+      .attr('class', CLASS.xgridFocus)
+      .append('line')
+      .attr('class', CLASS.xgridFocus);
+  }
+  $$.xgrid = d3.selectAll([]);
+  if (!config.grid_lines_front) {
+    $$.initGridLines();
+  }
+};
+ChartInternal.prototype.initGridLines = function() {
+  var $$ = this,
+    d3 = $$.d3;
+  $$.gridLines = $$.main
+    .append('g')
+    .attr('clip-path', $$.clipPathForGrid)
+    .attr('class', CLASS.grid + ' ' + CLASS.gridLines);
+  $$.gridLines.append('g').attr('class', CLASS.xgridLines);
+  $$.gridLines.append('g').attr('class', CLASS.ygridLines);
+  $$.xgridLines = d3.selectAll([]);
+};
+ChartInternal.prototype.updateXGrid = function(withoutUpdate) {
+  var $$ = this,
+    config = $$.config,
+    d3 = $$.d3,
+    xgridData = $$.generateGridData(config.grid_x_type, $$.x),
+    tickOffset = $$.isCategorized() ? $$.xAxis.tickOffset() : 0;
+
+  $$.xgridAttr = config.axis_rotated
+    ? {
+        x1: 0,
+        x2: $$.width,
+        y1: function(d) {
+          return $$.x(d) - tickOffset
+        },
+        y2: function(d) {
+          return $$.x(d) - tickOffset
+        }
+      }
+    : {
+        x1: function(d) {
+          return $$.x(d) + tickOffset
+        },
+        x2: function(d) {
+          return $$.x(d) + tickOffset
+        },
+        y1: 0,
+        y2: $$.height
+      };
+  $$.xgridAttr.opacity = function() {
+    var pos = +d3.select(this).attr(config.axis_rotated ? 'y1' : 'x1');
+    return pos === (config.axis_rotated ? $$.height : 0) ? 0 : 1
+  };
+
+  var xgrid = $$.main
+    .select('.' + CLASS.xgrids)
+    .selectAll('.' + CLASS.xgrid)
+    .data(xgridData);
+  var xgridEnter = xgrid
+    .enter()
+    .append('line')
+    .attr('class', CLASS.xgrid)
+    .attr('x1', $$.xgridAttr.x1)
+    .attr('x2', $$.xgridAttr.x2)
+    .attr('y1', $$.xgridAttr.y1)
+    .attr('y2', $$.xgridAttr.y2)
+    .style('opacity', 0);
+  $$.xgrid = xgridEnter.merge(xgrid);
+  if (!withoutUpdate) {
+    $$.xgrid
+      .attr('x1', $$.xgridAttr.x1)
+      .attr('x2', $$.xgridAttr.x2)
+      .attr('y1', $$.xgridAttr.y1)
+      .attr('y2', $$.xgridAttr.y2)
+      .style('opacity', $$.xgridAttr.opacity);
+  }
+  xgrid.exit().remove();
+};
+
+ChartInternal.prototype.updateYGrid = function() {
+  var $$ = this,
+    config = $$.config,
+    gridValues = $$.yAxis.tickValues() || $$.y.ticks(config.grid_y_ticks);
+  var ygrid = $$.main
+    .select('.' + CLASS.ygrids)
+    .selectAll('.' + CLASS.ygrid)
+    .data(gridValues);
+  var ygridEnter = ygrid
+    .enter()
+    .append('line')
+    // TODO: x1, x2, y1, y2, opacity need to be set here maybe
+    .attr('class', CLASS.ygrid);
+  $$.ygrid = ygridEnter.merge(ygrid);
+  $$.ygrid
+    .attr('x1', config.axis_rotated ? $$.y : 0)
+    .attr('x2', config.axis_rotated ? $$.y : $$.width)
+    .attr('y1', config.axis_rotated ? 0 : $$.y)
+    .attr('y2', config.axis_rotated ? $$.height : $$.y);
+  ygrid.exit().remove();
+  $$.smoothLines($$.ygrid, 'grid');
+};
+
+ChartInternal.prototype.gridTextAnchor = function(d) {
+  return d.position ? d.position : 'end'
+};
+ChartInternal.prototype.gridTextDx = function(d) {
+  return d.position === 'start' ? 4 : d.position === 'middle' ? 0 : -4
+};
+ChartInternal.prototype.xGridTextX = function(d) {
+  return d.position === 'start'
+    ? -this.height
+    : d.position === 'middle'
+    ? -this.height / 2
+    : 0
+};
+ChartInternal.prototype.yGridTextX = function(d) {
+  return d.position === 'start'
+    ? 0
+    : d.position === 'middle'
+    ? this.width / 2
+    : this.width
+};
+ChartInternal.prototype.updateGrid = function(duration) {
+  var $$ = this,
+    main = $$.main,
+    config = $$.config,
+    xgridLine,
+    xgridLineEnter,
+    ygridLine,
+    ygridLineEnter,
+    xv = $$.xv.bind($$),
+    yv = $$.yv.bind($$),
+    xGridTextX = $$.xGridTextX.bind($$),
+    yGridTextX = $$.yGridTextX.bind($$);
+
+  // hide if arc type
+  $$.grid.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');
+
+  main.select('line.' + CLASS.xgridFocus).style('visibility', 'hidden');
+  if (config.grid_x_show) {
+    $$.updateXGrid();
+  }
+  xgridLine = main
+    .select('.' + CLASS.xgridLines)
+    .selectAll('.' + CLASS.xgridLine)
+    .data(config.grid_x_lines);
+  // enter
+  xgridLineEnter = xgridLine
+    .enter()
+    .append('g')
+    .attr('class', function(d) {
+      return CLASS.xgridLine + (d['class'] ? ' ' + d['class'] : '')
+    });
+  xgridLineEnter
+    .append('line')
+    .attr('x1', config.axis_rotated ? 0 : xv)
+    .attr('x2', config.axis_rotated ? $$.width : xv)
+    .attr('y1', config.axis_rotated ? xv : 0)
+    .attr('y2', config.axis_rotated ? xv : $$.height)
+    .style('opacity', 0);
+  xgridLineEnter
+    .append('text')
+    .attr('text-anchor', $$.gridTextAnchor)
+    .attr('transform', config.axis_rotated ? '' : 'rotate(-90)')
+    .attr('x', config.axis_rotated ? yGridTextX : xGridTextX)
+    .attr('y', xv)
+    .attr('dx', $$.gridTextDx)
+    .attr('dy', -5)
+    .style('opacity', 0);
+  // udpate
+  $$.xgridLines = xgridLineEnter.merge(xgridLine);
+  // done in d3.transition() of the end of this function
+  // exit
+  xgridLine
+    .exit()
+    .transition()
+    .duration(duration)
+    .style('opacity', 0)
+    .remove();
+
+  // Y-Grid
+  if (config.grid_y_show) {
+    $$.updateYGrid();
+  }
+  ygridLine = main
+    .select('.' + CLASS.ygridLines)
+    .selectAll('.' + CLASS.ygridLine)
+    .data(config.grid_y_lines);
+  // enter
+  ygridLineEnter = ygridLine
+    .enter()
+    .append('g')
+    .attr('class', function(d) {
+      return CLASS.ygridLine + (d['class'] ? ' ' + d['class'] : '')
+    });
+  ygridLineEnter
+    .append('line')
+    .attr('x1', config.axis_rotated ? yv : 0)
+    .attr('x2', config.axis_rotated ? yv : $$.width)
+    .attr('y1', config.axis_rotated ? 0 : yv)
+    .attr('y2', config.axis_rotated ? $$.height : yv)
+    .style('opacity', 0);
+  ygridLineEnter
+    .append('text')
+    .attr('text-anchor', $$.gridTextAnchor)
+    .attr('transform', config.axis_rotated ? 'rotate(-90)' : '')
+    .attr('x', config.axis_rotated ? xGridTextX : yGridTextX)
+    .attr('y', yv)
+    .attr('dx', $$.gridTextDx)
+    .attr('dy', -5)
+    .style('opacity', 0);
+  // update
+  $$.ygridLines = ygridLineEnter.merge(ygridLine);
+  $$.ygridLines
+    .select('line')
+    .transition()
+    .duration(duration)
+    .attr('x1', config.axis_rotated ? yv : 0)
+    .attr('x2', config.axis_rotated ? yv : $$.width)
+    .attr('y1', config.axis_rotated ? 0 : yv)
+    .attr('y2', config.axis_rotated ? $$.height : yv)
+    .style('opacity', 1);
+  $$.ygridLines
+    .select('text')
+    .transition()
+    .duration(duration)
+    .attr(
+      'x',
+      config.axis_rotated ? $$.xGridTextX.bind($$) : $$.yGridTextX.bind($$)
+    )
+    .attr('y', yv)
+    .text(function(d) {
+      return d.text
+    })
+    .style('opacity', 1);
+  // exit
+  ygridLine
+    .exit()
+    .transition()
+    .duration(duration)
+    .style('opacity', 0)
+    .remove();
+};
+ChartInternal.prototype.redrawGrid = function(withTransition, transition) {
+  var $$ = this,
+    config = $$.config,
+    xv = $$.xv.bind($$),
+    lines = $$.xgridLines.select('line'),
+    texts = $$.xgridLines.select('text');
+  return [
+    (withTransition ? lines.transition(transition) : lines)
+      .attr('x1', config.axis_rotated ? 0 : xv)
+      .attr('x2', config.axis_rotated ? $$.width : xv)
+      .attr('y1', config.axis_rotated ? xv : 0)
+      .attr('y2', config.axis_rotated ? xv : $$.height)
+      .style('opacity', 1),
+    (withTransition ? texts.transition(transition) : texts)
+      .attr(
+        'x',
+        config.axis_rotated ? $$.yGridTextX.bind($$) : $$.xGridTextX.bind($$)
+      )
+      .attr('y', xv)
+      .text(function(d) {
+        return d.text
+      })
+      .style('opacity', 1)
+  ]
+};
+ChartInternal.prototype.showXGridFocus = function(selectedData) {
+  var $$ = this,
+    config = $$.config,
+    dataToShow = selectedData.filter(function(d) {
+      return d && isValue(d.value)
+    }),
+    focusEl = $$.main.selectAll('line.' + CLASS.xgridFocus),
+    xx = $$.xx.bind($$);
+  if (!config.tooltip_show) {
+    return
+  }
+  // Hide when stanford plot exists
+  if ($$.hasType('stanford') || $$.hasArcType()) {
+    return
+  }
+  focusEl
+    .style('visibility', 'visible')
+    .data([dataToShow[0]])
+    .attr(config.axis_rotated ? 'y1' : 'x1', xx)
+    .attr(config.axis_rotated ? 'y2' : 'x2', xx);
+  $$.smoothLines(focusEl, 'grid');
+};
+ChartInternal.prototype.hideXGridFocus = function() {
+  this.main.select('line.' + CLASS.xgridFocus).style('visibility', 'hidden');
+};
+ChartInternal.prototype.updateXgridFocus = function() {
+  var $$ = this,
+    config = $$.config;
+  $$.main
+    .select('line.' + CLASS.xgridFocus)
+    .attr('x1', config.axis_rotated ? 0 : -10)
+    .attr('x2', config.axis_rotated ? $$.width : -10)
+    .attr('y1', config.axis_rotated ? -10 : 0)
+    .attr('y2', config.axis_rotated ? -10 : $$.height);
+};
+ChartInternal.prototype.generateGridData = function(type, scale) {
+  var $$ = this,
+    gridData = [],
+    xDomain,
+    firstYear,
+    lastYear,
+    i,
+    tickNum = $$.main
+      .select('.' + CLASS.axisX)
+      .selectAll('.tick')
+      .size();
+  if (type === 'year') {
+    xDomain = $$.getXDomain();
+    firstYear = xDomain[0].getFullYear();
+    lastYear = xDomain[1].getFullYear();
+    for (i = firstYear; i <= lastYear; i++) {
+      gridData.push(new Date(i + '-01-01 00:00:00'));
+    }
+  } else {
+    gridData = scale.ticks(10);
+    if (gridData.length > tickNum) {
+      // use only int
+      gridData = gridData.filter(function(d) {
+        return ('' + d).indexOf('.') < 0
+      });
+    }
+  }
+  return gridData
+};
+ChartInternal.prototype.getGridFilterToRemove = function(params) {
+  return params
+    ? function(line) {
+        var found = false
+        ;[].concat(params).forEach(function(param) {
+          if (
+            ('value' in param && line.value === param.value) ||
+            ('class' in param && line['class'] === param['class'])
+          ) {
+            found = true;
+          }
+        });
+        return found
+      }
+    : function() {
+        return true
+      }
+};
+ChartInternal.prototype.removeGridLines = function(params, forX) {
+  var $$ = this,
+    config = $$.config,
+    toRemove = $$.getGridFilterToRemove(params),
+    toShow = function(line) {
+      return !toRemove(line)
+    },
+    classLines = forX ? CLASS.xgridLines : CLASS.ygridLines,
+    classLine = forX ? CLASS.xgridLine : CLASS.ygridLine;
+  $$.main
+    .select('.' + classLines)
+    .selectAll('.' + classLine)
+    .filter(toRemove)
+    .transition()
+    .duration(config.transition_duration)
+    .style('opacity', 0)
+    .remove();
+  if (forX) {
+    config.grid_x_lines = config.grid_x_lines.filter(toShow);
+  } else {
+    config.grid_y_lines = config.grid_y_lines.filter(toShow);
+  }
+};
+
+ChartInternal.prototype.initEventRect = function() {
+  var $$ = this,
+    config = $$.config;
+
+  $$.main
+    .select('.' + CLASS.chart)
+    .append('g')
+    .attr('class', CLASS.eventRects)
+    .style('fill-opacity', 0);
+  $$.eventRect = $$.main
+    .select('.' + CLASS.eventRects)
+    .append('rect')
+    .attr('class', CLASS.eventRect);
+
+  // event rect handle zoom event as well
+  if (config.zoom_enabled && $$.zoom) {
+    $$.eventRect.call($$.zoom).on('dblclick.zoom', null);
+    if (config.zoom_initialRange) {
+      // WORKAROUND: Add transition to apply transform immediately when no subchart
+      $$.eventRect
+        .transition()
+        .duration(0)
+        .call($$.zoom.transform, $$.zoomTransform(config.zoom_initialRange));
+    }
+  }
+};
+ChartInternal.prototype.redrawEventRect = function() {
+  const $$ = this,
+    d3 = $$.d3,
+    config = $$.config;
+
+  function mouseout() {
+    $$.svg.select('.' + CLASS.eventRect).style('cursor', null);
+    $$.hideXGridFocus();
+    $$.hideTooltip();
+    $$.unexpandCircles();
+    $$.unexpandBars();
+  }
+
+  const isHoveringDataPoint = (mouse, closest) =>
+    closest &&
+    ($$.isBarType(closest.id) ||
+      $$.dist(closest, mouse) < config.point_sensitivity);
+
+  const withName = d => (d ? $$.addName(Object.assign({}, d)) : null);
+
+  // rects for mouseover
+  $$.main
+    .select('.' + CLASS.eventRects)
+    .style(
+      'cursor',
+      config.zoom_enabled
+        ? config.axis_rotated
+          ? 'ns-resize'
+          : 'ew-resize'
+        : null
+    );
+
+  $$.eventRect
+    .attr('x', 0)
+    .attr('y', 0)
+    .attr('width', $$.width)
+    .attr('height', $$.height)
+    .on(
+      'mouseout',
+      config.interaction_enabled
+        ? function() {
+            if (!config) {
+              return
+            } // chart is destroyed
+            if ($$.hasArcType()) {
+              return
+            }
+            if ($$.mouseover) {
+              config.data_onmouseout.call($$.api, $$.mouseover);
+              $$.mouseover = undefined;
+            }
+            mouseout();
+          }
+        : null
+    )
+    .on(
+      'mousemove',
+      config.interaction_enabled
+        ? function() {
+            // do nothing when dragging
+            if ($$.dragging) {
+              return
+            }
+
+            const targetsToShow = $$.getTargetsToShow();
+
+            // do nothing if arc type
+            if ($$.hasArcType(targetsToShow)) {
+              return
+            }
+
+            const mouse = d3.mouse(this);
+            const closest = withName(
+              $$.findClosestFromTargets(targetsToShow, mouse)
+            );
+            const isMouseCloseToDataPoint = isHoveringDataPoint(mouse, closest);
+
+            // ensure onmouseout is always called if mousemove switch between 2 targets
+            if (
+              $$.mouseover &&
+              (!closest ||
+                closest.id !== $$.mouseover.id ||
+                closest.index !== $$.mouseover.index)
+            ) {
+              config.data_onmouseout.call($$.api, $$.mouseover);
+              $$.mouseover = undefined;
+            }
+            if (closest && !$$.mouseover) {
+              config.data_onmouseover.call($$.api, closest);
+              $$.mouseover = closest;
+            }
+
+            // show cursor as pointer if we're hovering a data point close enough
+            $$.svg
+              .select('.' + CLASS.eventRect)
+              .style('cursor', isMouseCloseToDataPoint ? 'pointer' : null);
+
+            // if tooltip not grouped, we want to display only data from closest data point
+            const showSingleDataPoint =
+              !config.tooltip_grouped || $$.hasType('stanford', targetsToShow);
+
+            // find data to highlight
+            let selectedData;
+            if (showSingleDataPoint) {
+              if (closest) {
+                selectedData = [closest];
+              }
+            } else {
+              let closestByX;
+              if (closest) {
+                // reuse closest value
+                closestByX = closest;
+              } else {
+                // try to find the closest value by X values from the mouse position
+                const mouseX = config.axis_rotated ? mouse[1] : mouse[0];
+                closestByX = $$.findClosestFromTargetsByX(
+                  targetsToShow,
+                  $$.x.invert(mouseX)
+                );
+              }
+
+              // highlight all data for this 'x' value
+              if (closestByX) {
+                selectedData = $$.filterByX(targetsToShow, closestByX.x);
+              }
+            }
+
+            // ensure we have data to show
+            if (!selectedData || selectedData.length === 0) {
+              return mouseout()
+            }
+
+            // inject names for each point
+            selectedData = selectedData.map(withName);
+
+            // show tooltip
+            $$.showTooltip(selectedData, this);
+
+            // expand points
+            if (config.point_focus_expand_enabled) {
+              $$.unexpandCircles();
+              selectedData.forEach(function(d) {
+                $$.expandCircles(d.index, d.id, false);
+              });
+            }
+
+            // expand bars
+            $$.unexpandBars();
+            selectedData.forEach(function(d) {
+              $$.expandBars(d.index, d.id, false);
+            });
+
+            // Show xgrid focus line
+            $$.showXGridFocus(selectedData);
+          }
+        : null
+    )
+    .on(
+      'click',
+      config.interaction_enabled
+        ? function() {
+            const targetsToShow = $$.getTargetsToShow();
+
+            if ($$.hasArcType(targetsToShow)) {
+              return
+            }
+
+            const mouse = d3.mouse(this);
+            const closest = withName(
+              $$.findClosestFromTargets(targetsToShow, mouse)
+            );
+
+            if (!isHoveringDataPoint(mouse, closest)) {
+              return
+            }
+
+            // select if selection enabled
+            let sameXData;
+            if (!config.data_selection_grouped || $$.isStanfordType(closest)) {
+              sameXData = [closest];
+            } else {
+              sameXData = $$.filterByX(targetsToShow, closest.x);
+            }
+
+            // toggle selected state
+            sameXData.forEach(function(d) {
+              $$.main
+                .selectAll(
+                  '.' + CLASS.shapes + $$.getTargetSelectorSuffix(d.id)
+                )
+                .selectAll('.' + CLASS.shape + '-' + d.index)
+                .each(function() {
+                  if (
+                    config.data_selection_grouped ||
+                    $$.isWithinShape(this, d)
+                  ) {
+                    $$.toggleShape(this, d, d.index);
+                  }
+                });
+            });
+
+            // call data_onclick on the closest data point
+            if (closest) {
+              const shape = $$.main
+                .selectAll(
+                  '.' + CLASS.shapes + $$.getTargetSelectorSuffix(closest.id)
+                )
+                .select('.' + CLASS.shape + '-' + closest.index);
+              config.data_onclick.call($$.api, closest, shape.node());
+            }
+          }
+        : null
+    )
+    .call(
+      config.interaction_enabled && config.data_selection_draggable && $$.drag
+        ? d3
+            .drag()
+            .on('drag', function() {
+              $$.drag(d3.mouse(this));
+            })
+            .on('start', function() {
+              $$.dragstart(d3.mouse(this));
+            })
+            .on('end', function() {
+              $$.dragend();
+            })
+        : function() {}
+    );
+};
+ChartInternal.prototype.getMousePosition = function(data) {
+  var $$ = this;
+  return [$$.x(data.x), $$.getYScale(data.id)(data.value)]
+};
+ChartInternal.prototype.dispatchEvent = function(type, mouse) {
+  var $$ = this,
+    selector = '.' + CLASS.eventRect,
+    eventRect = $$.main.select(selector).node(),
+    box = eventRect.getBoundingClientRect(),
+    x = box.left + (mouse ? mouse[0] : 0),
+    y = box.top + (mouse ? mouse[1] : 0),
+    event = document.createEvent('MouseEvents');
+
+  event.initMouseEvent(
+    type,
+    true,
+    true,
+    window,
+    0,
+    x,
+    y,
+    x,
+    y,
+    false,
+    false,
+    false,
+    false,
+    0,
+    null
+  );
+  eventRect.dispatchEvent(event);
+};
+
+ChartInternal.prototype.initLegend = function() {
+  var $$ = this;
+  $$.legendItemTextBox = {};
+  $$.legendHasRendered = false;
+  $$.legend = $$.svg.append('g').attr('transform', $$.getTranslate('legend'));
+  if (!$$.config.legend_show) {
+    $$.legend.style('visibility', 'hidden');
+    $$.hiddenLegendIds = $$.mapToIds($$.data.targets);
+    return
+  }
+  // MEMO: call here to update legend box and tranlate for all
+  // MEMO: translate will be updated by this, so transform not needed in updateLegend()
+  $$.updateLegendWithDefaults();
+};
+ChartInternal.prototype.updateLegendWithDefaults = function() {
+  var $$ = this;
+  $$.updateLegend($$.mapToIds($$.data.targets), {
+    withTransform: false,
+    withTransitionForTransform: false,
+    withTransition: false
+  });
+};
+ChartInternal.prototype.updateSizeForLegend = function(
+  legendHeight,
+  legendWidth
+) {
+  var $$ = this,
+    config = $$.config,
+    insetLegendPosition = {
+      top: $$.isLegendTop
+        ? $$.getCurrentPaddingTop() + config.legend_inset_y + 5.5
+        : $$.currentHeight -
+          legendHeight -
+          $$.getCurrentPaddingBottom() -
+          config.legend_inset_y,
+      left: $$.isLegendLeft
+        ? $$.getCurrentPaddingLeft() + config.legend_inset_x + 0.5
+        : $$.currentWidth -
+          legendWidth -
+          $$.getCurrentPaddingRight() -
+          config.legend_inset_x +
+          0.5
+    };
+
+  $$.margin3 = {
+    top: $$.isLegendRight
+      ? 0
+      : $$.isLegendInset
+      ? insetLegendPosition.top
+      : $$.currentHeight - legendHeight,
+    right: NaN,
+    bottom: 0,
+    left: $$.isLegendRight
+      ? $$.currentWidth - legendWidth
+      : $$.isLegendInset
+      ? insetLegendPosition.left
+      : 0
+  };
+};
+ChartInternal.prototype.transformLegend = function(withTransition) {
+  var $$ = this
+  ;(withTransition ? $$.legend.transition() : $$.legend).attr(
+    'transform',
+    $$.getTranslate('legend')
+  );
+};
+ChartInternal.prototype.updateLegendStep = function(step) {
+  this.legendStep = step;
+};
+ChartInternal.prototype.updateLegendItemWidth = function(w) {
+  this.legendItemWidth = w;
+};
+ChartInternal.prototype.updateLegendItemHeight = function(h) {
+  this.legendItemHeight = h;
+};
+ChartInternal.prototype.getLegendWidth = function() {
+  var $$ = this;
+  return $$.config.legend_show
+    ? $$.isLegendRight || $$.isLegendInset
+      ? $$.legendItemWidth * ($$.legendStep + 1)
+      : $$.currentWidth
+    : 0
+};
+ChartInternal.prototype.getLegendHeight = function() {
+  var $$ = this,
+    h = 0;
+  if ($$.config.legend_show) {
+    if ($$.isLegendRight) {
+      h = $$.currentHeight;
+    } else {
+      h = Math.max(20, $$.legendItemHeight) * ($$.legendStep + 1);
+    }
+  }
+  return h
+};
+ChartInternal.prototype.opacityForLegend = function(legendItem) {
+  return legendItem.classed(CLASS.legendItemHidden) ? null : 1
+};
+ChartInternal.prototype.opacityForUnfocusedLegend = function(legendItem) {
+  return legendItem.classed(CLASS.legendItemHidden) ? null : 0.3
+};
+ChartInternal.prototype.toggleFocusLegend = function(targetIds, focus) {
+  var $$ = this;
+  targetIds = $$.mapToTargetIds(targetIds);
+  $$.legend
+    .selectAll('.' + CLASS.legendItem)
+    .filter(function(id) {
+      return targetIds.indexOf(id) >= 0
+    })
+    .classed(CLASS.legendItemFocused, focus)
+    .transition()
+    .duration(100)
+    .style('opacity', function() {
+      var opacity = focus ? $$.opacityForLegend : $$.opacityForUnfocusedLegend;
+      return opacity.call($$, $$.d3.select(this))
+    });
+};
+ChartInternal.prototype.revertLegend = function() {
+  var $$ = this,
+    d3 = $$.d3;
+  $$.legend
+    .selectAll('.' + CLASS.legendItem)
+    .classed(CLASS.legendItemFocused, false)
+    .transition()
+    .duration(100)
+    .style('opacity', function() {
+      return $$.opacityForLegend(d3.select(this))
+    });
+};
+ChartInternal.prototype.showLegend = function(targetIds) {
+  var $$ = this,
+    config = $$.config;
+  if (!config.legend_show) {
+    config.legend_show = true;
+    $$.legend.style('visibility', 'visible');
+    if (!$$.legendHasRendered) {
+      $$.updateLegendWithDefaults();
+    }
+  }
+  $$.removeHiddenLegendIds(targetIds);
+  $$.legend
+    .selectAll($$.selectorLegends(targetIds))
+    .style('visibility', 'visible')
+    .transition()
+    .style('opacity', function() {
+      return $$.opacityForLegend($$.d3.select(this))
+    });
+};
+ChartInternal.prototype.hideLegend = function(targetIds) {
+  var $$ = this,
+    config = $$.config;
+  if (config.legend_show && isEmpty(targetIds)) {
+    config.legend_show = false;
+    $$.legend.style('visibility', 'hidden');
+  }
+  $$.addHiddenLegendIds(targetIds);
+  $$.legend
+    .selectAll($$.selectorLegends(targetIds))
+    .style('opacity', 0)
+    .style('visibility', 'hidden');
+};
+ChartInternal.prototype.clearLegendItemTextBoxCache = function() {
+  this.legendItemTextBox = {};
+};
+ChartInternal.prototype.updateLegend = function(
+  targetIds,
+  options,
+  transitions
+) {
+  var $$ = this,
+    config = $$.config;
+  var xForLegend,
+    xForLegendText,
+    xForLegendRect,
+    yForLegend,
+    yForLegendText,
+    yForLegendRect,
+    x1ForLegendTile,
+    x2ForLegendTile,
+    yForLegendTile;
+  var paddingTop = 4,
+    paddingRight = 10,
+    maxWidth = 0,
+    maxHeight = 0,
+    posMin = 10,
+    tileWidth = config.legend_item_tile_width + 5;
+  var l,
+    totalLength = 0,
+    offsets = {},
+    widths = {},
+    heights = {},
+    margins = [0],
+    steps = {},
+    step = 0;
+  var withTransition, withTransitionForTransform;
+  var texts, rects, tiles, background;
+
+  // Skip elements when their name is set to null
+  targetIds = targetIds.filter(function(id) {
+    return !isDefined(config.data_names[id]) || config.data_names[id] !== null
+  });
+
+  options = options || {};
+  withTransition = getOption(options, 'withTransition', true);
+  withTransitionForTransform = getOption(
+    options,
+    'withTransitionForTransform',
+    true
+  );
+
+  function getTextBox(textElement, id) {
+    if (!$$.legendItemTextBox[id]) {
+      $$.legendItemTextBox[id] = $$.getTextRect(
+        textElement.textContent,
+        CLASS.legendItem,
+        textElement
+      );
+    }
+    return $$.legendItemTextBox[id]
+  }
+
+  function updatePositions(textElement, id, index) {
+    var reset = index === 0,
+      isLast = index === targetIds.length - 1,
+      box = getTextBox(textElement, id),
+      itemWidth =
+        box.width +
+        tileWidth +
+        (isLast && !($$.isLegendRight || $$.isLegendInset) ? 0 : paddingRight) +
+        config.legend_padding,
+      itemHeight = box.height + paddingTop,
+      itemLength =
+        $$.isLegendRight || $$.isLegendInset ? itemHeight : itemWidth,
+      areaLength =
+        $$.isLegendRight || $$.isLegendInset
+          ? $$.getLegendHeight()
+          : $$.getLegendWidth(),
+      margin,
+      maxLength;
+
+    // MEMO: care about condifion of step, totalLength
+    function updateValues(id, withoutStep) {
+      if (!withoutStep) {
+        margin = (areaLength - totalLength - itemLength) / 2;
+        if (margin < posMin) {
+          margin = (areaLength - itemLength) / 2;
+          totalLength = 0;
+          step++;
+        }
+      }
+      steps[id] = step;
+      margins[step] = $$.isLegendInset ? 10 : margin;
+      offsets[id] = totalLength;
+      totalLength += itemLength;
+    }
+
+    if (reset) {
+      totalLength = 0;
+      step = 0;
+      maxWidth = 0;
+      maxHeight = 0;
+    }
+
+    if (config.legend_show && !$$.isLegendToShow(id)) {
+      widths[id] = heights[id] = steps[id] = offsets[id] = 0;
+      return
+    }
+
+    widths[id] = itemWidth;
+    heights[id] = itemHeight;
+
+    if (!maxWidth || itemWidth >= maxWidth) {
+      maxWidth = itemWidth;
+    }
+    if (!maxHeight || itemHeight >= maxHeight) {
+      maxHeight = itemHeight;
+    }
+    maxLength = $$.isLegendRight || $$.isLegendInset ? maxHeight : maxWidth;
+
+    if (config.legend_equally) {
+      Object.keys(widths).forEach(function(id) {
+        widths[id] = maxWidth;
+      });
+      Object.keys(heights).forEach(function(id) {
+        heights[id] = maxHeight;
+      });
+      margin = (areaLength - maxLength * targetIds.length) / 2;
+      if (margin < posMin) {
+        totalLength = 0;
+        step = 0;
+        targetIds.forEach(function(id) {
+          updateValues(id);
+        });
+      } else {
+        updateValues(id, true);
+      }
+    } else {
+      updateValues(id);
+    }
+  }
+
+  if ($$.isLegendInset) {
+    step = config.legend_inset_step
+      ? config.legend_inset_step
+      : targetIds.length;
+    $$.updateLegendStep(step);
+  }
+
+  if ($$.isLegendRight) {
+    xForLegend = function(id) {
+      return maxWidth * steps[id]
+    };
+    yForLegend = function(id) {
+      return margins[steps[id]] + offsets[id]
+    };
+  } else if ($$.isLegendInset) {
+    xForLegend = function(id) {
+      return maxWidth * steps[id] + 10
+    };
+    yForLegend = function(id) {
+      return margins[steps[id]] + offsets[id]
+    };
+  } else {
+    xForLegend = function(id) {
+      return margins[steps[id]] + offsets[id]
+    };
+    yForLegend = function(id) {
+      return maxHeight * steps[id]
+    };
+  }
+  xForLegendText = function(id, i) {
+    return xForLegend(id, i) + 4 + config.legend_item_tile_width
+  };
+  yForLegendText = function(id, i) {
+    return yForLegend(id, i) + 9
+  };
+  xForLegendRect = function(id, i) {
+    return xForLegend(id, i)
+  };
+  yForLegendRect = function(id, i) {
+    return yForLegend(id, i) - 5
+  };
+  x1ForLegendTile = function(id, i) {
+    return xForLegend(id, i) - 2
+  };
+  x2ForLegendTile = function(id, i) {
+    return xForLegend(id, i) - 2 + config.legend_item_tile_width
+  };
+  yForLegendTile = function(id, i) {
+    return yForLegend(id, i) + 4
+  };
+
+  // Define g for legend area
+  l = $$.legend
+    .selectAll('.' + CLASS.legendItem)
+    .data(targetIds)
+    .enter()
+    .append('g')
+    .attr('class', function(id) {
+      return $$.generateClass(CLASS.legendItem, id)
+    })
+    .style('visibility', function(id) {
+      return $$.isLegendToShow(id) ? 'visible' : 'hidden'
+    })
+    .style('cursor', function() {
+      return config.interaction_enabled ? 'pointer' : 'auto'
+    })
+    .on(
+      'click',
+      config.interaction_enabled
+        ? function(id) {
+            if (config.legend_item_onclick) {
+              config.legend_item_onclick.call($$, id);
+            } else {
+              if ($$.d3.event.altKey) {
+                $$.api.hide();
+                $$.api.show(id);
+              } else {
+                $$.api.toggle(id);
+                $$.isTargetToShow(id) ? $$.api.focus(id) : $$.api.revert();
+              }
+            }
+          }
+        : null
+    )
+    .on(
+      'mouseover',
+      config.interaction_enabled
+        ? function(id) {
+            if (config.legend_item_onmouseover) {
+              config.legend_item_onmouseover.call($$, id);
+            } else {
+              $$.d3.select(this).classed(CLASS.legendItemFocused, true);
+              if (!$$.transiting && $$.isTargetToShow(id)) {
+                $$.api.focus(id);
+              }
+            }
+          }
+        : null
+    )
+    .on(
+      'mouseout',
+      config.interaction_enabled
+        ? function(id) {
+            if (config.legend_item_onmouseout) {
+              config.legend_item_onmouseout.call($$, id);
+            } else {
+              $$.d3.select(this).classed(CLASS.legendItemFocused, false);
+              $$.api.revert();
+            }
+          }
+        : null
+    );
+
+  l.append('text')
+    .text(function(id) {
+      return isDefined(config.data_names[id]) ? config.data_names[id] : id
+    })
+    .each(function(id, i) {
+      updatePositions(this, id, i);
+    })
+    .style('pointer-events', 'none')
+    .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200)
+    .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendText);
+
+  l.append('rect')
+    .attr('class', CLASS.legendItemEvent)
+    .style('fill-opacity', 0)
+    .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendRect : -200)
+    .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendRect);
+
+  l.append('line')
+    .attr('class', CLASS.legendItemTile)
+    .style('stroke', $$.color)
+    .style('pointer-events', 'none')
+    .attr('x1', $$.isLegendRight || $$.isLegendInset ? x1ForLegendTile : -200)
+    .attr('y1', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile)
+    .attr('x2', $$.isLegendRight || $$.isLegendInset ? x2ForLegendTile : -200)
+    .attr('y2', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile)
+    .attr('stroke-width', config.legend_item_tile_height);
+
+  // Set background for inset legend
+  background = $$.legend.select('.' + CLASS.legendBackground + ' rect');
+  if ($$.isLegendInset && maxWidth > 0 && background.size() === 0) {
+    background = $$.legend
+      .insert('g', '.' + CLASS.legendItem)
+      .attr('class', CLASS.legendBackground)
+      .append('rect');
+  }
+
+  texts = $$.legend
+    .selectAll('text')
+    .data(targetIds)
+    .text(function(id) {
+      return isDefined(config.data_names[id]) ? config.data_names[id] : id
+    }) // MEMO: needed for update
+    .each(function(id, i) {
+      updatePositions(this, id, i);
+    })
+  ;(withTransition ? texts.transition() : texts)
+    .attr('x', xForLegendText)
+    .attr('y', yForLegendText);
+
+  rects = $$.legend.selectAll('rect.' + CLASS.legendItemEvent).data(targetIds)
+  ;(withTransition ? rects.transition() : rects)
+    .attr('width', function(id) {
+      return widths[id]
+    })
+    .attr('height', function(id) {
+      return heights[id]
+    })
+    .attr('x', xForLegendRect)
+    .attr('y', yForLegendRect);
+
+  tiles = $$.legend.selectAll('line.' + CLASS.legendItemTile).data(targetIds)
+  ;(withTransition ? tiles.transition() : tiles)
+    .style(
+      'stroke',
+      $$.levelColor
+        ? function(id) {
+            return $$.levelColor(
+              $$.cache[id].values.reduce(function(total, item) {
+                return total + item.value
+              }, 0)
+            )
+          }
+        : $$.color
+    )
+    .attr('x1', x1ForLegendTile)
+    .attr('y1', yForLegendTile)
+    .attr('x2', x2ForLegendTile)
+    .attr('y2', yForLegendTile);
+
+  if (background) {
+(withTransition ? background.transition() : background)
+      .attr('height', $$.getLegendHeight() - 12)
+      .attr('width', maxWidth * (step + 1) + 10);
+  }
+
+  // toggle legend state
+  $$.legend
+    .selectAll('.' + CLASS.legendItem)
+    .classed(CLASS.legendItemHidden, function(id) {
+      return !$$.isTargetToShow(id)
+    });
+
+  // Update all to reflect change of legend
+  $$.updateLegendItemWidth(maxWidth);
+  $$.updateLegendItemHeight(maxHeight);
+  $$.updateLegendStep(step);
+  // Update size and scale
+  $$.updateSizes();
+  $$.updateScales();
+  $$.updateSvgSize();
+  // Update g positions
+  $$.transformAll(withTransitionForTransform, transitions);
+  $$.legendHasRendered = true;
+};
+
+ChartInternal.prototype.initRegion = function() {
+  var $$ = this;
+  $$.region = $$.main
+    .append('g')
+    .attr('clip-path', $$.clipPath)
+    .attr('class', CLASS.regions);
+};
+ChartInternal.prototype.updateRegion = function(duration) {
+  var $$ = this,
+    config = $$.config;
+
+  // hide if arc type
+  $$.region.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');
+
+  var mainRegion = $$.main
+    .select('.' + CLASS.regions)
+    .selectAll('.' + CLASS.region)
+    .data(config.regions);
+  var g = mainRegion.enter().append('g');
+  g.append('rect')
+    .attr('x', $$.regionX.bind($$))
+    .attr('y', $$.regionY.bind($$))
+    .attr('width', $$.regionWidth.bind($$))
+    .attr('height', $$.regionHeight.bind($$))
+    .style('fill-opacity', function(d) {
+      return isValue(d.opacity) ? d.opacity : 0.1
+    });
+  g.append('text').text($$.labelRegion.bind($$));
+  $$.mainRegion = g.merge(mainRegion).attr('class', $$.classRegion.bind($$));
+  mainRegion
+    .exit()
+    .transition()
+    .duration(duration)
+    .style('opacity', 0)
+    .remove();
+};
+ChartInternal.prototype.redrawRegion = function(withTransition, transition) {
+  var $$ = this,
+    regions = $$.mainRegion,
+    regionLabels = $$.mainRegion.selectAll('text');
+  return [
+    (withTransition ? regions.transition(transition) : regions)
+      .attr('x', $$.regionX.bind($$))
+      .attr('y', $$.regionY.bind($$))
+      .attr('width', $$.regionWidth.bind($$))
+      .attr('height', $$.regionHeight.bind($$))
+      .style('fill-opacity', function(d) {
+        return isValue(d.opacity) ? d.opacity : 0.1
+      }),
+    (withTransition ? regionLabels.transition(transition) : regionLabels)
+      .attr('x', $$.labelOffsetX.bind($$))
+      .attr('y', $$.labelOffsetY.bind($$))
+      .attr('transform', $$.labelTransform.bind($$))
+      .attr('style', 'text-anchor: left;')
+  ]
+};
+ChartInternal.prototype.regionX = function(d) {
+  var $$ = this,
+    config = $$.config,
+    xPos,
+    yScale = d.axis === 'y' ? $$.y : $$.y2;
+  if (d.axis === 'y' || d.axis === 'y2') {
+    xPos = config.axis_rotated ? ('start' in d ? yScale(d.start) : 0) : 0;
+  } else {
+    xPos = config.axis_rotated
+      ? 0
+      : 'start' in d
+      ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start)
+      : 0;
+  }
+  return xPos
+};
+ChartInternal.prototype.regionY = function(d) {
+  var $$ = this,
+    config = $$.config,
+    yPos,
+    yScale = d.axis === 'y' ? $$.y : $$.y2;
+  if (d.axis === 'y' || d.axis === 'y2') {
+    yPos = config.axis_rotated ? 0 : 'end' in d ? yScale(d.end) : 0;
+  } else {
+    yPos = config.axis_rotated
+      ? 'start' in d
+        ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start)
+        : 0
+      : 0;
+  }
+  return yPos
+};
+ChartInternal.prototype.regionWidth = function(d) {
+  var $$ = this,
+    config = $$.config,
+    start = $$.regionX(d),
+    end,
+    yScale = d.axis === 'y' ? $$.y : $$.y2;
+  if (d.axis === 'y' || d.axis === 'y2') {
+    end = config.axis_rotated
+      ? 'end' in d
+        ? yScale(d.end)
+        : $$.width
+      : $$.width;
+  } else {
+    end = config.axis_rotated
+      ? $$.width
+      : 'end' in d
+      ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end)
+      : $$.width;
+  }
+  return end < start ? 0 : end - start
+};
+ChartInternal.prototype.regionHeight = function(d) {
+  var $$ = this,
+    config = $$.config,
+    start = this.regionY(d),
+    end,
+    yScale = d.axis === 'y' ? $$.y : $$.y2;
+  if (d.axis === 'y' || d.axis === 'y2') {
+    end = config.axis_rotated
+      ? $$.height
+      : 'start' in d
+      ? yScale(d.start)
+      : $$.height;
+  } else {
+    end = config.axis_rotated
+      ? 'end' in d
+        ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end)
+        : $$.height
+      : $$.height;
+  }
+  return end < start ? 0 : end - start
+};
+ChartInternal.prototype.isRegionOnX = function(d) {
+  return !d.axis || d.axis === 'x'
+};
+ChartInternal.prototype.labelRegion = function(d) {
+  return 'label' in d ? d.label : ''
+};
+ChartInternal.prototype.labelTransform = function(d) {
+  return 'vertical' in d && d.vertical ? 'rotate(90)' : ''
+};
+ChartInternal.prototype.labelOffsetX = function(d) {
+  var paddingX = 'paddingX' in d ? d.paddingX : 3;
+  var paddingY = 'paddingY' in d ? d.paddingY : 3;
+  return 'vertical' in d && d.vertical
+    ? this.regionY(d) + paddingY
+    : this.regionX(d) + paddingX
+};
+ChartInternal.prototype.labelOffsetY = function(d) {
+  var paddingX = 'paddingX' in d ? d.paddingX : 3;
+  var paddingY = 'paddingY' in d ? d.paddingY : 3;
+  return 'vertical' in d && d.vertical
+    ? -(this.regionX(d) + paddingX)
+    : this.regionY(d) + 10 + paddingY
+};
+
+function c3LogScale(d3, linearScale, logScale) {
+  var PROJECTION = [0.01, 10];
+
+  if (!linearScale) {
+    linearScale = d3.scaleLinear();
+    linearScale.range(PROJECTION);
+  }
+
+  if (!logScale) {
+    logScale = d3.scaleLog();
+    logScale.domain(PROJECTION);
+    logScale.nice();
+  }
+
+  // copied from https://github.com/compute-io/logspace
+  function logspace(a, b, len) {
+    var arr, end, tmp, d;
+
+    if (arguments.length < 3) {
+      len = 10;
+    } else {
+      if (len === 0) {
+        return []
+      }
+    }
+    // Calculate the increment:
+    end = len - 1;
+    d = (b - a) / end;
+
+    // Build the output array...
+    arr = new Array(len);
+    tmp = a;
+    arr[0] = Math.pow(10, tmp);
+    for (var i = 1; i < end; i++) {
+      tmp += d;
+      arr[i] = Math.pow(10, tmp);
+    }
+    arr[end] = Math.pow(10, b);
+    return arr
+  }
+
+  function scale(x) {
+    return logScale(linearScale(x))
+  }
+
+  scale.domain = function(x) {
+    if (!arguments.length) {
+      return linearScale.domain()
+    }
+    linearScale.domain(x);
+    return scale
+  };
+
+  scale.range = function(x) {
+    if (!arguments.length) {
+      return logScale.range()
+    }
+    logScale.range(x);
+    return scale
+  };
+
+  scale.ticks = function(m) {
+    return logspace(-2, 1, m || 10).map(function(v) {
+      return linearScale.invert(v)
+    })
+  };
+
+  scale.copy = function() {
+    return c3LogScale(d3, linearScale.copy(), logScale.copy())
+  };
+
+  return scale
+}
+
+ChartInternal.prototype.getScale = function(min, max, forTimeseries) {
+  return (forTimeseries ? this.d3.scaleTime() : this.d3.scaleLinear()).range([
+    min,
+    max
+  ])
+};
+ChartInternal.prototype.getX = function(min, max, domain, offset) {
+  var $$ = this,
+    scale = $$.getScale(min, max, $$.isTimeSeries()),
+    _scale = domain ? scale.domain(domain) : scale,
+    key;
+  // Define customized scale if categorized axis
+  if ($$.isCategorized()) {
+    offset =
+      offset ||
+      function() {
+        return 0
+      };
+    scale = function(d, raw) {
+      var v = _scale(d) + offset(d);
+      return raw ? v : Math.ceil(v)
+    };
+  } else {
+    scale = function(d, raw) {
+      var v = _scale(d);
+      return raw ? v : Math.ceil(v)
+    };
+  }
+  // define functions
+  for (key in _scale) {
+    scale[key] = _scale[key];
+  }
+  scale.orgDomain = function() {
+    return _scale.domain()
+  };
+  // define custom domain() for categorized axis
+  if ($$.isCategorized()) {
+    scale.domain = function(domain) {
+      if (!arguments.length) {
+        domain = this.orgDomain();
+        return [domain[0], domain[1] + 1]
+      }
+      _scale.domain(domain);
+      return scale
+    };
+  }
+  return scale
+};
+
+/**
+ * Creates and configures a D3 scale instance for the given type.
+ *
+ * By defaults it returns a Linear scale.
+ *
+ * @param {String} type Type of d3-scale to create. Type can be 'linear', 'time', 'timeseries' or 'log'.
+ * @param {Array} domain The scale domain such as [from, to]
+ * @param {Array} range The scale's range such as [from, to]
+ *
+ * @return A d3-scale instance
+ */
+ChartInternal.prototype.getY = function(type, domain, range) {
+  let scale;
+  if (type === 'timeseries' || type === 'time') {
+    scale = this.d3.scaleTime();
+  } else if (type === 'log') {
+    scale = c3LogScale(this.d3);
+  } else if (type === 'linear' || type === undefined) {
+    scale = this.d3.scaleLinear();
+  } else {
+    throw new Error(`Invalid Y axis type: "${type}"`)
+  }
+
+  if (domain) {
+    scale.domain(domain);
+  }
+
+  if (range) {
+    scale.range(range);
+  }
+
+  return scale
+};
+ChartInternal.prototype.getYScale = function(id) {
+  return this.axis.getId(id) === 'y2' ? this.y2 : this.y
+};
+ChartInternal.prototype.getSubYScale = function(id) {
+  return this.axis.getId(id) === 'y2' ? this.subY2 : this.subY
+};
+ChartInternal.prototype.updateScales = function() {
+  var $$ = this,
+    config = $$.config,
+    forInit = !$$.x;
+  // update edges
+  $$.xMin = config.axis_rotated ? 1 : 0;
+  $$.xMax = config.axis_rotated ? $$.height : $$.width;
+  $$.yMin = config.axis_rotated ? 0 : $$.height;
+  $$.yMax = config.axis_rotated ? $$.width : 1;
+  $$.subXMin = $$.xMin;
+  $$.subXMax = $$.xMax;
+  $$.subYMin = config.axis_rotated ? 0 : $$.height2;
+  $$.subYMax = config.axis_rotated ? $$.width2 : 1;
+  // update scales
+  $$.x = $$.getX(
+    $$.xMin,
+    $$.xMax,
+    forInit ? undefined : $$.x.orgDomain(),
+    function() {
+      return $$.xAxis.tickOffset()
+    }
+  );
+  $$.y = $$.getY(
+    config.axis_y_type,
+    forInit ? config.axis_y_default : $$.y.domain(),
+    [$$.yMin, $$.yMax]
+  );
+  $$.y2 = $$.getY(
+    config.axis_y2_type,
+    forInit ? config.axis_y2_default : $$.y2.domain(),
+    [$$.yMin, $$.yMax]
+  );
+  $$.subX = $$.getX($$.xMin, $$.xMax, $$.orgXDomain, function(d) {
+    return d % 1 ? 0 : $$.subXAxis.tickOffset()
+  });
+  $$.subY = $$.getY(
+    config.axis_y_type,
+    forInit ? config.axis_y_default : $$.subY.domain(),
+    [$$.subYMin, $$.subYMax]
+  );
+  $$.subY2 = $$.getY(
+    config.axis_y2_type,
+    forInit ? config.axis_y2_default : $$.subY2.domain(),
+    [$$.subYMin, $$.subYMax]
+  );
+  // update axes
+  $$.xAxisTickFormat = $$.axis.getXAxisTickFormat();
+  $$.xAxisTickValues = $$.axis.getXAxisTickValues();
+  $$.yAxisTickValues = $$.axis.getYAxisTickValues();
+  $$.y2AxisTickValues = $$.axis.getY2AxisTickValues();
+
+  $$.xAxis = $$.axis.getXAxis(
+    $$.x,
+    $$.xOrient,
+    $$.xAxisTickFormat,
+    $$.xAxisTickValues,
+    config.axis_x_tick_outer
+  );
+  $$.subXAxis = $$.axis.getXAxis(
+    $$.subX,
+    $$.subXOrient,
+    $$.xAxisTickFormat,
+    $$.xAxisTickValues,
+    config.axis_x_tick_outer
+  );
+  $$.yAxis = $$.axis.getYAxis(
+    'y',
+    $$.y,
+    $$.yOrient,
+    $$.yAxisTickValues,
+    config.axis_y_tick_outer
+  );
+  $$.y2Axis = $$.axis.getYAxis(
+    'y2',
+    $$.y2,
+    $$.y2Orient,
+    $$.y2AxisTickValues,
+    config.axis_y2_tick_outer
+  );
+
+  // Set initialized scales to brush and zoom
+  if (!forInit) {
+    if ($$.brush) {
+      $$.brush.updateScale($$.subX);
+    }
+  }
+  // update for arc
+  if ($$.updateArc) {
+    $$.updateArc();
+  }
+};
+
+ChartInternal.prototype.selectPoint = function(target, d, i) {
+  var $$ = this,
+    config = $$.config,
+    cx = (config.axis_rotated ? $$.circleY : $$.circleX).bind($$),
+    cy = (config.axis_rotated ? $$.circleX : $$.circleY).bind($$),
+    r = $$.pointSelectR.bind($$);
+  config.data_onselected.call($$.api, d, target.node());
+  // add selected-circle on low layer g
+  $$.main
+    .select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id))
+    .selectAll('.' + CLASS.selectedCircle + '-' + i)
+    .data([d])
+    .enter()
+    .append('circle')
+    .attr('class', function() {
+      return $$.generateClass(CLASS.selectedCircle, i)
+    })
+    .attr('cx', cx)
+    .attr('cy', cy)
+    .attr('stroke', function() {
+      return $$.color(d)
+    })
+    .attr('r', function(d) {
+      return $$.pointSelectR(d) * 1.4
+    })
+    .transition()
+    .duration(100)
+    .attr('r', r);
+};
+ChartInternal.prototype.unselectPoint = function(target, d, i) {
+  var $$ = this;
+  $$.config.data_onunselected.call($$.api, d, target.node());
+  // remove selected-circle from low layer g
+  $$.main
+    .select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id))
+    .selectAll('.' + CLASS.selectedCircle + '-' + i)
+    .transition()
+    .duration(100)
+    .attr('r', 0)
+    .remove();
+};
+ChartInternal.prototype.togglePoint = function(selected, target, d, i) {
+  selected ? this.selectPoint(target, d, i) : this.unselectPoint(target, d, i);
+};
+ChartInternal.prototype.selectPath = function(target, d) {
+  var $$ = this;
+  $$.config.data_onselected.call($$, d, target.node());
+  if ($$.config.interaction_brighten) {
+    target
+      .transition()
+      .duration(100)
+      .style('fill', function() {
+        return $$.d3.rgb($$.color(d)).brighter(0.75)
+      });
+  }
+};
+ChartInternal.prototype.unselectPath = function(target, d) {
+  var $$ = this;
+  $$.config.data_onunselected.call($$, d, target.node());
+  if ($$.config.interaction_brighten) {
+    target
+      .transition()
+      .duration(100)
+      .style('fill', function() {
+        return $$.color(d)
+      });
+  }
+};
+ChartInternal.prototype.togglePath = function(selected, target, d, i) {
+  selected ? this.selectPath(target, d, i) : this.unselectPath(target, d, i);
+};
+ChartInternal.prototype.getToggle = function(that, d) {
+  var $$ = this,
+    toggle;
+  if (that.nodeName === 'circle') {
+    if ($$.isStepType(d)) {
+      // circle is hidden in step chart, so treat as within the click area
+      toggle = function() {}; // TODO: how to select step chart?
+    } else {
+      toggle = $$.togglePoint;
+    }
+  } else if (that.nodeName === 'path') {
+    toggle = $$.togglePath;
+  }
+  return toggle
+};
+ChartInternal.prototype.toggleShape = function(that, d, i) {
+  var $$ = this,
+    d3 = $$.d3,
+    config = $$.config,
+    shape = d3.select(that),
+    isSelected = shape.classed(CLASS.SELECTED),
+    toggle = $$.getToggle(that, d).bind($$);
+
+  if (config.data_selection_enabled && config.data_selection_isselectable(d)) {
+    if (!config.data_selection_multiple) {
+      $$.main
+        .selectAll(
+          '.' +
+            CLASS.shapes +
+            (config.data_selection_grouped
+              ? $$.getTargetSelectorSuffix(d.id)
+              : '')
+        )
+        .selectAll('.' + CLASS.shape)
+        .each(function(d, i) {
+          var shape = d3.select(this);
+          if (shape.classed(CLASS.SELECTED)) {
+            toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
+          }
+        });
+    }
+    shape.classed(CLASS.SELECTED, !isSelected);
+    toggle(!isSelected, shape, d, i);
+  }
+};
+
+ChartInternal.prototype.initBar = function() {
+  var $$ = this;
+  $$.main
+    .select('.' + CLASS.chart)
+    .append('g')
+    .attr('class', CLASS.chartBars);
+};
+ChartInternal.prototype.updateTargetsForBar = function(targets) {
+  var $$ = this,
+    config = $$.config,
+    mainBars,
+    mainBarEnter,
+    classChartBar = $$.classChartBar.bind($$),
+    classBars = $$.classBars.bind($$),
+    classFocus = $$.classFocus.bind($$);
+  mainBars = $$.main
+    .select('.' + CLASS.chartBars)
+    .selectAll('.' + CLASS.chartBar)
+    .data(targets)
+    .attr('class', function(d) {
+      return classChartBar(d) + classFocus(d)
+    });
+  mainBarEnter = mainBars
+    .enter()
+    .append('g')
+    .attr('class', classChartBar)
+    .style('pointer-events', 'none');
+  // Bars for each data
+  mainBarEnter
+    .append('g')
+    .attr('class', classBars)
+    .style('cursor', function(d) {
+      return config.data_selection_isselectable(d) ? 'pointer' : null
+    });
+};
+ChartInternal.prototype.updateBar = function(durationForExit) {
+  var $$ = this,
+    barData = $$.barData.bind($$),
+    classBar = $$.classBar.bind($$),
+    initialOpacity = $$.initialOpacity.bind($$),
+    color = function(d) {
+      return $$.color(d.id)
+    };
+  var mainBar = $$.main
+    .selectAll('.' + CLASS.bars)
+    .selectAll('.' + CLASS.bar)
+    .data(barData);
+  var mainBarEnter = mainBar
+    .enter()
+    .append('path')
+    .attr('class', classBar)
+    .style('stroke', color)
+    .style('fill', color);
+  $$.mainBar = mainBarEnter.merge(mainBar).style('opacity', initialOpacity);
+  mainBar
+    .exit()
+    .transition()
+    .duration(durationForExit)
+    .style('opacity', 0);
+};
+ChartInternal.prototype.redrawBar = function(
+  drawBar,
+  withTransition,
+  transition
+) {
+  const $$ = this;
+
+  return [
+    (withTransition ? this.mainBar.transition(transition) : this.mainBar)
+      .attr('d', drawBar)
+      .style('stroke', this.color)
+      .style('fill', this.color)
+      .style('opacity', d => ($$.isTargetToShow(d.id) ? 1 : 0))
+  ]
+};
+ChartInternal.prototype.getBarW = function(axis, barTargetsNum) {
+  var $$ = this,
+    config = $$.config,
+    w =
+      typeof config.bar_width === 'number'
+        ? config.bar_width
+        : barTargetsNum
+        ? (axis.tickInterval() * config.bar_width_ratio) / barTargetsNum
+        : 0;
+  return config.bar_width_max && w > config.bar_width_max
+    ? config.bar_width_max
+    : w
+};
+ChartInternal.prototype.getBars = function(i, id) {
+  var $$ = this;
+  return (id
+    ? $$.main.selectAll('.' + CLASS.bars + $$.getTargetSelectorSuffix(id))
+    : $$.main
+  ).selectAll('.' + CLASS.bar + (isValue(i) ? '-' + i : ''))
+};
+ChartInternal.prototype.expandBars = function(i, id, reset) {
+  var $$ = this;
+  if (reset) {
+    $$.unexpandBars();
+  }
+  $$.getBars(i, id).classed(CLASS.EXPANDED, true);
+};
+ChartInternal.prototype.unexpandBars = function(i) {
+  var $$ = this;
+  $$.getBars(i).classed(CLASS.EXPANDED, false);
+};
+ChartInternal.prototype.generateDrawBar = function(barIndices, isSub) {
+  var $$ = this,
+    config = $$.config,
+    getPoints = $$.generateGetBarPoints(barIndices, isSub);
+  return function(d, i) {
+    // 4 points that make a bar
+    var points = getPoints(d, i);
+
+    // switch points if axis is rotated, not applicable for sub chart
+    var indexX = config.axis_rotated ? 1 : 0;
+    var indexY = config.axis_rotated ? 0 : 1;
+
+    var path =
+      'M ' +
+      points[0][indexX] +
+      ',' +
+      points[0][indexY] +
+      ' ' +
+      'L' +
+      points[1][indexX] +
+      ',' +
+      points[1][indexY] +
+      ' ' +
+      'L' +
+      points[2][indexX] +
+      ',' +
+      points[2][indexY] +
+      ' ' +
+      'L' +
+      points[3][indexX] +
+      ',' +
+      points[3][indexY] +
+      ' ' +
+      'z';
+
+    return path
+  }
+};
+ChartInternal.prototype.generateGetBarPoints = function(barIndices, isSub) {
+  var $$ = this,
+    axis = isSub ? $$.subXAxis : $$.xAxis,
+    barTargetsNum = barIndices.__max__ + 1,
+    barW = $$.getBarW(axis, barTargetsNum),
+    barX = $$.getShapeX(barW, barTargetsNum, barIndices, !!isSub),
+    barY = $$.getShapeY(!!isSub),
+    barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub),
+    barSpaceOffset = barW * ($$.config.bar_space / 2),
+    yScale = isSub ? $$.getSubYScale : $$.getYScale;
+  return function(d, i) {
+    var y0 = yScale.call($$, d.id)(0),
+      offset = barOffset(d, i) || y0, // offset is for stacked bar chart
+      posX = barX(d),
+      posY = barY(d);
+    // fix posY not to overflow opposite quadrant
+    if ($$.config.axis_rotated) {
+      if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) {
+        posY = y0;
+      }
+    }
+
+    posY -= y0 - offset;
+
+    // 4 points that make a bar
+    return [
+      [posX + barSpaceOffset, offset],
+      [posX + barSpaceOffset, posY],
+      [posX + barW - barSpaceOffset, posY],
+      [posX + barW - barSpaceOffset, offset]
+    ]
+  }
+};
+
+/**
+ * Returns whether the data point is within the given bar shape.
+ *
+ * @param mouse
+ * @param barShape
+ * @return {boolean}
+ */
+ChartInternal.prototype.isWithinBar = function(mouse, barShape) {
+  return isWithinBox(mouse, getBBox(barShape), 2)
+};
+
+ChartInternal.prototype.getShapeIndices = function(typeFilter) {
+  var $$ = this,
+    config = $$.config,
+    indices = {},
+    i = 0,
+    j,
+    k;
+  $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)).forEach(
+    function(d) {
+      for (j = 0; j < config.data_groups.length; j++) {
+        if (config.data_groups[j].indexOf(d.id) < 0) {
+          continue
+        }
+        for (k = 0; k < config.data_groups[j].length; k++) {
+          if (config.data_groups[j][k] in indices) {
+            indices[d.id] = indices[config.data_groups[j][k]];
+            break
+          }
+        }
+      }
+      if (isUndefined(indices[d.id])) {
+        indices[d.id] = i++;
+      }
+    }
+  );
+  indices.__max__ = i - 1;
+  return indices
+};
+ChartInternal.prototype.getShapeX = function(
+  offset,
+  targetsNum,
+  indices,
+  isSub
+) {
+  var $$ = this,
+    scale = isSub ? $$.subX : $$.x;
+  return function(d) {
+    var index = d.id in indices ? indices[d.id] : 0;
+    return d.x || d.x === 0 ? scale(d.x) - offset * (targetsNum / 2 - index) : 0
+  }
+};
+ChartInternal.prototype.getShapeY = function(isSub) {
+  const $$ = this;
+
+  return function(d) {
+    const scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id);
+    return scale(
+      $$.isTargetNormalized(d.id) ? $$.getRatio('index', d, true) : d.value
+    )
+  }
+};
+ChartInternal.prototype.getShapeOffset = function(typeFilter, indices, isSub) {
+  var $$ = this,
+    targets = $$.orderTargets(
+      $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))
+    ),
+    targetIds = targets.map(function(t) {
+      return t.id
+    });
+  return function(d, i) {
+    var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id),
+      y0 = scale(0),
+      offset = y0;
+    targets.forEach(function(t) {
+      const rowValues = $$.isStepType(d)
+        ? $$.convertValuesToStep(t.values)
+        : t.values;
+      const isTargetNormalized = $$.isTargetNormalized(d.id);
+      const values = rowValues.map(v =>
+        isTargetNormalized ? $$.getRatio('index', v, true) : v.value
+      );
+
+      if (t.id === d.id || indices[t.id] !== indices[d.id]) {
+        return
+      }
+      if (targetIds.indexOf(t.id) < targetIds.indexOf(d.id)) {
+        // check if the x values line up
+        if (isUndefined(rowValues[i]) || +rowValues[i].x !== +d.x) {
+          // "+" for timeseries
+          // if not, try to find the value that does line up
+          i = -1;
+          rowValues.forEach(function(v, j) {
+            const x1 = v.x.constructor === Date ? +v.x : v.x;
+            const x2 = d.x.constructor === Date ? +d.x : d.x;
+
+            if (x1 === x2) {
+              i = j;
+            }
+          });
+        }
+        if (i in rowValues && rowValues[i].value * d.value >= 0) {
+          offset += scale(values[i]) - y0;
+        }
+      }
+    });
+    return offset
+  }
+};
+ChartInternal.prototype.isWithinShape = function(that, d) {
+  var $$ = this,
+    shape = $$.d3.select(that),
+    isWithin;
+  if (!$$.isTargetToShow(d.id)) {
+    isWithin = false;
+  } else if (that.nodeName === 'circle') {
+    isWithin = $$.isStepType(d)
+      ? $$.isWithinStep(that, $$.getYScale(d.id)(d.value))
+      : $$.isWithinCircle(that, $$.pointSelectR(d) * 1.5);
+  } else if (that.nodeName === 'path') {
+    isWithin = shape.classed(CLASS.bar)
+      ? $$.isWithinBar($$.d3.mouse(that), that)
+      : true;
+  }
+  return isWithin
+};
+
+ChartInternal.prototype.getInterpolate = function(d) {
+  var $$ = this,
+    d3 = $$.d3,
+    types = {
+      linear: d3.curveLinear,
+      'linear-closed': d3.curveLinearClosed,
+      basis: d3.curveBasis,
+      'basis-open': d3.curveBasisOpen,
+      'basis-closed': d3.curveBasisClosed,
+      bundle: d3.curveBundle,
+      cardinal: d3.curveCardinal,
+      'cardinal-open': d3.curveCardinalOpen,
+      'cardinal-closed': d3.curveCardinalClosed,
+      monotone: d3.curveMonotoneX,
+      step: d3.curveStep,
+      'step-before': d3.curveStepBefore,
+      'step-after': d3.curveStepAfter
+    },
+    type;
+
+  if ($$.isSplineType(d)) {
+    type = types[$$.config.spline_interpolation_type] || types.cardinal;
+  } else if ($$.isStepType(d)) {
+    type = types[$$.config.line_step_type];
+  } else {
+    type = types.linear;
+  }
+  return type
+};
+
+ChartInternal.prototype.initLine = function() {
+  var $$ = this;
+  $$.main
+    .select('.' + CLASS.chart)
+    .append('g')
+    .attr('class', CLASS.chartLines);
+};
+ChartInternal.prototype.updateTargetsForLine = function(targets) {
+  var $$ = this,
+    config = $$.config,
+    mainLines,
+    mainLineEnter,
+    classChartLine = $$.classChartLine.bind($$),
+    classLines = $$.classLines.bind($$),
+    classAreas = $$.classAreas.bind($$),
+    classCircles = $$.classCircles.bind($$),
+    classFocus = $$.classFocus.bind($$);
+  mainLines = $$.main
+    .select('.' + CLASS.chartLines)
+    .selectAll('.' + CLASS.chartLine)
+    .data(targets)
+    .attr('class', function(d) {
+      return classChartLine(d) + classFocus(d)
+    });
+  mainLineEnter = mainLines
+    .enter()
+    .append('g')
+    .attr('class', classChartLine)
+    .style('opacity', 0)
+    .style('pointer-events', 'none');
+  // Lines for each data
+  mainLineEnter.append('g').attr('class', classLines);
+  // Areas
+  mainLineEnter.append('g').attr('class', classAreas);
+  // Circles for each data point on lines
+  mainLineEnter.append('g').attr('class', function(d) {
+    return $$.generateClass(CLASS.selectedCircles, d.id)
+  });
+  mainLineEnter
+    .append('g')
+    .attr('class', classCircles)
+    .style('cursor', function(d) {
+      return config.data_selection_isselectable(d) ? 'pointer' : null
+    });
+  // Update date for selected circles
+  targets.forEach(function(t) {
+    $$.main
+      .selectAll('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(t.id))
+      .selectAll('.' + CLASS.selectedCircle)
+      .each(function(d) {
+        d.value = t.values[d.index].value;
+      });
+  });
+  // MEMO: can not keep same color...
+  //mainLineUpdate.exit().remove();
+};
+ChartInternal.prototype.updateLine = function(durationForExit) {
+  var $$ = this;
+  var mainLine = $$.main
+    .selectAll('.' + CLASS.lines)
+    .selectAll('.' + CLASS.line)
+    .data($$.lineData.bind($$));
+  var mainLineEnter = mainLine
+    .enter()
+    .append('path')
+    .attr('class', $$.classLine.bind($$))
+    .style('stroke', $$.color);
+  $$.mainLine = mainLineEnter
+    .merge(mainLine)
+    .style('opacity', $$.initialOpacity.bind($$))
+    .style('shape-rendering', function(d) {
+      return $$.isStepType(d) ? 'crispEdges' : ''
+    })
+    .attr('transform', null);
+  mainLine
+    .exit()
+    .transition()
+    .duration(durationForExit)
+    .style('opacity', 0);
+};
+ChartInternal.prototype.redrawLine = function(
+  drawLine,
+  withTransition,
+  transition
+) {
+  return [
+    (withTransition ? this.mainLine.transition(transition) : this.mainLine)
+      .attr('d', drawLine)
+      .style('stroke', this.color)
+      .style('opacity', 1)
+  ]
+};
+ChartInternal.prototype.generateDrawLine = function(lineIndices, isSub) {
+  var $$ = this,
+    config = $$.config,
+    line = $$.d3.line(),
+    getPoints = $$.generateGetLinePoints(lineIndices, isSub),
+    yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale,
+    xValue = function(d) {
+      return (isSub ? $$.subxx : $$.xx).call($$, d)
+    },
+    yValue = function(d, i) {
+      return config.data_groups.length > 0
+        ? getPoints(d, i)[0][1]
+        : yScaleGetter.call($$, d.id)(d.value)
+    };
+
+  line = config.axis_rotated
+    ? line.x(yValue).y(xValue)
+    : line.x(xValue).y(yValue);
+  if (!config.line_connectNull) {
+    line = line.defined(function(d) {
+      return d.value != null
+    });
+  }
+  return function(d) {
+    var values = config.line_connectNull
+        ? $$.filterRemoveNull(d.values)
+        : d.values,
+      x = isSub ? $$.subX : $$.x,
+      y = yScaleGetter.call($$, d.id),
+      x0 = 0,
+      y0 = 0,
+      path;
+    if ($$.isLineType(d)) {
+      if (config.data_regions[d.id]) {
+        path = $$.lineWithRegions(values, x, y, config.data_regions[d.id]);
+      } else {
+        if ($$.isStepType(d)) {
+          values = $$.convertValuesToStep(values);
+        }
+        path = line.curve($$.getInterpolate(d))(values);
+      }
+    } else {
+      if (values[0]) {
+        x0 = x(values[0].x);
+        y0 = y(values[0].value);
+      }
+      path = config.axis_rotated ? 'M ' + y0 + ' ' + x0 : 'M ' + x0 + ' ' + y0;
+    }
+    return path ? path : 'M 0 0'
+  }
+};
+ChartInternal.prototype.generateGetLinePoints = function(lineIndices, isSub) {
+  // partial duplication of generateGetBarPoints
+  var $$ = this,
+    config = $$.config,
+    lineTargetsNum = lineIndices.__max__ + 1,
+    x = $$.getShapeX(0, lineTargetsNum, lineIndices, !!isSub),
+    y = $$.getShapeY(!!isSub),
+    lineOffset = $$.getShapeOffset($$.isLineType, lineIndices, !!isSub),
+    yScale = isSub ? $$.getSubYScale : $$.getYScale;
+  return function(d, i) {
+    var y0 = yScale.call($$, d.id)(0),
+      offset = lineOffset(d, i) || y0, // offset is for stacked area chart
+      posX = x(d),
+      posY = y(d);
+    // fix posY not to overflow opposite quadrant
+    if (config.axis_rotated) {
+      if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) {
+        posY = y0;
+      }
+    }
+    // 1 point that marks the line position
+    return [
+      [posX, posY - (y0 - offset)],
+      [posX, posY - (y0 - offset)], // needed for compatibility
+      [posX, posY - (y0 - offset)], // needed for compatibility
+      [posX, posY - (y0 - offset)] // needed for compatibility
+    ]
+  }
+};
+
+ChartInternal.prototype.lineWithRegions = function(d, x, y, _regions) {
+  var $$ = this,
+    config = $$.config,
+    prev = -1,
+    i,
+    j,
+    s = 'M',
+    sWithRegion,
+    xp,
+    yp,
+    dx,
+    dy,
+    dd,
+    diff,
+    diffx2,
+    xOffset = $$.isCategorized() ? 0.5 : 0,
+    xValue,
+    yValue,
+    regions = [];
+
+  function isWithinRegions(x, regions) {
+    var i;
+    for (i = 0; i < regions.length; i++) {
+      if (regions[i].start < x && x <= regions[i].end) {
+        return true
+      }
+    }
+    return false
+  }
+
+  // Check start/end of regions
+  if (isDefined(_regions)) {
+    for (i = 0; i < _regions.length; i++) {
+      regions[i] = {};
+      if (isUndefined(_regions[i].start)) {
+        regions[i].start = d[0].x;
+      } else {
+        regions[i].start = $$.isTimeSeries()
+          ? $$.parseDate(_regions[i].start)
+          : _regions[i].start;
+      }
+      if (isUndefined(_regions[i].end)) {
+        regions[i].end = d[d.length - 1].x;
+      } else {
+        regions[i].end = $$.isTimeSeries()
+          ? $$.parseDate(_regions[i].end)
+          : _regions[i].end;
+      }
+    }
+  }
+
+  // Set scales
+  xValue = config.axis_rotated
+    ? function(d) {
+        return y(d.value)
+      }
+    : function(d) {
+        return x(d.x)
+      };
+  yValue = config.axis_rotated
+    ? function(d) {
+        return x(d.x)
+      }
+    : function(d) {
+        return y(d.value)
+      };
+
+  // Define svg generator function for region
+  function generateM(points) {
+    return (
+      'M' +
+      points[0][0] +
+      ' ' +
+      points[0][1] +
+      ' ' +
+      points[1][0] +
+      ' ' +
+      points[1][1]
+    )
+  }
+  if ($$.isTimeSeries()) {
+    sWithRegion = function(d0, d1, j, diff) {
+      var x0 = d0.x.getTime(),
+        x_diff = d1.x - d0.x,
+        xv0 = new Date(x0 + x_diff * j),
+        xv1 = new Date(x0 + x_diff * (j + diff)),
+        points;
+      if (config.axis_rotated) {
+        points = [
+          [y(yp(j)), x(xv0)],
+          [y(yp(j + diff)), x(xv1)]
+        ];
+      } else {
+        points = [
+          [x(xv0), y(yp(j))],
+          [x(xv1), y(yp(j + diff))]
+        ];
+      }
+      return generateM(points)
+    };
+  } else {
+    sWithRegion = function(d0, d1, j, diff) {
+      var points;
+      if (config.axis_rotated) {
+        points = [
+          [y(yp(j), true), x(xp(j))],
+          [y(yp(j + diff), true), x(xp(j + diff))]
+        ];
+      } else {
+        points = [
+          [x(xp(j), true), y(yp(j))],
+          [x(xp(j + diff), true), y(yp(j + diff))]
+        ];
+      }
+      return generateM(points)
+    };
+  }
+
+  // Generate
+  for (i = 0; i < d.length; i++) {
+    // Draw as normal
+    if (isUndefined(regions) || !isWithinRegions(d[i].x, regions)) {
+      s += ' ' + xValue(d[i]) + ' ' + yValue(d[i]);
+    }
+    // Draw with region // TODO: Fix for horizotal charts
+    else {
+      xp = $$.getScale(
+        d[i - 1].x + xOffset,
+        d[i].x + xOffset,
+        $$.isTimeSeries()
+      );
+      yp = $$.getScale(d[i - 1].value, d[i].value);
+
+      dx = x(d[i].x) - x(d[i - 1].x);
+      dy = y(d[i].value) - y(d[i - 1].value);
+      dd = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
+      diff = 2 / dd;
+      diffx2 = diff * 2;
+
+      for (j = diff; j <= 1; j += diffx2) {
+        s += sWithRegion(d[i - 1], d[i], j, diff);
+      }
+    }
+    prev = d[i].x;
+  }
+
+  return s
+};
+
+ChartInternal.prototype.updateArea = function(durationForExit) {
+  var $$ = this,
+    d3 = $$.d3;
+  var mainArea = $$.main
+    .selectAll('.' + CLASS.areas)
+    .selectAll('.' + CLASS.area)
+    .data($$.lineData.bind($$));
+  var mainAreaEnter = mainArea
+    .enter()
+    .append('path')
+    .attr('class', $$.classArea.bind($$))
+    .style('fill', $$.color)
+    .style('opacity', function() {
+      $$.orgAreaOpacity = +d3.select(this).style('opacity');
+      return 0
+    });
+  $$.mainArea = mainAreaEnter
+    .merge(mainArea)
+    .style('opacity', $$.orgAreaOpacity);
+  mainArea
+    .exit()
+    .transition()
+    .duration(durationForExit)
+    .style('opacity', 0);
+};
+ChartInternal.prototype.redrawArea = function(
+  drawArea,
+  withTransition,
+  transition
+) {
+  return [
+    (withTransition ? this.mainArea.transition(transition) : this.mainArea)
+      .attr('d', drawArea)
+      .style('fill', this.color)
+      .style('opacity', this.orgAreaOpacity)
+  ]
+};
+ChartInternal.prototype.generateDrawArea = function(areaIndices, isSub) {
+  var $$ = this,
+    config = $$.config,
+    area = $$.d3.area(),
+    getPoints = $$.generateGetAreaPoints(areaIndices, isSub),
+    yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale,
+    xValue = function(d) {
+      return (isSub ? $$.subxx : $$.xx).call($$, d)
+    },
+    value0 = function(d, i) {
+      return config.data_groups.length > 0
+        ? getPoints(d, i)[0][1]
+        : yScaleGetter.call($$, d.id)($$.getAreaBaseValue(d.id))
+    },
+    value1 = function(d, i) {
+      return config.data_groups.length > 0
+        ? getPoints(d, i)[1][1]
+        : yScaleGetter.call($$, d.id)(d.value)
+    };
+
+  area = config.axis_rotated
+    ? area
+        .x0(value0)
+        .x1(value1)
+        .y(xValue)
+    : area
+        .x(xValue)
+        .y0(config.area_above ? 0 : value0)
+        .y1(value1);
+  if (!config.line_connectNull) {
+    area = area.defined(function(d) {
+      return d.value !== null
+    });
+  }
+
+  return function(d) {
+    var values = config.line_connectNull
+        ? $$.filterRemoveNull(d.values)
+        : d.values,
+      x0 = 0,
+      y0 = 0,
+      path;
+    if ($$.isAreaType(d)) {
+      if ($$.isStepType(d)) {
+        values = $$.convertValuesToStep(values);
+      }
+      path = area.curve($$.getInterpolate(d))(values);
+    } else {
+      if (values[0]) {
+        x0 = $$.x(values[0].x);
+        y0 = $$.getYScale(d.id)(values[0].value);
+      }
+      path = config.axis_rotated ? 'M ' + y0 + ' ' + x0 : 'M ' + x0 + ' ' + y0;
+    }
+    return path ? path : 'M 0 0'
+  }
+};
+ChartInternal.prototype.getAreaBaseValue = function() {
+  return 0
+};
+ChartInternal.prototype.generateGetAreaPoints = function(areaIndices, isSub) {
+  // partial duplication of generateGetBarPoints
+  var $$ = this,
+    config = $$.config,
+    areaTargetsNum = areaIndices.__max__ + 1,
+    x = $$.getShapeX(0, areaTargetsNum, areaIndices, !!isSub),
+    y = $$.getShapeY(!!isSub),
+    areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, !!isSub),
+    yScale = isSub ? $$.getSubYScale : $$.getYScale;
+  return function(d, i) {
+    var y0 = yScale.call($$, d.id)(0),
+      offset = areaOffset(d, i) || y0, // offset is for stacked area chart
+      posX = x(d),
+      posY = y(d);
+    // fix posY not to overflow opposite quadrant
+    if (config.axis_rotated) {
+      if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) {
+        posY = y0;
+      }
+    }
+    // 1 point that marks the area position
+    return [
+      [posX, offset],
+      [posX, posY - (y0 - offset)],
+      [posX, posY - (y0 - offset)], // needed for compatibility
+      [posX, offset] // needed for compatibility
+    ]
+  }
+};
+
+ChartInternal.prototype.updateCircle = function(cx, cy) {
+  var $$ = this;
+  var mainCircle = $$.main
+    .selectAll('.' + CLASS.circles)
+    .selectAll('.' + CLASS.circle)
+    .data($$.lineOrScatterOrStanfordData.bind($$));
+
+  var mainCircleEnter = mainCircle
+    .enter()
+    .append('circle')
+    .attr('shape-rendering', $$.isStanfordGraphType() ? 'crispEdges' : '')
+    .attr('class', $$.classCircle.bind($$))
+    .attr('cx', cx)
+    .attr('cy', cy)
+    .attr('r', $$.pointR.bind($$))
+    .style(
+      'color',
+      $$.isStanfordGraphType() ? $$.getStanfordPointColor.bind($$) : $$.color
+    );
+
+  $$.mainCircle = mainCircleEnter
+    .merge(mainCircle)
+    .style(
+      'opacity',
+      $$.isStanfordGraphType() ? 1 : $$.initialOpacityForCircle.bind($$)
+    );
+
+  mainCircle.exit().style('opacity', 0);
+};
+ChartInternal.prototype.redrawCircle = function(
+  cx,
+  cy,
+  withTransition,
+  transition
+) {
+  var $$ = this,
+    selectedCircles = $$.main.selectAll('.' + CLASS.selectedCircle);
+  return [
+    (withTransition ? $$.mainCircle.transition(transition) : $$.mainCircle)
+      .style('opacity', this.opacityForCircle.bind($$))
+      .style(
+        'color',
+        $$.isStanfordGraphType() ? $$.getStanfordPointColor.bind($$) : $$.color
+      )
+      .attr('cx', cx)
+      .attr('cy', cy),
+    (withTransition ? selectedCircles.transition(transition) : selectedCircles)
+      .attr('cx', cx)
+      .attr('cy', cy)
+  ]
+};
+ChartInternal.prototype.circleX = function(d) {
+  return d.x || d.x === 0 ? this.x(d.x) : null
+};
+ChartInternal.prototype.updateCircleY = function() {
+  var $$ = this,
+    lineIndices,
+    getPoints;
+  if ($$.config.data_groups.length > 0) {
+(lineIndices = $$.getShapeIndices($$.isLineType)),
+      (getPoints = $$.generateGetLinePoints(lineIndices));
+    $$.circleY = function(d, i) {
+      return getPoints(d, i)[0][1]
+    };
+  } else {
+    $$.circleY = function(d) {
+      return $$.getYScale(d.id)(d.value)
+    };
+  }
+};
+ChartInternal.prototype.getCircles = function(i, id) {
+  var $$ = this;
+  return (id
+    ? $$.main.selectAll('.' + CLASS.circles + $$.getTargetSelectorSuffix(id))
+    : $$.main
+  ).selectAll('.' + CLASS.circle + (isValue(i) ? '-' + i : ''))
+};
+ChartInternal.prototype.expandCircles = function(i, id, reset) {
+  var $$ = this,
+    r = $$.pointExpandedR.bind($$);
+  if (reset) {
+    $$.unexpandCircles();
+  }
+  $$.getCircles(i, id)
+    .classed(CLASS.EXPANDED, true)
+    .attr('r', r);
+};
+ChartInternal.prototype.unexpandCircles = function(i) {
+  var $$ = this,
+    r = $$.pointR.bind($$);
+  $$.getCircles(i)
+    .filter(function() {
+      return $$.d3.select(this).classed(CLASS.EXPANDED)
+    })
+    .classed(CLASS.EXPANDED, false)
+    .attr('r', r);
+};
+ChartInternal.prototype.pointR = function(d) {
+  var $$ = this,
+    config = $$.config;
+  return $$.isStepType(d)
+    ? 0
+    : isFunction(config.point_r)
+    ? config.point_r(d)
+    : config.point_r
+};
+ChartInternal.prototype.pointExpandedR = function(d) {
+  var $$ = this,
+    config = $$.config;
+  if (config.point_focus_expand_enabled) {
+    return isFunction(config.point_focus_expand_r)
+      ? config.point_focus_expand_r(d)
+      : config.point_focus_expand_r
+      ? config.point_focus_expand_r
+      : $$.pointR(d) * 1.75
+  } else {
+    return $$.pointR(d)
+  }
+};
+ChartInternal.prototype.pointSelectR = function(d) {
+  var $$ = this,
+    config = $$.config;
+  return isFunction(config.point_select_r)
+    ? config.point_select_r(d)
+    : config.point_select_r
+    ? config.point_select_r
+    : $$.pointR(d) * 4
+};
+ChartInternal.prototype.isWithinCircle = function(that, r) {
+  var d3 = this.d3,
+    mouse = d3.mouse(that),
+    d3_this = d3.select(that),
+    cx = +d3_this.attr('cx'),
+    cy = +d3_this.attr('cy');
+  return Math.sqrt(Math.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)) < r
+};
+ChartInternal.prototype.isWithinStep = function(that, y) {
+  return Math.abs(y - this.d3.mouse(that)[1]) < 30
+};
+
+ChartInternal.prototype.getCurrentWidth = function() {
+  var $$ = this,
+    config = $$.config;
+  return config.size_width ? config.size_width : $$.getParentWidth()
+};
+ChartInternal.prototype.getCurrentHeight = function() {
+  var $$ = this,
+    config = $$.config,
+    h = config.size_height ? config.size_height : $$.getParentHeight();
+  return h > 0
+    ? h
+    : 320 / ($$.hasType('gauge') && !config.gauge_fullCircle ? 2 : 1)
+};
+ChartInternal.prototype.getCurrentPaddingTop = function() {
+  var $$ = this,
+    config = $$.config,
+    padding = isValue(config.padding_top) ? config.padding_top : 0;
+  if ($$.title && $$.title.node()) {
+    padding += $$.getTitlePadding();
+  }
+  return padding
+};
+ChartInternal.prototype.getCurrentPaddingBottom = function() {
+  var config = this.config;
+  return isValue(config.padding_bottom) ? config.padding_bottom : 0
+};
+ChartInternal.prototype.getCurrentPaddingLeft = function(withoutRecompute) {
+  var $$ = this,
+    config = $$.config;
+  if (isValue(config.padding_left)) {
+    return config.padding_left
+  } else if (config.axis_rotated) {
+    return !config.axis_x_show || config.axis_x_inner
+      ? 1
+      : Math.max(ceil10($$.getAxisWidthByAxisId('x', withoutRecompute)), 40)
+  } else if (!config.axis_y_show || config.axis_y_inner) {
+    // && !config.axis_rotated
+    return $$.axis.getYAxisLabelPosition().isOuter ? 30 : 1
+  } else {
+    return ceil10($$.getAxisWidthByAxisId('y', withoutRecompute))
+  }
+};
+ChartInternal.prototype.getCurrentPaddingRight = function() {
+  var $$ = this,
+    config = $$.config,
+    padding = 0,
+    defaultPadding = 10,
+    legendWidthOnRight = $$.isLegendRight ? $$.getLegendWidth() + 20 : 0;
+
+  if (isValue(config.padding_right)) {
+    padding = config.padding_right + 1; // 1 is needed not to hide tick line
+  } else if (config.axis_rotated) {
+    padding = defaultPadding + legendWidthOnRight;
+  } else if (!config.axis_y2_show || config.axis_y2_inner) {
+    // && !config.axis_rotated
+    padding =
+      2 +
+      legendWidthOnRight +
+      ($$.axis.getY2AxisLabelPosition().isOuter ? 20 : 0);
+  } else {
+    padding = ceil10($$.getAxisWidthByAxisId('y2')) + legendWidthOnRight;
+  }
+
+  if ($$.colorScale && $$.colorScale.node()) {
+    padding += $$.getColorScalePadding();
+  }
+
+  return padding
+};
+
+ChartInternal.prototype.getParentRectValue = function(key) {
+  var parent = this.selectChart.node(),
+    v;
+  while (parent && parent.tagName !== 'BODY') {
+    try {
+      v = parent.getBoundingClientRect()[key];
+    } catch (e) {
+      if (key === 'width') {
+        // In IE in certain cases getBoundingClientRect
+        // will cause an "unspecified error"
+        v = parent.offsetWidth;
+      }
+    }
+    if (v) {
+      break
+    }
+    parent = parent.parentNode;
+  }
+  return v
+};
+ChartInternal.prototype.getParentWidth = function() {
+  return this.getParentRectValue('width')
+};
+ChartInternal.prototype.getParentHeight = function() {
+  var h = this.selectChart.style('height');
+  return h.indexOf('px') > 0 ? +h.replace('px', '') : 0
+};
+
+ChartInternal.prototype.getSvgLeft = function(withoutRecompute) {
+  var $$ = this,
+    config = $$.config,
+    hasLeftAxisRect =
+      config.axis_rotated || (!config.axis_rotated && !config.axis_y_inner),
+    leftAxisClass = config.axis_rotated ? CLASS.axisX : CLASS.axisY,
+    leftAxis = $$.main.select('.' + leftAxisClass).node(),
+    svgRect =
+      leftAxis && hasLeftAxisRect
+        ? leftAxis.getBoundingClientRect()
+        : { right: 0 },
+    chartRect = $$.selectChart.node().getBoundingClientRect(),
+    hasArc = $$.hasArcType(),
+    svgLeft =
+      svgRect.right -
+      chartRect.left -
+      (hasArc ? 0 : $$.getCurrentPaddingLeft(withoutRecompute));
+  return svgLeft > 0 ? svgLeft : 0
+};
+
+ChartInternal.prototype.getAxisWidthByAxisId = function(id, withoutRecompute) {
+  var $$ = this,
+    position = $$.axis.getLabelPositionById(id);
+  return (
+    $$.axis.getMaxTickWidth(id, withoutRecompute) + (position.isInner ? 20 : 40)
+  )
+};
+ChartInternal.prototype.getHorizontalAxisHeight = function(axisId) {
+  var $$ = this,
+    config = $$.config,
+    h = 30;
+  if (axisId === 'x' && !config.axis_x_show) {
+    return 8
+  }
+  if (axisId === 'x' && config.axis_x_height) {
+    return config.axis_x_height
+  }
+  if (axisId === 'y' && !config.axis_y_show) {
+    return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1
+  }
+  if (axisId === 'y2' && !config.axis_y2_show) {
+    return $$.rotated_padding_top
+  }
+  // Calculate x axis height when tick rotated
+  if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) {
+    h =
+      30 +
+      $$.axis.getMaxTickWidth(axisId) *
+        Math.cos((Math.PI * (90 - Math.abs(config.axis_x_tick_rotate))) / 180);
+  }
+  // Calculate y axis height when tick rotated
+  if (axisId === 'y' && config.axis_rotated && config.axis_y_tick_rotate) {
+    h =
+      30 +
+      $$.axis.getMaxTickWidth(axisId) *
+        Math.cos((Math.PI * (90 - Math.abs(config.axis_y_tick_rotate))) / 180);
+  }
+  return (
+    h +
+    ($$.axis.getLabelPositionById(axisId).isInner ? 0 : 10) +
+    (axisId === 'y2' ? -10 : 0)
+  )
+};
+
+ChartInternal.prototype.initBrush = function(scale) {
+  var $$ = this,
+    d3 = $$.d3;
+  // TODO: dynamically change brushY/brushX according to axis_rotated.
+  $$.brush = ($$.config.axis_rotated ? d3.brushY() : d3.brushX())
+    .on('brush', function() {
+      var event = d3.event.sourceEvent;
+      if (event && event.type === 'zoom') {
+        return
+      }
+      $$.redrawForBrush();
+    })
+    .on('end', function() {
+      var event = d3.event.sourceEvent;
+      if (event && event.type === 'zoom') {
+        return
+      }
+      if ($$.brush.empty() && event && event.type !== 'end') {
+        $$.brush.clear();
+      }
+    });
+  $$.brush.updateExtent = function() {
+    var range = this.scale.range(),
+      extent;
+    if ($$.config.axis_rotated) {
+      extent = [
+        [0, range[0]],
+        [$$.width2, range[1]]
+      ];
+    } else {
+      extent = [
+        [range[0], 0],
+        [range[1], $$.height2]
+      ];
+    }
+    this.extent(extent);
+    return this
+  };
+  $$.brush.updateScale = function(scale) {
+    this.scale = scale;
+    return this
+  };
+  $$.brush.update = function(scale) {
+    this.updateScale(scale || $$.subX).updateExtent();
+    $$.context.select('.' + CLASS.brush).call(this);
+  };
+  $$.brush.clear = function() {
+    $$.context.select('.' + CLASS.brush).call($$.brush.move, null);
+  };
+  $$.brush.selection = function() {
+    return d3.brushSelection($$.context.select('.' + CLASS.brush).node())
+  };
+  $$.brush.selectionAsValue = function(selectionAsValue, withTransition) {
+    var selection, brush;
+    if (selectionAsValue) {
+      if ($$.context) {
+        selection = [
+          this.scale(selectionAsValue[0]),
+          this.scale(selectionAsValue[1])
+        ];
+        brush = $$.context.select('.' + CLASS.brush);
+        if (withTransition) {
+          brush = brush.transition();
+        }
+        $$.brush.move(brush, selection);
+      }
+      return []
+    }
+    selection = $$.brush.selection() || [0, 0];
+    return [this.scale.invert(selection[0]), this.scale.invert(selection[1])]
+  };
+  $$.brush.empty = function() {
+    var selection = $$.brush.selection();
+    return !selection || selection[0] === selection[1]
+  };
+  return $$.brush.updateScale(scale)
+};
+ChartInternal.prototype.initSubchart = function() {
+  var $$ = this,
+    config = $$.config,
+    context = ($$.context = $$.svg
+      .append('g')
+      .attr('transform', $$.getTranslate('context')));
+
+  // set style
+  context.style('visibility', 'visible');
+
+  // Define g for chart area
+  context
+    .append('g')
+    .attr('clip-path', $$.clipPathForSubchart)
+    .attr('class', CLASS.chart);
+
+  // Define g for bar chart area
+  context
+    .select('.' + CLASS.chart)
+    .append('g')
+    .attr('class', CLASS.chartBars);
+
+  // Define g for line chart area
+  context
+    .select('.' + CLASS.chart)
+    .append('g')
+    .attr('class', CLASS.chartLines);
+
+  // Add extent rect for Brush
+  context
+    .append('g')
+    .attr('clip-path', $$.clipPath)
+    .attr('class', CLASS.brush);
+
+  // ATTENTION: This must be called AFTER chart added
+  // Add Axis
+  $$.axes.subx = context
+    .append('g')
+    .attr('class', CLASS.axisX)
+    .attr('transform', $$.getTranslate('subx'))
+    .attr('clip-path', config.axis_rotated ? '' : $$.clipPathForXAxis);
+};
+ChartInternal.prototype.initSubchartBrush = function() {
+  var $$ = this;
+  // Add extent rect for Brush
+  $$.initBrush($$.subX).updateExtent();
+  $$.context.select('.' + CLASS.brush).call($$.brush);
+};
+ChartInternal.prototype.updateTargetsForSubchart = function(targets) {
+  var $$ = this,
+    context = $$.context,
+    config = $$.config,
+    contextLineEnter,
+    contextLine,
+    contextBarEnter,
+    contextBar,
+    classChartBar = $$.classChartBar.bind($$),
+    classBars = $$.classBars.bind($$),
+    classChartLine = $$.classChartLine.bind($$),
+    classLines = $$.classLines.bind($$),
+    classAreas = $$.classAreas.bind($$);
+
+  //-- Bar --//
+  contextBar = context
+    .select('.' + CLASS.chartBars)
+    .selectAll('.' + CLASS.chartBar)
+    .data(targets);
+  contextBarEnter = contextBar
+    .enter()
+    .append('g')
+    .style('opacity', 0);
+  contextBarEnter.merge(contextBar).attr('class', classChartBar);
+  // Bars for each data
+  contextBarEnter.append('g').attr('class', classBars);
+
+  //-- Line --//
+  contextLine = context
+    .select('.' + CLASS.chartLines)
+    .selectAll('.' + CLASS.chartLine)
+    .data(targets);
+  contextLineEnter = contextLine
+    .enter()
+    .append('g')
+    .style('opacity', 0);
+  contextLineEnter.merge(contextLine).attr('class', classChartLine);
+  // Lines for each data
+  contextLineEnter.append('g').attr('class', classLines);
+  // Area
+  contextLineEnter.append('g').attr('class', classAreas);
+
+  //-- Brush --//
+  context
+    .selectAll('.' + CLASS.brush + ' rect')
+    .attr(
+      config.axis_rotated ? 'width' : 'height',
+      config.axis_rotated ? $$.width2 : $$.height2
+    );
+};
+ChartInternal.prototype.updateBarForSubchart = function(durationForExit) {
+  var $$ = this;
+  var contextBar = $$.context
+    .selectAll('.' + CLASS.bars)
+    .selectAll('.' + CLASS.bar)
+    .data($$.barData.bind($$));
+  var contextBarEnter = contextBar
+    .enter()
+    .append('path')
+    .attr('class', $$.classBar.bind($$))
+    .style('stroke', 'none')
+    .style('fill', $$.color);
+  contextBar
+    .exit()
+    .transition()
+    .duration(durationForExit)
+    .style('opacity', 0)
+    .remove();
+  $$.contextBar = contextBarEnter
+    .merge(contextBar)
+    .style('opacity', $$.initialOpacity.bind($$));
+};
+ChartInternal.prototype.redrawBarForSubchart = function(
+  drawBarOnSub,
+  withTransition,
+  duration
+) {
+(withTransition
+    ? this.contextBar.transition(Math.random().toString()).duration(duration)
+    : this.contextBar
+  )
+    .attr('d', drawBarOnSub)
+    .style('opacity', 1);
+};
+ChartInternal.prototype.updateLineForSubchart = function(durationForExit) {
+  var $$ = this;
+  var contextLine = $$.context
+    .selectAll('.' + CLASS.lines)
+    .selectAll('.' + CLASS.line)
+    .data($$.lineData.bind($$));
+  var contextLineEnter = contextLine
+    .enter()
+    .append('path')
+    .attr('class', $$.classLine.bind($$))
+    .style('stroke', $$.color);
+  contextLine
+    .exit()
+    .transition()
+    .duration(durationForExit)
+    .style('opacity', 0)
+    .remove();
+  $$.contextLine = contextLineEnter
+    .merge(contextLine)
+    .style('opacity', $$.initialOpacity.bind($$));
+};
+ChartInternal.prototype.redrawLineForSubchart = function(
+  drawLineOnSub,
+  withTransition,
+  duration
+) {
+(withTransition
+    ? this.contextLine.transition(Math.random().toString()).duration(duration)
+    : this.contextLine
+  )
+    .attr('d', drawLineOnSub)
+    .style('opacity', 1);
+};
+ChartInternal.prototype.updateAreaForSubchart = function(durationForExit) {
+  var $$ = this,
+    d3 = $$.d3;
+  var contextArea = $$.context
+    .selectAll('.' + CLASS.areas)
+    .selectAll('.' + CLASS.area)
+    .data($$.lineData.bind($$));
+  var contextAreaEnter = contextArea
+    .enter()
+    .append('path')
+    .attr('class', $$.classArea.bind($$))
+    .style('fill', $$.color)
+    .style('opacity', function() {
+      $$.orgAreaOpacity = +d3.select(this).style('opacity');
+      return 0
+    });
+  contextArea
+    .exit()
+    .transition()
+    .duration(durationForExit)
+    .style('opacity', 0)
+    .remove();
+  $$.contextArea = contextAreaEnter.merge(contextArea).style('opacity', 0);
+};
+ChartInternal.prototype.redrawAreaForSubchart = function(
+  drawAreaOnSub,
+  withTransition,
+  duration
+) {
+(withTransition
+    ? this.contextArea.transition(Math.random().toString()).duration(duration)
+    : this.contextArea
+  )
+    .attr('d', drawAreaOnSub)
+    .style('fill', this.color)
+    .style('opacity', this.orgAreaOpacity);
+};
+ChartInternal.prototype.redrawSubchart = function(
+  withSubchart,
+  transitions,
+  duration,
+  durationForExit,
+  areaIndices,
+  barIndices,
+  lineIndices
+) {
+  var $$ = this,
+    d3 = $$.d3,
+    drawAreaOnSub,
+    drawBarOnSub,
+    drawLineOnSub;
+
+  // reflect main chart to extent on subchart if zoomed
+  if (d3.event && d3.event.type === 'zoom') {
+    $$.brush.selectionAsValue($$.x.orgDomain());
+  }
+  // update subchart elements if needed
+  if (withSubchart) {
+    // extent rect
+    if (!$$.brush.empty()) {
+      $$.brush.selectionAsValue($$.x.orgDomain());
+    }
+    // setup drawer - MEMO: this must be called after axis updated
+    drawAreaOnSub = $$.generateDrawArea(areaIndices, true);
+    drawBarOnSub = $$.generateDrawBar(barIndices, true);
+    drawLineOnSub = $$.generateDrawLine(lineIndices, true);
+
+    $$.updateBarForSubchart(duration);
+    $$.updateLineForSubchart(duration);
+    $$.updateAreaForSubchart(duration);
+
+    $$.redrawBarForSubchart(drawBarOnSub, duration, duration);
+    $$.redrawLineForSubchart(drawLineOnSub, duration, duration);
+    $$.redrawAreaForSubchart(drawAreaOnSub, duration, duration);
+  }
+};
+ChartInternal.prototype.redrawForBrush = function() {
+  var $$ = this,
+    x = $$.x,
+    d3 = $$.d3,
+    s;
+  $$.redraw({
+    withTransition: false,
+    withY: $$.config.zoom_rescale,
+    withSubchart: false,
+    withUpdateXDomain: true,
+    withEventRect: false,
+    withDimension: false
+  });
+  // update zoom transation binded to event rect
+  s = d3.event.selection || $$.brush.scale.range();
+  $$.main
+    .select('.' + CLASS.eventRect)
+    .call(
+      $$.zoom.transform,
+      d3.zoomIdentity.scale($$.width / (s[1] - s[0])).translate(-s[0], 0)
+    );
+  $$.config.subchart_onbrush.call($$.api, x.orgDomain());
+};
+ChartInternal.prototype.transformContext = function(
+  withTransition,
+  transitions
+) {
+  var $$ = this,
+    subXAxis;
+  if (transitions && transitions.axisSubX) {
+    subXAxis = transitions.axisSubX;
+  } else {
+    subXAxis = $$.context.select('.' + CLASS.axisX);
+    if (withTransition) {
+      subXAxis = subXAxis.transition();
+    }
+  }
+  $$.context.attr('transform', $$.getTranslate('context'));
+  subXAxis.attr('transform', $$.getTranslate('subx'));
+};
+ChartInternal.prototype.getDefaultSelection = function() {
+  var $$ = this,
+    config = $$.config,
+    selection = isFunction(config.axis_x_selection)
+      ? config.axis_x_selection($$.getXDomain($$.data.targets))
+      : config.axis_x_selection;
+  if ($$.isTimeSeries()) {
+    selection = [$$.parseDate(selection[0]), $$.parseDate(selection[1])];
+  }
+  return selection
+};
+
+ChartInternal.prototype.removeSubchart = function() {
+  const $$ = this;
+
+  $$.brush = null;
+  $$.context.remove();
+  $$.context = null;
+};
+
+ChartInternal.prototype.initText = function() {
+  var $$ = this;
+  $$.main
+    .select('.' + CLASS.chart)
+    .append('g')
+    .attr('class', CLASS.chartTexts);
+  $$.mainText = $$.d3.selectAll([]);
+};
+ChartInternal.prototype.updateTargetsForText = function(targets) {
+  var $$ = this,
+    classChartText = $$.classChartText.bind($$),
+    classTexts = $$.classTexts.bind($$),
+    classFocus = $$.classFocus.bind($$);
+  var mainText = $$.main
+    .select('.' + CLASS.chartTexts)
+    .selectAll('.' + CLASS.chartText)
+    .data(targets);
+  var mainTextEnter = mainText
+    .enter()
+    .append('g')
+    .attr('class', classChartText)
+    .style('opacity', 0)
+    .style('pointer-events', 'none');
+  mainTextEnter.append('g').attr('class', classTexts);
+  mainTextEnter.merge(mainText).attr('class', function(d) {
+    return classChartText(d) + classFocus(d)
+  });
+};
+ChartInternal.prototype.updateText = function(
+  xForText,
+  yForText,
+  durationForExit
+) {
+  var $$ = this,
+    config = $$.config,
+    barOrLineData = $$.barOrLineData.bind($$),
+    classText = $$.classText.bind($$);
+  var mainText = $$.main
+    .selectAll('.' + CLASS.texts)
+    .selectAll('.' + CLASS.text)
+    .data(barOrLineData);
+  var mainTextEnter = mainText
+    .enter()
+    .append('text')
+    .attr('class', classText)
+    .attr('text-anchor', function(d) {
+      return config.axis_rotated ? (d.value < 0 ? 'end' : 'start') : 'middle'
+    })
+    .style('stroke', 'none')
+    .attr('x', xForText)
+    .attr('y', yForText)
+    .style('fill', function(d) {
+      return $$.color(d)
+    })
+    .style('fill-opacity', 0);
+  $$.mainText = mainTextEnter.merge(mainText).text(function(d, i, j) {
+    return $$.dataLabelFormat(d.id)(d.value, d.id, i, j)
+  });
+  mainText
+    .exit()
+    .transition()
+    .duration(durationForExit)
+    .style('fill-opacity', 0)
+    .remove();
+};
+ChartInternal.prototype.redrawText = function(
+  xForText,
+  yForText,
+  forFlow,
+  withTransition,
+  transition
+) {
+  return [
+    (withTransition ? this.mainText.transition(transition) : this.mainText)
+      .attr('x', xForText)
+      .attr('y', yForText)
+      .style('fill', this.color)
+      .style('fill-opacity', forFlow ? 0 : this.opacityForText.bind(this))
+  ]
+};
+ChartInternal.prototype.getTextRect = function(text, cls, element) {
+  var dummy = this.d3
+      .select('body')
+      .append('div')
+      .classed('c3', true),
+    svg = dummy
+      .append('svg')
+      .style('visibility', 'hidden')
+      .style('position', 'fixed')
+      .style('top', 0)
+      .style('left', 0),
+    font = this.d3.select(element).style('font'),
+    rect;
+  svg
+    .selectAll('.dummy')
+    .data([text])
+    .enter()
+    .append('text')
+    .classed(cls ? cls : '', true)
+    .style('font', font)
+    .text(text)
+    .each(function() {
+      rect = getBBox(this);
+    });
+  dummy.remove();
+  return rect
+};
+ChartInternal.prototype.generateXYForText = function(
+  areaIndices,
+  barIndices,
+  lineIndices,
+  forX
+) {
+  var $$ = this,
+    getAreaPoints = $$.generateGetAreaPoints(areaIndices, false),
+    getBarPoints = $$.generateGetBarPoints(barIndices, false),
+    getLinePoints = $$.generateGetLinePoints(lineIndices, false),
+    getter = forX ? $$.getXForText : $$.getYForText;
+  return function(d, i) {
+    var getPoints = $$.isAreaType(d)
+      ? getAreaPoints
+      : $$.isBarType(d)
+      ? getBarPoints
+      : getLinePoints;
+    return getter.call($$, getPoints(d, i), d, this)
+  }
+};
+ChartInternal.prototype.getXForText = function(points, d, textElement) {
+  var $$ = this,
+    box = getBBox(textElement),
+    xPos,
+    padding;
+  if ($$.config.axis_rotated) {
+    padding = $$.isBarType(d) ? 4 : 6;
+    xPos = points[2][1] + padding * (d.value < 0 ? -1 : 1);
+  } else {
+    xPos = $$.hasType('bar') ? (points[2][0] + points[0][0]) / 2 : points[0][0];
+  }
+  // show labels regardless of the domain if value is null
+  if (d.value === null) {
+    if (xPos > $$.width) {
+      xPos = $$.width - box.width;
+    } else if (xPos < 0) {
+      xPos = 4;
+    }
+  }
+  return xPos
+};
+ChartInternal.prototype.getYForText = function(points, d, textElement) {
+  var $$ = this,
+    box = getBBox(textElement),
+    yPos;
+  if ($$.config.axis_rotated) {
+    yPos = (points[0][0] + points[2][0] + box.height * 0.6) / 2;
+  } else {
+    yPos = points[2][1];
+    if (d.value < 0 || (d.value === 0 && !$$.hasPositiveValue)) {
+      yPos += box.height;
+      if ($$.isBarType(d) && $$.isSafari()) {
+        yPos -= 3;
+      } else if (!$$.isBarType(d) && $$.isChrome()) {
+        yPos += 3;
+      }
+    } else {
+      yPos += $$.isBarType(d) ? -3 : -6;
+    }
+  }
+  // show labels regardless of the domain if value is null
+  if (d.value === null && !$$.config.axis_rotated) {
+    if (yPos < box.height) {
+      yPos = box.height;
+    } else if (yPos > this.height) {
+      yPos = this.height - 4;
+    }
+  }
+  return yPos
+};
+
+ChartInternal.prototype.initTitle = function() {
+  var $$ = this;
+  $$.title = $$.svg
+    .append('text')
+    .text($$.config.title_text)
+    .attr('class', $$.CLASS.title);
+};
+ChartInternal.prototype.redrawTitle = function() {
+  var $$ = this;
+  $$.title.attr('x', $$.xForTitle.bind($$)).attr('y', $$.yForTitle.bind($$));
+};
+ChartInternal.prototype.xForTitle = function() {
+  var $$ = this,
+    config = $$.config,
+    position = config.title_position || 'left',
+    x;
+  if (position.indexOf('right') >= 0) {
+    x =
+      $$.currentWidth -
+      $$.getTextRect(
+        $$.title.node().textContent,
+        $$.CLASS.title,
+        $$.title.node()
+      ).width -
+      config.title_padding.right;
+  } else if (position.indexOf('center') >= 0) {
+    x = Math.max(
+      ($$.currentWidth -
+        $$.getTextRect(
+          $$.title.node().textContent,
+          $$.CLASS.title,
+          $$.title.node()
+        ).width) /
+        2,
+      0
+    );
+  } else {
+    // left
+    x = config.title_padding.left;
+  }
+  return x
+};
+ChartInternal.prototype.yForTitle = function() {
+  var $$ = this;
+  return (
+    $$.config.title_padding.top +
+    $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node())
+      .height
+  )
+};
+ChartInternal.prototype.getTitlePadding = function() {
+  var $$ = this;
+  return $$.yForTitle() + $$.config.title_padding.bottom
+};
+
+function powerOfTen(d) {
+  return d / Math.pow(10, Math.ceil(Math.log(d) / Math.LN10 - 1e-12)) === 1
+}
+
+ChartInternal.prototype.drawColorScale = function() {
+  var $$ = this,
+    d3 = $$.d3,
+    config = $$.config,
+    target = $$.data.targets[0],
+    barWidth,
+    barHeight,
+    axis,
+    points,
+    legendAxis,
+    axisScale,
+    inverseScale,
+    height;
+
+  barWidth = !isNaN(config.stanford_scaleWidth)
+    ? config.stanford_scaleWidth
+    : 20;
+  barHeight = 5;
+
+  if (barHeight < 0 || barWidth < 0) {
+    throw Error("Colorscale's barheight and barwidth must be greater than 0.")
+  }
+
+  height =
+    $$.height - config.stanford_padding.bottom - config.stanford_padding.top;
+
+  points = d3.range(config.stanford_padding.bottom, height, barHeight);
+
+  inverseScale = d3
+    .scaleSequential(target.colors)
+    .domain([points[points.length - 1], points[0]]);
+
+  if ($$.colorScale) {
+    $$.colorScale.remove();
+  }
+
+  $$.colorScale = $$.svg
+    .append('g')
+    .attr('width', 50)
+    .attr('height', height)
+    .attr('class', CLASS.colorScale);
+
+  $$.colorScale
+    .append('g')
+    .attr('transform', `translate(0, ${config.stanford_padding.top})`)
+    .selectAll('bars')
+    .data(points)
+    .enter()
+    .append('rect')
+    .attr('y', (d, i) => i * barHeight)
+    .attr('x', 0)
+    .attr('width', barWidth)
+    .attr('height', barHeight)
+    .attr('fill', function(d) {
+      return inverseScale(d)
+    });
+
+  // Legend Axis
+  axisScale = d3
+    .scaleLog()
+    .domain([target.minEpochs, target.maxEpochs])
+    .range([
+      points[0] +
+        config.stanford_padding.top +
+        points[points.length - 1] +
+        barHeight -
+        1,
+      points[0] + config.stanford_padding.top
+    ]);
+
+  legendAxis = d3.axisRight(axisScale);
+
+  if (config.stanford_scaleFormat === 'pow10') {
+    legendAxis.tickValues([1, 10, 100, 1000, 10000, 100000, 1000000, 10000000]);
+  } else if (isFunction(config.stanford_scaleFormat)) {
+    legendAxis.tickFormat(config.stanford_scaleFormat);
+  } else {
+    legendAxis.tickFormat(d3.format('d'));
+  }
+
+  if (isFunction(config.stanford_scaleValues)) {
+    legendAxis.tickValues(
+      config.stanford_scaleValues(target.minEpochs, target.maxEpochs)
+    );
+  }
+
+  // Draw Axis
+  axis = $$.colorScale
+    .append('g')
+    .attr('class', 'legend axis')
+    .attr('transform', `translate(${barWidth},0)`)
+    .call(legendAxis);
+
+  if (config.stanford_scaleFormat === 'pow10') {
+    axis
+      .selectAll('.tick text')
+      .text(null)
+      .filter(powerOfTen)
+      .text(10)
+      .append('tspan')
+      .attr('dy', '-.7em') // https://bl.ocks.org/mbostock/6738229
+      .text(function(d) {
+        return Math.round(Math.log(d) / Math.LN10)
+      });
+  }
+
+  $$.colorScale.attr(
+    'transform',
+    `translate(${$$.currentWidth - $$.xForColorScale()}, 0)`
+  );
+};
+
+ChartInternal.prototype.xForColorScale = function() {
+  var $$ = this;
+
+  return $$.config.stanford_padding.right + getBBox($$.colorScale.node()).width
+};
+
+ChartInternal.prototype.getColorScalePadding = function() {
+  var $$ = this;
+  return $$.xForColorScale() + $$.config.stanford_padding.left + 20
+};
+
+ChartInternal.prototype.isStanfordGraphType = function() {
+  var $$ = this;
+
+  return $$.config.data_type === 'stanford'
+};
+
+ChartInternal.prototype.initStanfordData = function() {
+  var $$ = this,
+    d3 = $$.d3,
+    config = $$.config,
+    target = $$.data.targets[0],
+    epochs,
+    maxEpochs,
+    minEpochs;
+
+  // Make larger values appear on top
+  target.values.sort(compareEpochs);
+
+  // Get array of epochs
+  epochs = target.values.map(a => a.epochs);
+
+  minEpochs = !isNaN(config.stanford_scaleMin)
+    ? config.stanford_scaleMin
+    : d3.min(epochs);
+  maxEpochs = !isNaN(config.stanford_scaleMax)
+    ? config.stanford_scaleMax
+    : d3.max(epochs);
+
+  if (minEpochs > maxEpochs) {
+    throw Error('Number of minEpochs has to be smaller than maxEpochs')
+  }
+
+  target.colors = isFunction(config.stanford_colors)
+    ? config.stanford_colors
+    : d3.interpolateHslLong(d3.hsl(250, 1, 0.5), d3.hsl(0, 1, 0.5));
+
+  target.colorscale = d3
+    .scaleSequentialLog(target.colors)
+    .domain([minEpochs, maxEpochs]);
+
+  target.minEpochs = minEpochs;
+  target.maxEpochs = maxEpochs;
+};
+
+ChartInternal.prototype.getStanfordPointColor = function(d) {
+  var $$ = this,
+    target = $$.data.targets[0];
+
+  return target.colorscale(d.epochs)
+};
+
+// http://jsfiddle.net/Xotic750/KtzLq/
+ChartInternal.prototype.getCentroid = function(points) {
+  var area = getRegionArea(points);
+
+  var x = 0,
+    y = 0,
+    i,
+    j,
+    f,
+    point1,
+    point2;
+
+  for (i = 0, j = points.length - 1; i < points.length; j = i, i += 1) {
+    point1 = points[i];
+    point2 = points[j];
+    f = point1.x * point2.y - point2.x * point1.y;
+    x += (point1.x + point2.x) * f;
+    y += (point1.y + point2.y) * f;
+  }
+
+  f = area * 6;
+
+  return {
+    x: x / f,
+    y: y / f
+  }
+};
+
+ChartInternal.prototype.getStanfordTooltipTitle = function(d) {
+  var $$ = this,
+    labelX = $$.axis.getLabelText('x'),
+    labelY = $$.axis.getLabelText('y');
+
+  return `
+      <tr><th>${labelX ? sanitise(labelX) : 'x'}</th><th class='value'>${
+    d.x
+  }</th></tr>
+      <tr><th>${labelY ? sanitise(labelY) : 'y'}</th><th class='value'>${
+    d.value
+  }</th></tr>
+    `
+};
+
+ChartInternal.prototype.countEpochsInRegion = function(region) {
+  var $$ = this,
+    target = $$.data.targets[0],
+    total,
+    count;
+
+  total = target.values.reduce(
+    (accumulator, currentValue) => accumulator + Number(currentValue.epochs),
+    0
+  );
+
+  count = target.values.reduce((accumulator, currentValue) => {
+    if (pointInRegion(currentValue, region)) {
+      return accumulator + Number(currentValue.epochs)
+    }
+
+    return accumulator
+  }, 0);
+
+  return {
+    value: count,
+    percentage: count !== 0 ? ((count / total) * 100).toFixed(1) : 0
+  }
+};
+
+var getRegionArea = function(points) {
+  // thanks to: https://stackoverflow.com/questions/16282330/find-centerpoint-of-polygon-in-javascript
+  var area = 0,
+    i,
+    j,
+    point1,
+    point2;
+
+  for (i = 0, j = points.length - 1; i < points.length; j = i, i += 1) {
+    point1 = points[i];
+    point2 = points[j];
+    area += point1.x * point2.y;
+    area -= point1.y * point2.x;
+  }
+
+  area /= 2;
+
+  return area
+};
+
+var pointInRegion = function(point, region) {
+  // thanks to: http://bl.ocks.org/bycoffe/5575904
+  // ray-casting algorithm based on
+  // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
+  let xi,
+    yi,
+    yj,
+    xj,
+    intersect,
+    x = point.x,
+    y = point.value,
+    inside = false;
+
+  for (let i = 0, j = region.length - 1; i < region.length; j = i++) {
+    xi = region[i].x;
+    yi = region[i].y;
+
+    xj = region[j].x;
+    yj = region[j].y;
+
+    intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
+
+    if (intersect) {
+      inside = !inside;
+    }
+  }
+
+  return inside
+};
+
+var compareEpochs = function(a, b) {
+  if (a.epochs < b.epochs) {
+    return -1
+  }
+  if (a.epochs > b.epochs) {
+    return 1
+  }
+
+  return 0
+};
+
+ChartInternal.prototype.initStanfordElements = function() {
+  var $$ = this;
+
+  // Avoid blocking eventRect
+  $$.stanfordElements = $$.main
+    .select('.' + CLASS.chart)
+    .append('g')
+    .attr('class', CLASS.stanfordElements);
+
+  $$.stanfordElements.append('g').attr('class', CLASS.stanfordLines);
+  $$.stanfordElements.append('g').attr('class', CLASS.stanfordTexts);
+  $$.stanfordElements.append('g').attr('class', CLASS.stanfordRegions);
+};
+
+ChartInternal.prototype.updateStanfordElements = function(duration) {
+  var $$ = this,
+    main = $$.main,
+    config = $$.config,
+    stanfordLine,
+    stanfordLineEnter,
+    stanfordRegion,
+    stanfordRegionEnter,
+    stanfordText,
+    stanfordTextEnter,
+    xvCustom = $$.xvCustom.bind($$),
+    yvCustom = $$.yvCustom.bind($$),
+    countPointsInRegion = $$.countEpochsInRegion.bind($$);
+
+  // Stanford-Lines
+  stanfordLine = main
+    .select('.' + CLASS.stanfordLines)
+    .style('shape-rendering', 'geometricprecision')
+    .selectAll('.' + CLASS.stanfordLine)
+    .data(config.stanford_lines);
+
+  // enter
+  stanfordLineEnter = stanfordLine
+    .enter()
+    .append('g')
+    .attr('class', function(d) {
+      return CLASS.stanfordLine + (d['class'] ? ' ' + d['class'] : '')
+    });
+  stanfordLineEnter
+    .append('line')
+    .attr('x1', d =>
+      config.axis_rotated ? yvCustom(d, 'value_y1') : xvCustom(d, 'value_x1')
+    )
+    .attr('x2', d =>
+      config.axis_rotated ? yvCustom(d, 'value_y2') : xvCustom(d, 'value_x2')
+    )
+    .attr('y1', d =>
+      config.axis_rotated ? xvCustom(d, 'value_x1') : yvCustom(d, 'value_y1')
+    )
+    .attr('y2', d =>
+      config.axis_rotated ? xvCustom(d, 'value_x2') : yvCustom(d, 'value_y2')
+    )
+    .style('opacity', 0);
+
+  // update
+  $$.stanfordLines = stanfordLineEnter.merge(stanfordLine);
+  $$.stanfordLines
+    .select('line')
+    .transition()
+    .duration(duration)
+    .attr('x1', d =>
+      config.axis_rotated ? yvCustom(d, 'value_y1') : xvCustom(d, 'value_x1')
+    )
+    .attr('x2', d =>
+      config.axis_rotated ? yvCustom(d, 'value_y2') : xvCustom(d, 'value_x2')
+    )
+    .attr('y1', d =>
+      config.axis_rotated ? xvCustom(d, 'value_x1') : yvCustom(d, 'value_y1')
+    )
+    .attr('y2', d =>
+      config.axis_rotated ? xvCustom(d, 'value_x2') : yvCustom(d, 'value_y2')
+    )
+    .style('opacity', 1);
+
+  // exit
+  stanfordLine
+    .exit()
+    .transition()
+    .duration(duration)
+    .style('opacity', 0)
+    .remove();
+
+  // Stanford-Text
+  stanfordText = main
+    .select('.' + CLASS.stanfordTexts)
+    .selectAll('.' + CLASS.stanfordText)
+    .data(config.stanford_texts);
+
+  // enter
+  stanfordTextEnter = stanfordText
+    .enter()
+    .append('g')
+    .attr('class', function(d) {
+      return CLASS.stanfordText + (d['class'] ? ' ' + d['class'] : '')
+    });
+  stanfordTextEnter
+    .append('text')
+    .attr('x', d => (config.axis_rotated ? yvCustom(d, 'y') : xvCustom(d, 'x')))
+    .attr('y', d => (config.axis_rotated ? xvCustom(d, 'x') : yvCustom(d, 'y')))
+    .style('opacity', 0);
+
+  // update
+  $$.stanfordTexts = stanfordTextEnter.merge(stanfordText);
+  $$.stanfordTexts
+    .select('text')
+    .transition()
+    .duration(duration)
+    .attr('x', d => (config.axis_rotated ? yvCustom(d, 'y') : xvCustom(d, 'x')))
+    .attr('y', d => (config.axis_rotated ? xvCustom(d, 'x') : yvCustom(d, 'y')))
+    .text(function(d) {
+      return d.content
+    })
+    .style('opacity', 1);
+
+  // exit
+  stanfordText
+    .exit()
+    .transition()
+    .duration(duration)
+    .style('opacity', 0)
+    .remove();
+
+  // Stanford-Regions
+  stanfordRegion = main
+    .select('.' + CLASS.stanfordRegions)
+    .selectAll('.' + CLASS.stanfordRegion)
+    .data(config.stanford_regions);
+
+  // enter
+  stanfordRegionEnter = stanfordRegion
+    .enter()
+    .append('g')
+    .attr('class', function(d) {
+      return CLASS.stanfordRegion + (d['class'] ? ' ' + d['class'] : '')
+    });
+  stanfordRegionEnter
+    .append('polygon')
+    .attr('points', d => {
+      return d.points
+        .map(value => {
+          return [
+            config.axis_rotated ? yvCustom(value, 'y') : xvCustom(value, 'x'),
+            config.axis_rotated ? xvCustom(value, 'x') : yvCustom(value, 'y')
+          ].join(',')
+        })
+        .join(' ')
+    })
+    .style('opacity', 0);
+  stanfordRegionEnter
+    .append('text')
+    .attr('x', d => $$.getCentroid(d.points).x)
+    .attr('y', d => $$.getCentroid(d.points).y)
+    .style('opacity', 0);
+
+  // update
+  $$.stanfordRegions = stanfordRegionEnter.merge(stanfordRegion);
+  $$.stanfordRegions
+    .select('polygon')
+    .transition()
+    .duration(duration)
+    .attr('points', d => {
+      return d.points
+        .map(value => {
+          return [
+            config.axis_rotated ? yvCustom(value, 'y') : xvCustom(value, 'x'),
+            config.axis_rotated ? xvCustom(value, 'x') : yvCustom(value, 'y')
+          ].join(',')
+        })
+        .join(' ')
+    })
+    .style('opacity', d => {
+      return d.opacity ? d.opacity : 0.2
+    });
+  $$.stanfordRegions
+    .select('text')
+    .transition()
+    .duration(duration)
+    .attr('x', d =>
+      config.axis_rotated
+        ? yvCustom($$.getCentroid(d.points), 'y')
+        : xvCustom($$.getCentroid(d.points), 'x')
+    )
+    .attr('y', d =>
+      config.axis_rotated
+        ? xvCustom($$.getCentroid(d.points), 'x')
+        : yvCustom($$.getCentroid(d.points), 'y')
+    )
+    .text(function(d) {
+      if (d.text) {
+        var value, percentage, temp;
+
+        if ($$.isStanfordGraphType()) {
+          temp = countPointsInRegion(d.points);
+          value = temp.value;
+          percentage = temp.percentage;
+        }
+
+        return d.text(value, percentage)
+      }
+
+      return ''
+    })
+    .attr('text-anchor', 'middle')
+    .attr('dominant-baseline', 'middle')
+    .style('opacity', 1);
+  // exit
+  stanfordRegion
+    .exit()
+    .transition()
+    .duration(duration)
+    .style('opacity', 0)
+    .remove();
+};
+
+ChartInternal.prototype.initTooltip = function() {
+  var $$ = this,
+    config = $$.config,
+    i;
+  $$.tooltip = $$.selectChart
+    .style('position', 'relative')
+    .append('div')
+    .attr('class', CLASS.tooltipContainer)
+    .style('position', 'absolute')
+    .style('pointer-events', 'none')
+    .style('display', 'none');
+  // Show tooltip if needed
+  if (config.tooltip_init_show) {
+    if ($$.isTimeSeries() && isString(config.tooltip_init_x)) {
+      config.tooltip_init_x = $$.parseDate(config.tooltip_init_x);
+      for (i = 0; i < $$.data.targets[0].values.length; i++) {
+        if ($$.data.targets[0].values[i].x - config.tooltip_init_x === 0) {
+          break
+        }
+      }
+      config.tooltip_init_x = i;
+    }
+    $$.tooltip.html(
+      config.tooltip_contents.call(
+        $$,
+        $$.data.targets.map(function(d) {
+          return $$.addName(d.values[config.tooltip_init_x])
+        }),
+        $$.axis.getXAxisTickFormat(),
+        $$.getYFormat($$.hasArcType()),
+        $$.color
+      )
+    );
+    $$.tooltip
+      .style('top', config.tooltip_init_position.top)
+      .style('left', config.tooltip_init_position.left)
+      .style('display', 'block');
+  }
+};
+ChartInternal.prototype.getTooltipSortFunction = function() {
+  var $$ = this,
+    config = $$.config;
+
+  if (config.data_groups.length === 0 || config.tooltip_order !== undefined) {
+    // if data are not grouped or if an order is specified
+    // for the tooltip values we sort them by their values
+
+    var order = config.tooltip_order;
+    if (order === undefined) {
+      order = config.data_order;
+    }
+
+    var valueOf = function(obj) {
+      return obj ? obj.value : null
+    };
+
+    // if data are not grouped, we sort them by their value
+    if (isString(order) && order.toLowerCase() === 'asc') {
+      return function(a, b) {
+        return valueOf(a) - valueOf(b)
+      }
+    } else if (isString(order) && order.toLowerCase() === 'desc') {
+      return function(a, b) {
+        return valueOf(b) - valueOf(a)
+      }
+    } else if (isFunction(order)) {
+      // if the function is from data_order we need
+      // to wrap the returned function in order to format
+      // the sorted value to the expected format
+
+      var sortFunction = order;
+
+      if (config.tooltip_order === undefined) {
+        sortFunction = function(a, b) {
+          return order(
+            a
+              ? {
+                  id: a.id,
+                  values: [a]
+                }
+              : null,
+            b
+              ? {
+                  id: b.id,
+                  values: [b]
+                }
+              : null
+          )
+        };
+      }
+
+      return sortFunction
+    } else if (isArray(order)) {
+      return function(a, b) {
+        return order.indexOf(a.id) - order.indexOf(b.id)
+      }
+    }
+  } else {
+    // if data are grouped, we follow the order of grouped targets
+    var ids = $$.orderTargets($$.data.targets).map(function(i) {
+      return i.id
+    });
+
+    // if it was either asc or desc we need to invert the order
+    // returned by orderTargets
+    if ($$.isOrderAsc() || $$.isOrderDesc()) {
+      ids = ids.reverse();
+    }
+
+    return function(a, b) {
+      return ids.indexOf(a.id) - ids.indexOf(b.id)
+    }
+  }
+};
+ChartInternal.prototype.getTooltipContent = function(
+  d,
+  defaultTitleFormat,
+  defaultValueFormat,
+  color
+) {
+  var $$ = this,
+    config = $$.config,
+    titleFormat = config.tooltip_format_title || defaultTitleFormat,
+    nameFormat =
+      config.tooltip_format_name ||
+      function(name) {
+        return name
+      },
+    text,
+    i,
+    title,
+    value,
+    name,
+    bgcolor;
+
+  var valueFormat = config.tooltip_format_value;
+  if (!valueFormat) {
+    valueFormat = $$.isTargetNormalized(d.id)
+      ? (v, ratio) => `${(ratio * 100).toFixed(2)}%`
+      : defaultValueFormat;
+  }
+
+  var tooltipSortFunction = this.getTooltipSortFunction();
+  if (tooltipSortFunction) {
+    d.sort(tooltipSortFunction);
+  }
+
+  for (i = 0; i < d.length; i++) {
+    if (!(d[i] && (d[i].value || d[i].value === 0))) {
+      continue
+    }
+
+    if ($$.isStanfordGraphType()) {
+      // Custom tooltip for stanford plots
+      if (!text) {
+        title = $$.getStanfordTooltipTitle(d[i]);
+        text = "<table class='" + $$.CLASS.tooltip + "'>" + title;
+      }
+
+      bgcolor = $$.getStanfordPointColor(d[i]);
+      name = sanitise(config.data_epochs); // Epochs key name
+      value = d[i].epochs;
+    } else {
+      // Regular tooltip
+      if (!text) {
+        title = sanitise(titleFormat ? titleFormat(d[i].x, d[i].index) : d[i].x);
+        text =
+          "<table class='" +
+          $$.CLASS.tooltip +
+          "'>" +
+          (title || title === 0
+            ? "<tr><th colspan='2'>" + title + '</th></tr>'
+            : '');
+      }
+
+      value = sanitise(
+        valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index, d)
+      );
+      if (value !== undefined) {
+        // Skip elements when their name is set to null
+        if (d[i].name === null) {
+          continue
+        }
+
+        name = sanitise(nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index));
+        bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
+      }
+    }
+
+    if (value !== undefined) {
+      text +=
+        "<tr class='" +
+        $$.CLASS.tooltipName +
+        '-' +
+        $$.getTargetSelectorSuffix(d[i].id) +
+        "'>";
+      text +=
+        "<td class='name'><span style='background-color:" +
+        bgcolor +
+        "'></span>" +
+        name +
+        '</td>';
+      text += "<td class='value'>" + value + '</td>';
+      text += '</tr>';
+    }
+  }
+  return text + '</table>'
+};
+ChartInternal.prototype.tooltipPosition = function(
+  dataToShow,
+  tWidth,
+  tHeight,
+  element
+) {
+  var $$ = this,
+    config = $$.config,
+    d3 = $$.d3;
+  var svgLeft, tooltipLeft, tooltipRight, tooltipTop, chartRight;
+  var forArc = $$.hasArcType(),
+    mouse = d3.mouse(element);
+  // Determin tooltip position
+  if (forArc) {
+    tooltipLeft =
+      ($$.width - ($$.isLegendRight ? $$.getLegendWidth() : 0)) / 2 + mouse[0];
+    tooltipTop =
+      ($$.hasType('gauge') ? $$.height : $$.height / 2) + mouse[1] + 20;
+  } else {
+    svgLeft = $$.getSvgLeft(true);
+    if (config.axis_rotated) {
+      tooltipLeft = svgLeft + mouse[0] + 100;
+      tooltipRight = tooltipLeft + tWidth;
+      chartRight = $$.currentWidth - $$.getCurrentPaddingRight();
+      tooltipTop = $$.x(dataToShow[0].x) + 20;
+    } else {
+      tooltipLeft =
+        svgLeft + $$.getCurrentPaddingLeft(true) + $$.x(dataToShow[0].x) + 20;
+      tooltipRight = tooltipLeft + tWidth;
+      chartRight = svgLeft + $$.currentWidth - $$.getCurrentPaddingRight();
+      tooltipTop = mouse[1] + 15;
+    }
+
+    if (tooltipRight > chartRight) {
+      // 20 is needed for Firefox to keep tooltip width
+      tooltipLeft -= tooltipRight - chartRight + 20;
+    }
+    if (tooltipTop + tHeight > $$.currentHeight) {
+      tooltipTop -= tHeight + 30;
+    }
+  }
+  if (tooltipTop < 0) {
+    tooltipTop = 0;
+  }
+  return {
+    top: tooltipTop,
+    left: tooltipLeft
+  }
+};
+ChartInternal.prototype.showTooltip = function(selectedData, element) {
+  var $$ = this,
+    config = $$.config;
+  var tWidth, tHeight, position;
+  var forArc = $$.hasArcType(),
+    dataToShow = selectedData.filter(function(d) {
+      return d && isValue(d.value)
+    }),
+    positionFunction =
+      config.tooltip_position || ChartInternal.prototype.tooltipPosition;
+  if (dataToShow.length === 0 || !config.tooltip_show) {
+    $$.hideTooltip();
+    return
+  }
+  $$.tooltip
+    .html(
+      config.tooltip_contents.call(
+        $$,
+        selectedData,
+        $$.axis.getXAxisTickFormat(),
+        $$.getYFormat(forArc),
+        $$.color
+      )
+    )
+    .style('display', 'block');
+
+  // Get tooltip dimensions
+  tWidth = $$.tooltip.property('offsetWidth');
+  tHeight = $$.tooltip.property('offsetHeight');
+
+  position = positionFunction.call(this, dataToShow, tWidth, tHeight, element);
+  // Set tooltip
+  $$.tooltip
+    .style('top', position.top + 'px')
+    .style('left', position.left + 'px');
+};
+ChartInternal.prototype.hideTooltip = function() {
+  this.tooltip.style('display', 'none');
+};
+
+ChartInternal.prototype.setTargetType = function(targetIds, type) {
+  var $$ = this,
+    config = $$.config;
+  $$.mapToTargetIds(targetIds).forEach(function(id) {
+    $$.withoutFadeIn[id] = type === config.data_types[id];
+    config.data_types[id] = type;
+  });
+  if (!targetIds) {
+    config.data_type = type;
+  }
+};
+ChartInternal.prototype.hasType = function(type, targets) {
+  var $$ = this,
+    types = $$.config.data_types,
+    has = false;
+  targets = targets || $$.data.targets;
+  if (targets && targets.length) {
+    targets.forEach(function(target) {
+      var t = types[target.id];
+      if ((t && t.indexOf(type) >= 0) || (!t && type === 'line')) {
+        has = true;
+      }
+    });
+  } else if (Object.keys(types).length) {
+    Object.keys(types).forEach(function(id) {
+      if (types[id] === type) {
+        has = true;
+      }
+    });
+  } else {
+    has = $$.config.data_type === type;
+  }
+  return has
+};
+ChartInternal.prototype.hasArcType = function(targets) {
+  return (
+    this.hasType('pie', targets) ||
+    this.hasType('donut', targets) ||
+    this.hasType('gauge', targets)
+  )
+};
+ChartInternal.prototype.isLineType = function(d) {
+  var config = this.config,
+    id = isString(d) ? d : d.id;
+  return (
+    !config.data_types[id] ||
+    ['line', 'spline', 'area', 'area-spline', 'step', 'area-step'].indexOf(
+      config.data_types[id]
+    ) >= 0
+  )
+};
+ChartInternal.prototype.isStepType = function(d) {
+  var id = isString(d) ? d : d.id;
+  return ['step', 'area-step'].indexOf(this.config.data_types[id]) >= 0
+};
+ChartInternal.prototype.isSplineType = function(d) {
+  var id = isString(d) ? d : d.id;
+  return ['spline', 'area-spline'].indexOf(this.config.data_types[id]) >= 0
+};
+ChartInternal.prototype.isAreaType = function(d) {
+  var id = isString(d) ? d : d.id;
+  return (
+    ['area', 'area-spline', 'area-step'].indexOf(this.config.data_types[id]) >=
+    0
+  )
+};
+ChartInternal.prototype.isBarType = function(d) {
+  var id = isString(d) ? d : d.id;
+  return this.config.data_types[id] === 'bar'
+};
+ChartInternal.prototype.isScatterType = function(d) {
+  var id = isString(d) ? d : d.id;
+  return this.config.data_types[id] === 'scatter'
+};
+ChartInternal.prototype.isStanfordType = function(d) {
+  var id = isString(d) ? d : d.id;
+  return this.config.data_types[id] === 'stanford'
+};
+ChartInternal.prototype.isPieType = function(d) {
+  var id = isString(d) ? d : d.id;
+  return this.config.data_types[id] === 'pie'
+};
+ChartInternal.prototype.isGaugeType = function(d) {
+  var id = isString(d) ? d : d.id;
+  return this.config.data_types[id] === 'gauge'
+};
+ChartInternal.prototype.isDonutType = function(d) {
+  var id = isString(d) ? d : d.id;
+  return this.config.data_types[id] === 'donut'
+};
+ChartInternal.prototype.isArcType = function(d) {
+  return this.isPieType(d) || this.isDonutType(d) || this.isGaugeType(d)
+};
+ChartInternal.prototype.lineData = function(d) {
+  return this.isLineType(d) ? [d] : []
+};
+ChartInternal.prototype.arcData = function(d) {
+  return this.isArcType(d.data) ? [d] : []
+};
+/* not used
+ function scatterData(d) {
+ return isScatterType(d) ? d.values : [];
+ }
+ */
+ChartInternal.prototype.barData = function(d) {
+  return this.isBarType(d) ? d.values : []
+};
+ChartInternal.prototype.lineOrScatterOrStanfordData = function(d) {
+  return this.isLineType(d) || this.isScatterType(d) || this.isStanfordType(d)
+    ? d.values
+    : []
+};
+ChartInternal.prototype.barOrLineData = function(d) {
+  return this.isBarType(d) || this.isLineType(d) ? d.values : []
+};
+
+ChartInternal.prototype.isSafari = function() {
+  var ua = window.navigator.userAgent;
+  return ua.indexOf('Safari') >= 0 && ua.indexOf('Chrome') < 0
+};
+ChartInternal.prototype.isChrome = function() {
+  var ua = window.navigator.userAgent;
+  return ua.indexOf('Chrome') >= 0
+};
+
+ChartInternal.prototype.initZoom = function() {
+  var $$ = this,
+    d3 = $$.d3,
+    config = $$.config,
+    startEvent;
+
+  $$.zoom = d3
+    .zoom()
+    .on('start', function() {
+      if (config.zoom_type !== 'scroll') {
+        return
+      }
+
+      var e = d3.event.sourceEvent;
+      if (e && e.type === 'brush') {
+        return
+      }
+      startEvent = e;
+      config.zoom_onzoomstart.call($$.api, e);
+    })
+    .on('zoom', function() {
+      if (config.zoom_type !== 'scroll') {
+        return
+      }
+
+      var e = d3.event.sourceEvent;
+      if (e && e.type === 'brush') {
+        return
+      }
+
+      $$.redrawForZoom();
+
+      config.zoom_onzoom.call($$.api, $$.x.orgDomain());
+    })
+    .on('end', function() {
+      if (config.zoom_type !== 'scroll') {
+        return
+      }
+
+      var e = d3.event.sourceEvent;
+      if (e && e.type === 'brush') {
+        return
+      }
+      // if click, do nothing. otherwise, click interaction will be canceled.
+      if (
+        e &&
+        startEvent.clientX === e.clientX &&
+        startEvent.clientY === e.clientY
+      ) {
+        return
+      }
+      config.zoom_onzoomend.call($$.api, $$.x.orgDomain());
+    });
+
+  $$.zoom.updateDomain = function() {
+    if (d3.event && d3.event.transform) {
+      $$.x.domain(d3.event.transform.rescaleX($$.subX).domain());
+    }
+    return this
+  };
+  $$.zoom.updateExtent = function() {
+    this.scaleExtent([1, Infinity])
+      .translateExtent([
+        [0, 0],
+        [$$.width, $$.height]
+      ])
+      .extent([
+        [0, 0],
+        [$$.width, $$.height]
+      ]);
+    return this
+  };
+  $$.zoom.update = function() {
+    return this.updateExtent().updateDomain()
+  };
+
+  return $$.zoom.updateExtent()
+};
+ChartInternal.prototype.zoomTransform = function(range) {
+  var $$ = this,
+    s = [$$.x(range[0]), $$.x(range[1])];
+  return $$.d3.zoomIdentity.scale($$.width / (s[1] - s[0])).translate(-s[0], 0)
+};
+
+ChartInternal.prototype.initDragZoom = function() {
+  const $$ = this;
+  const d3 = $$.d3;
+  const config = $$.config;
+  const context = ($$.context = $$.svg);
+  const brushXPos = $$.margin.left + 20.5;
+  const brushYPos = $$.margin.top + 0.5;
+
+  if (!(config.zoom_type === 'drag' && config.zoom_enabled)) {
+    return
+  }
+
+  const getZoomedDomain = selection =>
+    selection && selection.map(x => $$.x.invert(x));
+
+  const brush = ($$.dragZoomBrush = d3
+    .brushX()
+    .on('start', () => {
+      $$.api.unzoom();
+
+      $$.svg.select('.' + CLASS.dragZoom).classed('disabled', false);
+
+      config.zoom_onzoomstart.call($$.api, d3.event.sourceEvent);
+    })
+    .on('brush', () => {
+      config.zoom_onzoom.call($$.api, getZoomedDomain(d3.event.selection));
+    })
+    .on('end', () => {
+      if (d3.event.selection == null) {
+        return
+      }
+
+      const zoomedDomain = getZoomedDomain(d3.event.selection);
+
+      if (!config.zoom_disableDefaultBehavior) {
+        $$.api.zoom(zoomedDomain);
+      }
+
+      $$.svg.select('.' + CLASS.dragZoom).classed('disabled', true);
+
+      config.zoom_onzoomend.call($$.api, zoomedDomain);
+    }));
+
+  context
+    .append('g')
+    .classed(CLASS.dragZoom, true)
+    .attr('clip-path', $$.clipPath)
+    .attr('transform', 'translate(' + brushXPos + ',' + brushYPos + ')')
+    .call(brush);
+};
+
+ChartInternal.prototype.getZoomDomain = function() {
+  var $$ = this,
+    config = $$.config,
+    d3 = $$.d3,
+    min = d3.min([$$.orgXDomain[0], config.zoom_x_min]),
+    max = d3.max([$$.orgXDomain[1], config.zoom_x_max]);
+  return [min, max]
+};
+ChartInternal.prototype.redrawForZoom = function() {
+  var $$ = this,
+    d3 = $$.d3,
+    config = $$.config,
+    zoom = $$.zoom,
+    x = $$.x;
+  if (!config.zoom_enabled) {
+    return
+  }
+  if ($$.filterTargetsToShow($$.data.targets).length === 0) {
+    return
+  }
+
+  zoom.update();
+
+  if (config.zoom_disableDefaultBehavior) {
+    return
+  }
+
+  if ($$.isCategorized() && x.orgDomain()[0] === $$.orgXDomain[0]) {
+    x.domain([$$.orgXDomain[0] - 1e-10, x.orgDomain()[1]]);
+  }
+
+  $$.redraw({
+    withTransition: false,
+    withY: config.zoom_rescale,
+    withSubchart: false,
+    withEventRect: false,
+    withDimension: false
+  });
+
+  if (d3.event.sourceEvent && d3.event.sourceEvent.type === 'mousemove') {
+    $$.cancelClick = true;
+  }
+};
+
+export default c3;

+ 11320 - 0
public/plugin/c3-0.7.20/c3.js

@@ -0,0 +1,11320 @@
+/* @license C3.js v0.7.20 | (c) C3 Team and other contributors | http://c3js.org/ */
+(function (global, factory) {
+  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+  typeof define === 'function' && define.amd ? define(factory) :
+  (global = global || self, global.c3 = factory());
+}(this, (function () { 'use strict';
+
+  function ChartInternal(api) {
+      var $$ = this;
+      // Note: This part will be replaced by rollup-plugin-modify
+      // When bundling esm output. Beware of changing this line.
+      // TODO: Maybe we should check that the modification by rollup-plugin-modify
+      // is valid during unit tests.
+      $$.d3 = window.d3
+          ? window.d3
+          : typeof require !== 'undefined'
+              ? require('d3')
+              : undefined;
+      $$.api = api;
+      $$.config = $$.getDefaultConfig();
+      $$.data = {};
+      $$.cache = {};
+      $$.axes = {};
+  }
+
+  /**
+   * The Chart class
+   *
+   * The methods of this class is the public APIs of the chart object.
+   */
+  function Chart(config) {
+      this.internal = new ChartInternal(this);
+      this.internal.loadConfig(config);
+      this.internal.beforeInit(config);
+      this.internal.init();
+      this.internal.afterInit(config);
+      (function bindThis(fn, target, argThis) {
+          Object.keys(fn).forEach(function (key) {
+              target[key] = fn[key].bind(argThis);
+              if (Object.keys(fn[key]).length > 0) {
+                  bindThis(fn[key], target[key], argThis);
+              }
+          });
+      })(Chart.prototype, this, this);
+  }
+
+  var asHalfPixel = function (n) {
+      return Math.ceil(n) + 0.5;
+  };
+  var ceil10 = function (v) {
+      return Math.ceil(v / 10) * 10;
+  };
+  var diffDomain = function (d) {
+      return d[1] - d[0];
+  };
+  var getOption = function (options, key, defaultValue) {
+      return isDefined(options[key]) ? options[key] : defaultValue;
+  };
+  var getPathBox = function (path) {
+      var box = getBBox(path), items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)], minX = items[0].x, minY = Math.min(items[0].y, items[1].y);
+      return { x: minX, y: minY, width: box.width, height: box.height };
+  };
+  var getBBox = function (element) {
+      try {
+          return element.getBBox();
+      }
+      catch (ignore) {
+          // Firefox will throw an exception if getBBox() is called whereas the
+          // element is rendered with display:none
+          // See https://github.com/c3js/c3/issues/2692
+          // The previous code was using `getBoundingClientRect` which was returning
+          // everything at 0 in this case so let's reproduce this behavior here.
+          return { x: 0, y: 0, width: 0, height: 0 };
+      }
+  };
+  var hasValue = function (dict, value) {
+      var found = false;
+      Object.keys(dict).forEach(function (key) {
+          if (dict[key] === value) {
+              found = true;
+          }
+      });
+      return found;
+  };
+  var isArray = function (o) {
+      return Array.isArray(o);
+  };
+  var isDefined = function (v) {
+      return typeof v !== 'undefined';
+  };
+  var isEmpty = function (o) {
+      return (typeof o === 'undefined' ||
+          o === null ||
+          (isString(o) && o.length === 0) ||
+          (typeof o === 'object' && Object.keys(o).length === 0));
+  };
+  var isFunction = function (o) {
+      return typeof o === 'function';
+  };
+  var isNumber = function (o) {
+      return typeof o === 'number';
+  };
+  var isString = function (o) {
+      return typeof o === 'string';
+  };
+  var isUndefined = function (v) {
+      return typeof v === 'undefined';
+  };
+  var isValue = function (v) {
+      return v || v === 0;
+  };
+  var notEmpty = function (o) {
+      return !isEmpty(o);
+  };
+  var sanitise = function (str) {
+      return typeof str === 'string'
+          ? str.replace(/</g, '&lt;').replace(/>/g, '&gt;')
+          : str;
+  };
+  var flattenArray = function (arr) {
+      return Array.isArray(arr) ? [].concat.apply([], arr) : [];
+  };
+  /**
+   * Returns whether the point is within the given box.
+   *
+   * @param {Array} point An [x,y] coordinate
+   * @param {Object} box An object with {x, y, width, height} keys
+   * @param {Number} sensitivity An offset to ease check on very small boxes
+   */
+  var isWithinBox = function (point, box, sensitivity) {
+      if (sensitivity === void 0) { sensitivity = 0; }
+      var xStart = box.x - sensitivity;
+      var xEnd = box.x + box.width + sensitivity;
+      var yStart = box.y + box.height + sensitivity;
+      var yEnd = box.y - sensitivity;
+      return (xStart < point[0] && point[0] < xEnd && yEnd < point[1] && point[1] < yStart);
+  };
+  /**
+   * Returns Internet Explorer version number (or false if no Internet Explorer used).
+   *
+   * @param string agent Optional parameter to specify user agent
+   */
+  var getIEVersion = function (agent) {
+      // https://stackoverflow.com/questions/19999388/check-if-user-is-using-ie
+      if (typeof agent === 'undefined') {
+          agent = window.navigator.userAgent;
+      }
+      var pos = agent.indexOf('MSIE '); // up to IE10
+      if (pos > 0) {
+          return parseInt(agent.substring(pos + 5, agent.indexOf('.', pos)), 10);
+      }
+      pos = agent.indexOf('Trident/'); // IE11
+      if (pos > 0) {
+          pos = agent.indexOf('rv:');
+          return parseInt(agent.substring(pos + 3, agent.indexOf('.', pos)), 10);
+      }
+      return false;
+  };
+  /**
+   * Returns whether the used browser is Internet Explorer.
+   *
+   * @param version Optional parameter to specify IE version
+   */
+  var isIE = function (version) {
+      var ver = getIEVersion();
+      if (typeof version === 'undefined') {
+          return !!ver;
+      }
+      return version === ver;
+  };
+
+  function AxisInternal(component, params) {
+      var internal = this;
+      internal.component = component;
+      internal.params = params || {};
+      internal.d3 = component.d3;
+      internal.scale = internal.d3.scaleLinear();
+      internal.range;
+      internal.orient = 'bottom';
+      internal.innerTickSize = 6;
+      internal.outerTickSize = this.params.withOuterTick ? 6 : 0;
+      internal.tickPadding = 3;
+      internal.tickValues = null;
+      internal.tickFormat;
+      internal.tickArguments;
+      internal.tickOffset = 0;
+      internal.tickCulling = true;
+      internal.tickCentered;
+      internal.tickTextCharSize;
+      internal.tickTextRotate = internal.params.tickTextRotate;
+      internal.tickLength;
+      internal.axis = internal.generateAxis();
+  }
+  AxisInternal.prototype.axisX = function (selection, x, tickOffset) {
+      selection.attr('transform', function (d) {
+          return 'translate(' + Math.ceil(x(d) + tickOffset) + ', 0)';
+      });
+  };
+  AxisInternal.prototype.axisY = function (selection, y) {
+      selection.attr('transform', function (d) {
+          return 'translate(0,' + Math.ceil(y(d)) + ')';
+      });
+  };
+  AxisInternal.prototype.scaleExtent = function (domain) {
+      var start = domain[0], stop = domain[domain.length - 1];
+      return start < stop ? [start, stop] : [stop, start];
+  };
+  AxisInternal.prototype.generateTicks = function (scale) {
+      var internal = this;
+      var i, domain, ticks = [];
+      if (scale.ticks) {
+          return scale.ticks.apply(scale, internal.tickArguments);
+      }
+      domain = scale.domain();
+      for (i = Math.ceil(domain[0]); i < domain[1]; i++) {
+          ticks.push(i);
+      }
+      if (ticks.length > 0 && ticks[0] > 0) {
+          ticks.unshift(ticks[0] - (ticks[1] - ticks[0]));
+      }
+      return ticks;
+  };
+  AxisInternal.prototype.copyScale = function () {
+      var internal = this;
+      var newScale = internal.scale.copy(), domain;
+      if (internal.params.isCategory) {
+          domain = internal.scale.domain();
+          newScale.domain([domain[0], domain[1] - 1]);
+      }
+      return newScale;
+  };
+  AxisInternal.prototype.textFormatted = function (v) {
+      var internal = this, formatted = internal.tickFormat ? internal.tickFormat(v) : v;
+      return typeof formatted !== 'undefined' ? formatted : '';
+  };
+  AxisInternal.prototype.updateRange = function () {
+      var internal = this;
+      internal.range = internal.scale.rangeExtent
+          ? internal.scale.rangeExtent()
+          : internal.scaleExtent(internal.scale.range());
+      return internal.range;
+  };
+  AxisInternal.prototype.updateTickTextCharSize = function (tick) {
+      var internal = this;
+      if (internal.tickTextCharSize) {
+          return internal.tickTextCharSize;
+      }
+      var size = {
+          h: 11.5,
+          w: 5.5
+      };
+      tick
+          .select('text')
+          .text(function (d) {
+          return internal.textFormatted(d);
+      })
+          .each(function (d) {
+          var box = getBBox(this), text = internal.textFormatted(d), h = box.height, w = text ? box.width / text.length : undefined;
+          if (h && w) {
+              size.h = h;
+              size.w = w;
+          }
+      })
+          .text('');
+      internal.tickTextCharSize = size;
+      return size;
+  };
+  AxisInternal.prototype.isVertical = function () {
+      return this.orient === 'left' || this.orient === 'right';
+  };
+  AxisInternal.prototype.tspanData = function (d, i, scale) {
+      var internal = this;
+      var splitted = internal.params.tickMultiline
+          ? internal.splitTickText(d, scale)
+          : [].concat(internal.textFormatted(d));
+      if (internal.params.tickMultiline && internal.params.tickMultilineMax > 0) {
+          splitted = internal.ellipsify(splitted, internal.params.tickMultilineMax);
+      }
+      return splitted.map(function (s) {
+          return { index: i, splitted: s, length: splitted.length };
+      });
+  };
+  AxisInternal.prototype.splitTickText = function (d, scale) {
+      var internal = this, tickText = internal.textFormatted(d), maxWidth = internal.params.tickWidth, subtext, spaceIndex, textWidth, splitted = [];
+      if (Object.prototype.toString.call(tickText) === '[object Array]') {
+          return tickText;
+      }
+      if (!maxWidth || maxWidth <= 0) {
+          maxWidth = internal.isVertical()
+              ? 95
+              : internal.params.isCategory
+                  ? Math.ceil(scale(1) - scale(0)) - 12
+                  : 110;
+      }
+      function split(splitted, text) {
+          spaceIndex = undefined;
+          for (var i = 1; i < text.length; i++) {
+              if (text.charAt(i) === ' ') {
+                  spaceIndex = i;
+              }
+              subtext = text.substr(0, i + 1);
+              textWidth = internal.tickTextCharSize.w * subtext.length;
+              // if text width gets over tick width, split by space index or crrent index
+              if (maxWidth < textWidth) {
+                  return split(splitted.concat(text.substr(0, spaceIndex ? spaceIndex : i)), text.slice(spaceIndex ? spaceIndex + 1 : i));
+              }
+          }
+          return splitted.concat(text);
+      }
+      return split(splitted, tickText + '');
+  };
+  AxisInternal.prototype.ellipsify = function (splitted, max) {
+      if (splitted.length <= max) {
+          return splitted;
+      }
+      var ellipsified = splitted.slice(0, max);
+      var remaining = 3;
+      for (var i = max - 1; i >= 0; i--) {
+          var available = ellipsified[i].length;
+          ellipsified[i] = ellipsified[i]
+              .substr(0, available - remaining)
+              .padEnd(available, '.');
+          remaining -= available;
+          if (remaining <= 0) {
+              break;
+          }
+      }
+      return ellipsified;
+  };
+  AxisInternal.prototype.updateTickLength = function () {
+      var internal = this;
+      internal.tickLength =
+          Math.max(internal.innerTickSize, 0) + internal.tickPadding;
+  };
+  AxisInternal.prototype.lineY2 = function (d) {
+      var internal = this, tickPosition = internal.scale(d) + (internal.tickCentered ? 0 : internal.tickOffset);
+      return internal.range[0] < tickPosition && tickPosition < internal.range[1]
+          ? internal.innerTickSize
+          : 0;
+  };
+  AxisInternal.prototype.textY = function () {
+      var internal = this, rotate = internal.tickTextRotate;
+      return rotate
+          ? 11.5 - 2.5 * (rotate / 15) * (rotate > 0 ? 1 : -1)
+          : internal.tickLength;
+  };
+  AxisInternal.prototype.textTransform = function () {
+      var internal = this, rotate = internal.tickTextRotate;
+      return rotate ? 'rotate(' + rotate + ')' : '';
+  };
+  AxisInternal.prototype.textTextAnchor = function () {
+      var internal = this, rotate = internal.tickTextRotate;
+      return rotate ? (rotate > 0 ? 'start' : 'end') : 'middle';
+  };
+  AxisInternal.prototype.tspanDx = function () {
+      var internal = this, rotate = internal.tickTextRotate;
+      return rotate ? 8 * Math.sin(Math.PI * (rotate / 180)) : 0;
+  };
+  AxisInternal.prototype.tspanDy = function (d, i) {
+      var internal = this, dy = internal.tickTextCharSize.h;
+      if (i === 0) {
+          if (internal.isVertical()) {
+              dy = -((d.length - 1) * (internal.tickTextCharSize.h / 2) - 3);
+          }
+          else {
+              dy = '.71em';
+          }
+      }
+      return dy;
+  };
+  AxisInternal.prototype.generateAxis = function () {
+      var internal = this, d3 = internal.d3, params = internal.params;
+      function axis(g, transition) {
+          var self;
+          g.each(function () {
+              var g = (axis.g = d3.select(this));
+              var scale0 = this.__chart__ || internal.scale, scale1 = (this.__chart__ = internal.copyScale());
+              var ticksValues = internal.tickValues
+                  ? internal.tickValues
+                  : internal.generateTicks(scale1), ticks = g.selectAll('.tick').data(ticksValues, scale1), tickEnter = ticks
+                  .enter()
+                  .insert('g', '.domain')
+                  .attr('class', 'tick')
+                  .style('opacity', 1e-6), 
+              // MEMO: No exit transition. The reason is this transition affects max tick width calculation because old tick will be included in the ticks.
+              tickExit = ticks.exit().remove(), tickUpdate = ticks.merge(tickEnter), tickTransform, tickX, tickY;
+              if (params.isCategory) {
+                  internal.tickOffset = Math.ceil((scale1(1) - scale1(0)) / 2);
+                  tickX = internal.tickCentered ? 0 : internal.tickOffset;
+                  tickY = internal.tickCentered ? internal.tickOffset : 0;
+              }
+              else {
+                  internal.tickOffset = tickX = 0;
+              }
+              internal.updateRange();
+              internal.updateTickLength();
+              internal.updateTickTextCharSize(g.select('.tick'));
+              var lineUpdate = tickUpdate
+                  .select('line')
+                  .merge(tickEnter.append('line')), textUpdate = tickUpdate.select('text').merge(tickEnter.append('text'));
+              var tspans = tickUpdate
+                  .selectAll('text')
+                  .selectAll('tspan')
+                  .data(function (d, i) {
+                  return internal.tspanData(d, i, scale1);
+              }), tspanEnter = tspans.enter().append('tspan'), tspanUpdate = tspanEnter.merge(tspans).text(function (d) {
+                  return d.splitted;
+              });
+              tspans.exit().remove();
+              var path = g.selectAll('.domain').data([0]), pathUpdate = path
+                  .enter()
+                  .append('path')
+                  .merge(path)
+                  .attr('class', 'domain');
+              // TODO: each attr should be one function and change its behavior by internal.orient, probably
+              switch (internal.orient) {
+                  case 'bottom': {
+                      tickTransform = internal.axisX;
+                      lineUpdate
+                          .attr('x1', tickX)
+                          .attr('x2', tickX)
+                          .attr('y2', function (d, i) {
+                          return internal.lineY2(d, i);
+                      });
+                      textUpdate
+                          .attr('x', 0)
+                          .attr('y', function (d, i) {
+                          return internal.textY(d, i);
+                      })
+                          .attr('transform', function (d, i) {
+                          return internal.textTransform(d, i);
+                      })
+                          .style('text-anchor', function (d, i) {
+                          return internal.textTextAnchor(d, i);
+                      });
+                      tspanUpdate
+                          .attr('x', 0)
+                          .attr('dy', function (d, i) {
+                          return internal.tspanDy(d, i);
+                      })
+                          .attr('dx', function (d, i) {
+                          return internal.tspanDx(d, i);
+                      });
+                      pathUpdate.attr('d', 'M' +
+                          internal.range[0] +
+                          ',' +
+                          internal.outerTickSize +
+                          'V0H' +
+                          internal.range[1] +
+                          'V' +
+                          internal.outerTickSize);
+                      break;
+                  }
+                  case 'top': {
+                      // TODO: rotated tick text
+                      tickTransform = internal.axisX;
+                      lineUpdate
+                          .attr('x1', tickX)
+                          .attr('x2', tickX)
+                          .attr('y2', function (d, i) {
+                          return -1 * internal.lineY2(d, i);
+                      });
+                      textUpdate
+                          .attr('x', 0)
+                          .attr('y', function (d, i) {
+                          return (-1 * internal.textY(d, i) -
+                              (params.isCategory ? 2 : internal.tickLength - 2));
+                      })
+                          .attr('transform', function (d, i) {
+                          return internal.textTransform(d, i);
+                      })
+                          .style('text-anchor', function (d, i) {
+                          return internal.textTextAnchor(d, i);
+                      });
+                      tspanUpdate
+                          .attr('x', 0)
+                          .attr('dy', function (d, i) {
+                          return internal.tspanDy(d, i);
+                      })
+                          .attr('dx', function (d, i) {
+                          return internal.tspanDx(d, i);
+                      });
+                      pathUpdate.attr('d', 'M' +
+                          internal.range[0] +
+                          ',' +
+                          -internal.outerTickSize +
+                          'V0H' +
+                          internal.range[1] +
+                          'V' +
+                          -internal.outerTickSize);
+                      break;
+                  }
+                  case 'left': {
+                      tickTransform = internal.axisY;
+                      lineUpdate
+                          .attr('x2', -internal.innerTickSize)
+                          .attr('y1', tickY)
+                          .attr('y2', tickY);
+                      textUpdate
+                          .attr('x', -internal.tickLength)
+                          .attr('y', internal.tickOffset)
+                          .style('text-anchor', 'end');
+                      tspanUpdate
+                          .attr('x', -internal.tickLength)
+                          .attr('dy', function (d, i) {
+                          return internal.tspanDy(d, i);
+                      });
+                      pathUpdate.attr('d', 'M' +
+                          -internal.outerTickSize +
+                          ',' +
+                          internal.range[0] +
+                          'H0V' +
+                          internal.range[1] +
+                          'H' +
+                          -internal.outerTickSize);
+                      break;
+                  }
+                  case 'right': {
+                      tickTransform = internal.axisY;
+                      lineUpdate
+                          .attr('x2', internal.innerTickSize)
+                          .attr('y1', tickY)
+                          .attr('y2', tickY);
+                      textUpdate
+                          .attr('x', internal.tickLength)
+                          .attr('y', internal.tickOffset)
+                          .style('text-anchor', 'start');
+                      tspanUpdate.attr('x', internal.tickLength).attr('dy', function (d, i) {
+                          return internal.tspanDy(d, i);
+                      });
+                      pathUpdate.attr('d', 'M' +
+                          internal.outerTickSize +
+                          ',' +
+                          internal.range[0] +
+                          'H0V' +
+                          internal.range[1] +
+                          'H' +
+                          internal.outerTickSize);
+                      break;
+                  }
+              }
+              if (scale1.rangeBand) {
+                  var x = scale1, dx = x.rangeBand() / 2;
+                  scale0 = scale1 = function (d) {
+                      return x(d) + dx;
+                  };
+              }
+              else if (scale0.rangeBand) {
+                  scale0 = scale1;
+              }
+              else {
+                  tickExit.call(tickTransform, scale1, internal.tickOffset);
+              }
+              tickEnter.call(tickTransform, scale0, internal.tickOffset);
+              self = (transition ? tickUpdate.transition(transition) : tickUpdate)
+                  .style('opacity', 1)
+                  .call(tickTransform, scale1, internal.tickOffset);
+          });
+          return self;
+      }
+      axis.scale = function (x) {
+          if (!arguments.length) {
+              return internal.scale;
+          }
+          internal.scale = x;
+          return axis;
+      };
+      axis.orient = function (x) {
+          if (!arguments.length) {
+              return internal.orient;
+          }
+          internal.orient =
+              x in { top: 1, right: 1, bottom: 1, left: 1 } ? x + '' : 'bottom';
+          return axis;
+      };
+      axis.tickFormat = function (format) {
+          if (!arguments.length) {
+              return internal.tickFormat;
+          }
+          internal.tickFormat = format;
+          return axis;
+      };
+      axis.tickCentered = function (isCentered) {
+          if (!arguments.length) {
+              return internal.tickCentered;
+          }
+          internal.tickCentered = isCentered;
+          return axis;
+      };
+      axis.tickOffset = function () {
+          return internal.tickOffset;
+      };
+      axis.tickInterval = function () {
+          var interval, length;
+          if (params.isCategory) {
+              interval = internal.tickOffset * 2;
+          }
+          else {
+              length =
+                  axis.g
+                      .select('path.domain')
+                      .node()
+                      .getTotalLength() -
+                      internal.outerTickSize * 2;
+              interval = length / axis.g.selectAll('line').size();
+          }
+          return interval === Infinity ? 0 : interval;
+      };
+      axis.ticks = function () {
+          if (!arguments.length) {
+              return internal.tickArguments;
+          }
+          internal.tickArguments = arguments;
+          return axis;
+      };
+      axis.tickCulling = function (culling) {
+          if (!arguments.length) {
+              return internal.tickCulling;
+          }
+          internal.tickCulling = culling;
+          return axis;
+      };
+      axis.tickValues = function (x) {
+          if (typeof x === 'function') {
+              internal.tickValues = function () {
+                  return x(internal.scale.domain());
+              };
+          }
+          else {
+              if (!arguments.length) {
+                  return internal.tickValues;
+              }
+              internal.tickValues = x;
+          }
+          return axis;
+      };
+      return axis;
+  };
+
+  var CLASS = {
+      target: 'c3-target',
+      chart: 'c3-chart',
+      chartLine: 'c3-chart-line',
+      chartLines: 'c3-chart-lines',
+      chartBar: 'c3-chart-bar',
+      chartBars: 'c3-chart-bars',
+      chartText: 'c3-chart-text',
+      chartTexts: 'c3-chart-texts',
+      chartArc: 'c3-chart-arc',
+      chartArcs: 'c3-chart-arcs',
+      chartArcsTitle: 'c3-chart-arcs-title',
+      chartArcsBackground: 'c3-chart-arcs-background',
+      chartArcsGaugeUnit: 'c3-chart-arcs-gauge-unit',
+      chartArcsGaugeMax: 'c3-chart-arcs-gauge-max',
+      chartArcsGaugeMin: 'c3-chart-arcs-gauge-min',
+      selectedCircle: 'c3-selected-circle',
+      selectedCircles: 'c3-selected-circles',
+      eventRect: 'c3-event-rect',
+      eventRects: 'c3-event-rects',
+      eventRectsSingle: 'c3-event-rects-single',
+      eventRectsMultiple: 'c3-event-rects-multiple',
+      zoomRect: 'c3-zoom-rect',
+      brush: 'c3-brush',
+      dragZoom: 'c3-drag-zoom',
+      focused: 'c3-focused',
+      defocused: 'c3-defocused',
+      region: 'c3-region',
+      regions: 'c3-regions',
+      title: 'c3-title',
+      tooltipContainer: 'c3-tooltip-container',
+      tooltip: 'c3-tooltip',
+      tooltipName: 'c3-tooltip-name',
+      shape: 'c3-shape',
+      shapes: 'c3-shapes',
+      line: 'c3-line',
+      lines: 'c3-lines',
+      bar: 'c3-bar',
+      bars: 'c3-bars',
+      circle: 'c3-circle',
+      circles: 'c3-circles',
+      arc: 'c3-arc',
+      arcLabelLine: 'c3-arc-label-line',
+      arcs: 'c3-arcs',
+      area: 'c3-area',
+      areas: 'c3-areas',
+      empty: 'c3-empty',
+      text: 'c3-text',
+      texts: 'c3-texts',
+      gaugeValue: 'c3-gauge-value',
+      grid: 'c3-grid',
+      gridLines: 'c3-grid-lines',
+      xgrid: 'c3-xgrid',
+      xgrids: 'c3-xgrids',
+      xgridLine: 'c3-xgrid-line',
+      xgridLines: 'c3-xgrid-lines',
+      xgridFocus: 'c3-xgrid-focus',
+      ygrid: 'c3-ygrid',
+      ygrids: 'c3-ygrids',
+      ygridLine: 'c3-ygrid-line',
+      ygridLines: 'c3-ygrid-lines',
+      colorScale: 'c3-colorscale',
+      stanfordElements: 'c3-stanford-elements',
+      stanfordLine: 'c3-stanford-line',
+      stanfordLines: 'c3-stanford-lines',
+      stanfordRegion: 'c3-stanford-region',
+      stanfordRegions: 'c3-stanford-regions',
+      stanfordText: 'c3-stanford-text',
+      stanfordTexts: 'c3-stanford-texts',
+      axis: 'c3-axis',
+      axisX: 'c3-axis-x',
+      axisXLabel: 'c3-axis-x-label',
+      axisY: 'c3-axis-y',
+      axisYLabel: 'c3-axis-y-label',
+      axisY2: 'c3-axis-y2',
+      axisY2Label: 'c3-axis-y2-label',
+      legendBackground: 'c3-legend-background',
+      legendItem: 'c3-legend-item',
+      legendItemEvent: 'c3-legend-item-event',
+      legendItemTile: 'c3-legend-item-tile',
+      legendItemHidden: 'c3-legend-item-hidden',
+      legendItemFocused: 'c3-legend-item-focused',
+      dragarea: 'c3-dragarea',
+      EXPANDED: '_expanded_',
+      SELECTED: '_selected_',
+      INCLUDED: '_included_'
+  };
+
+  var AxisClass = /** @class */ (function () {
+      function AxisClass(owner) {
+          this.owner = owner;
+          this.d3 = owner.d3;
+          this.internal = AxisInternal;
+      }
+      return AxisClass;
+  }());
+  var Axis = AxisClass;
+  Axis.prototype.init = function init() {
+      var $$ = this.owner, config = $$.config, main = $$.main;
+      $$.axes.x = main
+          .append('g')
+          .attr('class', CLASS.axis + ' ' + CLASS.axisX)
+          .attr('clip-path', config.axis_x_inner ? '' : $$.clipPathForXAxis)
+          .attr('transform', $$.getTranslate('x'))
+          .style('visibility', config.axis_x_show ? 'visible' : 'hidden');
+      $$.axes.x
+          .append('text')
+          .attr('class', CLASS.axisXLabel)
+          .attr('transform', config.axis_rotated ? 'rotate(-90)' : '')
+          .style('text-anchor', this.textAnchorForXAxisLabel.bind(this));
+      $$.axes.y = main
+          .append('g')
+          .attr('class', CLASS.axis + ' ' + CLASS.axisY)
+          .attr('clip-path', config.axis_y_inner ? '' : $$.clipPathForYAxis)
+          .attr('transform', $$.getTranslate('y'))
+          .style('visibility', config.axis_y_show ? 'visible' : 'hidden');
+      $$.axes.y
+          .append('text')
+          .attr('class', CLASS.axisYLabel)
+          .attr('transform', config.axis_rotated ? '' : 'rotate(-90)')
+          .style('text-anchor', this.textAnchorForYAxisLabel.bind(this));
+      $$.axes.y2 = main
+          .append('g')
+          .attr('class', CLASS.axis + ' ' + CLASS.axisY2)
+          // clip-path?
+          .attr('transform', $$.getTranslate('y2'))
+          .style('visibility', config.axis_y2_show ? 'visible' : 'hidden');
+      $$.axes.y2
+          .append('text')
+          .attr('class', CLASS.axisY2Label)
+          .attr('transform', config.axis_rotated ? '' : 'rotate(-90)')
+          .style('text-anchor', this.textAnchorForY2AxisLabel.bind(this));
+  };
+  Axis.prototype.getXAxis = function getXAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) {
+      var $$ = this.owner, config = $$.config, axisParams = {
+          isCategory: $$.isCategorized(),
+          withOuterTick: withOuterTick,
+          tickMultiline: config.axis_x_tick_multiline,
+          tickMultilineMax: config.axis_x_tick_multiline
+              ? Number(config.axis_x_tick_multilineMax)
+              : 0,
+          tickWidth: config.axis_x_tick_width,
+          tickTextRotate: withoutRotateTickText ? 0 : config.axis_x_tick_rotate,
+          withoutTransition: withoutTransition
+      }, axis = new this.internal(this, axisParams).axis.scale(scale).orient(orient);
+      if ($$.isTimeSeries() && tickValues && typeof tickValues !== 'function') {
+          tickValues = tickValues.map(function (v) {
+              return $$.parseDate(v);
+          });
+      }
+      // Set tick
+      axis.tickFormat(tickFormat).tickValues(tickValues);
+      if ($$.isCategorized()) {
+          axis.tickCentered(config.axis_x_tick_centered);
+          if (isEmpty(config.axis_x_tick_culling)) {
+              config.axis_x_tick_culling = false;
+          }
+      }
+      return axis;
+  };
+  Axis.prototype.updateXAxisTickValues = function updateXAxisTickValues(targets, axis) {
+      var $$ = this.owner, config = $$.config, tickValues;
+      if (config.axis_x_tick_fit || config.axis_x_tick_count) {
+          tickValues = this.generateTickValues($$.mapTargetsToUniqueXs(targets), config.axis_x_tick_count, $$.isTimeSeries());
+      }
+      if (axis) {
+          axis.tickValues(tickValues);
+      }
+      else {
+          $$.xAxis.tickValues(tickValues);
+          $$.subXAxis.tickValues(tickValues);
+      }
+      return tickValues;
+  };
+  Axis.prototype.getYAxis = function getYAxis(axisId, scale, orient, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) {
+      var $$ = this.owner;
+      var config = $$.config;
+      var tickFormat = config["axis_" + axisId + "_tick_format"];
+      if (!tickFormat && $$.isAxisNormalized(axisId)) {
+          tickFormat = function (x) { return x + "%"; };
+      }
+      var axis = new this.internal(this, {
+          withOuterTick: withOuterTick,
+          withoutTransition: withoutTransition,
+          tickTextRotate: withoutRotateTickText ? 0 : config.axis_y_tick_rotate
+      }).axis
+          .scale(scale)
+          .orient(orient);
+      if (tickFormat) {
+          axis.tickFormat(tickFormat);
+      }
+      if ($$.isTimeSeriesY()) {
+          axis.ticks(config.axis_y_tick_time_type, config.axis_y_tick_time_interval);
+      }
+      else {
+          axis.tickValues(tickValues);
+      }
+      return axis;
+  };
+  Axis.prototype.getId = function getId(id) {
+      var config = this.owner.config;
+      return id in config.data_axes ? config.data_axes[id] : 'y';
+  };
+  Axis.prototype.getXAxisTickFormat = function getXAxisTickFormat() {
+      // #2251 previously set any negative values to a whole number,
+      // however both should be truncated according to the users format specification
+      var $$ = this.owner, config = $$.config;
+      var format = $$.isTimeSeries()
+          ? $$.defaultAxisTimeFormat
+          : $$.isCategorized()
+              ? $$.categoryName
+              : function (v) {
+                  return v;
+              };
+      if (config.axis_x_tick_format) {
+          if (isFunction(config.axis_x_tick_format)) {
+              format = config.axis_x_tick_format;
+          }
+          else if ($$.isTimeSeries()) {
+              format = function (date) {
+                  return date ? $$.axisTimeFormat(config.axis_x_tick_format)(date) : '';
+              };
+          }
+      }
+      return isFunction(format)
+          ? function (v) {
+              return format.call($$, v);
+          }
+          : format;
+  };
+  Axis.prototype.getTickValues = function getTickValues(tickValues, axis) {
+      return tickValues ? tickValues : axis ? axis.tickValues() : undefined;
+  };
+  Axis.prototype.getXAxisTickValues = function getXAxisTickValues() {
+      return this.getTickValues(this.owner.config.axis_x_tick_values, this.owner.xAxis);
+  };
+  Axis.prototype.getYAxisTickValues = function getYAxisTickValues() {
+      return this.getTickValues(this.owner.config.axis_y_tick_values, this.owner.yAxis);
+  };
+  Axis.prototype.getY2AxisTickValues = function getY2AxisTickValues() {
+      return this.getTickValues(this.owner.config.axis_y2_tick_values, this.owner.y2Axis);
+  };
+  Axis.prototype.getLabelOptionByAxisId = function getLabelOptionByAxisId(axisId) {
+      var $$ = this.owner, config = $$.config, option;
+      if (axisId === 'y') {
+          option = config.axis_y_label;
+      }
+      else if (axisId === 'y2') {
+          option = config.axis_y2_label;
+      }
+      else if (axisId === 'x') {
+          option = config.axis_x_label;
+      }
+      return option;
+  };
+  Axis.prototype.getLabelText = function getLabelText(axisId) {
+      var option = this.getLabelOptionByAxisId(axisId);
+      return isString(option) ? option : option ? option.text : null;
+  };
+  Axis.prototype.setLabelText = function setLabelText(axisId, text) {
+      var $$ = this.owner, config = $$.config, option = this.getLabelOptionByAxisId(axisId);
+      if (isString(option)) {
+          if (axisId === 'y') {
+              config.axis_y_label = text;
+          }
+          else if (axisId === 'y2') {
+              config.axis_y2_label = text;
+          }
+          else if (axisId === 'x') {
+              config.axis_x_label = text;
+          }
+      }
+      else if (option) {
+          option.text = text;
+      }
+  };
+  Axis.prototype.getLabelPosition = function getLabelPosition(axisId, defaultPosition) {
+      var option = this.getLabelOptionByAxisId(axisId), position = option && typeof option === 'object' && option.position
+          ? option.position
+          : defaultPosition;
+      return {
+          isInner: position.indexOf('inner') >= 0,
+          isOuter: position.indexOf('outer') >= 0,
+          isLeft: position.indexOf('left') >= 0,
+          isCenter: position.indexOf('center') >= 0,
+          isRight: position.indexOf('right') >= 0,
+          isTop: position.indexOf('top') >= 0,
+          isMiddle: position.indexOf('middle') >= 0,
+          isBottom: position.indexOf('bottom') >= 0
+      };
+  };
+  Axis.prototype.getXAxisLabelPosition = function getXAxisLabelPosition() {
+      return this.getLabelPosition('x', this.owner.config.axis_rotated ? 'inner-top' : 'inner-right');
+  };
+  Axis.prototype.getYAxisLabelPosition = function getYAxisLabelPosition() {
+      return this.getLabelPosition('y', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top');
+  };
+  Axis.prototype.getY2AxisLabelPosition = function getY2AxisLabelPosition() {
+      return this.getLabelPosition('y2', this.owner.config.axis_rotated ? 'inner-right' : 'inner-top');
+  };
+  Axis.prototype.getLabelPositionById = function getLabelPositionById(id) {
+      return id === 'y2'
+          ? this.getY2AxisLabelPosition()
+          : id === 'y'
+              ? this.getYAxisLabelPosition()
+              : this.getXAxisLabelPosition();
+  };
+  Axis.prototype.textForXAxisLabel = function textForXAxisLabel() {
+      return this.getLabelText('x');
+  };
+  Axis.prototype.textForYAxisLabel = function textForYAxisLabel() {
+      return this.getLabelText('y');
+  };
+  Axis.prototype.textForY2AxisLabel = function textForY2AxisLabel() {
+      return this.getLabelText('y2');
+  };
+  Axis.prototype.xForAxisLabel = function xForAxisLabel(forHorizontal, position) {
+      var $$ = this.owner;
+      if (forHorizontal) {
+          return position.isLeft ? 0 : position.isCenter ? $$.width / 2 : $$.width;
+      }
+      else {
+          return position.isBottom
+              ? -$$.height
+              : position.isMiddle
+                  ? -$$.height / 2
+                  : 0;
+      }
+  };
+  Axis.prototype.dxForAxisLabel = function dxForAxisLabel(forHorizontal, position) {
+      if (forHorizontal) {
+          return position.isLeft ? '0.5em' : position.isRight ? '-0.5em' : '0';
+      }
+      else {
+          return position.isTop ? '-0.5em' : position.isBottom ? '0.5em' : '0';
+      }
+  };
+  Axis.prototype.textAnchorForAxisLabel = function textAnchorForAxisLabel(forHorizontal, position) {
+      if (forHorizontal) {
+          return position.isLeft ? 'start' : position.isCenter ? 'middle' : 'end';
+      }
+      else {
+          return position.isBottom ? 'start' : position.isMiddle ? 'middle' : 'end';
+      }
+  };
+  Axis.prototype.xForXAxisLabel = function xForXAxisLabel() {
+      return this.xForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());
+  };
+  Axis.prototype.xForYAxisLabel = function xForYAxisLabel() {
+      return this.xForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());
+  };
+  Axis.prototype.xForY2AxisLabel = function xForY2AxisLabel() {
+      return this.xForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());
+  };
+  Axis.prototype.dxForXAxisLabel = function dxForXAxisLabel() {
+      return this.dxForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());
+  };
+  Axis.prototype.dxForYAxisLabel = function dxForYAxisLabel() {
+      return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());
+  };
+  Axis.prototype.dxForY2AxisLabel = function dxForY2AxisLabel() {
+      return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());
+  };
+  Axis.prototype.dyForXAxisLabel = function dyForXAxisLabel() {
+      var $$ = this.owner, config = $$.config, position = this.getXAxisLabelPosition();
+      if (config.axis_rotated) {
+          return position.isInner
+              ? '1.2em'
+              : -25 - ($$.config.axis_x_inner ? 0 : this.getMaxTickWidth('x'));
+      }
+      else {
+          return position.isInner ? '-0.5em' : $$.getHorizontalAxisHeight('x') - 10;
+      }
+  };
+  Axis.prototype.dyForYAxisLabel = function dyForYAxisLabel() {
+      var $$ = this.owner, position = this.getYAxisLabelPosition();
+      if ($$.config.axis_rotated) {
+          return position.isInner ? '-0.5em' : '3em';
+      }
+      else {
+          return position.isInner
+              ? '1.2em'
+              : -10 - ($$.config.axis_y_inner ? 0 : this.getMaxTickWidth('y') + 10);
+      }
+  };
+  Axis.prototype.dyForY2AxisLabel = function dyForY2AxisLabel() {
+      var $$ = this.owner, position = this.getY2AxisLabelPosition();
+      if ($$.config.axis_rotated) {
+          return position.isInner ? '1.2em' : '-2.2em';
+      }
+      else {
+          return position.isInner
+              ? '-0.5em'
+              : 15 + ($$.config.axis_y2_inner ? 0 : this.getMaxTickWidth('y2') + 15);
+      }
+  };
+  Axis.prototype.textAnchorForXAxisLabel = function textAnchorForXAxisLabel() {
+      var $$ = this.owner;
+      return this.textAnchorForAxisLabel(!$$.config.axis_rotated, this.getXAxisLabelPosition());
+  };
+  Axis.prototype.textAnchorForYAxisLabel = function textAnchorForYAxisLabel() {
+      var $$ = this.owner;
+      return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getYAxisLabelPosition());
+  };
+  Axis.prototype.textAnchorForY2AxisLabel = function textAnchorForY2AxisLabel() {
+      var $$ = this.owner;
+      return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getY2AxisLabelPosition());
+  };
+  Axis.prototype.getMaxTickWidth = function getMaxTickWidth(id, withoutRecompute) {
+      var $$ = this.owner, maxWidth = 0, targetsToShow, scale, axis, dummy, svg;
+      if (withoutRecompute && $$.currentMaxTickWidths[id]) {
+          return $$.currentMaxTickWidths[id];
+      }
+      if ($$.svg) {
+          targetsToShow = $$.filterTargetsToShow($$.data.targets);
+          if (id === 'y') {
+              scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y'));
+              axis = this.getYAxis(id, scale, $$.yOrient, $$.yAxisTickValues, false, true, true);
+          }
+          else if (id === 'y2') {
+              scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2'));
+              axis = this.getYAxis(id, scale, $$.y2Orient, $$.y2AxisTickValues, false, true, true);
+          }
+          else {
+              scale = $$.x.copy().domain($$.getXDomain(targetsToShow));
+              axis = this.getXAxis(scale, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, false, true, true);
+              this.updateXAxisTickValues(targetsToShow, axis);
+          }
+          dummy = $$.d3
+              .select('body')
+              .append('div')
+              .classed('c3', true);
+          (svg = dummy
+              .append('svg')
+              .style('visibility', 'hidden')
+              .style('position', 'fixed')
+              .style('top', 0)
+              .style('left', 0)),
+              svg
+                  .append('g')
+                  .call(axis)
+                  .each(function () {
+                  $$.d3
+                      .select(this)
+                      .selectAll('text')
+                      .each(function () {
+                      var box = getBBox(this);
+                      if (maxWidth < box.width) {
+                          maxWidth = box.width;
+                      }
+                  });
+                  dummy.remove();
+              });
+      }
+      $$.currentMaxTickWidths[id] =
+          maxWidth <= 0 ? $$.currentMaxTickWidths[id] : maxWidth;
+      return $$.currentMaxTickWidths[id];
+  };
+  Axis.prototype.updateLabels = function updateLabels(withTransition) {
+      var $$ = this.owner;
+      var axisXLabel = $$.main.select('.' + CLASS.axisX + ' .' + CLASS.axisXLabel), axisYLabel = $$.main.select('.' + CLASS.axisY + ' .' + CLASS.axisYLabel), axisY2Label = $$.main.select('.' + CLASS.axisY2 + ' .' + CLASS.axisY2Label);
+      (withTransition ? axisXLabel.transition() : axisXLabel)
+          .attr('x', this.xForXAxisLabel.bind(this))
+          .attr('dx', this.dxForXAxisLabel.bind(this))
+          .attr('dy', this.dyForXAxisLabel.bind(this))
+          .text(this.textForXAxisLabel.bind(this));
+      (withTransition ? axisYLabel.transition() : axisYLabel)
+          .attr('x', this.xForYAxisLabel.bind(this))
+          .attr('dx', this.dxForYAxisLabel.bind(this))
+          .attr('dy', this.dyForYAxisLabel.bind(this))
+          .text(this.textForYAxisLabel.bind(this));
+      (withTransition ? axisY2Label.transition() : axisY2Label)
+          .attr('x', this.xForY2AxisLabel.bind(this))
+          .attr('dx', this.dxForY2AxisLabel.bind(this))
+          .attr('dy', this.dyForY2AxisLabel.bind(this))
+          .text(this.textForY2AxisLabel.bind(this));
+  };
+  Axis.prototype.getPadding = function getPadding(padding, key, defaultValue, domainLength) {
+      var p = typeof padding === 'number' ? padding : padding[key];
+      if (!isValue(p)) {
+          return defaultValue;
+      }
+      if (padding.unit === 'ratio') {
+          return padding[key] * domainLength;
+      }
+      // assume padding is pixels if unit is not specified
+      return this.convertPixelsToAxisPadding(p, domainLength);
+  };
+  Axis.prototype.convertPixelsToAxisPadding = function convertPixelsToAxisPadding(pixels, domainLength) {
+      var $$ = this.owner, length = $$.config.axis_rotated ? $$.width : $$.height;
+      return domainLength * (pixels / length);
+  };
+  Axis.prototype.generateTickValues = function generateTickValues(values, tickCount, forTimeSeries) {
+      var tickValues = values, targetCount, start, end, count, interval, i, tickValue;
+      if (tickCount) {
+          targetCount = isFunction(tickCount) ? tickCount() : tickCount;
+          // compute ticks according to tickCount
+          if (targetCount === 1) {
+              tickValues = [values[0]];
+          }
+          else if (targetCount === 2) {
+              tickValues = [values[0], values[values.length - 1]];
+          }
+          else if (targetCount > 2) {
+              count = targetCount - 2;
+              start = values[0];
+              end = values[values.length - 1];
+              interval = (end - start) / (count + 1);
+              // re-construct unique values
+              tickValues = [start];
+              for (i = 0; i < count; i++) {
+                  tickValue = +start + interval * (i + 1);
+                  tickValues.push(forTimeSeries ? new Date(tickValue) : tickValue);
+              }
+              tickValues.push(end);
+          }
+      }
+      if (!forTimeSeries) {
+          tickValues = tickValues.sort(function (a, b) {
+              return a - b;
+          });
+      }
+      return tickValues;
+  };
+  Axis.prototype.generateTransitions = function generateTransitions(duration) {
+      var $$ = this.owner, axes = $$.axes;
+      return {
+          axisX: duration ? axes.x.transition().duration(duration) : axes.x,
+          axisY: duration ? axes.y.transition().duration(duration) : axes.y,
+          axisY2: duration ? axes.y2.transition().duration(duration) : axes.y2,
+          axisSubX: duration ? axes.subx.transition().duration(duration) : axes.subx
+      };
+  };
+  Axis.prototype.redraw = function redraw(duration, isHidden) {
+      var $$ = this.owner, transition = duration ? $$.d3.transition().duration(duration) : null;
+      $$.axes.x.style('opacity', isHidden ? 0 : 1).call($$.xAxis, transition);
+      $$.axes.y.style('opacity', isHidden ? 0 : 1).call($$.yAxis, transition);
+      $$.axes.y2.style('opacity', isHidden ? 0 : 1).call($$.y2Axis, transition);
+      $$.axes.subx.style('opacity', isHidden ? 0 : 1).call($$.subXAxis, transition);
+  };
+
+  var c3 = {
+      version: '0.7.20',
+      chart: {
+          fn: Chart.prototype,
+          internal: {
+              fn: ChartInternal.prototype,
+              axis: {
+                  fn: AxisClass.prototype,
+                  internal: {
+                      fn: AxisInternal.prototype
+                  }
+              }
+          }
+      },
+      generate: function (config) {
+          return new Chart(config);
+      }
+  };
+  ChartInternal.prototype.beforeInit = function () {
+      // can do something
+  };
+  ChartInternal.prototype.afterInit = function () {
+      // can do something
+  };
+  ChartInternal.prototype.init = function () {
+      var $$ = this, config = $$.config;
+      $$.initParams();
+      if (config.data_url) {
+          $$.convertUrlToData(config.data_url, config.data_mimeType, config.data_headers, config.data_keys, $$.initWithData);
+      }
+      else if (config.data_json) {
+          $$.initWithData($$.convertJsonToData(config.data_json, config.data_keys));
+      }
+      else if (config.data_rows) {
+          $$.initWithData($$.convertRowsToData(config.data_rows));
+      }
+      else if (config.data_columns) {
+          $$.initWithData($$.convertColumnsToData(config.data_columns));
+      }
+      else {
+          throw Error('url or json or rows or columns is required.');
+      }
+  };
+  ChartInternal.prototype.initParams = function () {
+      var $$ = this, d3 = $$.d3, config = $$.config;
+      // MEMO: clipId needs to be unique because it conflicts when multiple charts exist
+      $$.clipId = 'c3-' + new Date().valueOf() + '-clip';
+      $$.clipIdForXAxis = $$.clipId + '-xaxis';
+      $$.clipIdForYAxis = $$.clipId + '-yaxis';
+      $$.clipIdForGrid = $$.clipId + '-grid';
+      $$.clipIdForSubchart = $$.clipId + '-subchart';
+      $$.clipPath = $$.getClipPath($$.clipId);
+      $$.clipPathForXAxis = $$.getClipPath($$.clipIdForXAxis);
+      $$.clipPathForYAxis = $$.getClipPath($$.clipIdForYAxis);
+      $$.clipPathForGrid = $$.getClipPath($$.clipIdForGrid);
+      $$.clipPathForSubchart = $$.getClipPath($$.clipIdForSubchart);
+      $$.dragStart = null;
+      $$.dragging = false;
+      $$.flowing = false;
+      $$.cancelClick = false;
+      $$.mouseover = undefined;
+      $$.transiting = false;
+      $$.color = $$.generateColor();
+      $$.levelColor = $$.generateLevelColor();
+      $$.dataTimeParse = (config.data_xLocaltime ? d3.timeParse : d3.utcParse)($$.config.data_xFormat);
+      $$.axisTimeFormat = config.axis_x_localtime ? d3.timeFormat : d3.utcFormat;
+      $$.defaultAxisTimeFormat = function (date) {
+          if (date.getMilliseconds()) {
+              return d3.timeFormat('.%L')(date);
+          }
+          if (date.getSeconds()) {
+              return d3.timeFormat(':%S')(date);
+          }
+          if (date.getMinutes()) {
+              return d3.timeFormat('%I:%M')(date);
+          }
+          if (date.getHours()) {
+              return d3.timeFormat('%I %p')(date);
+          }
+          if (date.getDay() && date.getDate() !== 1) {
+              return d3.timeFormat('%-m/%-d')(date);
+          }
+          if (date.getDate() !== 1) {
+              return d3.timeFormat('%-m/%-d')(date);
+          }
+          if (date.getMonth()) {
+              return d3.timeFormat('%-m/%-d')(date);
+          }
+          return d3.timeFormat('%Y/%-m/%-d')(date);
+      };
+      $$.hiddenTargetIds = [];
+      $$.hiddenLegendIds = [];
+      $$.focusedTargetIds = [];
+      $$.defocusedTargetIds = [];
+      $$.xOrient = config.axis_rotated
+          ? config.axis_x_inner
+              ? 'right'
+              : 'left'
+          : config.axis_x_inner
+              ? 'top'
+              : 'bottom';
+      $$.yOrient = config.axis_rotated
+          ? config.axis_y_inner
+              ? 'top'
+              : 'bottom'
+          : config.axis_y_inner
+              ? 'right'
+              : 'left';
+      $$.y2Orient = config.axis_rotated
+          ? config.axis_y2_inner
+              ? 'bottom'
+              : 'top'
+          : config.axis_y2_inner
+              ? 'left'
+              : 'right';
+      $$.subXOrient = config.axis_rotated ? 'left' : 'bottom';
+      $$.isLegendRight = config.legend_position === 'right';
+      $$.isLegendInset = config.legend_position === 'inset';
+      $$.isLegendTop =
+          config.legend_inset_anchor === 'top-left' ||
+              config.legend_inset_anchor === 'top-right';
+      $$.isLegendLeft =
+          config.legend_inset_anchor === 'top-left' ||
+              config.legend_inset_anchor === 'bottom-left';
+      $$.legendStep = 0;
+      $$.legendItemWidth = 0;
+      $$.legendItemHeight = 0;
+      $$.currentMaxTickWidths = {
+          x: 0,
+          y: 0,
+          y2: 0
+      };
+      $$.rotated_padding_left = 30;
+      $$.rotated_padding_right = config.axis_rotated && !config.axis_x_show ? 0 : 30;
+      $$.rotated_padding_top = 5;
+      $$.withoutFadeIn = {};
+      $$.intervalForObserveInserted = undefined;
+      $$.axes.subx = d3.selectAll([]); // needs when excluding subchart.js
+  };
+  ChartInternal.prototype.initChartElements = function () {
+      if (this.initBar) {
+          this.initBar();
+      }
+      if (this.initLine) {
+          this.initLine();
+      }
+      if (this.initArc) {
+          this.initArc();
+      }
+      if (this.initGauge) {
+          this.initGauge();
+      }
+      if (this.initText) {
+          this.initText();
+      }
+  };
+  ChartInternal.prototype.initWithData = function (data) {
+      var $$ = this, d3 = $$.d3, config = $$.config;
+      var defs, main, binding = true;
+      $$.axis = new AxisClass($$);
+      if (!config.bindto) {
+          $$.selectChart = d3.selectAll([]);
+      }
+      else if (typeof config.bindto.node === 'function') {
+          $$.selectChart = config.bindto;
+      }
+      else {
+          $$.selectChart = d3.select(config.bindto);
+      }
+      if ($$.selectChart.empty()) {
+          $$.selectChart = d3
+              .select(document.createElement('div'))
+              .style('opacity', 0);
+          $$.observeInserted($$.selectChart);
+          binding = false;
+      }
+      $$.selectChart.html('').classed('c3', true);
+      // Init data as targets
+      $$.data.xs = {};
+      $$.data.targets = $$.convertDataToTargets(data);
+      if (config.data_filter) {
+          $$.data.targets = $$.data.targets.filter(config.data_filter);
+      }
+      // Set targets to hide if needed
+      if (config.data_hide) {
+          $$.addHiddenTargetIds(config.data_hide === true
+              ? $$.mapToIds($$.data.targets)
+              : config.data_hide);
+      }
+      if (config.legend_hide) {
+          $$.addHiddenLegendIds(config.legend_hide === true
+              ? $$.mapToIds($$.data.targets)
+              : config.legend_hide);
+      }
+      if ($$.isStanfordGraphType()) {
+          $$.initStanfordData();
+      }
+      // Init sizes and scales
+      $$.updateSizes();
+      $$.updateScales();
+      // Set domains for each scale
+      $$.x.domain(d3.extent($$.getXDomain($$.data.targets)));
+      $$.y.domain($$.getYDomain($$.data.targets, 'y'));
+      $$.y2.domain($$.getYDomain($$.data.targets, 'y2'));
+      $$.subX.domain($$.x.domain());
+      $$.subY.domain($$.y.domain());
+      $$.subY2.domain($$.y2.domain());
+      // Save original x domain for zoom update
+      $$.orgXDomain = $$.x.domain();
+      /*-- Basic Elements --*/
+      // Define svgs
+      $$.svg = $$.selectChart
+          .append('svg')
+          .style('overflow', 'hidden')
+          .on('mouseenter', function () {
+          return config.onmouseover.call($$);
+      })
+          .on('mouseleave', function () {
+          return config.onmouseout.call($$);
+      });
+      if ($$.config.svg_classname) {
+          $$.svg.attr('class', $$.config.svg_classname);
+      }
+      // Define defs
+      defs = $$.svg.append('defs');
+      $$.clipChart = $$.appendClip(defs, $$.clipId);
+      $$.clipXAxis = $$.appendClip(defs, $$.clipIdForXAxis);
+      $$.clipYAxis = $$.appendClip(defs, $$.clipIdForYAxis);
+      $$.clipGrid = $$.appendClip(defs, $$.clipIdForGrid);
+      $$.clipSubchart = $$.appendClip(defs, $$.clipIdForSubchart);
+      $$.updateSvgSize();
+      // Define regions
+      main = $$.main = $$.svg.append('g').attr('transform', $$.getTranslate('main'));
+      if ($$.initPie) {
+          $$.initPie();
+      }
+      if ($$.initDragZoom) {
+          $$.initDragZoom();
+      }
+      if (config.subchart_show && $$.initSubchart) {
+          $$.initSubchart();
+      }
+      if ($$.initTooltip) {
+          $$.initTooltip();
+      }
+      if ($$.initLegend) {
+          $$.initLegend();
+      }
+      if ($$.initTitle) {
+          $$.initTitle();
+      }
+      if ($$.initZoom) {
+          $$.initZoom();
+      }
+      if ($$.isStanfordGraphType()) {
+          $$.drawColorScale();
+      }
+      // Update selection based on size and scale
+      // TODO: currently this must be called after initLegend because of update of sizes, but it should be done in initSubchart.
+      if (config.subchart_show && $$.initSubchartBrush) {
+          $$.initSubchartBrush();
+      }
+      /*-- Main Region --*/
+      // text when empty
+      main
+          .append('text')
+          .attr('class', CLASS.text + ' ' + CLASS.empty)
+          .attr('text-anchor', 'middle') // horizontal centering of text at x position in all browsers.
+          .attr('dominant-baseline', 'middle'); // vertical centering of text at y position in all browsers, except IE.
+      // Regions
+      $$.initRegion();
+      // Grids
+      $$.initGrid();
+      // Define g for chart area
+      main
+          .append('g')
+          .attr('clip-path', $$.clipPath)
+          .attr('class', CLASS.chart);
+      // Grid lines
+      if (config.grid_lines_front) {
+          $$.initGridLines();
+      }
+      $$.initStanfordElements();
+      // Cover whole with rects for events
+      $$.initEventRect();
+      // Define g for chart
+      $$.initChartElements();
+      // Add Axis
+      $$.axis.init();
+      // Set targets
+      $$.updateTargets($$.data.targets);
+      // Set default extent if defined
+      if (config.axis_x_selection) {
+          $$.brush.selectionAsValue($$.getDefaultSelection());
+      }
+      // Draw with targets
+      if (binding) {
+          $$.updateDimension();
+          $$.config.oninit.call($$);
+          $$.redraw({
+              withTransition: false,
+              withTransform: true,
+              withUpdateXDomain: true,
+              withUpdateOrgXDomain: true,
+              withTransitionForAxis: false
+          });
+      }
+      // Bind to resize event
+      $$.bindResize();
+      // Bind to window focus event
+      $$.bindWindowFocus();
+      // export element of the chart
+      $$.api.element = $$.selectChart.node();
+  };
+  ChartInternal.prototype.smoothLines = function (el, type) {
+      var $$ = this;
+      if (type === 'grid') {
+          el.each(function () {
+              var g = $$.d3.select(this), x1 = g.attr('x1'), x2 = g.attr('x2'), y1 = g.attr('y1'), y2 = g.attr('y2');
+              g.attr({
+                  x1: Math.ceil(x1),
+                  x2: Math.ceil(x2),
+                  y1: Math.ceil(y1),
+                  y2: Math.ceil(y2)
+              });
+          });
+      }
+  };
+  ChartInternal.prototype.updateSizes = function () {
+      var $$ = this, config = $$.config;
+      var legendHeight = $$.legend ? $$.getLegendHeight() : 0, legendWidth = $$.legend ? $$.getLegendWidth() : 0, legendHeightForBottom = $$.isLegendRight || $$.isLegendInset ? 0 : legendHeight, hasArc = $$.hasArcType(), xAxisHeight = config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight('x'), subchartXAxisHeight = config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight('x', true), subchartHeight = config.subchart_show && !hasArc
+          ? config.subchart_size_height + subchartXAxisHeight
+          : 0;
+      $$.currentWidth = $$.getCurrentWidth();
+      $$.currentHeight = $$.getCurrentHeight();
+      // for main
+      $$.margin = config.axis_rotated
+          ? {
+              top: $$.getHorizontalAxisHeight('y2') + $$.getCurrentPaddingTop(),
+              right: hasArc ? 0 : $$.getCurrentPaddingRight(),
+              bottom: $$.getHorizontalAxisHeight('y') +
+                  legendHeightForBottom +
+                  $$.getCurrentPaddingBottom(),
+              left: subchartHeight + (hasArc ? 0 : $$.getCurrentPaddingLeft())
+          }
+          : {
+              top: 4 + $$.getCurrentPaddingTop(),
+              right: hasArc ? 0 : $$.getCurrentPaddingRight(),
+              bottom: xAxisHeight +
+                  subchartHeight +
+                  legendHeightForBottom +
+                  $$.getCurrentPaddingBottom(),
+              left: hasArc ? 0 : $$.getCurrentPaddingLeft()
+          };
+      // for subchart
+      $$.margin2 = config.axis_rotated
+          ? {
+              top: $$.margin.top,
+              right: NaN,
+              bottom: 20 + legendHeightForBottom,
+              left: $$.rotated_padding_left
+          }
+          : {
+              top: $$.currentHeight - subchartHeight - legendHeightForBottom,
+              right: NaN,
+              bottom: subchartXAxisHeight + legendHeightForBottom,
+              left: $$.margin.left
+          };
+      // for legend
+      $$.margin3 = {
+          top: 0,
+          right: NaN,
+          bottom: 0,
+          left: 0
+      };
+      if ($$.updateSizeForLegend) {
+          $$.updateSizeForLegend(legendHeight, legendWidth);
+      }
+      $$.width = $$.currentWidth - $$.margin.left - $$.margin.right;
+      $$.height = $$.currentHeight - $$.margin.top - $$.margin.bottom;
+      if ($$.width < 0) {
+          $$.width = 0;
+      }
+      if ($$.height < 0) {
+          $$.height = 0;
+      }
+      $$.width2 = config.axis_rotated
+          ? $$.margin.left - $$.rotated_padding_left - $$.rotated_padding_right
+          : $$.width;
+      $$.height2 = config.axis_rotated
+          ? $$.height
+          : $$.currentHeight - $$.margin2.top - $$.margin2.bottom;
+      if ($$.width2 < 0) {
+          $$.width2 = 0;
+      }
+      if ($$.height2 < 0) {
+          $$.height2 = 0;
+      }
+      // for arc
+      $$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0);
+      $$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10);
+      if ($$.hasType('gauge') && !config.gauge_fullCircle) {
+          $$.arcHeight += $$.height - $$.getGaugeLabelHeight();
+      }
+      if ($$.updateRadius) {
+          $$.updateRadius();
+      }
+      if ($$.isLegendRight && hasArc) {
+          $$.margin3.left = $$.arcWidth / 2 + $$.radiusExpanded * 1.1;
+      }
+  };
+  ChartInternal.prototype.updateTargets = function (targets) {
+      var $$ = this, config = $$.config;
+      /*-- Main --*/
+      //-- Text --//
+      $$.updateTargetsForText(targets);
+      //-- Bar --//
+      $$.updateTargetsForBar(targets);
+      //-- Line --//
+      $$.updateTargetsForLine(targets);
+      //-- Arc --//
+      if ($$.hasArcType() && $$.updateTargetsForArc) {
+          $$.updateTargetsForArc(targets);
+      }
+      /*-- Sub --*/
+      if (config.subchart_show && $$.updateTargetsForSubchart) {
+          $$.updateTargetsForSubchart(targets);
+      }
+      // Fade-in each chart
+      $$.showTargets();
+  };
+  ChartInternal.prototype.showTargets = function () {
+      var $$ = this;
+      $$.svg
+          .selectAll('.' + CLASS.target)
+          .filter(function (d) {
+          return $$.isTargetToShow(d.id);
+      })
+          .transition()
+          .duration($$.config.transition_duration)
+          .style('opacity', 1);
+  };
+  ChartInternal.prototype.redraw = function (options, transitions) {
+      var $$ = this, main = $$.main, d3 = $$.d3, config = $$.config;
+      var areaIndices = $$.getShapeIndices($$.isAreaType), barIndices = $$.getShapeIndices($$.isBarType), lineIndices = $$.getShapeIndices($$.isLineType);
+      var withY, withSubchart, withTransition, withTransitionForExit, withTransitionForAxis, withTransform, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain, withLegend, withEventRect, withDimension, withUpdateXAxis;
+      var hideAxis = $$.hasArcType();
+      var drawArea, drawBar, drawLine, xForText, yForText;
+      var duration, durationForExit, durationForAxis;
+      var transitionsToWait, waitForDraw, flow, transition;
+      var targetsToShow = $$.filterTargetsToShow($$.data.targets), tickValues, i, intervalForCulling, xDomainForZoom;
+      var xv = $$.xv.bind($$), cx, cy;
+      options = options || {};
+      withY = getOption(options, 'withY', true);
+      withSubchart = getOption(options, 'withSubchart', true);
+      withTransition = getOption(options, 'withTransition', true);
+      withTransform = getOption(options, 'withTransform', false);
+      withUpdateXDomain = getOption(options, 'withUpdateXDomain', false);
+      withUpdateOrgXDomain = getOption(options, 'withUpdateOrgXDomain', false);
+      withTrimXDomain = getOption(options, 'withTrimXDomain', true);
+      withUpdateXAxis = getOption(options, 'withUpdateXAxis', withUpdateXDomain);
+      withLegend = getOption(options, 'withLegend', false);
+      withEventRect = getOption(options, 'withEventRect', true);
+      withDimension = getOption(options, 'withDimension', true);
+      withTransitionForExit = getOption(options, 'withTransitionForExit', withTransition);
+      withTransitionForAxis = getOption(options, 'withTransitionForAxis', withTransition);
+      duration = withTransition ? config.transition_duration : 0;
+      durationForExit = withTransitionForExit ? duration : 0;
+      durationForAxis = withTransitionForAxis ? duration : 0;
+      transitions = transitions || $$.axis.generateTransitions(durationForAxis);
+      // update legend and transform each g
+      if (withLegend && config.legend_show) {
+          $$.updateLegend($$.mapToIds($$.data.targets), options, transitions);
+      }
+      else if (withDimension) {
+          // need to update dimension (e.g. axis.y.tick.values) because y tick values should change
+          // no need to update axis in it because they will be updated in redraw()
+          $$.updateDimension(true);
+      }
+      // MEMO: needed for grids calculation
+      if ($$.isCategorized() && targetsToShow.length === 0) {
+          $$.x.domain([0, $$.axes.x.selectAll('.tick').size()]);
+      }
+      if (targetsToShow.length) {
+          $$.updateXDomain(targetsToShow, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain);
+          if (!config.axis_x_tick_values) {
+              tickValues = $$.axis.updateXAxisTickValues(targetsToShow);
+          }
+      }
+      else {
+          $$.xAxis.tickValues([]);
+          $$.subXAxis.tickValues([]);
+      }
+      if (config.zoom_rescale && !options.flow) {
+          xDomainForZoom = $$.x.orgDomain();
+      }
+      $$.y.domain($$.getYDomain(targetsToShow, 'y', xDomainForZoom));
+      $$.y2.domain($$.getYDomain(targetsToShow, 'y2', xDomainForZoom));
+      if (!config.axis_y_tick_values && config.axis_y_tick_count) {
+          $$.yAxis.tickValues($$.axis.generateTickValues($$.y.domain(), config.axis_y_tick_count));
+      }
+      if (!config.axis_y2_tick_values && config.axis_y2_tick_count) {
+          $$.y2Axis.tickValues($$.axis.generateTickValues($$.y2.domain(), config.axis_y2_tick_count));
+      }
+      // axes
+      $$.axis.redraw(durationForAxis, hideAxis);
+      // Update axis label
+      $$.axis.updateLabels(withTransition);
+      // show/hide if manual culling needed
+      if ((withUpdateXDomain || withUpdateXAxis) && targetsToShow.length) {
+          if (config.axis_x_tick_culling && tickValues) {
+              for (i = 1; i < tickValues.length; i++) {
+                  if (tickValues.length / i < config.axis_x_tick_culling_max) {
+                      intervalForCulling = i;
+                      break;
+                  }
+              }
+              $$.svg.selectAll('.' + CLASS.axisX + ' .tick text').each(function (e) {
+                  var index = tickValues.indexOf(e);
+                  if (index >= 0) {
+                      d3.select(this).style('display', index % intervalForCulling ? 'none' : 'block');
+                  }
+              });
+          }
+          else {
+              $$.svg
+                  .selectAll('.' + CLASS.axisX + ' .tick text')
+                  .style('display', 'block');
+          }
+      }
+      // setup drawer - MEMO: these must be called after axis updated
+      drawArea = $$.generateDrawArea
+          ? $$.generateDrawArea(areaIndices, false)
+          : undefined;
+      drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices) : undefined;
+      drawLine = $$.generateDrawLine
+          ? $$.generateDrawLine(lineIndices, false)
+          : undefined;
+      xForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, true);
+      yForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, false);
+      // update circleY based on updated parameters
+      $$.updateCircleY();
+      // generate circle x/y functions depending on updated params
+      cx = ($$.config.axis_rotated ? $$.circleY : $$.circleX).bind($$);
+      cy = ($$.config.axis_rotated ? $$.circleX : $$.circleY).bind($$);
+      // Update sub domain
+      if (withY) {
+          $$.subY.domain($$.getYDomain(targetsToShow, 'y'));
+          $$.subY2.domain($$.getYDomain(targetsToShow, 'y2'));
+      }
+      // xgrid focus
+      $$.updateXgridFocus();
+      // Data empty label positioning and text.
+      main
+          .select('text.' + CLASS.text + '.' + CLASS.empty)
+          .attr('x', $$.width / 2)
+          .attr('y', $$.height / 2)
+          .text(config.data_empty_label_text)
+          .transition()
+          .style('opacity', targetsToShow.length ? 0 : 1);
+      // event rect
+      if (withEventRect) {
+          $$.redrawEventRect();
+      }
+      // grid
+      $$.updateGrid(duration);
+      $$.updateStanfordElements(duration);
+      // rect for regions
+      $$.updateRegion(duration);
+      // bars
+      $$.updateBar(durationForExit);
+      // lines, areas and circles
+      $$.updateLine(durationForExit);
+      $$.updateArea(durationForExit);
+      $$.updateCircle(cx, cy);
+      // text
+      if ($$.hasDataLabel()) {
+          $$.updateText(xForText, yForText, durationForExit);
+      }
+      // title
+      if ($$.redrawTitle) {
+          $$.redrawTitle();
+      }
+      // arc
+      if ($$.redrawArc) {
+          $$.redrawArc(duration, durationForExit, withTransform);
+      }
+      // subchart
+      if (config.subchart_show && $$.redrawSubchart) {
+          $$.redrawSubchart(withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices);
+      }
+      if ($$.isStanfordGraphType()) {
+          $$.drawColorScale();
+      }
+      // circles for select
+      main
+          .selectAll('.' + CLASS.selectedCircles)
+          .filter($$.isBarType.bind($$))
+          .selectAll('circle')
+          .remove();
+      if (options.flow) {
+          flow = $$.generateFlow({
+              targets: targetsToShow,
+              flow: options.flow,
+              duration: options.flow.duration,
+              drawBar: drawBar,
+              drawLine: drawLine,
+              drawArea: drawArea,
+              cx: cx,
+              cy: cy,
+              xv: xv,
+              xForText: xForText,
+              yForText: yForText
+          });
+      }
+      if (duration && $$.isTabVisible()) {
+          // Only use transition if tab visible. See #938.
+          // transition should be derived from one transition
+          transition = d3.transition().duration(duration);
+          transitionsToWait = [];
+          [
+              $$.redrawBar(drawBar, true, transition),
+              $$.redrawLine(drawLine, true, transition),
+              $$.redrawArea(drawArea, true, transition),
+              $$.redrawCircle(cx, cy, true, transition),
+              $$.redrawText(xForText, yForText, options.flow, true, transition),
+              $$.redrawRegion(true, transition),
+              $$.redrawGrid(true, transition)
+          ].forEach(function (transitions) {
+              transitions.forEach(function (transition) {
+                  transitionsToWait.push(transition);
+              });
+          });
+          // Wait for end of transitions to call flow and onrendered callback
+          waitForDraw = $$.generateWait();
+          transitionsToWait.forEach(function (t) {
+              waitForDraw.add(t);
+          });
+          waitForDraw(function () {
+              if (flow) {
+                  flow();
+              }
+              if (config.onrendered) {
+                  config.onrendered.call($$);
+              }
+          });
+      }
+      else {
+          $$.redrawBar(drawBar);
+          $$.redrawLine(drawLine);
+          $$.redrawArea(drawArea);
+          $$.redrawCircle(cx, cy);
+          $$.redrawText(xForText, yForText, options.flow);
+          $$.redrawRegion();
+          $$.redrawGrid();
+          if (flow) {
+              flow();
+          }
+          if (config.onrendered) {
+              config.onrendered.call($$);
+          }
+      }
+      // update fadein condition
+      $$.mapToIds($$.data.targets).forEach(function (id) {
+          $$.withoutFadeIn[id] = true;
+      });
+  };
+  ChartInternal.prototype.updateAndRedraw = function (options) {
+      var $$ = this, config = $$.config, transitions;
+      options = options || {};
+      // same with redraw
+      options.withTransition = getOption(options, 'withTransition', true);
+      options.withTransform = getOption(options, 'withTransform', false);
+      options.withLegend = getOption(options, 'withLegend', false);
+      // NOT same with redraw
+      options.withUpdateXDomain = getOption(options, 'withUpdateXDomain', true);
+      options.withUpdateOrgXDomain = getOption(options, 'withUpdateOrgXDomain', true);
+      options.withTransitionForExit = false;
+      options.withTransitionForTransform = getOption(options, 'withTransitionForTransform', options.withTransition);
+      // MEMO: this needs to be called before updateLegend and it means this ALWAYS needs to be called)
+      $$.updateSizes();
+      // MEMO: called in updateLegend in redraw if withLegend
+      if (!(options.withLegend && config.legend_show)) {
+          transitions = $$.axis.generateTransitions(options.withTransitionForAxis ? config.transition_duration : 0);
+          // Update scales
+          $$.updateScales();
+          $$.updateSvgSize();
+          // Update g positions
+          $$.transformAll(options.withTransitionForTransform, transitions);
+      }
+      // Draw with new sizes & scales
+      $$.redraw(options, transitions);
+  };
+  ChartInternal.prototype.redrawWithoutRescale = function () {
+      this.redraw({
+          withY: false,
+          withSubchart: false,
+          withEventRect: false,
+          withTransitionForAxis: false
+      });
+  };
+  ChartInternal.prototype.isTimeSeries = function () {
+      return this.config.axis_x_type === 'timeseries';
+  };
+  ChartInternal.prototype.isCategorized = function () {
+      return this.config.axis_x_type.indexOf('categor') >= 0;
+  };
+  ChartInternal.prototype.isCustomX = function () {
+      var $$ = this, config = $$.config;
+      return !$$.isTimeSeries() && (config.data_x || notEmpty(config.data_xs));
+  };
+  ChartInternal.prototype.isTimeSeriesY = function () {
+      return this.config.axis_y_type === 'timeseries';
+  };
+  ChartInternal.prototype.getTranslate = function (target) {
+      var $$ = this, config = $$.config, x, y;
+      if (target === 'main') {
+          x = asHalfPixel($$.margin.left);
+          y = asHalfPixel($$.margin.top);
+      }
+      else if (target === 'context') {
+          x = asHalfPixel($$.margin2.left);
+          y = asHalfPixel($$.margin2.top);
+      }
+      else if (target === 'legend') {
+          x = $$.margin3.left;
+          y = $$.margin3.top;
+      }
+      else if (target === 'x') {
+          x = 0;
+          y = config.axis_rotated ? 0 : $$.height;
+      }
+      else if (target === 'y') {
+          x = 0;
+          y = config.axis_rotated ? $$.height : 0;
+      }
+      else if (target === 'y2') {
+          x = config.axis_rotated ? 0 : $$.width;
+          y = config.axis_rotated ? 1 : 0;
+      }
+      else if (target === 'subx') {
+          x = 0;
+          y = config.axis_rotated ? 0 : $$.height2;
+      }
+      else if (target === 'arc') {
+          x = $$.arcWidth / 2;
+          y = $$.arcHeight / 2 - ($$.hasType('gauge') ? 6 : 0); // to prevent wrong display of min and max label
+      }
+      return 'translate(' + x + ',' + y + ')';
+  };
+  ChartInternal.prototype.initialOpacity = function (d) {
+      return d.value !== null && this.withoutFadeIn[d.id] ? 1 : 0;
+  };
+  ChartInternal.prototype.initialOpacityForCircle = function (d) {
+      return d.value !== null && this.withoutFadeIn[d.id]
+          ? this.opacityForCircle(d)
+          : 0;
+  };
+  ChartInternal.prototype.opacityForCircle = function (d) {
+      var isPointShouldBeShown = isFunction(this.config.point_show)
+          ? this.config.point_show(d)
+          : this.config.point_show;
+      var opacity = isPointShouldBeShown || this.isStanfordType(d) ? 1 : 0;
+      return isValue(d.value) ? (this.isScatterType(d) ? 0.5 : opacity) : 0;
+  };
+  ChartInternal.prototype.opacityForText = function () {
+      return this.hasDataLabel() ? 1 : 0;
+  };
+  ChartInternal.prototype.xx = function (d) {
+      return d ? this.x(d.x) : null;
+  };
+  ChartInternal.prototype.xvCustom = function (d, xyValue) {
+      var $$ = this, value = xyValue ? d[xyValue] : d.value;
+      if ($$.isTimeSeries()) {
+          value = $$.parseDate(d.value);
+      }
+      else if ($$.isCategorized() && typeof d.value === 'string') {
+          value = $$.config.axis_x_categories.indexOf(d.value);
+      }
+      return Math.ceil($$.x(value));
+  };
+  ChartInternal.prototype.yvCustom = function (d, xyValue) {
+      var $$ = this, yScale = d.axis && d.axis === 'y2' ? $$.y2 : $$.y, value = xyValue ? d[xyValue] : d.value;
+      return Math.ceil(yScale(value));
+  };
+  ChartInternal.prototype.xv = function (d) {
+      var $$ = this, value = d.value;
+      if ($$.isTimeSeries()) {
+          value = $$.parseDate(d.value);
+      }
+      else if ($$.isCategorized() && typeof d.value === 'string') {
+          value = $$.config.axis_x_categories.indexOf(d.value);
+      }
+      return Math.ceil($$.x(value));
+  };
+  ChartInternal.prototype.yv = function (d) {
+      var $$ = this, yScale = d.axis && d.axis === 'y2' ? $$.y2 : $$.y;
+      return Math.ceil(yScale(d.value));
+  };
+  ChartInternal.prototype.subxx = function (d) {
+      return d ? this.subX(d.x) : null;
+  };
+  ChartInternal.prototype.transformMain = function (withTransition, transitions) {
+      var $$ = this, xAxis, yAxis, y2Axis;
+      if (transitions && transitions.axisX) {
+          xAxis = transitions.axisX;
+      }
+      else {
+          xAxis = $$.main.select('.' + CLASS.axisX);
+          if (withTransition) {
+              xAxis = xAxis.transition();
+          }
+      }
+      if (transitions && transitions.axisY) {
+          yAxis = transitions.axisY;
+      }
+      else {
+          yAxis = $$.main.select('.' + CLASS.axisY);
+          if (withTransition) {
+              yAxis = yAxis.transition();
+          }
+      }
+      if (transitions && transitions.axisY2) {
+          y2Axis = transitions.axisY2;
+      }
+      else {
+          y2Axis = $$.main.select('.' + CLASS.axisY2);
+          if (withTransition) {
+              y2Axis = y2Axis.transition();
+          }
+      }
+      (withTransition ? $$.main.transition() : $$.main).attr('transform', $$.getTranslate('main'));
+      xAxis.attr('transform', $$.getTranslate('x'));
+      yAxis.attr('transform', $$.getTranslate('y'));
+      y2Axis.attr('transform', $$.getTranslate('y2'));
+      $$.main
+          .select('.' + CLASS.chartArcs)
+          .attr('transform', $$.getTranslate('arc'));
+  };
+  ChartInternal.prototype.transformAll = function (withTransition, transitions) {
+      var $$ = this;
+      $$.transformMain(withTransition, transitions);
+      if ($$.config.subchart_show) {
+          $$.transformContext(withTransition, transitions);
+      }
+      if ($$.legend) {
+          $$.transformLegend(withTransition);
+      }
+  };
+  ChartInternal.prototype.updateSvgSize = function () {
+      var $$ = this, brush = $$.svg.select("." + CLASS.brush + " .overlay");
+      $$.svg.attr('width', $$.currentWidth).attr('height', $$.currentHeight);
+      $$.svg
+          .selectAll(['#' + $$.clipId, '#' + $$.clipIdForGrid])
+          .select('rect')
+          .attr('width', $$.width)
+          .attr('height', $$.height);
+      $$.svg
+          .select('#' + $$.clipIdForXAxis)
+          .select('rect')
+          .attr('x', $$.getXAxisClipX.bind($$))
+          .attr('y', $$.getXAxisClipY.bind($$))
+          .attr('width', $$.getXAxisClipWidth.bind($$))
+          .attr('height', $$.getXAxisClipHeight.bind($$));
+      $$.svg
+          .select('#' + $$.clipIdForYAxis)
+          .select('rect')
+          .attr('x', $$.getYAxisClipX.bind($$))
+          .attr('y', $$.getYAxisClipY.bind($$))
+          .attr('width', $$.getYAxisClipWidth.bind($$))
+          .attr('height', $$.getYAxisClipHeight.bind($$));
+      $$.svg
+          .select('#' + $$.clipIdForSubchart)
+          .select('rect')
+          .attr('width', $$.width)
+          .attr('height', (brush.size() && brush.attr('height')) || 0);
+      // MEMO: parent div's height will be bigger than svg when <!DOCTYPE html>
+      $$.selectChart.style('max-height', $$.currentHeight + 'px');
+  };
+  ChartInternal.prototype.updateDimension = function (withoutAxis) {
+      var $$ = this;
+      if (!withoutAxis) {
+          if ($$.config.axis_rotated) {
+              $$.axes.x.call($$.xAxis);
+              $$.axes.subx.call($$.subXAxis);
+          }
+          else {
+              $$.axes.y.call($$.yAxis);
+              $$.axes.y2.call($$.y2Axis);
+          }
+      }
+      $$.updateSizes();
+      $$.updateScales();
+      $$.updateSvgSize();
+      $$.transformAll(false);
+  };
+  ChartInternal.prototype.observeInserted = function (selection) {
+      var $$ = this, observer;
+      if (typeof MutationObserver === 'undefined') {
+          window.console.error('MutationObserver not defined.');
+          return;
+      }
+      observer = new MutationObserver(function (mutations) {
+          mutations.forEach(function (mutation) {
+              if (mutation.type === 'childList' && mutation.previousSibling) {
+                  observer.disconnect();
+                  // need to wait for completion of load because size calculation requires the actual sizes determined after that completion
+                  $$.intervalForObserveInserted = window.setInterval(function () {
+                      // parentNode will NOT be null when completed
+                      if (selection.node().parentNode) {
+                          window.clearInterval($$.intervalForObserveInserted);
+                          $$.updateDimension();
+                          if ($$.brush) {
+                              $$.brush.update();
+                          }
+                          $$.config.oninit.call($$);
+                          $$.redraw({
+                              withTransform: true,
+                              withUpdateXDomain: true,
+                              withUpdateOrgXDomain: true,
+                              withTransition: false,
+                              withTransitionForTransform: false,
+                              withLegend: true
+                          });
+                          selection.transition().style('opacity', 1);
+                      }
+                  }, 10);
+              }
+          });
+      });
+      observer.observe(selection.node(), {
+          attributes: true,
+          childList: true,
+          characterData: true
+      });
+  };
+  /**
+   * Binds handlers to the window resize event.
+   */
+  ChartInternal.prototype.bindResize = function () {
+      var $$ = this, config = $$.config;
+      $$.resizeFunction = $$.generateResize(); // need to call .remove
+      $$.resizeFunction.add(function () {
+          config.onresize.call($$);
+      });
+      if (config.resize_auto) {
+          $$.resizeFunction.add(function () {
+              if ($$.resizeTimeout !== undefined) {
+                  window.clearTimeout($$.resizeTimeout);
+              }
+              $$.resizeTimeout = window.setTimeout(function () {
+                  delete $$.resizeTimeout;
+                  $$.updateAndRedraw({
+                      withUpdateXDomain: false,
+                      withUpdateOrgXDomain: false,
+                      withTransition: false,
+                      withTransitionForTransform: false,
+                      withLegend: true
+                  });
+                  if ($$.brush) {
+                      $$.brush.update();
+                  }
+              }, 100);
+          });
+      }
+      $$.resizeFunction.add(function () {
+          config.onresized.call($$);
+      });
+      $$.resizeIfElementDisplayed = function () {
+          // if element not displayed skip it
+          if ($$.api == null || !$$.api.element.offsetParent) {
+              return;
+          }
+          $$.resizeFunction();
+      };
+      window.addEventListener('resize', $$.resizeIfElementDisplayed, false);
+  };
+  /**
+   * Binds handlers to the window focus event.
+   */
+  ChartInternal.prototype.bindWindowFocus = function () {
+      var _this = this;
+      if (this.windowFocusHandler) {
+          // The handler is already set
+          return;
+      }
+      this.windowFocusHandler = function () {
+          _this.redraw();
+      };
+      window.addEventListener('focus', this.windowFocusHandler);
+  };
+  /**
+   * Unbinds from the window focus event.
+   */
+  ChartInternal.prototype.unbindWindowFocus = function () {
+      window.removeEventListener('focus', this.windowFocusHandler);
+      delete this.windowFocusHandler;
+  };
+  ChartInternal.prototype.generateResize = function () {
+      var resizeFunctions = [];
+      function callResizeFunctions() {
+          resizeFunctions.forEach(function (f) {
+              f();
+          });
+      }
+      callResizeFunctions.add = function (f) {
+          resizeFunctions.push(f);
+      };
+      callResizeFunctions.remove = function (f) {
+          for (var i = 0; i < resizeFunctions.length; i++) {
+              if (resizeFunctions[i] === f) {
+                  resizeFunctions.splice(i, 1);
+                  break;
+              }
+          }
+      };
+      return callResizeFunctions;
+  };
+  ChartInternal.prototype.endall = function (transition, callback) {
+      var n = 0;
+      transition
+          .each(function () {
+          ++n;
+      })
+          .on('end', function () {
+          if (!--n) {
+              callback.apply(this, arguments);
+          }
+      });
+  };
+  ChartInternal.prototype.generateWait = function () {
+      var $$ = this;
+      var transitionsToWait = [], f = function (callback) {
+          var timer = setInterval(function () {
+              if (!$$.isTabVisible()) {
+                  return;
+              }
+              var done = 0;
+              transitionsToWait.forEach(function (t) {
+                  if (t.empty()) {
+                      done += 1;
+                      return;
+                  }
+                  try {
+                      t.transition();
+                  }
+                  catch (e) {
+                      done += 1;
+                  }
+              });
+              if (done === transitionsToWait.length) {
+                  clearInterval(timer);
+                  if (callback) {
+                      callback();
+                  }
+              }
+          }, 50);
+      };
+      f.add = function (transition) {
+          transitionsToWait.push(transition);
+      };
+      return f;
+  };
+  ChartInternal.prototype.parseDate = function (date) {
+      var $$ = this, parsedDate;
+      if (date instanceof Date) {
+          parsedDate = date;
+      }
+      else if (typeof date === 'string') {
+          parsedDate = $$.dataTimeParse(date);
+      }
+      else if (typeof date === 'object') {
+          parsedDate = new Date(+date);
+      }
+      else if (typeof date === 'number' && !isNaN(date)) {
+          parsedDate = new Date(+date);
+      }
+      if (!parsedDate || isNaN(+parsedDate)) {
+          window.console.error("Failed to parse x '" + date + "' to Date object");
+      }
+      return parsedDate;
+  };
+  ChartInternal.prototype.isTabVisible = function () {
+      return !document.hidden;
+  };
+  ChartInternal.prototype.getPathBox = getPathBox;
+  ChartInternal.prototype.CLASS = CLASS;
+
+  /* jshint ignore:start */
+  (function () {
+      if (!('SVGPathSeg' in window)) {
+          // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg
+          window.SVGPathSeg = function (type, typeAsLetter, owningPathSegList) {
+              this.pathSegType = type;
+              this.pathSegTypeAsLetter = typeAsLetter;
+              this._owningPathSegList = owningPathSegList;
+          };
+          window.SVGPathSeg.prototype.classname = 'SVGPathSeg';
+          window.SVGPathSeg.PATHSEG_UNKNOWN = 0;
+          window.SVGPathSeg.PATHSEG_CLOSEPATH = 1;
+          window.SVGPathSeg.PATHSEG_MOVETO_ABS = 2;
+          window.SVGPathSeg.PATHSEG_MOVETO_REL = 3;
+          window.SVGPathSeg.PATHSEG_LINETO_ABS = 4;
+          window.SVGPathSeg.PATHSEG_LINETO_REL = 5;
+          window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;
+          window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;
+          window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;
+          window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;
+          window.SVGPathSeg.PATHSEG_ARC_ABS = 10;
+          window.SVGPathSeg.PATHSEG_ARC_REL = 11;
+          window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;
+          window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;
+          window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;
+          window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;
+          window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
+          window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
+          window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
+          window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
+          // Notify owning PathSegList on any changes so they can be synchronized back to the path element.
+          window.SVGPathSeg.prototype._segmentChanged = function () {
+              if (this._owningPathSegList)
+                  this._owningPathSegList.segmentChanged(this);
+          };
+          window.SVGPathSegClosePath = function (owningPathSegList) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CLOSEPATH, 'z', owningPathSegList);
+          };
+          window.SVGPathSegClosePath.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegClosePath.prototype.toString = function () {
+              return '[object SVGPathSegClosePath]';
+          };
+          window.SVGPathSegClosePath.prototype._asPathString = function () {
+              return this.pathSegTypeAsLetter;
+          };
+          window.SVGPathSegClosePath.prototype.clone = function () {
+              return new window.SVGPathSegClosePath(undefined);
+          };
+          window.SVGPathSegMovetoAbs = function (owningPathSegList, x, y) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_ABS, 'M', owningPathSegList);
+              this._x = x;
+              this._y = y;
+          };
+          window.SVGPathSegMovetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegMovetoAbs.prototype.toString = function () {
+              return '[object SVGPathSegMovetoAbs]';
+          };
+          window.SVGPathSegMovetoAbs.prototype._asPathString = function () {
+              return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
+          };
+          window.SVGPathSegMovetoAbs.prototype.clone = function () {
+              return new window.SVGPathSegMovetoAbs(undefined, this._x, this._y);
+          };
+          Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegMovetoRel = function (owningPathSegList, x, y) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_REL, 'm', owningPathSegList);
+              this._x = x;
+              this._y = y;
+          };
+          window.SVGPathSegMovetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegMovetoRel.prototype.toString = function () {
+              return '[object SVGPathSegMovetoRel]';
+          };
+          window.SVGPathSegMovetoRel.prototype._asPathString = function () {
+              return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
+          };
+          window.SVGPathSegMovetoRel.prototype.clone = function () {
+              return new window.SVGPathSegMovetoRel(undefined, this._x, this._y);
+          };
+          Object.defineProperty(window.SVGPathSegMovetoRel.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegMovetoRel.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegLinetoAbs = function (owningPathSegList, x, y) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_ABS, 'L', owningPathSegList);
+              this._x = x;
+              this._y = y;
+          };
+          window.SVGPathSegLinetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegLinetoAbs.prototype.toString = function () {
+              return '[object SVGPathSegLinetoAbs]';
+          };
+          window.SVGPathSegLinetoAbs.prototype._asPathString = function () {
+              return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
+          };
+          window.SVGPathSegLinetoAbs.prototype.clone = function () {
+              return new window.SVGPathSegLinetoAbs(undefined, this._x, this._y);
+          };
+          Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegLinetoRel = function (owningPathSegList, x, y) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_REL, 'l', owningPathSegList);
+              this._x = x;
+              this._y = y;
+          };
+          window.SVGPathSegLinetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegLinetoRel.prototype.toString = function () {
+              return '[object SVGPathSegLinetoRel]';
+          };
+          window.SVGPathSegLinetoRel.prototype._asPathString = function () {
+              return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
+          };
+          window.SVGPathSegLinetoRel.prototype.clone = function () {
+              return new window.SVGPathSegLinetoRel(undefined, this._x, this._y);
+          };
+          Object.defineProperty(window.SVGPathSegLinetoRel.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegLinetoRel.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegCurvetoCubicAbs = function (owningPathSegList, x, y, x1, y1, x2, y2) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, 'C', owningPathSegList);
+              this._x = x;
+              this._y = y;
+              this._x1 = x1;
+              this._y1 = y1;
+              this._x2 = x2;
+              this._y2 = y2;
+          };
+          window.SVGPathSegCurvetoCubicAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegCurvetoCubicAbs.prototype.toString = function () {
+              return '[object SVGPathSegCurvetoCubicAbs]';
+          };
+          window.SVGPathSegCurvetoCubicAbs.prototype._asPathString = function () {
+              return (this.pathSegTypeAsLetter +
+                  ' ' +
+                  this._x1 +
+                  ' ' +
+                  this._y1 +
+                  ' ' +
+                  this._x2 +
+                  ' ' +
+                  this._y2 +
+                  ' ' +
+                  this._x +
+                  ' ' +
+                  this._y);
+          };
+          window.SVGPathSegCurvetoCubicAbs.prototype.clone = function () {
+              return new window.SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2);
+          };
+          Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'x1', {
+              get: function () {
+                  return this._x1;
+              },
+              set: function (x1) {
+                  this._x1 = x1;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'y1', {
+              get: function () {
+                  return this._y1;
+              },
+              set: function (y1) {
+                  this._y1 = y1;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'x2', {
+              get: function () {
+                  return this._x2;
+              },
+              set: function (x2) {
+                  this._x2 = x2;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'y2', {
+              get: function () {
+                  return this._y2;
+              },
+              set: function (y2) {
+                  this._y2 = y2;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegCurvetoCubicRel = function (owningPathSegList, x, y, x1, y1, x2, y2) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, 'c', owningPathSegList);
+              this._x = x;
+              this._y = y;
+              this._x1 = x1;
+              this._y1 = y1;
+              this._x2 = x2;
+              this._y2 = y2;
+          };
+          window.SVGPathSegCurvetoCubicRel.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegCurvetoCubicRel.prototype.toString = function () {
+              return '[object SVGPathSegCurvetoCubicRel]';
+          };
+          window.SVGPathSegCurvetoCubicRel.prototype._asPathString = function () {
+              return (this.pathSegTypeAsLetter +
+                  ' ' +
+                  this._x1 +
+                  ' ' +
+                  this._y1 +
+                  ' ' +
+                  this._x2 +
+                  ' ' +
+                  this._y2 +
+                  ' ' +
+                  this._x +
+                  ' ' +
+                  this._y);
+          };
+          window.SVGPathSegCurvetoCubicRel.prototype.clone = function () {
+              return new window.SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2);
+          };
+          Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'x1', {
+              get: function () {
+                  return this._x1;
+              },
+              set: function (x1) {
+                  this._x1 = x1;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'y1', {
+              get: function () {
+                  return this._y1;
+              },
+              set: function (y1) {
+                  this._y1 = y1;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'x2', {
+              get: function () {
+                  return this._x2;
+              },
+              set: function (x2) {
+                  this._x2 = x2;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'y2', {
+              get: function () {
+                  return this._y2;
+              },
+              set: function (y2) {
+                  this._y2 = y2;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegCurvetoQuadraticAbs = function (owningPathSegList, x, y, x1, y1) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, 'Q', owningPathSegList);
+              this._x = x;
+              this._y = y;
+              this._x1 = x1;
+              this._y1 = y1;
+          };
+          window.SVGPathSegCurvetoQuadraticAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegCurvetoQuadraticAbs.prototype.toString = function () {
+              return '[object SVGPathSegCurvetoQuadraticAbs]';
+          };
+          window.SVGPathSegCurvetoQuadraticAbs.prototype._asPathString = function () {
+              return (this.pathSegTypeAsLetter +
+                  ' ' +
+                  this._x1 +
+                  ' ' +
+                  this._y1 +
+                  ' ' +
+                  this._x +
+                  ' ' +
+                  this._y);
+          };
+          window.SVGPathSegCurvetoQuadraticAbs.prototype.clone = function () {
+              return new window.SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1);
+          };
+          Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'x1', {
+              get: function () {
+                  return this._x1;
+              },
+              set: function (x1) {
+                  this._x1 = x1;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'y1', {
+              get: function () {
+                  return this._y1;
+              },
+              set: function (y1) {
+                  this._y1 = y1;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegCurvetoQuadraticRel = function (owningPathSegList, x, y, x1, y1) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, 'q', owningPathSegList);
+              this._x = x;
+              this._y = y;
+              this._x1 = x1;
+              this._y1 = y1;
+          };
+          window.SVGPathSegCurvetoQuadraticRel.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegCurvetoQuadraticRel.prototype.toString = function () {
+              return '[object SVGPathSegCurvetoQuadraticRel]';
+          };
+          window.SVGPathSegCurvetoQuadraticRel.prototype._asPathString = function () {
+              return (this.pathSegTypeAsLetter +
+                  ' ' +
+                  this._x1 +
+                  ' ' +
+                  this._y1 +
+                  ' ' +
+                  this._x +
+                  ' ' +
+                  this._y);
+          };
+          window.SVGPathSegCurvetoQuadraticRel.prototype.clone = function () {
+              return new window.SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1);
+          };
+          Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'x1', {
+              get: function () {
+                  return this._x1;
+              },
+              set: function (x1) {
+                  this._x1 = x1;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'y1', {
+              get: function () {
+                  return this._y1;
+              },
+              set: function (y1) {
+                  this._y1 = y1;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegArcAbs = function (owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_ABS, 'A', owningPathSegList);
+              this._x = x;
+              this._y = y;
+              this._r1 = r1;
+              this._r2 = r2;
+              this._angle = angle;
+              this._largeArcFlag = largeArcFlag;
+              this._sweepFlag = sweepFlag;
+          };
+          window.SVGPathSegArcAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegArcAbs.prototype.toString = function () {
+              return '[object SVGPathSegArcAbs]';
+          };
+          window.SVGPathSegArcAbs.prototype._asPathString = function () {
+              return (this.pathSegTypeAsLetter +
+                  ' ' +
+                  this._r1 +
+                  ' ' +
+                  this._r2 +
+                  ' ' +
+                  this._angle +
+                  ' ' +
+                  (this._largeArcFlag ? '1' : '0') +
+                  ' ' +
+                  (this._sweepFlag ? '1' : '0') +
+                  ' ' +
+                  this._x +
+                  ' ' +
+                  this._y);
+          };
+          window.SVGPathSegArcAbs.prototype.clone = function () {
+              return new window.SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag);
+          };
+          Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'r1', {
+              get: function () {
+                  return this._r1;
+              },
+              set: function (r1) {
+                  this._r1 = r1;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'r2', {
+              get: function () {
+                  return this._r2;
+              },
+              set: function (r2) {
+                  this._r2 = r2;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'angle', {
+              get: function () {
+                  return this._angle;
+              },
+              set: function (angle) {
+                  this._angle = angle;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'largeArcFlag', {
+              get: function () {
+                  return this._largeArcFlag;
+              },
+              set: function (largeArcFlag) {
+                  this._largeArcFlag = largeArcFlag;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'sweepFlag', {
+              get: function () {
+                  return this._sweepFlag;
+              },
+              set: function (sweepFlag) {
+                  this._sweepFlag = sweepFlag;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegArcRel = function (owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_REL, 'a', owningPathSegList);
+              this._x = x;
+              this._y = y;
+              this._r1 = r1;
+              this._r2 = r2;
+              this._angle = angle;
+              this._largeArcFlag = largeArcFlag;
+              this._sweepFlag = sweepFlag;
+          };
+          window.SVGPathSegArcRel.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegArcRel.prototype.toString = function () {
+              return '[object SVGPathSegArcRel]';
+          };
+          window.SVGPathSegArcRel.prototype._asPathString = function () {
+              return (this.pathSegTypeAsLetter +
+                  ' ' +
+                  this._r1 +
+                  ' ' +
+                  this._r2 +
+                  ' ' +
+                  this._angle +
+                  ' ' +
+                  (this._largeArcFlag ? '1' : '0') +
+                  ' ' +
+                  (this._sweepFlag ? '1' : '0') +
+                  ' ' +
+                  this._x +
+                  ' ' +
+                  this._y);
+          };
+          window.SVGPathSegArcRel.prototype.clone = function () {
+              return new window.SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag);
+          };
+          Object.defineProperty(window.SVGPathSegArcRel.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegArcRel.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegArcRel.prototype, 'r1', {
+              get: function () {
+                  return this._r1;
+              },
+              set: function (r1) {
+                  this._r1 = r1;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegArcRel.prototype, 'r2', {
+              get: function () {
+                  return this._r2;
+              },
+              set: function (r2) {
+                  this._r2 = r2;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegArcRel.prototype, 'angle', {
+              get: function () {
+                  return this._angle;
+              },
+              set: function (angle) {
+                  this._angle = angle;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegArcRel.prototype, 'largeArcFlag', {
+              get: function () {
+                  return this._largeArcFlag;
+              },
+              set: function (largeArcFlag) {
+                  this._largeArcFlag = largeArcFlag;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegArcRel.prototype, 'sweepFlag', {
+              get: function () {
+                  return this._sweepFlag;
+              },
+              set: function (sweepFlag) {
+                  this._sweepFlag = sweepFlag;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegLinetoHorizontalAbs = function (owningPathSegList, x) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, 'H', owningPathSegList);
+              this._x = x;
+          };
+          window.SVGPathSegLinetoHorizontalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegLinetoHorizontalAbs.prototype.toString = function () {
+              return '[object SVGPathSegLinetoHorizontalAbs]';
+          };
+          window.SVGPathSegLinetoHorizontalAbs.prototype._asPathString = function () {
+              return this.pathSegTypeAsLetter + ' ' + this._x;
+          };
+          window.SVGPathSegLinetoHorizontalAbs.prototype.clone = function () {
+              return new window.SVGPathSegLinetoHorizontalAbs(undefined, this._x);
+          };
+          Object.defineProperty(window.SVGPathSegLinetoHorizontalAbs.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegLinetoHorizontalRel = function (owningPathSegList, x) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, 'h', owningPathSegList);
+              this._x = x;
+          };
+          window.SVGPathSegLinetoHorizontalRel.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegLinetoHorizontalRel.prototype.toString = function () {
+              return '[object SVGPathSegLinetoHorizontalRel]';
+          };
+          window.SVGPathSegLinetoHorizontalRel.prototype._asPathString = function () {
+              return this.pathSegTypeAsLetter + ' ' + this._x;
+          };
+          window.SVGPathSegLinetoHorizontalRel.prototype.clone = function () {
+              return new window.SVGPathSegLinetoHorizontalRel(undefined, this._x);
+          };
+          Object.defineProperty(window.SVGPathSegLinetoHorizontalRel.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegLinetoVerticalAbs = function (owningPathSegList, y) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, 'V', owningPathSegList);
+              this._y = y;
+          };
+          window.SVGPathSegLinetoVerticalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegLinetoVerticalAbs.prototype.toString = function () {
+              return '[object SVGPathSegLinetoVerticalAbs]';
+          };
+          window.SVGPathSegLinetoVerticalAbs.prototype._asPathString = function () {
+              return this.pathSegTypeAsLetter + ' ' + this._y;
+          };
+          window.SVGPathSegLinetoVerticalAbs.prototype.clone = function () {
+              return new window.SVGPathSegLinetoVerticalAbs(undefined, this._y);
+          };
+          Object.defineProperty(window.SVGPathSegLinetoVerticalAbs.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegLinetoVerticalRel = function (owningPathSegList, y) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, 'v', owningPathSegList);
+              this._y = y;
+          };
+          window.SVGPathSegLinetoVerticalRel.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegLinetoVerticalRel.prototype.toString = function () {
+              return '[object SVGPathSegLinetoVerticalRel]';
+          };
+          window.SVGPathSegLinetoVerticalRel.prototype._asPathString = function () {
+              return this.pathSegTypeAsLetter + ' ' + this._y;
+          };
+          window.SVGPathSegLinetoVerticalRel.prototype.clone = function () {
+              return new window.SVGPathSegLinetoVerticalRel(undefined, this._y);
+          };
+          Object.defineProperty(window.SVGPathSegLinetoVerticalRel.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegCurvetoCubicSmoothAbs = function (owningPathSegList, x, y, x2, y2) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, 'S', owningPathSegList);
+              this._x = x;
+              this._y = y;
+              this._x2 = x2;
+              this._y2 = y2;
+          };
+          window.SVGPathSegCurvetoCubicSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegCurvetoCubicSmoothAbs.prototype.toString = function () {
+              return '[object SVGPathSegCurvetoCubicSmoothAbs]';
+          };
+          window.SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString = function () {
+              return (this.pathSegTypeAsLetter +
+                  ' ' +
+                  this._x2 +
+                  ' ' +
+                  this._y2 +
+                  ' ' +
+                  this._x +
+                  ' ' +
+                  this._y);
+          };
+          window.SVGPathSegCurvetoCubicSmoothAbs.prototype.clone = function () {
+              return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2);
+          };
+          Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, 'x2', {
+              get: function () {
+                  return this._x2;
+              },
+              set: function (x2) {
+                  this._x2 = x2;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, 'y2', {
+              get: function () {
+                  return this._y2;
+              },
+              set: function (y2) {
+                  this._y2 = y2;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegCurvetoCubicSmoothRel = function (owningPathSegList, x, y, x2, y2) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, 's', owningPathSegList);
+              this._x = x;
+              this._y = y;
+              this._x2 = x2;
+              this._y2 = y2;
+          };
+          window.SVGPathSegCurvetoCubicSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegCurvetoCubicSmoothRel.prototype.toString = function () {
+              return '[object SVGPathSegCurvetoCubicSmoothRel]';
+          };
+          window.SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString = function () {
+              return (this.pathSegTypeAsLetter +
+                  ' ' +
+                  this._x2 +
+                  ' ' +
+                  this._y2 +
+                  ' ' +
+                  this._x +
+                  ' ' +
+                  this._y);
+          };
+          window.SVGPathSegCurvetoCubicSmoothRel.prototype.clone = function () {
+              return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2);
+          };
+          Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, 'x2', {
+              get: function () {
+                  return this._x2;
+              },
+              set: function (x2) {
+                  this._x2 = x2;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, 'y2', {
+              get: function () {
+                  return this._y2;
+              },
+              set: function (y2) {
+                  this._y2 = y2;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegCurvetoQuadraticSmoothAbs = function (owningPathSegList, x, y) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, 'T', owningPathSegList);
+              this._x = x;
+              this._y = y;
+          };
+          window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString = function () {
+              return '[object SVGPathSegCurvetoQuadraticSmoothAbs]';
+          };
+          window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString = function () {
+              return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
+          };
+          window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone = function () {
+              return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y);
+          };
+          Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          window.SVGPathSegCurvetoQuadraticSmoothRel = function (owningPathSegList, x, y) {
+              window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, 't', owningPathSegList);
+              this._x = x;
+              this._y = y;
+          };
+          window.SVGPathSegCurvetoQuadraticSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
+          window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString = function () {
+              return '[object SVGPathSegCurvetoQuadraticSmoothRel]';
+          };
+          window.SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString = function () {
+              return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y;
+          };
+          window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone = function () {
+              return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y);
+          };
+          Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, 'x', {
+              get: function () {
+                  return this._x;
+              },
+              set: function (x) {
+                  this._x = x;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, 'y', {
+              get: function () {
+                  return this._y;
+              },
+              set: function (y) {
+                  this._y = y;
+                  this._segmentChanged();
+              },
+              enumerable: true
+          });
+          // Add createSVGPathSeg* functions to window.SVGPathElement.
+          // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-Interfacewindow.SVGPathElement.
+          window.SVGPathElement.prototype.createSVGPathSegClosePath = function () {
+              return new window.SVGPathSegClosePath(undefined);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegMovetoAbs = function (x, y) {
+              return new window.SVGPathSegMovetoAbs(undefined, x, y);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegMovetoRel = function (x, y) {
+              return new window.SVGPathSegMovetoRel(undefined, x, y);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegLinetoAbs = function (x, y) {
+              return new window.SVGPathSegLinetoAbs(undefined, x, y);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegLinetoRel = function (x, y) {
+              return new window.SVGPathSegLinetoRel(undefined, x, y);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function (x, y, x1, y1, x2, y2) {
+              return new window.SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function (x, y, x1, y1, x2, y2) {
+              return new window.SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function (x, y, x1, y1) {
+              return new window.SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function (x, y, x1, y1) {
+              return new window.SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegArcAbs = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
+              return new window.SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegArcRel = function (x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
+              return new window.SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function (x) {
+              return new window.SVGPathSegLinetoHorizontalAbs(undefined, x);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function (x) {
+              return new window.SVGPathSegLinetoHorizontalRel(undefined, x);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function (y) {
+              return new window.SVGPathSegLinetoVerticalAbs(undefined, y);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function (y) {
+              return new window.SVGPathSegLinetoVerticalRel(undefined, y);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function (x, y, x2, y2) {
+              return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function (x, y, x2, y2) {
+              return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function (x, y) {
+              return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y);
+          };
+          window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function (x, y) {
+              return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y);
+          };
+          if (!('getPathSegAtLength' in window.SVGPathElement.prototype)) {
+              // Add getPathSegAtLength to SVGPathElement.
+              // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-__svg__SVGPathElement__getPathSegAtLength
+              // This polyfill requires SVGPathElement.getTotalLength to implement the distance-along-a-path algorithm.
+              window.SVGPathElement.prototype.getPathSegAtLength = function (distance) {
+                  if (distance === undefined || !isFinite(distance))
+                      throw 'Invalid arguments.';
+                  var measurementElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
+                  measurementElement.setAttribute('d', this.getAttribute('d'));
+                  var lastPathSegment = measurementElement.pathSegList.numberOfItems - 1;
+                  // If the path is empty, return 0.
+                  if (lastPathSegment <= 0)
+                      return 0;
+                  do {
+                      measurementElement.pathSegList.removeItem(lastPathSegment);
+                      if (distance > measurementElement.getTotalLength())
+                          break;
+                      lastPathSegment--;
+                  } while (lastPathSegment > 0);
+                  return lastPathSegment;
+              };
+          }
+      }
+      if (!('SVGPathSegList' in window)) {
+          // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList
+          window.SVGPathSegList = function (pathElement) {
+              this._pathElement = pathElement;
+              this._list = this._parsePath(this._pathElement.getAttribute('d'));
+              // Use a MutationObserver to catch changes to the path's "d" attribute.
+              this._mutationObserverConfig = {
+                  attributes: true,
+                  attributeFilter: ['d']
+              };
+              this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this));
+              this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
+          };
+          window.SVGPathSegList.prototype.classname = 'SVGPathSegList';
+          Object.defineProperty(window.SVGPathSegList.prototype, 'numberOfItems', {
+              get: function () {
+                  this._checkPathSynchronizedToList();
+                  return this._list.length;
+              },
+              enumerable: true
+          });
+          // Add the pathSegList accessors to window.SVGPathElement.
+          // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData
+          Object.defineProperty(window.SVGPathElement.prototype, 'pathSegList', {
+              get: function () {
+                  if (!this._pathSegList)
+                      this._pathSegList = new window.SVGPathSegList(this);
+                  return this._pathSegList;
+              },
+              enumerable: true
+          });
+          // FIXME: The following are not implemented and simply return window.SVGPathElement.pathSegList.
+          Object.defineProperty(window.SVGPathElement.prototype, 'normalizedPathSegList', {
+              get: function () {
+                  return this.pathSegList;
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathElement.prototype, 'animatedPathSegList', {
+              get: function () {
+                  return this.pathSegList;
+              },
+              enumerable: true
+          });
+          Object.defineProperty(window.SVGPathElement.prototype, 'animatedNormalizedPathSegList', {
+              get: function () {
+                  return this.pathSegList;
+              },
+              enumerable: true
+          });
+          // Process any pending mutations to the path element and update the list as needed.
+          // This should be the first call of all public functions and is needed because
+          // MutationObservers are not synchronous so we can have pending asynchronous mutations.
+          window.SVGPathSegList.prototype._checkPathSynchronizedToList = function () {
+              this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords());
+          };
+          window.SVGPathSegList.prototype._updateListFromPathMutations = function (mutationRecords) {
+              if (!this._pathElement)
+                  return;
+              var hasPathMutations = false;
+              mutationRecords.forEach(function (record) {
+                  if (record.attributeName == 'd')
+                      hasPathMutations = true;
+              });
+              if (hasPathMutations)
+                  this._list = this._parsePath(this._pathElement.getAttribute('d'));
+          };
+          // Serialize the list and update the path's 'd' attribute.
+          window.SVGPathSegList.prototype._writeListToPath = function () {
+              this._pathElementMutationObserver.disconnect();
+              this._pathElement.setAttribute('d', window.SVGPathSegList._pathSegArrayAsString(this._list));
+              this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
+          };
+          // When a path segment changes the list needs to be synchronized back to the path element.
+          window.SVGPathSegList.prototype.segmentChanged = function (pathSeg) {
+              this._writeListToPath();
+          };
+          window.SVGPathSegList.prototype.clear = function () {
+              this._checkPathSynchronizedToList();
+              this._list.forEach(function (pathSeg) {
+                  pathSeg._owningPathSegList = null;
+              });
+              this._list = [];
+              this._writeListToPath();
+          };
+          window.SVGPathSegList.prototype.initialize = function (newItem) {
+              this._checkPathSynchronizedToList();
+              this._list = [newItem];
+              newItem._owningPathSegList = this;
+              this._writeListToPath();
+              return newItem;
+          };
+          window.SVGPathSegList.prototype._checkValidIndex = function (index) {
+              if (isNaN(index) || index < 0 || index >= this.numberOfItems)
+                  throw 'INDEX_SIZE_ERR';
+          };
+          window.SVGPathSegList.prototype.getItem = function (index) {
+              this._checkPathSynchronizedToList();
+              this._checkValidIndex(index);
+              return this._list[index];
+          };
+          window.SVGPathSegList.prototype.insertItemBefore = function (newItem, index) {
+              this._checkPathSynchronizedToList();
+              // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
+              if (index > this.numberOfItems)
+                  index = this.numberOfItems;
+              if (newItem._owningPathSegList) {
+                  // SVG2 spec says to make a copy.
+                  newItem = newItem.clone();
+              }
+              this._list.splice(index, 0, newItem);
+              newItem._owningPathSegList = this;
+              this._writeListToPath();
+              return newItem;
+          };
+          window.SVGPathSegList.prototype.replaceItem = function (newItem, index) {
+              this._checkPathSynchronizedToList();
+              if (newItem._owningPathSegList) {
+                  // SVG2 spec says to make a copy.
+                  newItem = newItem.clone();
+              }
+              this._checkValidIndex(index);
+              this._list[index] = newItem;
+              newItem._owningPathSegList = this;
+              this._writeListToPath();
+              return newItem;
+          };
+          window.SVGPathSegList.prototype.removeItem = function (index) {
+              this._checkPathSynchronizedToList();
+              this._checkValidIndex(index);
+              var item = this._list[index];
+              this._list.splice(index, 1);
+              this._writeListToPath();
+              return item;
+          };
+          window.SVGPathSegList.prototype.appendItem = function (newItem) {
+              this._checkPathSynchronizedToList();
+              if (newItem._owningPathSegList) {
+                  // SVG2 spec says to make a copy.
+                  newItem = newItem.clone();
+              }
+              this._list.push(newItem);
+              newItem._owningPathSegList = this;
+              // TODO: Optimize this to just append to the existing attribute.
+              this._writeListToPath();
+              return newItem;
+          };
+          window.SVGPathSegList._pathSegArrayAsString = function (pathSegArray) {
+              var string = '';
+              var first = true;
+              pathSegArray.forEach(function (pathSeg) {
+                  if (first) {
+                      first = false;
+                      string += pathSeg._asPathString();
+                  }
+                  else {
+                      string += ' ' + pathSeg._asPathString();
+                  }
+              });
+              return string;
+          };
+          // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp.
+          window.SVGPathSegList.prototype._parsePath = function (string) {
+              if (!string || string.length == 0)
+                  return [];
+              var owningPathSegList = this;
+              var Builder = function () {
+                  this.pathSegList = [];
+              };
+              Builder.prototype.appendSegment = function (pathSeg) {
+                  this.pathSegList.push(pathSeg);
+              };
+              var Source = function (string) {
+                  this._string = string;
+                  this._currentIndex = 0;
+                  this._endIndex = this._string.length;
+                  this._previousCommand = window.SVGPathSeg.PATHSEG_UNKNOWN;
+                  this._skipOptionalSpaces();
+              };
+              Source.prototype._isCurrentSpace = function () {
+                  var character = this._string[this._currentIndex];
+                  return (character <= ' ' &&
+                      (character == ' ' ||
+                          character == '\n' ||
+                          character == '\t' ||
+                          character == '\r' ||
+                          character == '\f'));
+              };
+              Source.prototype._skipOptionalSpaces = function () {
+                  while (this._currentIndex < this._endIndex && this._isCurrentSpace())
+                      this._currentIndex++;
+                  return this._currentIndex < this._endIndex;
+              };
+              Source.prototype._skipOptionalSpacesOrDelimiter = function () {
+                  if (this._currentIndex < this._endIndex &&
+                      !this._isCurrentSpace() &&
+                      this._string.charAt(this._currentIndex) != ',')
+                      return false;
+                  if (this._skipOptionalSpaces()) {
+                      if (this._currentIndex < this._endIndex &&
+                          this._string.charAt(this._currentIndex) == ',') {
+                          this._currentIndex++;
+                          this._skipOptionalSpaces();
+                      }
+                  }
+                  return this._currentIndex < this._endIndex;
+              };
+              Source.prototype.hasMoreData = function () {
+                  return this._currentIndex < this._endIndex;
+              };
+              Source.prototype.peekSegmentType = function () {
+                  var lookahead = this._string[this._currentIndex];
+                  return this._pathSegTypeFromChar(lookahead);
+              };
+              Source.prototype._pathSegTypeFromChar = function (lookahead) {
+                  switch (lookahead) {
+                      case 'Z':
+                      case 'z':
+                          return window.SVGPathSeg.PATHSEG_CLOSEPATH;
+                      case 'M':
+                          return window.SVGPathSeg.PATHSEG_MOVETO_ABS;
+                      case 'm':
+                          return window.SVGPathSeg.PATHSEG_MOVETO_REL;
+                      case 'L':
+                          return window.SVGPathSeg.PATHSEG_LINETO_ABS;
+                      case 'l':
+                          return window.SVGPathSeg.PATHSEG_LINETO_REL;
+                      case 'C':
+                          return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;
+                      case 'c':
+                          return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;
+                      case 'Q':
+                          return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;
+                      case 'q':
+                          return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;
+                      case 'A':
+                          return window.SVGPathSeg.PATHSEG_ARC_ABS;
+                      case 'a':
+                          return window.SVGPathSeg.PATHSEG_ARC_REL;
+                      case 'H':
+                          return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;
+                      case 'h':
+                          return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;
+                      case 'V':
+                          return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;
+                      case 'v':
+                          return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;
+                      case 'S':
+                          return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
+                      case 's':
+                          return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;
+                      case 'T':
+                          return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
+                      case 't':
+                          return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;
+                      default:
+                          return window.SVGPathSeg.PATHSEG_UNKNOWN;
+                  }
+              };
+              Source.prototype._nextCommandHelper = function (lookahead, previousCommand) {
+                  // Check for remaining coordinates in the current command.
+                  if ((lookahead == '+' ||
+                      lookahead == '-' ||
+                      lookahead == '.' ||
+                      (lookahead >= '0' && lookahead <= '9')) &&
+                      previousCommand != window.SVGPathSeg.PATHSEG_CLOSEPATH) {
+                      if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_ABS)
+                          return window.SVGPathSeg.PATHSEG_LINETO_ABS;
+                      if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_REL)
+                          return window.SVGPathSeg.PATHSEG_LINETO_REL;
+                      return previousCommand;
+                  }
+                  return window.SVGPathSeg.PATHSEG_UNKNOWN;
+              };
+              Source.prototype.initialCommandIsMoveTo = function () {
+                  // If the path is empty it is still valid, so return true.
+                  if (!this.hasMoreData())
+                      return true;
+                  var command = this.peekSegmentType();
+                  // Path must start with moveTo.
+                  return (command == window.SVGPathSeg.PATHSEG_MOVETO_ABS ||
+                      command == window.SVGPathSeg.PATHSEG_MOVETO_REL);
+              };
+              // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp.
+              // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
+              Source.prototype._parseNumber = function () {
+                  var exponent = 0;
+                  var integer = 0;
+                  var frac = 1;
+                  var decimal = 0;
+                  var sign = 1;
+                  var expsign = 1;
+                  var startIndex = this._currentIndex;
+                  this._skipOptionalSpaces();
+                  // Read the sign.
+                  if (this._currentIndex < this._endIndex &&
+                      this._string.charAt(this._currentIndex) == '+')
+                      this._currentIndex++;
+                  else if (this._currentIndex < this._endIndex &&
+                      this._string.charAt(this._currentIndex) == '-') {
+                      this._currentIndex++;
+                      sign = -1;
+                  }
+                  if (this._currentIndex == this._endIndex ||
+                      ((this._string.charAt(this._currentIndex) < '0' ||
+                          this._string.charAt(this._currentIndex) > '9') &&
+                          this._string.charAt(this._currentIndex) != '.'))
+                      // The first character of a number must be one of [0-9+-.].
+                      return undefined;
+                  // Read the integer part, build right-to-left.
+                  var startIntPartIndex = this._currentIndex;
+                  while (this._currentIndex < this._endIndex &&
+                      this._string.charAt(this._currentIndex) >= '0' &&
+                      this._string.charAt(this._currentIndex) <= '9')
+                      this._currentIndex++; // Advance to first non-digit.
+                  if (this._currentIndex != startIntPartIndex) {
+                      var scanIntPartIndex = this._currentIndex - 1;
+                      var multiplier = 1;
+                      while (scanIntPartIndex >= startIntPartIndex) {
+                          integer +=
+                              multiplier * (this._string.charAt(scanIntPartIndex--) - '0');
+                          multiplier *= 10;
+                      }
+                  }
+                  // Read the decimals.
+                  if (this._currentIndex < this._endIndex &&
+                      this._string.charAt(this._currentIndex) == '.') {
+                      this._currentIndex++;
+                      // There must be a least one digit following the .
+                      if (this._currentIndex >= this._endIndex ||
+                          this._string.charAt(this._currentIndex) < '0' ||
+                          this._string.charAt(this._currentIndex) > '9')
+                          return undefined;
+                      while (this._currentIndex < this._endIndex &&
+                          this._string.charAt(this._currentIndex) >= '0' &&
+                          this._string.charAt(this._currentIndex) <= '9') {
+                          frac *= 10;
+                          decimal += (this._string.charAt(this._currentIndex) - '0') / frac;
+                          this._currentIndex += 1;
+                      }
+                  }
+                  // Read the exponent part.
+                  if (this._currentIndex != startIndex &&
+                      this._currentIndex + 1 < this._endIndex &&
+                      (this._string.charAt(this._currentIndex) == 'e' ||
+                          this._string.charAt(this._currentIndex) == 'E') &&
+                      this._string.charAt(this._currentIndex + 1) != 'x' &&
+                      this._string.charAt(this._currentIndex + 1) != 'm') {
+                      this._currentIndex++;
+                      // Read the sign of the exponent.
+                      if (this._string.charAt(this._currentIndex) == '+') {
+                          this._currentIndex++;
+                      }
+                      else if (this._string.charAt(this._currentIndex) == '-') {
+                          this._currentIndex++;
+                          expsign = -1;
+                      }
+                      // There must be an exponent.
+                      if (this._currentIndex >= this._endIndex ||
+                          this._string.charAt(this._currentIndex) < '0' ||
+                          this._string.charAt(this._currentIndex) > '9')
+                          return undefined;
+                      while (this._currentIndex < this._endIndex &&
+                          this._string.charAt(this._currentIndex) >= '0' &&
+                          this._string.charAt(this._currentIndex) <= '9') {
+                          exponent *= 10;
+                          exponent += this._string.charAt(this._currentIndex) - '0';
+                          this._currentIndex++;
+                      }
+                  }
+                  var number = integer + decimal;
+                  number *= sign;
+                  if (exponent)
+                      number *= Math.pow(10, expsign * exponent);
+                  if (startIndex == this._currentIndex)
+                      return undefined;
+                  this._skipOptionalSpacesOrDelimiter();
+                  return number;
+              };
+              Source.prototype._parseArcFlag = function () {
+                  if (this._currentIndex >= this._endIndex)
+                      return undefined;
+                  var flag = false;
+                  var flagChar = this._string.charAt(this._currentIndex++);
+                  if (flagChar == '0')
+                      flag = false;
+                  else if (flagChar == '1')
+                      flag = true;
+                  else
+                      return undefined;
+                  this._skipOptionalSpacesOrDelimiter();
+                  return flag;
+              };
+              Source.prototype.parseSegment = function () {
+                  var lookahead = this._string[this._currentIndex];
+                  var command = this._pathSegTypeFromChar(lookahead);
+                  if (command == window.SVGPathSeg.PATHSEG_UNKNOWN) {
+                      // Possibly an implicit command. Not allowed if this is the first command.
+                      if (this._previousCommand == window.SVGPathSeg.PATHSEG_UNKNOWN)
+                          return null;
+                      command = this._nextCommandHelper(lookahead, this._previousCommand);
+                      if (command == window.SVGPathSeg.PATHSEG_UNKNOWN)
+                          return null;
+                  }
+                  else {
+                      this._currentIndex++;
+                  }
+                  this._previousCommand = command;
+                  switch (command) {
+                      case window.SVGPathSeg.PATHSEG_MOVETO_REL:
+                          return new window.SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+                      case window.SVGPathSeg.PATHSEG_MOVETO_ABS:
+                          return new window.SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+                      case window.SVGPathSeg.PATHSEG_LINETO_REL:
+                          return new window.SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+                      case window.SVGPathSeg.PATHSEG_LINETO_ABS:
+                          return new window.SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+                      case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
+                          return new window.SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());
+                      case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
+                          return new window.SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());
+                      case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
+                          return new window.SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());
+                      case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
+                          return new window.SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());
+                      case window.SVGPathSeg.PATHSEG_CLOSEPATH:
+                          this._skipOptionalSpaces();
+                          return new window.SVGPathSegClosePath(owningPathSegList);
+                      case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
+                          var points = {
+                              x1: this._parseNumber(),
+                              y1: this._parseNumber(),
+                              x2: this._parseNumber(),
+                              y2: this._parseNumber(),
+                              x: this._parseNumber(),
+                              y: this._parseNumber()
+                          };
+                          return new window.SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
+                      case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
+                          var points = {
+                              x1: this._parseNumber(),
+                              y1: this._parseNumber(),
+                              x2: this._parseNumber(),
+                              y2: this._parseNumber(),
+                              x: this._parseNumber(),
+                              y: this._parseNumber()
+                          };
+                          return new window.SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
+                      case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
+                          var points = {
+                              x2: this._parseNumber(),
+                              y2: this._parseNumber(),
+                              x: this._parseNumber(),
+                              y: this._parseNumber()
+                          };
+                          return new window.SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2);
+                      case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
+                          var points = {
+                              x2: this._parseNumber(),
+                              y2: this._parseNumber(),
+                              x: this._parseNumber(),
+                              y: this._parseNumber()
+                          };
+                          return new window.SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2);
+                      case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
+                          var points = {
+                              x1: this._parseNumber(),
+                              y1: this._parseNumber(),
+                              x: this._parseNumber(),
+                              y: this._parseNumber()
+                          };
+                          return new window.SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);
+                      case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
+                          var points = {
+                              x1: this._parseNumber(),
+                              y1: this._parseNumber(),
+                              x: this._parseNumber(),
+                              y: this._parseNumber()
+                          };
+                          return new window.SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);
+                      case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
+                          return new window.SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+                      case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
+                          return new window.SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+                      case window.SVGPathSeg.PATHSEG_ARC_REL:
+                          var points = {
+                              x1: this._parseNumber(),
+                              y1: this._parseNumber(),
+                              arcAngle: this._parseNumber(),
+                              arcLarge: this._parseArcFlag(),
+                              arcSweep: this._parseArcFlag(),
+                              x: this._parseNumber(),
+                              y: this._parseNumber()
+                          };
+                          return new window.SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
+                      case window.SVGPathSeg.PATHSEG_ARC_ABS:
+                          var points = {
+                              x1: this._parseNumber(),
+                              y1: this._parseNumber(),
+                              arcAngle: this._parseNumber(),
+                              arcLarge: this._parseArcFlag(),
+                              arcSweep: this._parseArcFlag(),
+                              x: this._parseNumber(),
+                              y: this._parseNumber()
+                          };
+                          return new window.SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
+                      default:
+                          throw 'Unknown path seg type.';
+                  }
+              };
+              var builder = new Builder();
+              var source = new Source(string);
+              if (!source.initialCommandIsMoveTo())
+                  return [];
+              while (source.hasMoreData()) {
+                  var pathSeg = source.parseSegment();
+                  if (!pathSeg)
+                      return [];
+                  builder.appendSegment(pathSeg);
+              }
+              return builder.pathSegList;
+          };
+      }
+  })();
+  // String.padEnd polyfill for IE11
+  //
+  // https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
+  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
+  if (!String.prototype.padEnd) {
+      String.prototype.padEnd = function padEnd(targetLength, padString) {
+          targetLength = targetLength >> 0; //floor if number or convert non-number to 0;
+          padString = String(typeof padString !== 'undefined' ? padString : ' ');
+          if (this.length > targetLength) {
+              return String(this);
+          }
+          else {
+              targetLength = targetLength - this.length;
+              if (targetLength > padString.length) {
+                  padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
+              }
+              return String(this) + padString.slice(0, targetLength);
+          }
+      };
+  }
+  // Object.assign polyfill for IE11
+  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill
+  if (typeof Object.assign !== 'function') {
+      // Must be writable: true, enumerable: false, configurable: true
+      Object.defineProperty(Object, 'assign', {
+          value: function assign(target, varArgs) {
+              if (target === null || target === undefined) {
+                  throw new TypeError('Cannot convert undefined or null to object');
+              }
+              var to = Object(target);
+              for (var index = 1; index < arguments.length; index++) {
+                  var nextSource = arguments[index];
+                  if (nextSource !== null && nextSource !== undefined) {
+                      for (var nextKey in nextSource) {
+                          // Avoid bugs when hasOwnProperty is shadowed
+                          if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
+                              to[nextKey] = nextSource[nextKey];
+                          }
+                      }
+                  }
+              }
+              return to;
+          },
+          writable: true,
+          configurable: true
+      });
+  }
+  /* jshint ignore:end */
+
+  Chart.prototype.axis = function () { };
+  Chart.prototype.axis.labels = function (labels) {
+      var $$ = this.internal;
+      if (arguments.length) {
+          Object.keys(labels).forEach(function (axisId) {
+              $$.axis.setLabelText(axisId, labels[axisId]);
+          });
+          $$.axis.updateLabels();
+      }
+      // TODO: return some values?
+  };
+  Chart.prototype.axis.max = function (max) {
+      var $$ = this.internal, config = $$.config;
+      if (arguments.length) {
+          if (typeof max === 'object') {
+              if (isValue(max.x)) {
+                  config.axis_x_max = max.x;
+              }
+              if (isValue(max.y)) {
+                  config.axis_y_max = max.y;
+              }
+              if (isValue(max.y2)) {
+                  config.axis_y2_max = max.y2;
+              }
+          }
+          else {
+              config.axis_y_max = config.axis_y2_max = max;
+          }
+          $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true });
+      }
+      else {
+          return {
+              x: config.axis_x_max,
+              y: config.axis_y_max,
+              y2: config.axis_y2_max
+          };
+      }
+  };
+  Chart.prototype.axis.min = function (min) {
+      var $$ = this.internal, config = $$.config;
+      if (arguments.length) {
+          if (typeof min === 'object') {
+              if (isValue(min.x)) {
+                  config.axis_x_min = min.x;
+              }
+              if (isValue(min.y)) {
+                  config.axis_y_min = min.y;
+              }
+              if (isValue(min.y2)) {
+                  config.axis_y2_min = min.y2;
+              }
+          }
+          else {
+              config.axis_y_min = config.axis_y2_min = min;
+          }
+          $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true });
+      }
+      else {
+          return {
+              x: config.axis_x_min,
+              y: config.axis_y_min,
+              y2: config.axis_y2_min
+          };
+      }
+  };
+  Chart.prototype.axis.range = function (range) {
+      if (arguments.length) {
+          if (isDefined(range.max)) {
+              this.axis.max(range.max);
+          }
+          if (isDefined(range.min)) {
+              this.axis.min(range.min);
+          }
+      }
+      else {
+          return {
+              max: this.axis.max(),
+              min: this.axis.min()
+          };
+      }
+  };
+  Chart.prototype.axis.types = function (types) {
+      var $$ = this.internal;
+      if (types === undefined) {
+          return {
+              y: $$.config.axis_y_type,
+              y2: $$.config.axis_y2_type
+          };
+      }
+      else {
+          if (isDefined(types.y)) {
+              $$.config.axis_y_type = types.y;
+          }
+          if (isDefined(types.y2)) {
+              $$.config.axis_y2_type = types.y2;
+          }
+          $$.updateScales();
+          $$.redraw();
+      }
+  };
+
+  Chart.prototype.category = function (i, category) {
+      var $$ = this.internal, config = $$.config;
+      if (arguments.length > 1) {
+          config.axis_x_categories[i] = category;
+          $$.redraw();
+      }
+      return config.axis_x_categories[i];
+  };
+  Chart.prototype.categories = function (categories) {
+      var $$ = this.internal, config = $$.config;
+      if (!arguments.length) {
+          return config.axis_x_categories;
+      }
+      config.axis_x_categories = categories;
+      $$.redraw();
+      return config.axis_x_categories;
+  };
+
+  Chart.prototype.resize = function (size) {
+      var $$ = this.internal, config = $$.config;
+      config.size_width = size ? size.width : null;
+      config.size_height = size ? size.height : null;
+      this.flush();
+  };
+  Chart.prototype.flush = function () {
+      var $$ = this.internal;
+      $$.updateAndRedraw({
+          withLegend: true,
+          withTransition: false,
+          withTransitionForTransform: false
+      });
+  };
+  Chart.prototype.destroy = function () {
+      var $$ = this.internal;
+      window.clearInterval($$.intervalForObserveInserted);
+      if ($$.resizeTimeout !== undefined) {
+          window.clearTimeout($$.resizeTimeout);
+      }
+      window.removeEventListener('resize', $$.resizeIfElementDisplayed);
+      // Removes the inner resize functions
+      $$.resizeFunction.remove();
+      // Unbinds from the window focus event
+      $$.unbindWindowFocus();
+      $$.selectChart.classed('c3', false).html('');
+      // MEMO: this is needed because the reference of some elements will not be released, then memory leak will happen.
+      Object.keys($$).forEach(function (key) {
+          $$[key] = null;
+      });
+      return null;
+  };
+
+  // TODO: fix
+  Chart.prototype.color = function (id) {
+      var $$ = this.internal;
+      return $$.color(id); // more patterns
+  };
+
+  Chart.prototype.data = function (targetIds) {
+      var targets = this.internal.data.targets;
+      return typeof targetIds === 'undefined'
+          ? targets
+          : targets.filter(function (t) {
+              return [].concat(targetIds).indexOf(t.id) >= 0;
+          });
+  };
+  Chart.prototype.data.shown = function (targetIds) {
+      return this.internal.filterTargetsToShow(this.data(targetIds));
+  };
+  /**
+   * Get values of the data loaded in the chart.
+   *
+   * @param {String|Array} targetId This API returns the value of specified target.
+   * @param flat
+   * @return {Array} Data values
+   */
+  Chart.prototype.data.values = function (targetId, flat) {
+      if (flat === void 0) { flat = true; }
+      var values = null;
+      if (targetId) {
+          var targets = this.data(targetId);
+          if (targets && isArray(targets)) {
+              values = targets.reduce(function (ret, v) {
+                  var dataValue = v.values.map(function (d) { return d.value; });
+                  if (flat) {
+                      ret = ret.concat(dataValue);
+                  }
+                  else {
+                      ret.push(dataValue);
+                  }
+                  return ret;
+              }, []);
+          }
+      }
+      return values;
+  };
+  Chart.prototype.data.names = function (names) {
+      this.internal.clearLegendItemTextBoxCache();
+      return this.internal.updateDataAttributes('names', names);
+  };
+  Chart.prototype.data.colors = function (colors) {
+      return this.internal.updateDataAttributes('colors', colors);
+  };
+  Chart.prototype.data.axes = function (axes) {
+      return this.internal.updateDataAttributes('axes', axes);
+  };
+  Chart.prototype.data.stackNormalized = function (normalized) {
+      if (normalized === undefined) {
+          return this.internal.isStackNormalized();
+      }
+      this.internal.config.data_stack_normalize = !!normalized;
+      this.internal.redraw();
+  };
+
+  Chart.prototype.donut = function () { };
+  Chart.prototype.donut.padAngle = function (padAngle) {
+      if (padAngle === undefined) {
+          return this.internal.config.donut_padAngle;
+      }
+      this.internal.config.donut_padAngle = padAngle;
+      this.flush();
+  };
+
+  Chart.prototype.flow = function (args) {
+      var $$ = this.internal, targets, data, notfoundIds = [], orgDataCount = $$.getMaxDataCount(), dataCount, domain, baseTarget, baseValue, length = 0, tail = 0, diff, to;
+      if (args.json) {
+          data = $$.convertJsonToData(args.json, args.keys);
+      }
+      else if (args.rows) {
+          data = $$.convertRowsToData(args.rows);
+      }
+      else if (args.columns) {
+          data = $$.convertColumnsToData(args.columns);
+      }
+      else {
+          return;
+      }
+      targets = $$.convertDataToTargets(data, true);
+      // Update/Add data
+      $$.data.targets.forEach(function (t) {
+          var found = false, i, j;
+          for (i = 0; i < targets.length; i++) {
+              if (t.id === targets[i].id) {
+                  found = true;
+                  if (t.values[t.values.length - 1]) {
+                      tail = t.values[t.values.length - 1].index + 1;
+                  }
+                  length = targets[i].values.length;
+                  for (j = 0; j < length; j++) {
+                      targets[i].values[j].index = tail + j;
+                      if (!$$.isTimeSeries()) {
+                          targets[i].values[j].x = tail + j;
+                      }
+                  }
+                  t.values = t.values.concat(targets[i].values);
+                  targets.splice(i, 1);
+                  break;
+              }
+          }
+          if (!found) {
+              notfoundIds.push(t.id);
+          }
+      });
+      // Append null for not found targets
+      $$.data.targets.forEach(function (t) {
+          var i, j;
+          for (i = 0; i < notfoundIds.length; i++) {
+              if (t.id === notfoundIds[i]) {
+                  tail = t.values[t.values.length - 1].index + 1;
+                  for (j = 0; j < length; j++) {
+                      t.values.push({
+                          id: t.id,
+                          index: tail + j,
+                          x: $$.isTimeSeries() ? $$.getOtherTargetX(tail + j) : tail + j,
+                          value: null
+                      });
+                  }
+              }
+          }
+      });
+      // Generate null values for new target
+      if ($$.data.targets.length) {
+          targets.forEach(function (t) {
+              var i, missing = [];
+              for (i = $$.data.targets[0].values[0].index; i < tail; i++) {
+                  missing.push({
+                      id: t.id,
+                      index: i,
+                      x: $$.isTimeSeries() ? $$.getOtherTargetX(i) : i,
+                      value: null
+                  });
+              }
+              t.values.forEach(function (v) {
+                  v.index += tail;
+                  if (!$$.isTimeSeries()) {
+                      v.x += tail;
+                  }
+              });
+              t.values = missing.concat(t.values);
+          });
+      }
+      $$.data.targets = $$.data.targets.concat(targets); // add remained
+      // check data count because behavior needs to change when it's only one
+      dataCount = $$.getMaxDataCount();
+      baseTarget = $$.data.targets[0];
+      baseValue = baseTarget.values[0];
+      // Update length to flow if needed
+      if (isDefined(args.to)) {
+          length = 0;
+          to = $$.isTimeSeries() ? $$.parseDate(args.to) : args.to;
+          baseTarget.values.forEach(function (v) {
+              if (v.x < to) {
+                  length++;
+              }
+          });
+      }
+      else if (isDefined(args.length)) {
+          length = args.length;
+      }
+      // If only one data, update the domain to flow from left edge of the chart
+      if (!orgDataCount) {
+          if ($$.isTimeSeries()) {
+              if (baseTarget.values.length > 1) {
+                  diff = baseTarget.values[baseTarget.values.length - 1].x - baseValue.x;
+              }
+              else {
+                  diff = baseValue.x - $$.getXDomain($$.data.targets)[0];
+              }
+          }
+          else {
+              diff = 1;
+          }
+          domain = [baseValue.x - diff, baseValue.x];
+          $$.updateXDomain(null, true, true, false, domain);
+      }
+      else if (orgDataCount === 1) {
+          if ($$.isTimeSeries()) {
+              diff =
+                  (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2;
+              domain = [new Date(+baseValue.x - diff), new Date(+baseValue.x + diff)];
+              $$.updateXDomain(null, true, true, false, domain);
+          }
+      }
+      // Set targets
+      $$.updateTargets($$.data.targets);
+      // Redraw with new targets
+      $$.redraw({
+          flow: {
+              index: baseValue.index,
+              length: length,
+              duration: isValue(args.duration)
+                  ? args.duration
+                  : $$.config.transition_duration,
+              done: args.done,
+              orgDataCount: orgDataCount
+          },
+          withLegend: true,
+          withTransition: orgDataCount > 1,
+          withTrimXDomain: false,
+          withUpdateXAxis: true
+      });
+  };
+  ChartInternal.prototype.generateFlow = function (args) {
+      var $$ = this, config = $$.config, d3 = $$.d3;
+      return function () {
+          var targets = args.targets, flow = args.flow, drawBar = args.drawBar, drawLine = args.drawLine, drawArea = args.drawArea, cx = args.cx, cy = args.cy, xv = args.xv, xForText = args.xForText, yForText = args.yForText, duration = args.duration;
+          var translateX, scaleX = 1, transform, flowIndex = flow.index, flowLength = flow.length, flowStart = $$.getValueOnIndex($$.data.targets[0].values, flowIndex), flowEnd = $$.getValueOnIndex($$.data.targets[0].values, flowIndex + flowLength), orgDomain = $$.x.domain(), domain, durationForFlow = flow.duration || duration, done = flow.done || function () { }, wait = $$.generateWait();
+          var xgrid, xgridLines, mainRegion, mainText, mainBar, mainLine, mainArea, mainCircle;
+          // set flag
+          $$.flowing = true;
+          // remove head data after rendered
+          $$.data.targets.forEach(function (d) {
+              d.values.splice(0, flowLength);
+          });
+          // update x domain to generate axis elements for flow
+          domain = $$.updateXDomain(targets, true, true);
+          // update elements related to x scale
+          if ($$.updateXGrid) {
+              $$.updateXGrid(true);
+          }
+          xgrid = $$.xgrid || d3.selectAll([]); // xgrid needs to be obtained after updateXGrid
+          xgridLines = $$.xgridLines || d3.selectAll([]);
+          mainRegion = $$.mainRegion || d3.selectAll([]);
+          mainText = $$.mainText || d3.selectAll([]);
+          mainBar = $$.mainBar || d3.selectAll([]);
+          mainLine = $$.mainLine || d3.selectAll([]);
+          mainArea = $$.mainArea || d3.selectAll([]);
+          mainCircle = $$.mainCircle || d3.selectAll([]);
+          // generate transform to flow
+          if (!flow.orgDataCount) {
+              // if empty
+              if ($$.data.targets[0].values.length !== 1) {
+                  translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
+              }
+              else {
+                  if ($$.isTimeSeries()) {
+                      flowStart = $$.getValueOnIndex($$.data.targets[0].values, 0);
+                      flowEnd = $$.getValueOnIndex($$.data.targets[0].values, $$.data.targets[0].values.length - 1);
+                      translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);
+                  }
+                  else {
+                      translateX = diffDomain(domain) / 2;
+                  }
+              }
+          }
+          else if (flow.orgDataCount === 1 ||
+              (flowStart && flowStart.x) === (flowEnd && flowEnd.x)) {
+              translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
+          }
+          else {
+              if ($$.isTimeSeries()) {
+                  translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
+              }
+              else {
+                  translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);
+              }
+          }
+          scaleX = diffDomain(orgDomain) / diffDomain(domain);
+          transform = 'translate(' + translateX + ',0) scale(' + scaleX + ',1)';
+          $$.hideXGridFocus();
+          var flowTransition = d3
+              .transition()
+              .ease(d3.easeLinear)
+              .duration(durationForFlow);
+          wait.add($$.xAxis($$.axes.x, flowTransition));
+          wait.add(mainBar.transition(flowTransition).attr('transform', transform));
+          wait.add(mainLine.transition(flowTransition).attr('transform', transform));
+          wait.add(mainArea.transition(flowTransition).attr('transform', transform));
+          wait.add(mainCircle.transition(flowTransition).attr('transform', transform));
+          wait.add(mainText.transition(flowTransition).attr('transform', transform));
+          wait.add(mainRegion
+              .filter($$.isRegionOnX)
+              .transition(flowTransition)
+              .attr('transform', transform));
+          wait.add(xgrid.transition(flowTransition).attr('transform', transform));
+          wait.add(xgridLines.transition(flowTransition).attr('transform', transform));
+          wait(function () {
+              var i, shapes = [], texts = [];
+              // remove flowed elements
+              if (flowLength) {
+                  for (i = 0; i < flowLength; i++) {
+                      shapes.push('.' + CLASS.shape + '-' + (flowIndex + i));
+                      texts.push('.' + CLASS.text + '-' + (flowIndex + i));
+                  }
+                  $$.svg
+                      .selectAll('.' + CLASS.shapes)
+                      .selectAll(shapes)
+                      .remove();
+                  $$.svg
+                      .selectAll('.' + CLASS.texts)
+                      .selectAll(texts)
+                      .remove();
+                  $$.svg.select('.' + CLASS.xgrid).remove();
+              }
+              // draw again for removing flowed elements and reverting attr
+              xgrid
+                  .attr('transform', null)
+                  .attr('x1', $$.xgridAttr.x1)
+                  .attr('x2', $$.xgridAttr.x2)
+                  .attr('y1', $$.xgridAttr.y1)
+                  .attr('y2', $$.xgridAttr.y2)
+                  .style('opacity', $$.xgridAttr.opacity);
+              xgridLines.attr('transform', null);
+              xgridLines
+                  .select('line')
+                  .attr('x1', config.axis_rotated ? 0 : xv)
+                  .attr('x2', config.axis_rotated ? $$.width : xv);
+              xgridLines
+                  .select('text')
+                  .attr('x', config.axis_rotated ? $$.width : 0)
+                  .attr('y', xv);
+              mainBar.attr('transform', null).attr('d', drawBar);
+              mainLine.attr('transform', null).attr('d', drawLine);
+              mainArea.attr('transform', null).attr('d', drawArea);
+              mainCircle
+                  .attr('transform', null)
+                  .attr('cx', cx)
+                  .attr('cy', cy);
+              mainText
+                  .attr('transform', null)
+                  .attr('x', xForText)
+                  .attr('y', yForText)
+                  .style('fill-opacity', $$.opacityForText.bind($$));
+              mainRegion.attr('transform', null);
+              mainRegion
+                  .filter($$.isRegionOnX)
+                  .attr('x', $$.regionX.bind($$))
+                  .attr('width', $$.regionWidth.bind($$));
+              // callback for end of flow
+              done();
+              $$.flowing = false;
+          });
+      };
+  };
+
+  Chart.prototype.focus = function (targetIds) {
+      var $$ = this.internal, candidates;
+      targetIds = $$.mapToTargetIds(targetIds);
+      (candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$)))),
+          this.revert();
+      this.defocus();
+      candidates.classed(CLASS.focused, true).classed(CLASS.defocused, false);
+      if ($$.hasArcType()) {
+          $$.expandArc(targetIds);
+      }
+      $$.toggleFocusLegend(targetIds, true);
+      $$.focusedTargetIds = targetIds;
+      $$.defocusedTargetIds = $$.defocusedTargetIds.filter(function (id) {
+          return targetIds.indexOf(id) < 0;
+      });
+  };
+  Chart.prototype.defocus = function (targetIds) {
+      var $$ = this.internal, candidates;
+      targetIds = $$.mapToTargetIds(targetIds);
+      (candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$)))),
+          candidates.classed(CLASS.focused, false).classed(CLASS.defocused, true);
+      if ($$.hasArcType()) {
+          $$.unexpandArc(targetIds);
+      }
+      $$.toggleFocusLegend(targetIds, false);
+      $$.focusedTargetIds = $$.focusedTargetIds.filter(function (id) {
+          return targetIds.indexOf(id) < 0;
+      });
+      $$.defocusedTargetIds = targetIds;
+  };
+  Chart.prototype.revert = function (targetIds) {
+      var $$ = this.internal, candidates;
+      targetIds = $$.mapToTargetIds(targetIds);
+      candidates = $$.svg.selectAll($$.selectorTargets(targetIds)); // should be for all targets
+      candidates.classed(CLASS.focused, false).classed(CLASS.defocused, false);
+      if ($$.hasArcType()) {
+          $$.unexpandArc(targetIds);
+      }
+      if ($$.config.legend_show) {
+          $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$)));
+          $$.legend
+              .selectAll($$.selectorLegends(targetIds))
+              .filter(function () {
+              return $$.d3.select(this).classed(CLASS.legendItemFocused);
+          })
+              .classed(CLASS.legendItemFocused, false);
+      }
+      $$.focusedTargetIds = [];
+      $$.defocusedTargetIds = [];
+  };
+
+  Chart.prototype.xgrids = function (grids) {
+      var $$ = this.internal, config = $$.config;
+      if (!grids) {
+          return config.grid_x_lines;
+      }
+      config.grid_x_lines = grids;
+      $$.redrawWithoutRescale();
+      return config.grid_x_lines;
+  };
+  Chart.prototype.xgrids.add = function (grids) {
+      var $$ = this.internal;
+      return this.xgrids($$.config.grid_x_lines.concat(grids ? grids : []));
+  };
+  Chart.prototype.xgrids.remove = function (params) {
+      // TODO: multiple
+      var $$ = this.internal;
+      $$.removeGridLines(params, true);
+  };
+  Chart.prototype.ygrids = function (grids) {
+      var $$ = this.internal, config = $$.config;
+      if (!grids) {
+          return config.grid_y_lines;
+      }
+      config.grid_y_lines = grids;
+      $$.redrawWithoutRescale();
+      return config.grid_y_lines;
+  };
+  Chart.prototype.ygrids.add = function (grids) {
+      var $$ = this.internal;
+      return this.ygrids($$.config.grid_y_lines.concat(grids ? grids : []));
+  };
+  Chart.prototype.ygrids.remove = function (params) {
+      // TODO: multiple
+      var $$ = this.internal;
+      $$.removeGridLines(params, false);
+  };
+
+  Chart.prototype.groups = function (groups) {
+      var $$ = this.internal, config = $$.config;
+      if (isUndefined(groups)) {
+          return config.data_groups;
+      }
+      config.data_groups = groups;
+      $$.redraw();
+      return config.data_groups;
+  };
+
+  Chart.prototype.legend = function () { };
+  Chart.prototype.legend.show = function (targetIds) {
+      var $$ = this.internal;
+      $$.showLegend($$.mapToTargetIds(targetIds));
+      $$.updateAndRedraw({ withLegend: true });
+  };
+  Chart.prototype.legend.hide = function (targetIds) {
+      var $$ = this.internal;
+      $$.hideLegend($$.mapToTargetIds(targetIds));
+      $$.updateAndRedraw({ withLegend: false });
+  };
+
+  Chart.prototype.load = function (args) {
+      var $$ = this.internal, config = $$.config;
+      // update xs if specified
+      if (args.xs) {
+          $$.addXs(args.xs);
+      }
+      // update names if exists
+      if ('names' in args) {
+          Chart.prototype.data.names.bind(this)(args.names);
+      }
+      // update classes if exists
+      if ('classes' in args) {
+          Object.keys(args.classes).forEach(function (id) {
+              config.data_classes[id] = args.classes[id];
+          });
+      }
+      // update categories if exists
+      if ('categories' in args && $$.isCategorized()) {
+          config.axis_x_categories = args.categories;
+      }
+      // update axes if exists
+      if ('axes' in args) {
+          Object.keys(args.axes).forEach(function (id) {
+              config.data_axes[id] = args.axes[id];
+          });
+      }
+      // update colors if exists
+      if ('colors' in args) {
+          Object.keys(args.colors).forEach(function (id) {
+              config.data_colors[id] = args.colors[id];
+          });
+      }
+      // use cache if exists
+      if ('cacheIds' in args && $$.hasCaches(args.cacheIds)) {
+          $$.load($$.getCaches(args.cacheIds), args.done);
+          return;
+      }
+      // unload if needed
+      if (args.unload) {
+          // TODO: do not unload if target will load (included in url/rows/columns)
+          $$.unload($$.mapToTargetIds(args.unload === true ? null : args.unload), function () {
+              $$.loadFromArgs(args);
+          });
+      }
+      else {
+          $$.loadFromArgs(args);
+      }
+  };
+  Chart.prototype.unload = function (args) {
+      var $$ = this.internal;
+      args = args || {};
+      if (args instanceof Array) {
+          args = { ids: args };
+      }
+      else if (typeof args === 'string') {
+          args = { ids: [args] };
+      }
+      $$.unload($$.mapToTargetIds(args.ids), function () {
+          $$.redraw({
+              withUpdateOrgXDomain: true,
+              withUpdateXDomain: true,
+              withLegend: true
+          });
+          if (args.done) {
+              args.done();
+          }
+      });
+  };
+
+  Chart.prototype.pie = function () { };
+  Chart.prototype.pie.padAngle = function (padAngle) {
+      if (padAngle === undefined) {
+          return this.internal.config.pie_padAngle;
+      }
+      this.internal.config.pie_padAngle = padAngle;
+      this.flush();
+  };
+
+  Chart.prototype.regions = function (regions) {
+      var $$ = this.internal, config = $$.config;
+      if (!regions) {
+          return config.regions;
+      }
+      config.regions = regions;
+      $$.redrawWithoutRescale();
+      return config.regions;
+  };
+  Chart.prototype.regions.add = function (regions) {
+      var $$ = this.internal, config = $$.config;
+      if (!regions) {
+          return config.regions;
+      }
+      config.regions = config.regions.concat(regions);
+      $$.redrawWithoutRescale();
+      return config.regions;
+  };
+  Chart.prototype.regions.remove = function (options) {
+      var $$ = this.internal, config = $$.config, duration, classes, regions;
+      options = options || {};
+      duration = getOption(options, 'duration', config.transition_duration);
+      classes = getOption(options, 'classes', [CLASS.region]);
+      regions = $$.main.select('.' + CLASS.regions).selectAll(classes.map(function (c) {
+          return '.' + c;
+      }));
+      (duration ? regions.transition().duration(duration) : regions)
+          .style('opacity', 0)
+          .remove();
+      config.regions = config.regions.filter(function (region) {
+          var found = false;
+          if (!region['class']) {
+              return true;
+          }
+          region['class'].split(' ').forEach(function (c) {
+              if (classes.indexOf(c) >= 0) {
+                  found = true;
+              }
+          });
+          return !found;
+      });
+      return config.regions;
+  };
+
+  Chart.prototype.selected = function (targetId) {
+      var $$ = this.internal, d3 = $$.d3;
+      return $$.main
+          .selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(targetId))
+          .selectAll('.' + CLASS.shape)
+          .filter(function () {
+          return d3.select(this).classed(CLASS.SELECTED);
+      })
+          .nodes()
+          .map(function (d) {
+          var data = d.__data__;
+          return data.data ? data.data : data;
+      });
+  };
+  Chart.prototype.select = function (ids, indices, resetOther) {
+      var $$ = this.internal, d3 = $$.d3, config = $$.config;
+      if (!config.data_selection_enabled) {
+          return;
+      }
+      $$.main
+          .selectAll('.' + CLASS.shapes)
+          .selectAll('.' + CLASS.shape)
+          .each(function (d, i) {
+          var shape = d3.select(this), id = d.data ? d.data.id : d.id, toggle = $$.getToggle(this, d).bind($$), isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, isTargetIndex = !indices || indices.indexOf(i) >= 0, isSelected = shape.classed(CLASS.SELECTED);
+          // line/area selection not supported yet
+          if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
+              return;
+          }
+          if (isTargetId && isTargetIndex) {
+              if (config.data_selection_isselectable(d) && !isSelected) {
+                  toggle(true, shape.classed(CLASS.SELECTED, true), d, i);
+              }
+          }
+          else if (isDefined(resetOther) && resetOther) {
+              if (isSelected) {
+                  toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
+              }
+          }
+      });
+  };
+  Chart.prototype.unselect = function (ids, indices) {
+      var $$ = this.internal, d3 = $$.d3, config = $$.config;
+      if (!config.data_selection_enabled) {
+          return;
+      }
+      $$.main
+          .selectAll('.' + CLASS.shapes)
+          .selectAll('.' + CLASS.shape)
+          .each(function (d, i) {
+          var shape = d3.select(this), id = d.data ? d.data.id : d.id, toggle = $$.getToggle(this, d).bind($$), isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, isTargetIndex = !indices || indices.indexOf(i) >= 0, isSelected = shape.classed(CLASS.SELECTED);
+          // line/area selection not supported yet
+          if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
+              return;
+          }
+          if (isTargetId && isTargetIndex) {
+              if (config.data_selection_isselectable(d)) {
+                  if (isSelected) {
+                      toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
+                  }
+              }
+          }
+      });
+  };
+
+  Chart.prototype.show = function (targetIds, options) {
+      var $$ = this.internal, targets;
+      targetIds = $$.mapToTargetIds(targetIds);
+      options = options || {};
+      $$.removeHiddenTargetIds(targetIds);
+      targets = $$.svg.selectAll($$.selectorTargets(targetIds));
+      targets
+          .transition()
+          .style('display', isIE() ? 'block' : 'initial', 'important')
+          .style('opacity', 1, 'important')
+          .call($$.endall, function () {
+          targets.style('opacity', null).style('opacity', 1);
+      });
+      if (options.withLegend) {
+          $$.showLegend(targetIds);
+      }
+      $$.redraw({
+          withUpdateOrgXDomain: true,
+          withUpdateXDomain: true,
+          withLegend: true
+      });
+  };
+  Chart.prototype.hide = function (targetIds, options) {
+      var $$ = this.internal, targets;
+      targetIds = $$.mapToTargetIds(targetIds);
+      options = options || {};
+      $$.addHiddenTargetIds(targetIds);
+      targets = $$.svg.selectAll($$.selectorTargets(targetIds));
+      targets
+          .transition()
+          .style('opacity', 0, 'important')
+          .call($$.endall, function () {
+          targets.style('opacity', null).style('opacity', 0);
+          targets.style('display', 'none');
+      });
+      if (options.withLegend) {
+          $$.hideLegend(targetIds);
+      }
+      $$.redraw({
+          withUpdateOrgXDomain: true,
+          withUpdateXDomain: true,
+          withLegend: true
+      });
+  };
+  Chart.prototype.toggle = function (targetIds, options) {
+      var that = this, $$ = this.internal;
+      $$.mapToTargetIds(targetIds).forEach(function (targetId) {
+          $$.isTargetToShow(targetId)
+              ? that.hide(targetId, options)
+              : that.show(targetId, options);
+      });
+  };
+
+  Chart.prototype.subchart = function () { };
+  Chart.prototype.subchart.isShown = function () {
+      var $$ = this.internal;
+      return $$.config.subchart_show;
+  };
+  Chart.prototype.subchart.show = function () {
+      var $$ = this.internal;
+      if ($$.config.subchart_show) {
+          return;
+      }
+      $$.config.subchart_show = true;
+      // insert DOM
+      $$.initSubchart();
+      // update dimensions with sub chart now visible
+      $$.updateDimension();
+      // insert brush (depends on sizes previously updated)
+      $$.initSubchartBrush();
+      // attach data
+      $$.updateTargetsForSubchart($$.getTargets());
+      // reset fade-in state
+      $$.mapToIds($$.data.targets).forEach(function (id) {
+          $$.withoutFadeIn[id] = false;
+      });
+      // redraw chart !
+      $$.updateAndRedraw();
+      // update visible targets !
+      $$.showTargets();
+  };
+  Chart.prototype.subchart.hide = function () {
+      var $$ = this.internal;
+      if (!$$.config.subchart_show) {
+          return;
+      }
+      $$.config.subchart_show = false;
+      // remove DOM
+      $$.removeSubchart();
+      // re-render chart
+      $$.redraw();
+  };
+
+  Chart.prototype.tooltip = function () { };
+  Chart.prototype.tooltip.show = function (args) {
+      var $$ = this.internal, targets, data, mouse = {};
+      // determine mouse position on the chart
+      if (args.mouse) {
+          mouse = args.mouse;
+      }
+      else {
+          // determine focus data
+          if (args.data) {
+              data = args.data;
+          }
+          else if (typeof args.x !== 'undefined') {
+              if (args.id) {
+                  targets = $$.data.targets.filter(function (t) {
+                      return t.id === args.id;
+                  });
+              }
+              else {
+                  targets = $$.data.targets;
+              }
+              data = $$.filterByX(targets, args.x).slice(0, 1)[0];
+          }
+          mouse = data ? $$.getMousePosition(data) : null;
+      }
+      // emulate mouse events to show
+      $$.dispatchEvent('mousemove', mouse);
+      $$.config.tooltip_onshow.call($$, data);
+  };
+  Chart.prototype.tooltip.hide = function () {
+      // TODO: get target data by checking the state of focus
+      this.internal.dispatchEvent('mouseout', 0);
+      this.internal.config.tooltip_onhide.call(this);
+  };
+
+  Chart.prototype.transform = function (type, targetIds) {
+      var $$ = this.internal, options = ['pie', 'donut'].indexOf(type) >= 0 ? { withTransform: true } : null;
+      $$.transformTo(targetIds, type, options);
+  };
+  ChartInternal.prototype.transformTo = function (targetIds, type, optionsForRedraw) {
+      var $$ = this, withTransitionForAxis = !$$.hasArcType(), options = optionsForRedraw || {
+          withTransitionForAxis: withTransitionForAxis
+      };
+      options.withTransitionForTransform = false;
+      $$.transiting = false;
+      $$.setTargetType(targetIds, type);
+      $$.updateTargets($$.data.targets); // this is needed when transforming to arc
+      $$.updateAndRedraw(options);
+  };
+
+  Chart.prototype.x = function (x) {
+      var $$ = this.internal;
+      if (arguments.length) {
+          $$.updateTargetX($$.data.targets, x);
+          $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true });
+      }
+      return $$.data.xs;
+  };
+  Chart.prototype.xs = function (xs) {
+      var $$ = this.internal;
+      if (arguments.length) {
+          $$.updateTargetXs($$.data.targets, xs);
+          $$.redraw({ withUpdateOrgXDomain: true, withUpdateXDomain: true });
+      }
+      return $$.data.xs;
+  };
+
+  Chart.prototype.zoom = function (domain) {
+      var $$ = this.internal;
+      if (domain) {
+          if ($$.isTimeSeries()) {
+              domain = domain.map(function (x) {
+                  return $$.parseDate(x);
+              });
+          }
+          if ($$.config.subchart_show) {
+              $$.brush.selectionAsValue(domain, true);
+          }
+          else {
+              $$.updateXDomain(null, true, false, false, domain);
+              $$.redraw({ withY: $$.config.zoom_rescale, withSubchart: false });
+          }
+          $$.config.zoom_onzoom.call(this, $$.x.orgDomain());
+          return domain;
+      }
+      else {
+          return $$.x.domain();
+      }
+  };
+  Chart.prototype.zoom.enable = function (enabled) {
+      var $$ = this.internal;
+      $$.config.zoom_enabled = enabled;
+      $$.updateAndRedraw();
+  };
+  Chart.prototype.unzoom = function () {
+      var $$ = this.internal;
+      if ($$.config.subchart_show) {
+          $$.brush.clear();
+      }
+      else {
+          $$.updateXDomain(null, true, false, false, $$.subX.domain());
+          $$.redraw({ withY: $$.config.zoom_rescale, withSubchart: false });
+      }
+  };
+  Chart.prototype.zoom.max = function (max) {
+      var $$ = this.internal, config = $$.config, d3 = $$.d3;
+      if (max === 0 || max) {
+          config.zoom_x_max = d3.max([$$.orgXDomain[1], max]);
+      }
+      else {
+          return config.zoom_x_max;
+      }
+  };
+  Chart.prototype.zoom.min = function (min) {
+      var $$ = this.internal, config = $$.config, d3 = $$.d3;
+      if (min === 0 || min) {
+          config.zoom_x_min = d3.min([$$.orgXDomain[0], min]);
+      }
+      else {
+          return config.zoom_x_min;
+      }
+  };
+  Chart.prototype.zoom.range = function (range) {
+      if (arguments.length) {
+          if (isDefined(range.max)) {
+              this.domain.max(range.max);
+          }
+          if (isDefined(range.min)) {
+              this.domain.min(range.min);
+          }
+      }
+      else {
+          return {
+              max: this.domain.max(),
+              min: this.domain.min()
+          };
+      }
+  };
+
+  ChartInternal.prototype.initPie = function () {
+      var $$ = this, d3 = $$.d3;
+      $$.pie = d3
+          .pie()
+          .padAngle(this.getPadAngle.bind(this))
+          .value(function (d) {
+          return d.values.reduce(function (a, b) {
+              return a + b.value;
+          }, 0);
+      });
+      var orderFct = $$.getOrderFunction();
+      // we need to reverse the returned order if asc or desc to have the slice in expected order.
+      if (orderFct && ($$.isOrderAsc() || $$.isOrderDesc())) {
+          var defaultSort_1 = orderFct;
+          orderFct = function (t1, t2) { return defaultSort_1(t1, t2) * -1; };
+      }
+      $$.pie.sort(orderFct || null);
+  };
+  ChartInternal.prototype.updateRadius = function () {
+      var $$ = this, config = $$.config, w = config.gauge_width || config.donut_width, gaugeArcWidth = $$.filterTargetsToShow($$.data.targets).length *
+          $$.config.gauge_arcs_minWidth;
+      $$.radiusExpanded =
+          (Math.min($$.arcWidth, $$.arcHeight) / 2) * ($$.hasType('gauge') ? 0.85 : 1);
+      $$.radius = $$.radiusExpanded * 0.95;
+      $$.innerRadiusRatio = w ? ($$.radius - w) / $$.radius : 0.6;
+      $$.innerRadius =
+          $$.hasType('donut') || $$.hasType('gauge')
+              ? $$.radius * $$.innerRadiusRatio
+              : 0;
+      $$.gaugeArcWidth = w
+          ? w
+          : gaugeArcWidth <= $$.radius - $$.innerRadius
+              ? $$.radius - $$.innerRadius
+              : gaugeArcWidth <= $$.radius
+                  ? gaugeArcWidth
+                  : $$.radius;
+  };
+  ChartInternal.prototype.getPadAngle = function () {
+      if (this.hasType('pie')) {
+          return this.config.pie_padAngle || 0;
+      }
+      else if (this.hasType('donut')) {
+          return this.config.donut_padAngle || 0;
+      }
+      else {
+          return 0;
+      }
+  };
+  ChartInternal.prototype.updateArc = function () {
+      var $$ = this;
+      $$.svgArc = $$.getSvgArc();
+      $$.svgArcExpanded = $$.getSvgArcExpanded();
+      $$.svgArcExpandedSub = $$.getSvgArcExpanded(0.98);
+  };
+  ChartInternal.prototype.updateAngle = function (d) {
+      var $$ = this, config = $$.config, found = false, index = 0, gMin, gMax, gTic, gValue;
+      if (!config) {
+          return null;
+      }
+      $$.pie($$.filterTargetsToShow($$.data.targets)).forEach(function (t) {
+          if (!found && t.data.id === d.data.id) {
+              found = true;
+              d = t;
+              d.index = index;
+          }
+          index++;
+      });
+      if (isNaN(d.startAngle)) {
+          d.startAngle = 0;
+      }
+      if (isNaN(d.endAngle)) {
+          d.endAngle = d.startAngle;
+      }
+      if ($$.isGaugeType(d.data)) {
+          gMin = config.gauge_min;
+          gMax = config.gauge_max;
+          gTic = (Math.PI * (config.gauge_fullCircle ? 2 : 1)) / (gMax - gMin);
+          gValue = d.value < gMin ? 0 : d.value < gMax ? d.value - gMin : gMax - gMin;
+          d.startAngle = config.gauge_startingAngle;
+          d.endAngle = d.startAngle + gTic * gValue;
+      }
+      return found ? d : null;
+  };
+  ChartInternal.prototype.getSvgArc = function () {
+      var $$ = this, hasGaugeType = $$.hasType('gauge'), singleArcWidth = $$.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length, arc = $$.d3
+          .arc()
+          .outerRadius(function (d) {
+          return hasGaugeType ? $$.radius - singleArcWidth * d.index : $$.radius;
+      })
+          .innerRadius(function (d) {
+          return hasGaugeType
+              ? $$.radius - singleArcWidth * (d.index + 1)
+              : $$.innerRadius;
+      }), newArc = function (d, withoutUpdate) {
+          var updated;
+          if (withoutUpdate) {
+              return arc(d);
+          } // for interpolate
+          updated = $$.updateAngle(d);
+          return updated ? arc(updated) : 'M 0 0';
+      };
+      newArc.centroid = arc.centroid;
+      return newArc;
+  };
+  ChartInternal.prototype.getSvgArcExpanded = function (rate) {
+      rate = rate || 1;
+      var $$ = this, hasGaugeType = $$.hasType('gauge'), singleArcWidth = $$.gaugeArcWidth / $$.filterTargetsToShow($$.data.targets).length, expandWidth = Math.min($$.radiusExpanded * rate - $$.radius, singleArcWidth * 0.8 - (1 - rate) * 100), arc = $$.d3
+          .arc()
+          .outerRadius(function (d) {
+          return hasGaugeType
+              ? $$.radius - singleArcWidth * d.index + expandWidth
+              : $$.radiusExpanded * rate;
+      })
+          .innerRadius(function (d) {
+          return hasGaugeType
+              ? $$.radius - singleArcWidth * (d.index + 1)
+              : $$.innerRadius;
+      });
+      return function (d) {
+          var updated = $$.updateAngle(d);
+          return updated ? arc(updated) : 'M 0 0';
+      };
+  };
+  ChartInternal.prototype.getArc = function (d, withoutUpdate, force) {
+      return force || this.isArcType(d.data)
+          ? this.svgArc(d, withoutUpdate)
+          : 'M 0 0';
+  };
+  ChartInternal.prototype.transformForArcLabel = function (d) {
+      var $$ = this, config = $$.config, updated = $$.updateAngle(d), c, x, y, h, ratio, translate = '', hasGauge = $$.hasType('gauge');
+      if (updated && !hasGauge) {
+          c = this.svgArc.centroid(updated);
+          x = isNaN(c[0]) ? 0 : c[0];
+          y = isNaN(c[1]) ? 0 : c[1];
+          h = Math.sqrt(x * x + y * y);
+          if ($$.hasType('donut') && config.donut_label_ratio) {
+              ratio = isFunction(config.donut_label_ratio)
+                  ? config.donut_label_ratio(d, $$.radius, h)
+                  : config.donut_label_ratio;
+          }
+          else if ($$.hasType('pie') && config.pie_label_ratio) {
+              ratio = isFunction(config.pie_label_ratio)
+                  ? config.pie_label_ratio(d, $$.radius, h)
+                  : config.pie_label_ratio;
+          }
+          else {
+              ratio =
+                  $$.radius && h
+                      ? ((36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) *
+                          $$.radius) /
+                          h
+                      : 0;
+          }
+          translate = 'translate(' + x * ratio + ',' + y * ratio + ')';
+      }
+      else if (updated &&
+          hasGauge &&
+          $$.filterTargetsToShow($$.data.targets).length > 1) {
+          var y1 = Math.sin(updated.endAngle - Math.PI / 2);
+          x = Math.cos(updated.endAngle - Math.PI / 2) * ($$.radiusExpanded + 25);
+          y = y1 * ($$.radiusExpanded + 15 - Math.abs(y1 * 10)) + 3;
+          translate = 'translate(' + x + ',' + y + ')';
+      }
+      return translate;
+  };
+  /**
+   * @deprecated Use `getRatio('arc', d)` instead.
+   */
+  ChartInternal.prototype.getArcRatio = function (d) {
+      return this.getRatio('arc', d);
+  };
+  ChartInternal.prototype.convertToArcData = function (d) {
+      return this.addName({
+          id: d.data.id,
+          value: d.value,
+          ratio: this.getRatio('arc', d),
+          index: d.index
+      });
+  };
+  ChartInternal.prototype.textForArcLabel = function (d) {
+      var $$ = this, updated, value, ratio, id, format;
+      if (!$$.shouldShowArcLabel()) {
+          return '';
+      }
+      updated = $$.updateAngle(d);
+      value = updated ? updated.value : null;
+      ratio = $$.getRatio('arc', updated);
+      id = d.data.id;
+      if (!$$.hasType('gauge') && !$$.meetsArcLabelThreshold(ratio)) {
+          return '';
+      }
+      format = $$.getArcLabelFormat();
+      return format
+          ? format(value, ratio, id)
+          : $$.defaultArcValueFormat(value, ratio);
+  };
+  ChartInternal.prototype.textForGaugeMinMax = function (value, isMax) {
+      var $$ = this, format = $$.getGaugeLabelExtents();
+      return format ? format(value, isMax) : value;
+  };
+  ChartInternal.prototype.expandArc = function (targetIds) {
+      var $$ = this, interval;
+      // MEMO: avoid to cancel transition
+      if ($$.transiting) {
+          interval = window.setInterval(function () {
+              if (!$$.transiting) {
+                  window.clearInterval(interval);
+                  if ($$.legend.selectAll('.c3-legend-item-focused').size() > 0) {
+                      $$.expandArc(targetIds);
+                  }
+              }
+          }, 10);
+          return;
+      }
+      targetIds = $$.mapToTargetIds(targetIds);
+      $$.svg
+          .selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc))
+          .each(function (d) {
+          if (!$$.shouldExpand(d.data.id)) {
+              return;
+          }
+          $$.d3
+              .select(this)
+              .selectAll('path')
+              .transition()
+              .duration($$.expandDuration(d.data.id))
+              .attr('d', $$.svgArcExpanded)
+              .transition()
+              .duration($$.expandDuration(d.data.id) * 2)
+              .attr('d', $$.svgArcExpandedSub)
+              .each(function (d) {
+              if ($$.isDonutType(d.data)) ;
+          });
+      });
+  };
+  ChartInternal.prototype.unexpandArc = function (targetIds) {
+      var $$ = this;
+      if ($$.transiting) {
+          return;
+      }
+      targetIds = $$.mapToTargetIds(targetIds);
+      $$.svg
+          .selectAll($$.selectorTargets(targetIds, '.' + CLASS.chartArc))
+          .selectAll('path')
+          .transition()
+          .duration(function (d) {
+          return $$.expandDuration(d.data.id);
+      })
+          .attr('d', $$.svgArc);
+      $$.svg.selectAll('.' + CLASS.arc);
+  };
+  ChartInternal.prototype.expandDuration = function (id) {
+      var $$ = this, config = $$.config;
+      if ($$.isDonutType(id)) {
+          return config.donut_expand_duration;
+      }
+      else if ($$.isGaugeType(id)) {
+          return config.gauge_expand_duration;
+      }
+      else if ($$.isPieType(id)) {
+          return config.pie_expand_duration;
+      }
+      else {
+          return 50;
+      }
+  };
+  ChartInternal.prototype.shouldExpand = function (id) {
+      var $$ = this, config = $$.config;
+      return (($$.isDonutType(id) && config.donut_expand) ||
+          ($$.isGaugeType(id) && config.gauge_expand) ||
+          ($$.isPieType(id) && config.pie_expand));
+  };
+  ChartInternal.prototype.shouldShowArcLabel = function () {
+      var $$ = this, config = $$.config, shouldShow = true;
+      if ($$.hasType('donut')) {
+          shouldShow = config.donut_label_show;
+      }
+      else if ($$.hasType('pie')) {
+          shouldShow = config.pie_label_show;
+      }
+      // when gauge, always true
+      return shouldShow;
+  };
+  ChartInternal.prototype.meetsArcLabelThreshold = function (ratio) {
+      var $$ = this, config = $$.config, threshold = $$.hasType('donut')
+          ? config.donut_label_threshold
+          : config.pie_label_threshold;
+      return ratio >= threshold;
+  };
+  ChartInternal.prototype.getArcLabelFormat = function () {
+      var $$ = this, config = $$.config, format = config.pie_label_format;
+      if ($$.hasType('gauge')) {
+          format = config.gauge_label_format;
+      }
+      else if ($$.hasType('donut')) {
+          format = config.donut_label_format;
+      }
+      return format;
+  };
+  ChartInternal.prototype.getGaugeLabelExtents = function () {
+      var $$ = this, config = $$.config;
+      return config.gauge_label_extents;
+  };
+  ChartInternal.prototype.getArcTitle = function () {
+      var $$ = this;
+      return $$.hasType('donut') ? $$.config.donut_title : '';
+  };
+  ChartInternal.prototype.updateTargetsForArc = function (targets) {
+      var $$ = this, main = $$.main, mainPies, mainPieEnter, classChartArc = $$.classChartArc.bind($$), classArcs = $$.classArcs.bind($$), classFocus = $$.classFocus.bind($$);
+      mainPies = main
+          .select('.' + CLASS.chartArcs)
+          .selectAll('.' + CLASS.chartArc)
+          .data($$.pie(targets))
+          .attr('class', function (d) {
+          return classChartArc(d) + classFocus(d.data);
+      });
+      mainPieEnter = mainPies
+          .enter()
+          .append('g')
+          .attr('class', classChartArc);
+      mainPieEnter.append('g').attr('class', classArcs);
+      mainPieEnter
+          .append('text')
+          .attr('dy', $$.hasType('gauge') ? '-.1em' : '.35em')
+          .style('opacity', 0)
+          .style('text-anchor', 'middle')
+          .style('pointer-events', 'none');
+      // MEMO: can not keep same color..., but not bad to update color in redraw
+      //mainPieUpdate.exit().remove();
+  };
+  ChartInternal.prototype.initArc = function () {
+      var $$ = this;
+      $$.arcs = $$.main
+          .select('.' + CLASS.chart)
+          .append('g')
+          .attr('class', CLASS.chartArcs)
+          .attr('transform', $$.getTranslate('arc'));
+      $$.arcs
+          .append('text')
+          .attr('class', CLASS.chartArcsTitle)
+          .style('text-anchor', 'middle')
+          .text($$.getArcTitle());
+  };
+  ChartInternal.prototype.redrawArc = function (duration, durationForExit, withTransform) {
+      var $$ = this, d3 = $$.d3, config = $$.config, main = $$.main, arcs, mainArc, arcLabelLines, mainArcLabelLine, hasGaugeType = $$.hasType('gauge');
+      arcs = main
+          .selectAll('.' + CLASS.arcs)
+          .selectAll('.' + CLASS.arc)
+          .data($$.arcData.bind($$));
+      mainArc = arcs
+          .enter()
+          .append('path')
+          .attr('class', $$.classArc.bind($$))
+          .style('fill', function (d) {
+          return $$.color(d.data);
+      })
+          .style('cursor', function (d) {
+          return config.interaction_enabled && config.data_selection_isselectable(d)
+              ? 'pointer'
+              : null;
+      })
+          .each(function (d) {
+          if ($$.isGaugeType(d.data)) {
+              d.startAngle = d.endAngle = config.gauge_startingAngle;
+          }
+          this._current = d;
+      })
+          .merge(arcs);
+      if (hasGaugeType) {
+          arcLabelLines = main
+              .selectAll('.' + CLASS.arcs)
+              .selectAll('.' + CLASS.arcLabelLine)
+              .data($$.arcData.bind($$));
+          mainArcLabelLine = arcLabelLines
+              .enter()
+              .append('rect')
+              .attr('class', function (d) {
+              return (CLASS.arcLabelLine +
+                  ' ' +
+                  CLASS.target +
+                  ' ' +
+                  CLASS.target +
+                  '-' +
+                  d.data.id);
+          })
+              .merge(arcLabelLines);
+          if ($$.filterTargetsToShow($$.data.targets).length === 1) {
+              mainArcLabelLine.style('display', 'none');
+          }
+          else {
+              mainArcLabelLine
+                  .style('fill', function (d) {
+                  return $$.levelColor
+                      ? $$.levelColor(d.data.values.reduce(function (total, item) {
+                          return total + item.value;
+                      }, 0))
+                      : $$.color(d.data);
+              })
+                  .style('display', config.gauge_labelLine_show ? '' : 'none')
+                  .each(function (d) {
+                  var lineLength = 0, lineThickness = 2, x = 0, y = 0, transform = '';
+                  if ($$.hiddenTargetIds.indexOf(d.data.id) < 0) {
+                      var updated = $$.updateAngle(d), innerLineLength = ($$.gaugeArcWidth /
+                          $$.filterTargetsToShow($$.data.targets).length) *
+                          (updated.index + 1), lineAngle = updated.endAngle - Math.PI / 2, arcInnerRadius = $$.radius - innerLineLength, linePositioningAngle = lineAngle - (arcInnerRadius === 0 ? 0 : 1 / arcInnerRadius);
+                      lineLength = $$.radiusExpanded - $$.radius + innerLineLength;
+                      x = Math.cos(linePositioningAngle) * arcInnerRadius;
+                      y = Math.sin(linePositioningAngle) * arcInnerRadius;
+                      transform =
+                          'rotate(' +
+                              (lineAngle * 180) / Math.PI +
+                              ', ' +
+                              x +
+                              ', ' +
+                              y +
+                              ')';
+                  }
+                  d3.select(this)
+                      .attr('x', x)
+                      .attr('y', y)
+                      .attr('width', lineLength)
+                      .attr('height', lineThickness)
+                      .attr('transform', transform)
+                      .style('stroke-dasharray', '0, ' + (lineLength + lineThickness) + ', 0');
+              });
+          }
+      }
+      mainArc
+          .attr('transform', function (d) {
+          return !$$.isGaugeType(d.data) && withTransform ? 'scale(0)' : '';
+      })
+          .on('mouseover', config.interaction_enabled
+          ? function (d) {
+              var updated, arcData;
+              if ($$.transiting) {
+                  // skip while transiting
+                  return;
+              }
+              updated = $$.updateAngle(d);
+              if (updated) {
+                  arcData = $$.convertToArcData(updated);
+                  // transitions
+                  $$.expandArc(updated.data.id);
+                  $$.api.focus(updated.data.id);
+                  $$.toggleFocusLegend(updated.data.id, true);
+                  $$.config.data_onmouseover(arcData, this);
+              }
+          }
+          : null)
+          .on('mousemove', config.interaction_enabled
+          ? function (d) {
+              var updated = $$.updateAngle(d), arcData, selectedData;
+              if (updated) {
+                  (arcData = $$.convertToArcData(updated)),
+                      (selectedData = [arcData]);
+                  $$.showTooltip(selectedData, this);
+              }
+          }
+          : null)
+          .on('mouseout', config.interaction_enabled
+          ? function (d) {
+              var updated, arcData;
+              if ($$.transiting) {
+                  // skip while transiting
+                  return;
+              }
+              updated = $$.updateAngle(d);
+              if (updated) {
+                  arcData = $$.convertToArcData(updated);
+                  // transitions
+                  $$.unexpandArc(updated.data.id);
+                  $$.api.revert();
+                  $$.revertLegend();
+                  $$.hideTooltip();
+                  $$.config.data_onmouseout(arcData, this);
+              }
+          }
+          : null)
+          .on('click', config.interaction_enabled
+          ? function (d, i) {
+              var updated = $$.updateAngle(d), arcData;
+              if (updated) {
+                  arcData = $$.convertToArcData(updated);
+                  if ($$.toggleShape) {
+                      $$.toggleShape(this, arcData, i);
+                  }
+                  $$.config.data_onclick.call($$.api, arcData, this);
+              }
+          }
+          : null)
+          .each(function () {
+          $$.transiting = true;
+      })
+          .transition()
+          .duration(duration)
+          .attrTween('d', function (d) {
+          var updated = $$.updateAngle(d), interpolate;
+          if (!updated) {
+              return function () {
+                  return 'M 0 0';
+              };
+          }
+          //                if (this._current === d) {
+          //                    this._current = {
+          //                        startAngle: Math.PI*2,
+          //                        endAngle: Math.PI*2,
+          //                    };
+          //                }
+          if (isNaN(this._current.startAngle)) {
+              this._current.startAngle = 0;
+          }
+          if (isNaN(this._current.endAngle)) {
+              this._current.endAngle = this._current.startAngle;
+          }
+          interpolate = d3.interpolate(this._current, updated);
+          this._current = interpolate(0);
+          return function (t) {
+              // prevents crashing the charts once in transition and chart.destroy() has been called
+              if ($$.config === null) {
+                  return 'M 0 0';
+              }
+              var interpolated = interpolate(t);
+              interpolated.data = d.data; // data.id will be updated by interporator
+              return $$.getArc(interpolated, true);
+          };
+      })
+          .attr('transform', withTransform ? 'scale(1)' : '')
+          .style('fill', function (d) {
+          return $$.levelColor
+              ? $$.levelColor(d.data.values.reduce(function (total, item) {
+                  return total + item.value;
+              }, 0))
+              : $$.color(d.data.id);
+      }) // Where gauge reading color would receive customization.
+          .call($$.endall, function () {
+          $$.transiting = false;
+      });
+      arcs
+          .exit()
+          .transition()
+          .duration(durationForExit)
+          .style('opacity', 0)
+          .remove();
+      main
+          .selectAll('.' + CLASS.chartArc)
+          .select('text')
+          .style('opacity', 0)
+          .attr('class', function (d) {
+          return $$.isGaugeType(d.data) ? CLASS.gaugeValue : '';
+      })
+          .text($$.textForArcLabel.bind($$))
+          .attr('transform', $$.transformForArcLabel.bind($$))
+          .style('font-size', function (d) {
+          return $$.isGaugeType(d.data) &&
+              $$.filterTargetsToShow($$.data.targets).length === 1
+              ? Math.round($$.radius / 5) + 'px'
+              : '';
+      })
+          .transition()
+          .duration(duration)
+          .style('opacity', function (d) {
+          return $$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? 1 : 0;
+      });
+      main
+          .select('.' + CLASS.chartArcsTitle)
+          .style('opacity', $$.hasType('donut') || hasGaugeType ? 1 : 0);
+      if (hasGaugeType) {
+          var index_1 = 0;
+          var backgroundArc = $$.arcs
+              .select('g.' + CLASS.chartArcsBackground)
+              .selectAll('path.' + CLASS.chartArcsBackground)
+              .data($$.data.targets);
+          backgroundArc
+              .enter()
+              .append('path')
+              .attr('class', function (d, i) {
+              return CLASS.chartArcsBackground + ' ' + CLASS.chartArcsBackground + '-' + i;
+          })
+              .merge(backgroundArc)
+              .attr('d', function (d1) {
+              if ($$.hiddenTargetIds.indexOf(d1.id) >= 0) {
+                  return 'M 0 0';
+              }
+              var d = {
+                  data: [{ value: config.gauge_max }],
+                  startAngle: config.gauge_startingAngle,
+                  endAngle: -1 *
+                      config.gauge_startingAngle *
+                      (config.gauge_fullCircle ? Math.PI : 1),
+                  index: index_1++
+              };
+              return $$.getArc(d, true, true);
+          });
+          backgroundArc.exit().remove();
+          $$.arcs
+              .select('.' + CLASS.chartArcsGaugeUnit)
+              .attr('dy', '.75em')
+              .text(config.gauge_label_show ? config.gauge_units : '');
+          $$.arcs
+              .select('.' + CLASS.chartArcsGaugeMin)
+              .attr('dx', -1 *
+              ($$.innerRadius +
+                  ($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2)) +
+              'px')
+              .attr('dy', '1.2em')
+              .text(config.gauge_label_show
+              ? $$.textForGaugeMinMax(config.gauge_min, false)
+              : '');
+          $$.arcs
+              .select('.' + CLASS.chartArcsGaugeMax)
+              .attr('dx', $$.innerRadius +
+              ($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2) +
+              'px')
+              .attr('dy', '1.2em')
+              .text(config.gauge_label_show
+              ? $$.textForGaugeMinMax(config.gauge_max, true)
+              : '');
+      }
+  };
+  ChartInternal.prototype.initGauge = function () {
+      var arcs = this.arcs;
+      if (this.hasType('gauge')) {
+          arcs.append('g').attr('class', CLASS.chartArcsBackground);
+          arcs
+              .append('text')
+              .attr('class', CLASS.chartArcsGaugeUnit)
+              .style('text-anchor', 'middle')
+              .style('pointer-events', 'none');
+          arcs
+              .append('text')
+              .attr('class', CLASS.chartArcsGaugeMin)
+              .style('text-anchor', 'middle')
+              .style('pointer-events', 'none');
+          arcs
+              .append('text')
+              .attr('class', CLASS.chartArcsGaugeMax)
+              .style('text-anchor', 'middle')
+              .style('pointer-events', 'none');
+      }
+  };
+  ChartInternal.prototype.getGaugeLabelHeight = function () {
+      return this.config.gauge_label_show ? 20 : 0;
+  };
+
+  /**
+   * Store value into cache
+   *
+   * @param key
+   * @param value
+   */
+  ChartInternal.prototype.addToCache = function (key, value) {
+      this.cache["$" + key] = value;
+  };
+  /**
+   * Returns a cached value or undefined
+   *
+   * @param key
+   * @return {*}
+   */
+  ChartInternal.prototype.getFromCache = function (key) {
+      return this.cache["$" + key];
+  };
+  /**
+   * Reset cached data
+   */
+  ChartInternal.prototype.resetCache = function () {
+      var _this = this;
+      Object.keys(this.cache)
+          .filter(function (key) { return /^\$/.test(key); })
+          .forEach(function (key) {
+          delete _this.cache[key];
+      });
+  };
+  // Old API that stores Targets
+  ChartInternal.prototype.hasCaches = function (ids) {
+      for (var i = 0; i < ids.length; i++) {
+          if (!(ids[i] in this.cache)) {
+              return false;
+          }
+      }
+      return true;
+  };
+  ChartInternal.prototype.addCache = function (id, target) {
+      this.cache[id] = this.cloneTarget(target);
+  };
+  ChartInternal.prototype.getCaches = function (ids) {
+      var targets = [], i;
+      for (i = 0; i < ids.length; i++) {
+          if (ids[i] in this.cache) {
+              targets.push(this.cloneTarget(this.cache[ids[i]]));
+          }
+      }
+      return targets;
+  };
+
+  ChartInternal.prototype.categoryName = function (i) {
+      var config = this.config;
+      return i < config.axis_x_categories.length ? config.axis_x_categories[i] : i;
+  };
+
+  ChartInternal.prototype.generateTargetClass = function (targetId) {
+      return targetId || targetId === 0 ? ('-' + targetId).replace(/\s/g, '-') : '';
+  };
+  ChartInternal.prototype.generateClass = function (prefix, targetId) {
+      return ' ' + prefix + ' ' + prefix + this.generateTargetClass(targetId);
+  };
+  ChartInternal.prototype.classText = function (d) {
+      return this.generateClass(CLASS.text, d.index);
+  };
+  ChartInternal.prototype.classTexts = function (d) {
+      return this.generateClass(CLASS.texts, d.id);
+  };
+  ChartInternal.prototype.classShape = function (d) {
+      return this.generateClass(CLASS.shape, d.index);
+  };
+  ChartInternal.prototype.classShapes = function (d) {
+      return this.generateClass(CLASS.shapes, d.id);
+  };
+  ChartInternal.prototype.classLine = function (d) {
+      return this.classShape(d) + this.generateClass(CLASS.line, d.id);
+  };
+  ChartInternal.prototype.classLines = function (d) {
+      return this.classShapes(d) + this.generateClass(CLASS.lines, d.id);
+  };
+  ChartInternal.prototype.classCircle = function (d) {
+      return this.classShape(d) + this.generateClass(CLASS.circle, d.index);
+  };
+  ChartInternal.prototype.classCircles = function (d) {
+      return this.classShapes(d) + this.generateClass(CLASS.circles, d.id);
+  };
+  ChartInternal.prototype.classBar = function (d) {
+      return this.classShape(d) + this.generateClass(CLASS.bar, d.index);
+  };
+  ChartInternal.prototype.classBars = function (d) {
+      return this.classShapes(d) + this.generateClass(CLASS.bars, d.id);
+  };
+  ChartInternal.prototype.classArc = function (d) {
+      return this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id);
+  };
+  ChartInternal.prototype.classArcs = function (d) {
+      return this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id);
+  };
+  ChartInternal.prototype.classArea = function (d) {
+      return this.classShape(d) + this.generateClass(CLASS.area, d.id);
+  };
+  ChartInternal.prototype.classAreas = function (d) {
+      return this.classShapes(d) + this.generateClass(CLASS.areas, d.id);
+  };
+  ChartInternal.prototype.classRegion = function (d, i) {
+      return (this.generateClass(CLASS.region, i) + ' ' + ('class' in d ? d['class'] : ''));
+  };
+  ChartInternal.prototype.classEvent = function (d) {
+      return this.generateClass(CLASS.eventRect, d.index);
+  };
+  ChartInternal.prototype.classTarget = function (id) {
+      var $$ = this;
+      var additionalClassSuffix = $$.config.data_classes[id], additionalClass = '';
+      if (additionalClassSuffix) {
+          additionalClass = ' ' + CLASS.target + '-' + additionalClassSuffix;
+      }
+      return $$.generateClass(CLASS.target, id) + additionalClass;
+  };
+  ChartInternal.prototype.classFocus = function (d) {
+      return this.classFocused(d) + this.classDefocused(d);
+  };
+  ChartInternal.prototype.classFocused = function (d) {
+      return ' ' + (this.focusedTargetIds.indexOf(d.id) >= 0 ? CLASS.focused : '');
+  };
+  ChartInternal.prototype.classDefocused = function (d) {
+      return (' ' + (this.defocusedTargetIds.indexOf(d.id) >= 0 ? CLASS.defocused : ''));
+  };
+  ChartInternal.prototype.classChartText = function (d) {
+      return CLASS.chartText + this.classTarget(d.id);
+  };
+  ChartInternal.prototype.classChartLine = function (d) {
+      return CLASS.chartLine + this.classTarget(d.id);
+  };
+  ChartInternal.prototype.classChartBar = function (d) {
+      return CLASS.chartBar + this.classTarget(d.id);
+  };
+  ChartInternal.prototype.classChartArc = function (d) {
+      return CLASS.chartArc + this.classTarget(d.data.id);
+  };
+  ChartInternal.prototype.getTargetSelectorSuffix = function (targetId) {
+      var targetClass = this.generateTargetClass(targetId);
+      if (window.CSS && window.CSS.escape) {
+          return window.CSS.escape(targetClass);
+      }
+      // fallback on imperfect method for old browsers (does not handles unicode)
+      return targetClass.replace(/([?!@#$%^&*()=+,.<>'":;\[\]\/|~`{}\\])/g, '\\$1');
+  };
+  ChartInternal.prototype.selectorTarget = function (id, prefix) {
+      return (prefix || '') + '.' + CLASS.target + this.getTargetSelectorSuffix(id);
+  };
+  ChartInternal.prototype.selectorTargets = function (ids, prefix) {
+      var $$ = this;
+      ids = ids || [];
+      return ids.length
+          ? ids.map(function (id) {
+              return $$.selectorTarget(id, prefix);
+          })
+          : null;
+  };
+  ChartInternal.prototype.selectorLegend = function (id) {
+      return '.' + CLASS.legendItem + this.getTargetSelectorSuffix(id);
+  };
+  ChartInternal.prototype.selectorLegends = function (ids) {
+      var $$ = this;
+      return ids && ids.length
+          ? ids.map(function (id) {
+              return $$.selectorLegend(id);
+          })
+          : null;
+  };
+
+  ChartInternal.prototype.getClipPath = function (id) {
+      return 'url(' + (isIE(9) ? '' : document.URL.split('#')[0]) + '#' + id + ')';
+  };
+  ChartInternal.prototype.appendClip = function (parent, id) {
+      return parent
+          .append('clipPath')
+          .attr('id', id)
+          .append('rect');
+  };
+  ChartInternal.prototype.getAxisClipX = function (forHorizontal) {
+      // axis line width + padding for left
+      var left = Math.max(30, this.margin.left);
+      return forHorizontal ? -(1 + left) : -(left - 1);
+  };
+  ChartInternal.prototype.getAxisClipY = function (forHorizontal) {
+      return forHorizontal ? -20 : -this.margin.top;
+  };
+  ChartInternal.prototype.getXAxisClipX = function () {
+      var $$ = this;
+      return $$.getAxisClipX(!$$.config.axis_rotated);
+  };
+  ChartInternal.prototype.getXAxisClipY = function () {
+      var $$ = this;
+      return $$.getAxisClipY(!$$.config.axis_rotated);
+  };
+  ChartInternal.prototype.getYAxisClipX = function () {
+      var $$ = this;
+      return $$.config.axis_y_inner ? -1 : $$.getAxisClipX($$.config.axis_rotated);
+  };
+  ChartInternal.prototype.getYAxisClipY = function () {
+      var $$ = this;
+      return $$.getAxisClipY($$.config.axis_rotated);
+  };
+  ChartInternal.prototype.getAxisClipWidth = function (forHorizontal) {
+      var $$ = this, left = Math.max(30, $$.margin.left), right = Math.max(30, $$.margin.right);
+      // width + axis line width + padding for left/right
+      return forHorizontal ? $$.width + 2 + left + right : $$.margin.left + 20;
+  };
+  ChartInternal.prototype.getAxisClipHeight = function (forHorizontal) {
+      // less than 20 is not enough to show the axis label 'outer' without legend
+      return ((forHorizontal ? this.margin.bottom : this.margin.top + this.height) + 20);
+  };
+  ChartInternal.prototype.getXAxisClipWidth = function () {
+      var $$ = this;
+      return $$.getAxisClipWidth(!$$.config.axis_rotated);
+  };
+  ChartInternal.prototype.getXAxisClipHeight = function () {
+      var $$ = this;
+      return $$.getAxisClipHeight(!$$.config.axis_rotated);
+  };
+  ChartInternal.prototype.getYAxisClipWidth = function () {
+      var $$ = this;
+      return ($$.getAxisClipWidth($$.config.axis_rotated) +
+          ($$.config.axis_y_inner ? 20 : 0));
+  };
+  ChartInternal.prototype.getYAxisClipHeight = function () {
+      var $$ = this;
+      return $$.getAxisClipHeight($$.config.axis_rotated);
+  };
+
+  ChartInternal.prototype.generateColor = function () {
+      var $$ = this, config = $$.config, d3 = $$.d3, colors = config.data_colors, pattern = notEmpty(config.color_pattern)
+          ? config.color_pattern
+          : d3.schemeCategory10, callback = config.data_color, ids = [];
+      return function (d) {
+          var id = d.id || (d.data && d.data.id) || d, color;
+          // if callback function is provided
+          if (colors[id] instanceof Function) {
+              color = colors[id](d);
+          }
+          // if specified, choose that color
+          else if (colors[id]) {
+              color = colors[id];
+          }
+          // if not specified, choose from pattern
+          else {
+              if (ids.indexOf(id) < 0) {
+                  ids.push(id);
+              }
+              color = pattern[ids.indexOf(id) % pattern.length];
+              colors[id] = color;
+          }
+          return callback instanceof Function ? callback(color, d) : color;
+      };
+  };
+  ChartInternal.prototype.generateLevelColor = function () {
+      var $$ = this, config = $$.config, colors = config.color_pattern, threshold = config.color_threshold, asValue = threshold.unit === 'value', values = threshold.values && threshold.values.length ? threshold.values : [], max = threshold.max || 100;
+      return notEmpty(threshold) && notEmpty(colors)
+          ? function (value) {
+              var i, v, color = colors[colors.length - 1];
+              for (i = 0; i < values.length; i++) {
+                  v = asValue ? value : (value * 100) / max;
+                  if (v < values[i]) {
+                      color = colors[i];
+                      break;
+                  }
+              }
+              return color;
+          }
+          : null;
+  };
+
+  ChartInternal.prototype.getDefaultConfig = function () {
+      var config = {
+          bindto: '#chart',
+          svg_classname: undefined,
+          size_width: undefined,
+          size_height: undefined,
+          padding_left: undefined,
+          padding_right: undefined,
+          padding_top: undefined,
+          padding_bottom: undefined,
+          resize_auto: true,
+          zoom_enabled: false,
+          zoom_initialRange: undefined,
+          zoom_type: 'scroll',
+          zoom_disableDefaultBehavior: false,
+          zoom_privileged: false,
+          zoom_rescale: false,
+          zoom_onzoom: function () { },
+          zoom_onzoomstart: function () { },
+          zoom_onzoomend: function () { },
+          zoom_x_min: undefined,
+          zoom_x_max: undefined,
+          interaction_brighten: true,
+          interaction_enabled: true,
+          onmouseover: function () { },
+          onmouseout: function () { },
+          onresize: function () { },
+          onresized: function () { },
+          oninit: function () { },
+          onrendered: function () { },
+          transition_duration: 350,
+          data_epochs: 'epochs',
+          data_x: undefined,
+          data_xs: {},
+          data_xFormat: '%Y-%m-%d',
+          data_xLocaltime: true,
+          data_xSort: true,
+          data_idConverter: function (id) {
+              return id;
+          },
+          data_names: {},
+          data_classes: {},
+          data_groups: [],
+          data_axes: {},
+          data_type: undefined,
+          data_types: {},
+          data_labels: {},
+          data_order: 'desc',
+          data_regions: {},
+          data_color: undefined,
+          data_colors: {},
+          data_hide: false,
+          data_filter: undefined,
+          data_selection_enabled: false,
+          data_selection_grouped: false,
+          data_selection_isselectable: function () {
+              return true;
+          },
+          data_selection_multiple: true,
+          data_selection_draggable: false,
+          data_stack_normalize: false,
+          data_onclick: function () { },
+          data_onmouseover: function () { },
+          data_onmouseout: function () { },
+          data_onselected: function () { },
+          data_onunselected: function () { },
+          data_url: undefined,
+          data_headers: undefined,
+          data_json: undefined,
+          data_rows: undefined,
+          data_columns: undefined,
+          data_mimeType: undefined,
+          data_keys: undefined,
+          // configuration for no plot-able data supplied.
+          data_empty_label_text: '',
+          // subchart
+          subchart_show: false,
+          subchart_size_height: 60,
+          subchart_axis_x_show: true,
+          subchart_onbrush: function () { },
+          // color
+          color_pattern: [],
+          color_threshold: {},
+          // legend
+          legend_show: true,
+          legend_hide: false,
+          legend_position: 'bottom',
+          legend_inset_anchor: 'top-left',
+          legend_inset_x: 10,
+          legend_inset_y: 0,
+          legend_inset_step: undefined,
+          legend_item_onclick: undefined,
+          legend_item_onmouseover: undefined,
+          legend_item_onmouseout: undefined,
+          legend_equally: false,
+          legend_padding: 0,
+          legend_item_tile_width: 10,
+          legend_item_tile_height: 10,
+          // axis
+          axis_rotated: false,
+          axis_x_show: true,
+          axis_x_type: 'indexed',
+          axis_x_localtime: true,
+          axis_x_categories: [],
+          axis_x_tick_centered: false,
+          axis_x_tick_format: undefined,
+          axis_x_tick_culling: {},
+          axis_x_tick_culling_max: 10,
+          axis_x_tick_count: undefined,
+          axis_x_tick_fit: true,
+          axis_x_tick_values: null,
+          axis_x_tick_rotate: 0,
+          axis_x_tick_outer: true,
+          axis_x_tick_multiline: true,
+          axis_x_tick_multilineMax: 0,
+          axis_x_tick_width: null,
+          axis_x_max: undefined,
+          axis_x_min: undefined,
+          axis_x_padding: {},
+          axis_x_height: undefined,
+          axis_x_selection: undefined,
+          axis_x_label: {},
+          axis_x_inner: undefined,
+          axis_y_show: true,
+          axis_y_type: 'linear',
+          axis_y_max: undefined,
+          axis_y_min: undefined,
+          axis_y_inverted: false,
+          axis_y_center: undefined,
+          axis_y_inner: undefined,
+          axis_y_label: {},
+          axis_y_tick_format: undefined,
+          axis_y_tick_outer: true,
+          axis_y_tick_values: null,
+          axis_y_tick_rotate: 0,
+          axis_y_tick_count: undefined,
+          axis_y_tick_time_type: undefined,
+          axis_y_tick_time_interval: undefined,
+          axis_y_padding: {},
+          axis_y_default: undefined,
+          axis_y2_show: false,
+          axis_y2_type: 'linear',
+          axis_y2_max: undefined,
+          axis_y2_min: undefined,
+          axis_y2_inverted: false,
+          axis_y2_center: undefined,
+          axis_y2_inner: undefined,
+          axis_y2_label: {},
+          axis_y2_tick_format: undefined,
+          axis_y2_tick_outer: true,
+          axis_y2_tick_values: null,
+          axis_y2_tick_count: undefined,
+          axis_y2_padding: {},
+          axis_y2_default: undefined,
+          // grid
+          grid_x_show: false,
+          grid_x_type: 'tick',
+          grid_x_lines: [],
+          grid_y_show: false,
+          // not used
+          // grid_y_type: 'tick',
+          grid_y_lines: [],
+          grid_y_ticks: 10,
+          grid_focus_show: true,
+          grid_lines_front: true,
+          // point - point of each data
+          point_show: true,
+          point_r: 2.5,
+          point_sensitivity: 10,
+          point_focus_expand_enabled: true,
+          point_focus_expand_r: undefined,
+          point_select_r: undefined,
+          // line
+          line_connectNull: false,
+          line_step_type: 'step',
+          // bar
+          bar_width: undefined,
+          bar_width_ratio: 0.6,
+          bar_width_max: undefined,
+          bar_zerobased: true,
+          bar_space: 0,
+          // area
+          area_zerobased: true,
+          area_above: false,
+          // pie
+          pie_label_show: true,
+          pie_label_format: undefined,
+          pie_label_threshold: 0.05,
+          pie_label_ratio: undefined,
+          pie_expand: {},
+          pie_expand_duration: 50,
+          pie_padAngle: 0,
+          // gauge
+          gauge_fullCircle: false,
+          gauge_label_show: true,
+          gauge_labelLine_show: true,
+          gauge_label_format: undefined,
+          gauge_min: 0,
+          gauge_max: 100,
+          gauge_startingAngle: (-1 * Math.PI) / 2,
+          gauge_label_extents: undefined,
+          gauge_units: undefined,
+          gauge_width: undefined,
+          gauge_arcs_minWidth: 5,
+          gauge_expand: {},
+          gauge_expand_duration: 50,
+          // donut
+          donut_label_show: true,
+          donut_label_format: undefined,
+          donut_label_threshold: 0.05,
+          donut_label_ratio: undefined,
+          donut_width: undefined,
+          donut_title: '',
+          donut_expand: {},
+          donut_expand_duration: 50,
+          donut_padAngle: 0,
+          // spline
+          spline_interpolation_type: 'cardinal',
+          // stanford
+          stanford_lines: [],
+          stanford_regions: [],
+          stanford_texts: [],
+          stanford_scaleMin: undefined,
+          stanford_scaleMax: undefined,
+          stanford_scaleWidth: undefined,
+          stanford_scaleFormat: undefined,
+          stanford_scaleValues: undefined,
+          stanford_colors: undefined,
+          stanford_padding: {
+              top: 0,
+              right: 0,
+              bottom: 0,
+              left: 0
+          },
+          // region - region to change style
+          regions: [],
+          // tooltip - show when mouseover on each data
+          tooltip_show: true,
+          tooltip_grouped: true,
+          tooltip_order: undefined,
+          tooltip_format_title: undefined,
+          tooltip_format_name: undefined,
+          tooltip_format_value: undefined,
+          tooltip_horizontal: undefined,
+          tooltip_position: undefined,
+          tooltip_contents: function (d, defaultTitleFormat, defaultValueFormat, color) {
+              return this.getTooltipContent
+                  ? this.getTooltipContent(d, defaultTitleFormat, defaultValueFormat, color)
+                  : '';
+          },
+          tooltip_init_show: false,
+          tooltip_init_x: 0,
+          tooltip_init_position: { top: '0px', left: '50px' },
+          tooltip_onshow: function () { },
+          tooltip_onhide: function () { },
+          // title
+          title_text: undefined,
+          title_padding: {
+              top: 0,
+              right: 0,
+              bottom: 0,
+              left: 0
+          },
+          title_position: 'top-center'
+      };
+      Object.keys(this.additionalConfig).forEach(function (key) {
+          config[key] = this.additionalConfig[key];
+      }, this);
+      return config;
+  };
+  ChartInternal.prototype.additionalConfig = {};
+  ChartInternal.prototype.loadConfig = function (config) {
+      var this_config = this.config, target, keys, read;
+      function find() {
+          var key = keys.shift();
+          //        console.log("key =>", key, ", target =>", target);
+          if (key && target && typeof target === 'object' && key in target) {
+              target = target[key];
+              return find();
+          }
+          else if (!key) {
+              return target;
+          }
+          else {
+              return undefined;
+          }
+      }
+      Object.keys(this_config).forEach(function (key) {
+          target = config;
+          keys = key.split('_');
+          read = find();
+          //        console.log("CONFIG : ", key, read);
+          if (isDefined(read)) {
+              this_config[key] = read;
+          }
+      });
+  };
+
+  ChartInternal.prototype.convertUrlToData = function (url, mimeType, headers, keys, done) {
+      var $$ = this, type = mimeType ? mimeType : 'csv', f, converter;
+      if (type === 'json') {
+          f = $$.d3.json;
+          converter = $$.convertJsonToData;
+      }
+      else if (type === 'tsv') {
+          f = $$.d3.tsv;
+          converter = $$.convertXsvToData;
+      }
+      else {
+          f = $$.d3.csv;
+          converter = $$.convertXsvToData;
+      }
+      f(url, headers)
+          .then(function (data) {
+          done.call($$, converter.call($$, data, keys));
+      })
+          .catch(function (error) {
+          throw error;
+      });
+  };
+  ChartInternal.prototype.convertXsvToData = function (xsv) {
+      var keys = xsv.columns, rows = xsv;
+      if (rows.length === 0) {
+          return {
+              keys: keys,
+              rows: [keys.reduce(function (row, key) {
+                      var _a;
+                      return Object.assign(row, (_a = {}, _a[key] = null, _a));
+                  }, {})]
+          };
+      }
+      else {
+          // [].concat() is to convert result into a plain array otherwise
+          // test is not happy because rows have properties.
+          return { keys: keys, rows: [].concat(xsv) };
+      }
+  };
+  ChartInternal.prototype.convertJsonToData = function (json, keys) {
+      var $$ = this, new_rows = [], targetKeys, data;
+      if (keys) {
+          // when keys specified, json would be an array that includes objects
+          if (keys.x) {
+              targetKeys = keys.value.concat(keys.x);
+              $$.config.data_x = keys.x;
+          }
+          else {
+              targetKeys = keys.value;
+          }
+          new_rows.push(targetKeys);
+          json.forEach(function (o) {
+              var new_row = [];
+              targetKeys.forEach(function (key) {
+                  // convert undefined to null because undefined data will be removed in convertDataToTargets()
+                  var v = $$.findValueInJson(o, key);
+                  if (isUndefined(v)) {
+                      v = null;
+                  }
+                  new_row.push(v);
+              });
+              new_rows.push(new_row);
+          });
+          data = $$.convertRowsToData(new_rows);
+      }
+      else {
+          Object.keys(json).forEach(function (key) {
+              new_rows.push([key].concat(json[key]));
+          });
+          data = $$.convertColumnsToData(new_rows);
+      }
+      return data;
+  };
+  /**
+   * Finds value from the given nested object by the given path.
+   * If it's not found, then this returns undefined.
+   * @param {Object} object the object
+   * @param {string} path the path
+   */
+  ChartInternal.prototype.findValueInJson = function (object, path) {
+      if (path in object) {
+          // If object has a key that contains . or [], return the key's value
+          // instead of searching for an inner object.
+          // See https://github.com/c3js/c3/issues/1691 for details.
+          return object[path];
+      }
+      path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties (replace [] with .)
+      path = path.replace(/^\./, ''); // strip a leading dot
+      var pathArray = path.split('.');
+      for (var i = 0; i < pathArray.length; ++i) {
+          var k = pathArray[i];
+          if (k in object) {
+              object = object[k];
+          }
+          else {
+              return;
+          }
+      }
+      return object;
+  };
+  /**
+   * Converts the rows to normalized data.
+   * @param {any[][]} rows The row data
+   * @return {Object}
+   */
+  ChartInternal.prototype.convertRowsToData = function (rows) {
+      var newRows = [];
+      var keys = rows[0];
+      for (var i = 1; i < rows.length; i++) {
+          var newRow = {};
+          for (var j = 0; j < rows[i].length; j++) {
+              if (isUndefined(rows[i][j])) {
+                  throw new Error('Source data is missing a component at (' + i + ',' + j + ')!');
+              }
+              newRow[keys[j]] = rows[i][j];
+          }
+          newRows.push(newRow);
+      }
+      return { keys: keys, rows: newRows };
+  };
+  /**
+   * Converts the columns to normalized data.
+   * @param {any[][]} columns The column data
+   * @return {Object}
+   */
+  ChartInternal.prototype.convertColumnsToData = function (columns) {
+      var newRows = [];
+      var keys = [];
+      for (var i = 0; i < columns.length; i++) {
+          var key = columns[i][0];
+          for (var j = 1; j < columns[i].length; j++) {
+              if (isUndefined(newRows[j - 1])) {
+                  newRows[j - 1] = {};
+              }
+              if (isUndefined(columns[i][j])) {
+                  throw new Error('Source data is missing a component at (' + i + ',' + j + ')!');
+              }
+              newRows[j - 1][key] = columns[i][j];
+          }
+          keys.push(key);
+      }
+      return { keys: keys, rows: newRows };
+  };
+  /**
+   * Converts the data format into the target format.
+   * @param {!Object} data
+   * @param {!Array} data.keys Ordered list of target IDs.
+   * @param {!Array} data.rows Rows of data to convert.
+   * @param {boolean} appendXs True to append to $$.data.xs, False to replace.
+   * @return {!Array}
+   */
+  ChartInternal.prototype.convertDataToTargets = function (data, appendXs) {
+      var $$ = this, config = $$.config, targets, ids, xs, keys, epochs;
+      // handles format where keys are not orderly provided
+      if (isArray(data)) {
+          keys = Object.keys(data[0]);
+      }
+      else {
+          keys = data.keys;
+          data = data.rows;
+      }
+      xs = keys.filter($$.isX, $$);
+      if (!$$.isStanfordGraphType()) {
+          ids = keys.filter($$.isNotX, $$);
+      }
+      else {
+          epochs = keys.filter($$.isEpochs, $$);
+          ids = keys.filter($$.isNotXAndNotEpochs, $$);
+          if (xs.length !== 1 || epochs.length !== 1 || ids.length !== 1) {
+              throw new Error("You must define the 'x' key name and the 'epochs' for Stanford Diagrams");
+          }
+      }
+      // save x for update data by load when custom x and c3.x API
+      ids.forEach(function (id) {
+          var xKey = $$.getXKey(id);
+          if ($$.isCustomX() || $$.isTimeSeries()) {
+              // if included in input data
+              if (xs.indexOf(xKey) >= 0) {
+                  $$.data.xs[id] = (appendXs && $$.data.xs[id]
+                      ? $$.data.xs[id]
+                      : []).concat(data
+                      .map(function (d) {
+                      return d[xKey];
+                  })
+                      .filter(isValue)
+                      .map(function (rawX, i) {
+                      return $$.generateTargetX(rawX, id, i);
+                  }));
+              }
+              // if not included in input data, find from preloaded data of other id's x
+              else if (config.data_x) {
+                  $$.data.xs[id] = $$.getOtherTargetXs();
+              }
+              // if not included in input data, find from preloaded data
+              else if (notEmpty(config.data_xs)) {
+                  $$.data.xs[id] = $$.getXValuesOfXKey(xKey, $$.data.targets);
+              }
+              // MEMO: if no x included, use same x of current will be used
+          }
+          else {
+              $$.data.xs[id] = data.map(function (d, i) {
+                  return i;
+              });
+          }
+      });
+      // check x is defined
+      ids.forEach(function (id) {
+          if (!$$.data.xs[id]) {
+              throw new Error('x is not defined for id = "' + id + '".');
+          }
+      });
+      // convert to target
+      targets = ids.map(function (id, index) {
+          var convertedId = config.data_idConverter(id);
+          return {
+              id: convertedId,
+              id_org: id,
+              values: data
+                  .map(function (d, i) {
+                  var xKey = $$.getXKey(id), rawX = d[xKey], value = d[id] !== null && !isNaN(d[id]) ? +d[id] : null, x, returnData;
+                  // use x as categories if custom x and categorized
+                  if ($$.isCustomX() && $$.isCategorized() && !isUndefined(rawX)) {
+                      if (index === 0 && i === 0) {
+                          config.axis_x_categories = [];
+                      }
+                      x = config.axis_x_categories.indexOf(rawX);
+                      if (x === -1) {
+                          x = config.axis_x_categories.length;
+                          config.axis_x_categories.push(rawX);
+                      }
+                  }
+                  else {
+                      x = $$.generateTargetX(rawX, id, i);
+                  }
+                  // mark as x = undefined if value is undefined and filter to remove after mapped
+                  if (isUndefined(d[id]) || $$.data.xs[id].length <= i) {
+                      x = undefined;
+                  }
+                  returnData = { x: x, value: value, id: convertedId };
+                  if ($$.isStanfordGraphType()) {
+                      returnData.epochs = d[epochs];
+                  }
+                  return returnData;
+              })
+                  .filter(function (v) {
+                  return isDefined(v.x);
+              })
+          };
+      });
+      // finish targets
+      targets.forEach(function (t) {
+          var i;
+          // sort values by its x
+          if (config.data_xSort) {
+              t.values = t.values.sort(function (v1, v2) {
+                  var x1 = v1.x || v1.x === 0 ? v1.x : Infinity, x2 = v2.x || v2.x === 0 ? v2.x : Infinity;
+                  return x1 - x2;
+              });
+          }
+          // indexing each value
+          i = 0;
+          t.values.forEach(function (v) {
+              v.index = i++;
+          });
+          // this needs to be sorted because its index and value.index is identical
+          $$.data.xs[t.id].sort(function (v1, v2) {
+              return v1 - v2;
+          });
+      });
+      // cache information about values
+      $$.hasNegativeValue = $$.hasNegativeValueInTargets(targets);
+      $$.hasPositiveValue = $$.hasPositiveValueInTargets(targets);
+      // set target types
+      if (config.data_type) {
+          $$.setTargetType($$.mapToIds(targets).filter(function (id) {
+              return !(id in config.data_types);
+          }), config.data_type);
+      }
+      // cache as original id keyed
+      targets.forEach(function (d) {
+          $$.addCache(d.id_org, d);
+      });
+      return targets;
+  };
+
+  ChartInternal.prototype.isEpochs = function (key) {
+      var $$ = this, config = $$.config;
+      return config.data_epochs && key === config.data_epochs;
+  };
+  ChartInternal.prototype.isX = function (key) {
+      var $$ = this, config = $$.config;
+      return ((config.data_x && key === config.data_x) ||
+          (notEmpty(config.data_xs) && hasValue(config.data_xs, key)));
+  };
+  ChartInternal.prototype.isNotX = function (key) {
+      return !this.isX(key);
+  };
+  ChartInternal.prototype.isNotXAndNotEpochs = function (key) {
+      return !this.isX(key) && !this.isEpochs(key);
+  };
+  /**
+   * Returns whether the normalized stack option is enabled or not.
+   *
+   * To be enabled it must also have data.groups defined.
+   *
+   * @return {boolean}
+   */
+  ChartInternal.prototype.isStackNormalized = function () {
+      return this.config.data_stack_normalize && this.config.data_groups.length > 0;
+  };
+  /**
+   * Returns whether the axis is normalized or not.
+   *
+   * An axis is normalized as long as one of its associated target
+   * is normalized.
+   *
+   * @param axisId Axis ID (y or y2)
+   * @return {Boolean}
+   */
+  ChartInternal.prototype.isAxisNormalized = function (axisId) {
+      var $$ = this;
+      if (!$$.isStackNormalized()) {
+          // shortcut
+          return false;
+      }
+      return $$.data.targets
+          .filter(function (target) { return $$.axis.getId(target.id) === axisId; })
+          .some(function (target) { return $$.isTargetNormalized(target.id); });
+  };
+  /**
+   * Returns whether the values for this target ID is normalized or not.
+   *
+   * To be normalized the option needs to be enabled and target needs
+   * to be defined in `data.groups`.
+   *
+   * @param targetId ID of the target
+   * @return {Boolean} True if the target is normalized, false otherwise.
+   */
+  ChartInternal.prototype.isTargetNormalized = function (targetId) {
+      var $$ = this;
+      return ($$.isStackNormalized() &&
+          $$.config.data_groups.some(function (group) { return group.includes(targetId); }));
+  };
+  ChartInternal.prototype.getXKey = function (id) {
+      var $$ = this, config = $$.config;
+      return config.data_x
+          ? config.data_x
+          : notEmpty(config.data_xs)
+              ? config.data_xs[id]
+              : null;
+  };
+  /**
+   * Get sum of visible data per index for given axis.
+   *
+   * Expect axisId to be either 'y' or 'y2'.
+   *
+   * @private
+   * @param axisId Compute sum for data associated to given axis.
+   * @return {Array}
+   */
+  ChartInternal.prototype.getTotalPerIndex = function (axisId) {
+      var $$ = this;
+      if (!$$.isStackNormalized()) {
+          return null;
+      }
+      var cached = $$.getFromCache('getTotalPerIndex');
+      if (cached !== undefined) {
+          return cached[axisId];
+      }
+      var sum = { y: [], y2: [] };
+      $$.data.targets
+          // keep only target that are normalized
+          .filter(function (target) { return $$.isTargetNormalized(target.id); })
+          // keep only target that are visible
+          .filter(function (target) { return $$.isTargetToShow(target.id); })
+          // compute sum per axis
+          .forEach(function (target) {
+          var sumByAxis = sum[$$.axis.getId(target.id)];
+          target.values.forEach(function (v, i) {
+              if (!sumByAxis[i]) {
+                  sumByAxis[i] = 0;
+              }
+              sumByAxis[i] += isNumber(v.value) ? v.value : 0;
+          });
+      });
+      $$.addToCache('getTotalPerIndex', sum);
+      return sum[axisId];
+  };
+  /**
+   * Get sum of visible data.
+   *
+   * Should be used for normalised data only since all values
+   * are expected to be positive.
+   *
+   * @private
+   * @return {Number}
+   */
+  ChartInternal.prototype.getTotalDataSum = function () {
+      var $$ = this;
+      var cached = $$.getFromCache('getTotalDataSum');
+      if (cached !== undefined) {
+          return cached;
+      }
+      var totalDataSum = flattenArray($$.data.targets
+          .filter(function (target) { return $$.isTargetToShow(target.id); })
+          .map(function (target) { return target.values; }))
+          .map(function (d) { return d.value; })
+          .reduce(function (p, c) { return p + c; }, 0);
+      $$.addToCache('getTotalDataSum', totalDataSum);
+      return totalDataSum;
+  };
+  ChartInternal.prototype.getXValuesOfXKey = function (key, targets) {
+      var $$ = this, xValues, ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : [];
+      ids.forEach(function (id) {
+          if ($$.getXKey(id) === key) {
+              xValues = $$.data.xs[id];
+          }
+      });
+      return xValues;
+  };
+  ChartInternal.prototype.getXValue = function (id, i) {
+      var $$ = this;
+      return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i])
+          ? $$.data.xs[id][i]
+          : i;
+  };
+  ChartInternal.prototype.getOtherTargetXs = function () {
+      var $$ = this, idsForX = Object.keys($$.data.xs);
+      return idsForX.length ? $$.data.xs[idsForX[0]] : null;
+  };
+  ChartInternal.prototype.getOtherTargetX = function (index) {
+      var xs = this.getOtherTargetXs();
+      return xs && index < xs.length ? xs[index] : null;
+  };
+  ChartInternal.prototype.addXs = function (xs) {
+      var $$ = this;
+      Object.keys(xs).forEach(function (id) {
+          $$.config.data_xs[id] = xs[id];
+      });
+  };
+  ChartInternal.prototype.addName = function (data) {
+      var $$ = this, name;
+      if (data) {
+          name = $$.config.data_names[data.id];
+          data.name = name !== undefined ? name : data.id;
+      }
+      return data;
+  };
+  ChartInternal.prototype.getValueOnIndex = function (values, index) {
+      var valueOnIndex = values.filter(function (v) {
+          return v.index === index;
+      });
+      return valueOnIndex.length ? valueOnIndex[0] : null;
+  };
+  ChartInternal.prototype.updateTargetX = function (targets, x) {
+      var $$ = this;
+      targets.forEach(function (t) {
+          t.values.forEach(function (v, i) {
+              v.x = $$.generateTargetX(x[i], t.id, i);
+          });
+          $$.data.xs[t.id] = x;
+      });
+  };
+  ChartInternal.prototype.updateTargetXs = function (targets, xs) {
+      var $$ = this;
+      targets.forEach(function (t) {
+          if (xs[t.id]) {
+              $$.updateTargetX([t], xs[t.id]);
+          }
+      });
+  };
+  ChartInternal.prototype.generateTargetX = function (rawX, id, index) {
+      var $$ = this, x;
+      if ($$.isTimeSeries()) {
+          x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index));
+      }
+      else if ($$.isCustomX() && !$$.isCategorized()) {
+          x = isValue(rawX) ? +rawX : $$.getXValue(id, index);
+      }
+      else {
+          x = index;
+      }
+      return x;
+  };
+  ChartInternal.prototype.cloneTarget = function (target) {
+      return {
+          id: target.id,
+          id_org: target.id_org,
+          values: target.values.map(function (d) {
+              return {
+                  x: d.x,
+                  value: d.value,
+                  id: d.id
+              };
+          })
+      };
+  };
+  ChartInternal.prototype.getMaxDataCount = function () {
+      var $$ = this;
+      return $$.d3.max($$.data.targets, function (t) {
+          return t.values.length;
+      });
+  };
+  ChartInternal.prototype.mapToIds = function (targets) {
+      return targets.map(function (d) {
+          return d.id;
+      });
+  };
+  ChartInternal.prototype.mapToTargetIds = function (ids) {
+      var $$ = this;
+      return ids ? [].concat(ids) : $$.mapToIds($$.data.targets);
+  };
+  ChartInternal.prototype.hasTarget = function (targets, id) {
+      var ids = this.mapToIds(targets), i;
+      for (i = 0; i < ids.length; i++) {
+          if (ids[i] === id) {
+              return true;
+          }
+      }
+      return false;
+  };
+  ChartInternal.prototype.isTargetToShow = function (targetId) {
+      return this.hiddenTargetIds.indexOf(targetId) < 0;
+  };
+  ChartInternal.prototype.isLegendToShow = function (targetId) {
+      return this.hiddenLegendIds.indexOf(targetId) < 0;
+  };
+  /**
+   * Returns only visible targets.
+   *
+   * This is the same as calling {@link filterTargetsToShow} on $$.data.targets.
+   *
+   * @return {Array}
+   */
+  ChartInternal.prototype.getTargetsToShow = function () {
+      var $$ = this;
+      return $$.filterTargetsToShow($$.data.targets);
+  };
+  ChartInternal.prototype.filterTargetsToShow = function (targets) {
+      var $$ = this;
+      return targets.filter(function (t) {
+          return $$.isTargetToShow(t.id);
+      });
+  };
+  /**
+   * @return {Array} Returns all the targets attached to the chart, visible or not
+   */
+  ChartInternal.prototype.getTargets = function () {
+      var $$ = this;
+      return $$.data.targets;
+  };
+  ChartInternal.prototype.mapTargetsToUniqueXs = function (targets) {
+      var $$ = this;
+      var xs = $$.d3
+          .set($$.d3.merge(targets.map(function (t) {
+          return t.values.map(function (v) {
+              return +v.x;
+          });
+      })))
+          .values();
+      xs = $$.isTimeSeries()
+          ? xs.map(function (x) {
+              return new Date(+x);
+          })
+          : xs.map(function (x) {
+              return +x;
+          });
+      return xs.sort(function (a, b) {
+          return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
+      });
+  };
+  ChartInternal.prototype.addHiddenTargetIds = function (targetIds) {
+      targetIds = targetIds instanceof Array ? targetIds : new Array(targetIds);
+      for (var i = 0; i < targetIds.length; i++) {
+          if (this.hiddenTargetIds.indexOf(targetIds[i]) < 0) {
+              this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds[i]);
+          }
+      }
+      this.resetCache();
+  };
+  ChartInternal.prototype.removeHiddenTargetIds = function (targetIds) {
+      this.hiddenTargetIds = this.hiddenTargetIds.filter(function (id) {
+          return targetIds.indexOf(id) < 0;
+      });
+      this.resetCache();
+  };
+  ChartInternal.prototype.addHiddenLegendIds = function (targetIds) {
+      targetIds = targetIds instanceof Array ? targetIds : new Array(targetIds);
+      for (var i = 0; i < targetIds.length; i++) {
+          if (this.hiddenLegendIds.indexOf(targetIds[i]) < 0) {
+              this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds[i]);
+          }
+      }
+  };
+  ChartInternal.prototype.removeHiddenLegendIds = function (targetIds) {
+      this.hiddenLegendIds = this.hiddenLegendIds.filter(function (id) {
+          return targetIds.indexOf(id) < 0;
+      });
+  };
+  ChartInternal.prototype.getValuesAsIdKeyed = function (targets) {
+      var ys = {};
+      targets.forEach(function (t) {
+          ys[t.id] = [];
+          t.values.forEach(function (v) {
+              ys[t.id].push(v.value);
+          });
+      });
+      return ys;
+  };
+  ChartInternal.prototype.checkValueInTargets = function (targets, checker) {
+      var ids = Object.keys(targets), i, j, values;
+      for (i = 0; i < ids.length; i++) {
+          values = targets[ids[i]].values;
+          for (j = 0; j < values.length; j++) {
+              if (checker(values[j].value)) {
+                  return true;
+              }
+          }
+      }
+      return false;
+  };
+  ChartInternal.prototype.hasNegativeValueInTargets = function (targets) {
+      return this.checkValueInTargets(targets, function (v) {
+          return v < 0;
+      });
+  };
+  ChartInternal.prototype.hasPositiveValueInTargets = function (targets) {
+      return this.checkValueInTargets(targets, function (v) {
+          return v > 0;
+      });
+  };
+  ChartInternal.prototype.isOrderDesc = function () {
+      var config = this.config;
+      return (typeof config.data_order === 'string' &&
+          config.data_order.toLowerCase() === 'desc');
+  };
+  ChartInternal.prototype.isOrderAsc = function () {
+      var config = this.config;
+      return (typeof config.data_order === 'string' &&
+          config.data_order.toLowerCase() === 'asc');
+  };
+  ChartInternal.prototype.getOrderFunction = function () {
+      var $$ = this, config = $$.config, orderAsc = $$.isOrderAsc(), orderDesc = $$.isOrderDesc();
+      if (orderAsc || orderDesc) {
+          var reducer = function (p, c) {
+              return p + Math.abs(c.value);
+          };
+          return function (t1, t2) {
+              var t1Sum = t1.values.reduce(reducer, 0), t2Sum = t2.values.reduce(reducer, 0);
+              return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum;
+          };
+      }
+      else if (isFunction(config.data_order)) {
+          return config.data_order;
+      }
+      else if (isArray(config.data_order)) {
+          var order = config.data_order;
+          return function (t1, t2) {
+              return order.indexOf(t1.id) - order.indexOf(t2.id);
+          };
+      }
+  };
+  ChartInternal.prototype.orderTargets = function (targets) {
+      var fct = this.getOrderFunction();
+      if (fct) {
+          targets.sort(fct);
+      }
+      return targets;
+  };
+  /**
+   * Returns all the values from the given targets at the given index.
+   *
+   * @param {Array} targets
+   * @param {Number} index
+   * @return {Array}
+   */
+  ChartInternal.prototype.filterByIndex = function (targets, index) {
+      return this.d3.merge(targets.map(function (t) { return t.values.filter(function (v) { return v.index === index; }); }));
+  };
+  ChartInternal.prototype.filterByX = function (targets, x) {
+      return this.d3
+          .merge(targets.map(function (t) {
+          return t.values;
+      }))
+          .filter(function (v) {
+          return v.x - x === 0;
+      });
+  };
+  ChartInternal.prototype.filterRemoveNull = function (data) {
+      return data.filter(function (d) {
+          return isValue(d.value);
+      });
+  };
+  ChartInternal.prototype.filterByXDomain = function (targets, xDomain) {
+      return targets.map(function (t) {
+          return {
+              id: t.id,
+              id_org: t.id_org,
+              values: t.values.filter(function (v) {
+                  return xDomain[0] <= v.x && v.x <= xDomain[1];
+              })
+          };
+      });
+  };
+  ChartInternal.prototype.hasDataLabel = function () {
+      var config = this.config;
+      if (typeof config.data_labels === 'boolean' && config.data_labels) {
+          return true;
+      }
+      else if (typeof config.data_labels === 'object' &&
+          notEmpty(config.data_labels)) {
+          return true;
+      }
+      return false;
+  };
+  ChartInternal.prototype.getDataLabelLength = function (min, max, key) {
+      var $$ = this, lengths = [0, 0], paddingCoef = 1.3;
+      $$.selectChart
+          .select('svg')
+          .selectAll('.dummy')
+          .data([min, max])
+          .enter()
+          .append('text')
+          .text(function (d) {
+          return $$.dataLabelFormat(d.id)(d);
+      })
+          .each(function (d, i) {
+          lengths[i] = getBBox(this)[key] * paddingCoef;
+      })
+          .remove();
+      return lengths;
+  };
+  /**
+   * Returns true if the given data point is not arc type, otherwise false.
+   * @param {Object} d The data point
+   * @return {boolean}
+   */
+  ChartInternal.prototype.isNoneArc = function (d) {
+      return this.hasTarget(this.data.targets, d.id);
+  };
+  /**
+   * Returns true if the given data point is arc type, otherwise false.
+   * @param {Object} d The data point
+   * @return {boolean}
+   */
+  ChartInternal.prototype.isArc = function (d) {
+      return 'data' in d && this.hasTarget(this.data.targets, d.data.id);
+  };
+  /**
+   * Find the closest point from the given pos among the given targets or
+   * undefined if none satisfies conditions.
+   *
+   * @param {Array} targets
+   * @param {Array} pos An [x,y] coordinate
+   * @return {Object|undefined}
+   */
+  ChartInternal.prototype.findClosestFromTargets = function (targets, pos) {
+      var $$ = this;
+      // for each target, find the closest point
+      var candidates = targets
+          .map(function (t) {
+          return $$.findClosest(t.values, pos, $$.config.tooltip_horizontal
+              ? $$.horizontalDistance.bind($$)
+              : $$.dist.bind($$), $$.config.point_sensitivity);
+      })
+          .filter(function (v) { return v; });
+      // returns the closest of candidates
+      if (candidates.length === 0) {
+          return undefined;
+      }
+      else if (candidates.length === 1) {
+          return candidates[0];
+      }
+      else {
+          return $$.findClosest(candidates, pos, $$.dist.bind($$));
+      }
+  };
+  /**
+   * Find the closest point from the x value or undefined if none satisfies conditions.
+   *
+   * @param {Array} targets
+   * @param {Array} x A value on X axis
+   * @return {Object|undefined}
+   */
+  ChartInternal.prototype.findClosestFromTargetsByX = function (targets, x) {
+      var closest;
+      var diff;
+      targets.forEach(function (t) {
+          t.values.forEach(function (d) {
+              var newDiff = Math.abs(x - d.x);
+              if (diff === undefined || newDiff < diff) {
+                  closest = d;
+                  diff = newDiff;
+              }
+          });
+      });
+      return closest;
+  };
+  /**
+   * Using given compute distance method, returns the closest data point from the
+   * given position.
+   *
+   * Giving optionally a minimum distance to satisfy.
+   *
+   * @param {Array} dataPoints List of DataPoints
+   * @param {Array} pos An [x,y] coordinate
+   * @param {Function} computeDist Function to compute distance between 2 points
+   * @param {Number} minDist Minimal distance to satisfy
+   * @return {Object|undefined} Closest data point
+   */
+  ChartInternal.prototype.findClosest = function (dataPoints, pos, computeDist, minDist) {
+      if (minDist === void 0) { minDist = Infinity; }
+      var $$ = this;
+      var closest;
+      // find closest bar
+      dataPoints
+          .filter(function (v) { return v && $$.isBarType(v.id); })
+          .forEach(function (v) {
+          if (!closest) {
+              var shape = $$.main
+                  .select('.' +
+                  CLASS.bars +
+                  $$.getTargetSelectorSuffix(v.id) +
+                  ' .' +
+                  CLASS.bar +
+                  '-' +
+                  v.index)
+                  .node();
+              if ($$.isWithinBar(pos, shape)) {
+                  closest = v;
+              }
+          }
+      });
+      // find closest point from non-bar
+      dataPoints
+          .filter(function (v) { return v && !$$.isBarType(v.id); })
+          .forEach(function (v) {
+          var d = computeDist(v, pos);
+          if (d < minDist) {
+              minDist = d;
+              closest = v;
+          }
+      });
+      return closest;
+  };
+  ChartInternal.prototype.dist = function (data, pos) {
+      var $$ = this, config = $$.config, xIndex = config.axis_rotated ? 1 : 0, yIndex = config.axis_rotated ? 0 : 1, y = $$.circleY(data, data.index), x = $$.x(data.x);
+      return Math.sqrt(Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2));
+  };
+  ChartInternal.prototype.horizontalDistance = function (data, pos) {
+      var $$ = this, config = $$.config, xIndex = config.axis_rotated ? 1 : 0, x = $$.x(data.x);
+      return Math.abs(x - pos[xIndex]);
+  };
+  ChartInternal.prototype.convertValuesToStep = function (values) {
+      var converted = [].concat(values), i;
+      if (!this.isCategorized()) {
+          return values;
+      }
+      for (i = values.length + 1; 0 < i; i--) {
+          converted[i] = converted[i - 1];
+      }
+      converted[0] = {
+          x: converted[0].x - 1,
+          value: converted[0].value,
+          id: converted[0].id
+      };
+      converted[values.length + 1] = {
+          x: converted[values.length].x + 1,
+          value: converted[values.length].value,
+          id: converted[values.length].id
+      };
+      return converted;
+  };
+  /**
+   * Get ratio value
+   *
+   * @param {String} type Ratio for given type
+   * @param {Object} d Data value object
+   * @param {Boolean} asPercent Convert the return as percent or not
+   * @return {Number} Ratio value
+   * @private
+   */
+  ChartInternal.prototype.getRatio = function (type, d, asPercent) {
+      if (asPercent === void 0) { asPercent = false; }
+      var $$ = this;
+      var api = $$.api;
+      var ratio = 0;
+      if (d && api.data.shown.call(api).length) {
+          ratio = d.ratio || d.value;
+          if (type === 'arc') {
+              if ($$.hasType('gauge')) {
+                  ratio =
+                      (d.endAngle - d.startAngle) /
+                          (Math.PI * ($$.config.gauge_fullCircle ? 2 : 1));
+              }
+              else {
+                  var total = $$.getTotalDataSum();
+                  ratio = d.value / total;
+              }
+          }
+          else if (type === 'index') {
+              var total = $$.getTotalPerIndex($$.axis.getId(d.id));
+              d.ratio =
+                  isNumber(d.value) && total && total[d.index] > 0
+                      ? d.value / total[d.index]
+                      : 0;
+              ratio = d.ratio;
+          }
+      }
+      return asPercent && ratio ? ratio * 100 : ratio;
+  };
+  ChartInternal.prototype.updateDataAttributes = function (name, attrs) {
+      var $$ = this, config = $$.config, current = config['data_' + name];
+      if (typeof attrs === 'undefined') {
+          return current;
+      }
+      Object.keys(attrs).forEach(function (id) {
+          current[id] = attrs[id];
+      });
+      $$.redraw({
+          withLegend: true
+      });
+      return current;
+  };
+
+  ChartInternal.prototype.load = function (targets, args) {
+      var $$ = this;
+      if (targets) {
+          // filter loading targets if needed
+          if (args.filter) {
+              targets = targets.filter(args.filter);
+          }
+          // set type if args.types || args.type specified
+          if (args.type || args.types) {
+              targets.forEach(function (t) {
+                  var type = args.types && args.types[t.id] ? args.types[t.id] : args.type;
+                  $$.setTargetType(t.id, type);
+              });
+          }
+          // Update/Add data
+          $$.data.targets.forEach(function (d) {
+              for (var i = 0; i < targets.length; i++) {
+                  if (d.id === targets[i].id) {
+                      d.values = targets[i].values;
+                      targets.splice(i, 1);
+                      break;
+                  }
+              }
+          });
+          $$.data.targets = $$.data.targets.concat(targets); // add remained
+      }
+      // Set targets
+      $$.updateTargets($$.data.targets);
+      // Redraw with new targets
+      $$.redraw({
+          withUpdateOrgXDomain: true,
+          withUpdateXDomain: true,
+          withLegend: true
+      });
+      if (args.done) {
+          args.done();
+      }
+  };
+  ChartInternal.prototype.loadFromArgs = function (args) {
+      var $$ = this;
+      $$.resetCache();
+      if (args.data) {
+          $$.load($$.convertDataToTargets(args.data), args);
+      }
+      else if (args.url) {
+          $$.convertUrlToData(args.url, args.mimeType, args.headers, args.keys, function (data) {
+              $$.load($$.convertDataToTargets(data), args);
+          });
+      }
+      else if (args.json) {
+          $$.load($$.convertDataToTargets($$.convertJsonToData(args.json, args.keys)), args);
+      }
+      else if (args.rows) {
+          $$.load($$.convertDataToTargets($$.convertRowsToData(args.rows)), args);
+      }
+      else if (args.columns) {
+          $$.load($$.convertDataToTargets($$.convertColumnsToData(args.columns)), args);
+      }
+      else {
+          $$.load(null, args);
+      }
+  };
+  ChartInternal.prototype.unload = function (targetIds, done) {
+      var $$ = this;
+      $$.resetCache();
+      if (!done) {
+          done = function () { };
+      }
+      // filter existing target
+      targetIds = targetIds.filter(function (id) {
+          return $$.hasTarget($$.data.targets, id);
+      });
+      // If no target, call done and return
+      if (!targetIds || targetIds.length === 0) {
+          done();
+          return;
+      }
+      $$.svg
+          .selectAll(targetIds.map(function (id) {
+          return $$.selectorTarget(id);
+      }))
+          .transition()
+          .style('opacity', 0)
+          .remove()
+          .call($$.endall, done);
+      targetIds.forEach(function (id) {
+          // Reset fadein for future load
+          $$.withoutFadeIn[id] = false;
+          // Remove target's elements
+          if ($$.legend) {
+              $$.legend
+                  .selectAll('.' + CLASS.legendItem + $$.getTargetSelectorSuffix(id))
+                  .remove();
+          }
+          // Remove target
+          $$.data.targets = $$.data.targets.filter(function (t) {
+              return t.id !== id;
+          });
+      });
+  };
+
+  ChartInternal.prototype.getYDomainMin = function (targets) {
+      var $$ = this, config = $$.config, ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets), j, k, baseId, idsInGroup, id, hasNegativeValue;
+      if (config.data_groups.length > 0) {
+          hasNegativeValue = $$.hasNegativeValueInTargets(targets);
+          for (j = 0; j < config.data_groups.length; j++) {
+              // Determine baseId
+              idsInGroup = config.data_groups[j].filter(function (id) {
+                  return ids.indexOf(id) >= 0;
+              });
+              if (idsInGroup.length === 0) {
+                  continue;
+              }
+              baseId = idsInGroup[0];
+              // Consider negative values
+              if (hasNegativeValue && ys[baseId]) {
+                  ys[baseId].forEach(function (v, i) {
+                      ys[baseId][i] = v < 0 ? v : 0;
+                  });
+              }
+              // Compute min
+              for (k = 1; k < idsInGroup.length; k++) {
+                  id = idsInGroup[k];
+                  if (!ys[id]) {
+                      continue;
+                  }
+                  ys[id].forEach(function (v, i) {
+                      if ($$.axis.getId(id) === $$.axis.getId(baseId) &&
+                          ys[baseId] &&
+                          !(hasNegativeValue && +v > 0)) {
+                          ys[baseId][i] += +v;
+                      }
+                  });
+              }
+          }
+      }
+      return $$.d3.min(Object.keys(ys).map(function (key) {
+          return $$.d3.min(ys[key]);
+      }));
+  };
+  ChartInternal.prototype.getYDomainMax = function (targets) {
+      var $$ = this, config = $$.config, ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets), j, k, baseId, idsInGroup, id, hasPositiveValue;
+      if (config.data_groups.length > 0) {
+          hasPositiveValue = $$.hasPositiveValueInTargets(targets);
+          for (j = 0; j < config.data_groups.length; j++) {
+              // Determine baseId
+              idsInGroup = config.data_groups[j].filter(function (id) {
+                  return ids.indexOf(id) >= 0;
+              });
+              if (idsInGroup.length === 0) {
+                  continue;
+              }
+              baseId = idsInGroup[0];
+              // Consider positive values
+              if (hasPositiveValue && ys[baseId]) {
+                  ys[baseId].forEach(function (v, i) {
+                      ys[baseId][i] = v > 0 ? v : 0;
+                  });
+              }
+              // Compute max
+              for (k = 1; k < idsInGroup.length; k++) {
+                  id = idsInGroup[k];
+                  if (!ys[id]) {
+                      continue;
+                  }
+                  ys[id].forEach(function (v, i) {
+                      if ($$.axis.getId(id) === $$.axis.getId(baseId) &&
+                          ys[baseId] &&
+                          !(hasPositiveValue && +v < 0)) {
+                          ys[baseId][i] += +v;
+                      }
+                  });
+              }
+          }
+      }
+      return $$.d3.max(Object.keys(ys).map(function (key) {
+          return $$.d3.max(ys[key]);
+      }));
+  };
+  ChartInternal.prototype.getYDomain = function (targets, axisId, xDomain) {
+      var $$ = this, config = $$.config;
+      if ($$.isAxisNormalized(axisId)) {
+          return [0, 100];
+      }
+      var targetsByAxisId = targets.filter(function (t) {
+          return $$.axis.getId(t.id) === axisId;
+      }), yTargets = xDomain
+          ? $$.filterByXDomain(targetsByAxisId, xDomain)
+          : targetsByAxisId, yMin = axisId === 'y2' ? config.axis_y2_min : config.axis_y_min, yMax = axisId === 'y2' ? config.axis_y2_max : config.axis_y_max, yDomainMin = $$.getYDomainMin(yTargets), yDomainMax = $$.getYDomainMax(yTargets), domain, domainLength, padding_top, padding_bottom, center = axisId === 'y2' ? config.axis_y2_center : config.axis_y_center, yDomainAbs, lengths, diff, ratio, isAllPositive, isAllNegative, isZeroBased = ($$.hasType('bar', yTargets) && config.bar_zerobased) ||
+          ($$.hasType('area', yTargets) && config.area_zerobased), isInverted = axisId === 'y2' ? config.axis_y2_inverted : config.axis_y_inverted, showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated, showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated;
+      // MEMO: avoid inverting domain unexpectedly
+      yDomainMin = isValue(yMin)
+          ? yMin
+          : isValue(yMax)
+              ? yDomainMin < yMax
+                  ? yDomainMin
+                  : yMax - 10
+              : yDomainMin;
+      yDomainMax = isValue(yMax)
+          ? yMax
+          : isValue(yMin)
+              ? yMin < yDomainMax
+                  ? yDomainMax
+                  : yMin + 10
+              : yDomainMax;
+      if (yTargets.length === 0) {
+          // use current domain if target of axisId is none
+          return axisId === 'y2' ? $$.y2.domain() : $$.y.domain();
+      }
+      if (isNaN(yDomainMin)) {
+          // set minimum to zero when not number
+          yDomainMin = 0;
+      }
+      if (isNaN(yDomainMax)) {
+          // set maximum to have same value as yDomainMin
+          yDomainMax = yDomainMin;
+      }
+      if (yDomainMin === yDomainMax) {
+          yDomainMin < 0 ? (yDomainMax = 0) : (yDomainMin = 0);
+      }
+      isAllPositive = yDomainMin >= 0 && yDomainMax >= 0;
+      isAllNegative = yDomainMin <= 0 && yDomainMax <= 0;
+      // Cancel zerobased if axis_*_min / axis_*_max specified
+      if ((isValue(yMin) && isAllPositive) || (isValue(yMax) && isAllNegative)) {
+          isZeroBased = false;
+      }
+      // Bar/Area chart should be 0-based if all positive|negative
+      if (isZeroBased) {
+          if (isAllPositive) {
+              yDomainMin = 0;
+          }
+          if (isAllNegative) {
+              yDomainMax = 0;
+          }
+      }
+      domainLength = Math.abs(yDomainMax - yDomainMin);
+      padding_top = padding_bottom = domainLength * 0.1;
+      if (typeof center !== 'undefined') {
+          yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax));
+          yDomainMax = center + yDomainAbs;
+          yDomainMin = center - yDomainAbs;
+      }
+      // add padding for data label
+      if (showHorizontalDataLabel) {
+          lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'width');
+          diff = diffDomain($$.y.range());
+          ratio = [lengths[0] / diff, lengths[1] / diff];
+          padding_top += domainLength * (ratio[1] / (1 - ratio[0] - ratio[1]));
+          padding_bottom += domainLength * (ratio[0] / (1 - ratio[0] - ratio[1]));
+      }
+      else if (showVerticalDataLabel) {
+          lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, 'height');
+          var pixelsToAxisPadding = $$.getY(config["axis_" + axisId + "_type"], 
+          // input domain as pixels
+          [0, config.axis_rotated ? $$.width : $$.height], 
+          // output range as axis padding
+          [0, domainLength]);
+          padding_top += pixelsToAxisPadding(lengths[1]);
+          padding_bottom += pixelsToAxisPadding(lengths[0]);
+      }
+      if (axisId === 'y' && notEmpty(config.axis_y_padding)) {
+          padding_top = $$.axis.getPadding(config.axis_y_padding, 'top', padding_top, domainLength);
+          padding_bottom = $$.axis.getPadding(config.axis_y_padding, 'bottom', padding_bottom, domainLength);
+      }
+      if (axisId === 'y2' && notEmpty(config.axis_y2_padding)) {
+          padding_top = $$.axis.getPadding(config.axis_y2_padding, 'top', padding_top, domainLength);
+          padding_bottom = $$.axis.getPadding(config.axis_y2_padding, 'bottom', padding_bottom, domainLength);
+      }
+      // Bar/Area chart should be 0-based if all positive|negative
+      if (isZeroBased) {
+          if (isAllPositive) {
+              padding_bottom = yDomainMin;
+          }
+          if (isAllNegative) {
+              padding_top = -yDomainMax;
+          }
+      }
+      domain = [yDomainMin - padding_bottom, yDomainMax + padding_top];
+      return isInverted ? domain.reverse() : domain;
+  };
+  ChartInternal.prototype.getXDomainMin = function (targets) {
+      var $$ = this, config = $$.config;
+      return isDefined(config.axis_x_min)
+          ? $$.isTimeSeries()
+              ? this.parseDate(config.axis_x_min)
+              : config.axis_x_min
+          : $$.d3.min(targets, function (t) {
+              return $$.d3.min(t.values, function (v) {
+                  return v.x;
+              });
+          });
+  };
+  ChartInternal.prototype.getXDomainMax = function (targets) {
+      var $$ = this, config = $$.config;
+      return isDefined(config.axis_x_max)
+          ? $$.isTimeSeries()
+              ? this.parseDate(config.axis_x_max)
+              : config.axis_x_max
+          : $$.d3.max(targets, function (t) {
+              return $$.d3.max(t.values, function (v) {
+                  return v.x;
+              });
+          });
+  };
+  ChartInternal.prototype.getXDomainPadding = function (domain) {
+      var $$ = this, config = $$.config, diff = domain[1] - domain[0], maxDataCount, padding, paddingLeft, paddingRight;
+      if ($$.isCategorized()) {
+          padding = 0;
+      }
+      else if ($$.hasType('bar')) {
+          maxDataCount = $$.getMaxDataCount();
+          padding = maxDataCount > 1 ? diff / (maxDataCount - 1) / 2 : 0.5;
+      }
+      else {
+          padding = diff * 0.01;
+      }
+      if (typeof config.axis_x_padding === 'object' &&
+          notEmpty(config.axis_x_padding)) {
+          paddingLeft = isValue(config.axis_x_padding.left)
+              ? config.axis_x_padding.left
+              : padding;
+          paddingRight = isValue(config.axis_x_padding.right)
+              ? config.axis_x_padding.right
+              : padding;
+      }
+      else if (typeof config.axis_x_padding === 'number') {
+          paddingLeft = paddingRight = config.axis_x_padding;
+      }
+      else {
+          paddingLeft = paddingRight = padding;
+      }
+      return { left: paddingLeft, right: paddingRight };
+  };
+  ChartInternal.prototype.getXDomain = function (targets) {
+      var $$ = this, xDomain = [$$.getXDomainMin(targets), $$.getXDomainMax(targets)], firstX = xDomain[0], lastX = xDomain[1], padding = $$.getXDomainPadding(xDomain), min = 0, max = 0;
+      // show center of x domain if min and max are the same
+      if (firstX - lastX === 0 && !$$.isCategorized()) {
+          if ($$.isTimeSeries()) {
+              firstX = new Date(firstX.getTime() * 0.5);
+              lastX = new Date(lastX.getTime() * 1.5);
+          }
+          else {
+              firstX = firstX === 0 ? 1 : firstX * 0.5;
+              lastX = lastX === 0 ? -1 : lastX * 1.5;
+          }
+      }
+      if (firstX || firstX === 0) {
+          min = $$.isTimeSeries()
+              ? new Date(firstX.getTime() - padding.left)
+              : firstX - padding.left;
+      }
+      if (lastX || lastX === 0) {
+          max = $$.isTimeSeries()
+              ? new Date(lastX.getTime() + padding.right)
+              : lastX + padding.right;
+      }
+      return [min, max];
+  };
+  ChartInternal.prototype.updateXDomain = function (targets, withUpdateXDomain, withUpdateOrgXDomain, withTrim, domain) {
+      var $$ = this, config = $$.config;
+      if (withUpdateOrgXDomain) {
+          $$.x.domain(domain ? domain : $$.d3.extent($$.getXDomain(targets)));
+          $$.orgXDomain = $$.x.domain();
+          if (config.zoom_enabled) {
+              $$.zoom.update();
+          }
+          $$.subX.domain($$.x.domain());
+          if ($$.brush) {
+              $$.brush.updateScale($$.subX);
+          }
+      }
+      if (withUpdateXDomain) {
+          $$.x.domain(domain
+              ? domain
+              : !$$.brush || $$.brush.empty()
+                  ? $$.orgXDomain
+                  : $$.brush.selectionAsValue());
+      }
+      // Trim domain when too big by zoom mousemove event
+      if (withTrim) {
+          $$.x.domain($$.trimXDomain($$.x.orgDomain()));
+      }
+      return $$.x.domain();
+  };
+  ChartInternal.prototype.trimXDomain = function (domain) {
+      var zoomDomain = this.getZoomDomain(), min = zoomDomain[0], max = zoomDomain[1];
+      if (domain[0] <= min) {
+          domain[1] = +domain[1] + (min - domain[0]);
+          domain[0] = min;
+      }
+      if (max <= domain[1]) {
+          domain[0] = +domain[0] - (domain[1] - max);
+          domain[1] = max;
+      }
+      return domain;
+  };
+
+  ChartInternal.prototype.drag = function (mouse) {
+      var $$ = this, config = $$.config, main = $$.main, d3 = $$.d3;
+      var sx, sy, mx, my, minX, maxX, minY, maxY;
+      if ($$.hasArcType()) {
+          return;
+      }
+      if (!config.data_selection_enabled) {
+          return;
+      } // do nothing if not selectable
+      if (!config.data_selection_multiple) {
+          return;
+      } // skip when single selection because drag is used for multiple selection
+      sx = $$.dragStart[0];
+      sy = $$.dragStart[1];
+      mx = mouse[0];
+      my = mouse[1];
+      minX = Math.min(sx, mx);
+      maxX = Math.max(sx, mx);
+      minY = config.data_selection_grouped ? $$.margin.top : Math.min(sy, my);
+      maxY = config.data_selection_grouped ? $$.height : Math.max(sy, my);
+      main
+          .select('.' + CLASS.dragarea)
+          .attr('x', minX)
+          .attr('y', minY)
+          .attr('width', maxX - minX)
+          .attr('height', maxY - minY);
+      // TODO: binary search when multiple xs
+      main
+          .selectAll('.' + CLASS.shapes)
+          .selectAll('.' + CLASS.shape)
+          .each(function (d, i) {
+          if (!config.data_selection_isselectable(d)) {
+              return;
+          }
+          var shape = d3.select(this), isSelected = shape.classed(CLASS.SELECTED), isIncluded = shape.classed(CLASS.INCLUDED), _x, _y, _w, _h, toggle, isWithin = false, box;
+          if (shape.classed(CLASS.circle)) {
+              _x = shape.attr('cx') * 1;
+              _y = shape.attr('cy') * 1;
+              toggle = $$.togglePoint;
+              isWithin = minX < _x && _x < maxX && minY < _y && _y < maxY;
+          }
+          else if (shape.classed(CLASS.bar)) {
+              box = getPathBox(this);
+              _x = box.x;
+              _y = box.y;
+              _w = box.width;
+              _h = box.height;
+              toggle = $$.togglePath;
+              isWithin =
+                  !(maxX < _x || _x + _w < minX) && !(maxY < _y || _y + _h < minY);
+          }
+          else {
+              // line/area selection not supported yet
+              return;
+          }
+          if (isWithin ^ isIncluded) {
+              shape.classed(CLASS.INCLUDED, !isIncluded);
+              // TODO: included/unincluded callback here
+              shape.classed(CLASS.SELECTED, !isSelected);
+              toggle.call($$, !isSelected, shape, d, i);
+          }
+      });
+  };
+  ChartInternal.prototype.dragstart = function (mouse) {
+      var $$ = this, config = $$.config;
+      if ($$.hasArcType()) {
+          return;
+      }
+      if (!config.data_selection_enabled) {
+          return;
+      } // do nothing if not selectable
+      $$.dragStart = mouse;
+      $$.main
+          .select('.' + CLASS.chart)
+          .append('rect')
+          .attr('class', CLASS.dragarea)
+          .style('opacity', 0.1);
+      $$.dragging = true;
+  };
+  ChartInternal.prototype.dragend = function () {
+      var $$ = this, config = $$.config;
+      if ($$.hasArcType()) {
+          return;
+      }
+      if (!config.data_selection_enabled) {
+          return;
+      } // do nothing if not selectable
+      $$.main
+          .select('.' + CLASS.dragarea)
+          .transition()
+          .duration(100)
+          .style('opacity', 0)
+          .remove();
+      $$.main.selectAll('.' + CLASS.shape).classed(CLASS.INCLUDED, false);
+      $$.dragging = false;
+  };
+
+  ChartInternal.prototype.getYFormat = function (forArc) {
+      var $$ = this, formatForY = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.yFormat, formatForY2 = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.y2Format;
+      return function (v, ratio, id) {
+          var format = $$.axis.getId(id) === 'y2' ? formatForY2 : formatForY;
+          return format.call($$, v, ratio);
+      };
+  };
+  ChartInternal.prototype.yFormat = function (v) {
+      var $$ = this, config = $$.config, format = config.axis_y_tick_format
+          ? config.axis_y_tick_format
+          : $$.defaultValueFormat;
+      return format(v);
+  };
+  ChartInternal.prototype.y2Format = function (v) {
+      var $$ = this, config = $$.config, format = config.axis_y2_tick_format
+          ? config.axis_y2_tick_format
+          : $$.defaultValueFormat;
+      return format(v);
+  };
+  ChartInternal.prototype.defaultValueFormat = function (v) {
+      return isValue(v) ? +v : '';
+  };
+  ChartInternal.prototype.defaultArcValueFormat = function (v, ratio) {
+      return (ratio * 100).toFixed(1) + '%';
+  };
+  ChartInternal.prototype.dataLabelFormat = function (targetId) {
+      var $$ = this, data_labels = $$.config.data_labels, format, defaultFormat = function (v) {
+          return isValue(v) ? +v : '';
+      };
+      // find format according to axis id
+      if (typeof data_labels.format === 'function') {
+          format = data_labels.format;
+      }
+      else if (typeof data_labels.format === 'object') {
+          if (data_labels.format[targetId]) {
+              format =
+                  data_labels.format[targetId] === true
+                      ? defaultFormat
+                      : data_labels.format[targetId];
+          }
+          else {
+              format = function () {
+                  return '';
+              };
+          }
+      }
+      else {
+          format = defaultFormat;
+      }
+      return format;
+  };
+
+  ChartInternal.prototype.initGrid = function () {
+      var $$ = this, config = $$.config, d3 = $$.d3;
+      $$.grid = $$.main
+          .append('g')
+          .attr('clip-path', $$.clipPathForGrid)
+          .attr('class', CLASS.grid);
+      if (config.grid_x_show) {
+          $$.grid.append('g').attr('class', CLASS.xgrids);
+      }
+      if (config.grid_y_show) {
+          $$.grid.append('g').attr('class', CLASS.ygrids);
+      }
+      if (config.grid_focus_show) {
+          $$.grid
+              .append('g')
+              .attr('class', CLASS.xgridFocus)
+              .append('line')
+              .attr('class', CLASS.xgridFocus);
+      }
+      $$.xgrid = d3.selectAll([]);
+      if (!config.grid_lines_front) {
+          $$.initGridLines();
+      }
+  };
+  ChartInternal.prototype.initGridLines = function () {
+      var $$ = this, d3 = $$.d3;
+      $$.gridLines = $$.main
+          .append('g')
+          .attr('clip-path', $$.clipPathForGrid)
+          .attr('class', CLASS.grid + ' ' + CLASS.gridLines);
+      $$.gridLines.append('g').attr('class', CLASS.xgridLines);
+      $$.gridLines.append('g').attr('class', CLASS.ygridLines);
+      $$.xgridLines = d3.selectAll([]);
+  };
+  ChartInternal.prototype.updateXGrid = function (withoutUpdate) {
+      var $$ = this, config = $$.config, d3 = $$.d3, xgridData = $$.generateGridData(config.grid_x_type, $$.x), tickOffset = $$.isCategorized() ? $$.xAxis.tickOffset() : 0;
+      $$.xgridAttr = config.axis_rotated
+          ? {
+              x1: 0,
+              x2: $$.width,
+              y1: function (d) {
+                  return $$.x(d) - tickOffset;
+              },
+              y2: function (d) {
+                  return $$.x(d) - tickOffset;
+              }
+          }
+          : {
+              x1: function (d) {
+                  return $$.x(d) + tickOffset;
+              },
+              x2: function (d) {
+                  return $$.x(d) + tickOffset;
+              },
+              y1: 0,
+              y2: $$.height
+          };
+      $$.xgridAttr.opacity = function () {
+          var pos = +d3.select(this).attr(config.axis_rotated ? 'y1' : 'x1');
+          return pos === (config.axis_rotated ? $$.height : 0) ? 0 : 1;
+      };
+      var xgrid = $$.main
+          .select('.' + CLASS.xgrids)
+          .selectAll('.' + CLASS.xgrid)
+          .data(xgridData);
+      var xgridEnter = xgrid
+          .enter()
+          .append('line')
+          .attr('class', CLASS.xgrid)
+          .attr('x1', $$.xgridAttr.x1)
+          .attr('x2', $$.xgridAttr.x2)
+          .attr('y1', $$.xgridAttr.y1)
+          .attr('y2', $$.xgridAttr.y2)
+          .style('opacity', 0);
+      $$.xgrid = xgridEnter.merge(xgrid);
+      if (!withoutUpdate) {
+          $$.xgrid
+              .attr('x1', $$.xgridAttr.x1)
+              .attr('x2', $$.xgridAttr.x2)
+              .attr('y1', $$.xgridAttr.y1)
+              .attr('y2', $$.xgridAttr.y2)
+              .style('opacity', $$.xgridAttr.opacity);
+      }
+      xgrid.exit().remove();
+  };
+  ChartInternal.prototype.updateYGrid = function () {
+      var $$ = this, config = $$.config, gridValues = $$.yAxis.tickValues() || $$.y.ticks(config.grid_y_ticks);
+      var ygrid = $$.main
+          .select('.' + CLASS.ygrids)
+          .selectAll('.' + CLASS.ygrid)
+          .data(gridValues);
+      var ygridEnter = ygrid
+          .enter()
+          .append('line')
+          // TODO: x1, x2, y1, y2, opacity need to be set here maybe
+          .attr('class', CLASS.ygrid);
+      $$.ygrid = ygridEnter.merge(ygrid);
+      $$.ygrid
+          .attr('x1', config.axis_rotated ? $$.y : 0)
+          .attr('x2', config.axis_rotated ? $$.y : $$.width)
+          .attr('y1', config.axis_rotated ? 0 : $$.y)
+          .attr('y2', config.axis_rotated ? $$.height : $$.y);
+      ygrid.exit().remove();
+      $$.smoothLines($$.ygrid, 'grid');
+  };
+  ChartInternal.prototype.gridTextAnchor = function (d) {
+      return d.position ? d.position : 'end';
+  };
+  ChartInternal.prototype.gridTextDx = function (d) {
+      return d.position === 'start' ? 4 : d.position === 'middle' ? 0 : -4;
+  };
+  ChartInternal.prototype.xGridTextX = function (d) {
+      return d.position === 'start'
+          ? -this.height
+          : d.position === 'middle'
+              ? -this.height / 2
+              : 0;
+  };
+  ChartInternal.prototype.yGridTextX = function (d) {
+      return d.position === 'start'
+          ? 0
+          : d.position === 'middle'
+              ? this.width / 2
+              : this.width;
+  };
+  ChartInternal.prototype.updateGrid = function (duration) {
+      var $$ = this, main = $$.main, config = $$.config, xgridLine, xgridLineEnter, ygridLine, ygridLineEnter, xv = $$.xv.bind($$), yv = $$.yv.bind($$), xGridTextX = $$.xGridTextX.bind($$), yGridTextX = $$.yGridTextX.bind($$);
+      // hide if arc type
+      $$.grid.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');
+      main.select('line.' + CLASS.xgridFocus).style('visibility', 'hidden');
+      if (config.grid_x_show) {
+          $$.updateXGrid();
+      }
+      xgridLine = main
+          .select('.' + CLASS.xgridLines)
+          .selectAll('.' + CLASS.xgridLine)
+          .data(config.grid_x_lines);
+      // enter
+      xgridLineEnter = xgridLine
+          .enter()
+          .append('g')
+          .attr('class', function (d) {
+          return CLASS.xgridLine + (d['class'] ? ' ' + d['class'] : '');
+      });
+      xgridLineEnter
+          .append('line')
+          .attr('x1', config.axis_rotated ? 0 : xv)
+          .attr('x2', config.axis_rotated ? $$.width : xv)
+          .attr('y1', config.axis_rotated ? xv : 0)
+          .attr('y2', config.axis_rotated ? xv : $$.height)
+          .style('opacity', 0);
+      xgridLineEnter
+          .append('text')
+          .attr('text-anchor', $$.gridTextAnchor)
+          .attr('transform', config.axis_rotated ? '' : 'rotate(-90)')
+          .attr('x', config.axis_rotated ? yGridTextX : xGridTextX)
+          .attr('y', xv)
+          .attr('dx', $$.gridTextDx)
+          .attr('dy', -5)
+          .style('opacity', 0);
+      // udpate
+      $$.xgridLines = xgridLineEnter.merge(xgridLine);
+      // done in d3.transition() of the end of this function
+      // exit
+      xgridLine
+          .exit()
+          .transition()
+          .duration(duration)
+          .style('opacity', 0)
+          .remove();
+      // Y-Grid
+      if (config.grid_y_show) {
+          $$.updateYGrid();
+      }
+      ygridLine = main
+          .select('.' + CLASS.ygridLines)
+          .selectAll('.' + CLASS.ygridLine)
+          .data(config.grid_y_lines);
+      // enter
+      ygridLineEnter = ygridLine
+          .enter()
+          .append('g')
+          .attr('class', function (d) {
+          return CLASS.ygridLine + (d['class'] ? ' ' + d['class'] : '');
+      });
+      ygridLineEnter
+          .append('line')
+          .attr('x1', config.axis_rotated ? yv : 0)
+          .attr('x2', config.axis_rotated ? yv : $$.width)
+          .attr('y1', config.axis_rotated ? 0 : yv)
+          .attr('y2', config.axis_rotated ? $$.height : yv)
+          .style('opacity', 0);
+      ygridLineEnter
+          .append('text')
+          .attr('text-anchor', $$.gridTextAnchor)
+          .attr('transform', config.axis_rotated ? 'rotate(-90)' : '')
+          .attr('x', config.axis_rotated ? xGridTextX : yGridTextX)
+          .attr('y', yv)
+          .attr('dx', $$.gridTextDx)
+          .attr('dy', -5)
+          .style('opacity', 0);
+      // update
+      $$.ygridLines = ygridLineEnter.merge(ygridLine);
+      $$.ygridLines
+          .select('line')
+          .transition()
+          .duration(duration)
+          .attr('x1', config.axis_rotated ? yv : 0)
+          .attr('x2', config.axis_rotated ? yv : $$.width)
+          .attr('y1', config.axis_rotated ? 0 : yv)
+          .attr('y2', config.axis_rotated ? $$.height : yv)
+          .style('opacity', 1);
+      $$.ygridLines
+          .select('text')
+          .transition()
+          .duration(duration)
+          .attr('x', config.axis_rotated ? $$.xGridTextX.bind($$) : $$.yGridTextX.bind($$))
+          .attr('y', yv)
+          .text(function (d) {
+          return d.text;
+      })
+          .style('opacity', 1);
+      // exit
+      ygridLine
+          .exit()
+          .transition()
+          .duration(duration)
+          .style('opacity', 0)
+          .remove();
+  };
+  ChartInternal.prototype.redrawGrid = function (withTransition, transition) {
+      var $$ = this, config = $$.config, xv = $$.xv.bind($$), lines = $$.xgridLines.select('line'), texts = $$.xgridLines.select('text');
+      return [
+          (withTransition ? lines.transition(transition) : lines)
+              .attr('x1', config.axis_rotated ? 0 : xv)
+              .attr('x2', config.axis_rotated ? $$.width : xv)
+              .attr('y1', config.axis_rotated ? xv : 0)
+              .attr('y2', config.axis_rotated ? xv : $$.height)
+              .style('opacity', 1),
+          (withTransition ? texts.transition(transition) : texts)
+              .attr('x', config.axis_rotated ? $$.yGridTextX.bind($$) : $$.xGridTextX.bind($$))
+              .attr('y', xv)
+              .text(function (d) {
+              return d.text;
+          })
+              .style('opacity', 1)
+      ];
+  };
+  ChartInternal.prototype.showXGridFocus = function (selectedData) {
+      var $$ = this, config = $$.config, dataToShow = selectedData.filter(function (d) {
+          return d && isValue(d.value);
+      }), focusEl = $$.main.selectAll('line.' + CLASS.xgridFocus), xx = $$.xx.bind($$);
+      if (!config.tooltip_show) {
+          return;
+      }
+      // Hide when stanford plot exists
+      if ($$.hasType('stanford') || $$.hasArcType()) {
+          return;
+      }
+      focusEl
+          .style('visibility', 'visible')
+          .data([dataToShow[0]])
+          .attr(config.axis_rotated ? 'y1' : 'x1', xx)
+          .attr(config.axis_rotated ? 'y2' : 'x2', xx);
+      $$.smoothLines(focusEl, 'grid');
+  };
+  ChartInternal.prototype.hideXGridFocus = function () {
+      this.main.select('line.' + CLASS.xgridFocus).style('visibility', 'hidden');
+  };
+  ChartInternal.prototype.updateXgridFocus = function () {
+      var $$ = this, config = $$.config;
+      $$.main
+          .select('line.' + CLASS.xgridFocus)
+          .attr('x1', config.axis_rotated ? 0 : -10)
+          .attr('x2', config.axis_rotated ? $$.width : -10)
+          .attr('y1', config.axis_rotated ? -10 : 0)
+          .attr('y2', config.axis_rotated ? -10 : $$.height);
+  };
+  ChartInternal.prototype.generateGridData = function (type, scale) {
+      var $$ = this, gridData = [], xDomain, firstYear, lastYear, i, tickNum = $$.main
+          .select('.' + CLASS.axisX)
+          .selectAll('.tick')
+          .size();
+      if (type === 'year') {
+          xDomain = $$.getXDomain();
+          firstYear = xDomain[0].getFullYear();
+          lastYear = xDomain[1].getFullYear();
+          for (i = firstYear; i <= lastYear; i++) {
+              gridData.push(new Date(i + '-01-01 00:00:00'));
+          }
+      }
+      else {
+          gridData = scale.ticks(10);
+          if (gridData.length > tickNum) {
+              // use only int
+              gridData = gridData.filter(function (d) {
+                  return ('' + d).indexOf('.') < 0;
+              });
+          }
+      }
+      return gridData;
+  };
+  ChartInternal.prototype.getGridFilterToRemove = function (params) {
+      return params
+          ? function (line) {
+              var found = false;
+              [].concat(params).forEach(function (param) {
+                  if (('value' in param && line.value === param.value) ||
+                      ('class' in param && line['class'] === param['class'])) {
+                      found = true;
+                  }
+              });
+              return found;
+          }
+          : function () {
+              return true;
+          };
+  };
+  ChartInternal.prototype.removeGridLines = function (params, forX) {
+      var $$ = this, config = $$.config, toRemove = $$.getGridFilterToRemove(params), toShow = function (line) {
+          return !toRemove(line);
+      }, classLines = forX ? CLASS.xgridLines : CLASS.ygridLines, classLine = forX ? CLASS.xgridLine : CLASS.ygridLine;
+      $$.main
+          .select('.' + classLines)
+          .selectAll('.' + classLine)
+          .filter(toRemove)
+          .transition()
+          .duration(config.transition_duration)
+          .style('opacity', 0)
+          .remove();
+      if (forX) {
+          config.grid_x_lines = config.grid_x_lines.filter(toShow);
+      }
+      else {
+          config.grid_y_lines = config.grid_y_lines.filter(toShow);
+      }
+  };
+
+  ChartInternal.prototype.initEventRect = function () {
+      var $$ = this, config = $$.config;
+      $$.main
+          .select('.' + CLASS.chart)
+          .append('g')
+          .attr('class', CLASS.eventRects)
+          .style('fill-opacity', 0);
+      $$.eventRect = $$.main
+          .select('.' + CLASS.eventRects)
+          .append('rect')
+          .attr('class', CLASS.eventRect);
+      // event rect handle zoom event as well
+      if (config.zoom_enabled && $$.zoom) {
+          $$.eventRect.call($$.zoom).on('dblclick.zoom', null);
+          if (config.zoom_initialRange) {
+              // WORKAROUND: Add transition to apply transform immediately when no subchart
+              $$.eventRect
+                  .transition()
+                  .duration(0)
+                  .call($$.zoom.transform, $$.zoomTransform(config.zoom_initialRange));
+          }
+      }
+  };
+  ChartInternal.prototype.redrawEventRect = function () {
+      var $$ = this, d3 = $$.d3, config = $$.config;
+      function mouseout() {
+          $$.svg.select('.' + CLASS.eventRect).style('cursor', null);
+          $$.hideXGridFocus();
+          $$.hideTooltip();
+          $$.unexpandCircles();
+          $$.unexpandBars();
+      }
+      var isHoveringDataPoint = function (mouse, closest) {
+          return closest &&
+              ($$.isBarType(closest.id) ||
+                  $$.dist(closest, mouse) < config.point_sensitivity);
+      };
+      var withName = function (d) { return (d ? $$.addName(Object.assign({}, d)) : null); };
+      // rects for mouseover
+      $$.main
+          .select('.' + CLASS.eventRects)
+          .style('cursor', config.zoom_enabled
+          ? config.axis_rotated
+              ? 'ns-resize'
+              : 'ew-resize'
+          : null);
+      $$.eventRect
+          .attr('x', 0)
+          .attr('y', 0)
+          .attr('width', $$.width)
+          .attr('height', $$.height)
+          .on('mouseout', config.interaction_enabled
+          ? function () {
+              if (!config) {
+                  return;
+              } // chart is destroyed
+              if ($$.hasArcType()) {
+                  return;
+              }
+              if ($$.mouseover) {
+                  config.data_onmouseout.call($$.api, $$.mouseover);
+                  $$.mouseover = undefined;
+              }
+              mouseout();
+          }
+          : null)
+          .on('mousemove', config.interaction_enabled
+          ? function () {
+              // do nothing when dragging
+              if ($$.dragging) {
+                  return;
+              }
+              var targetsToShow = $$.getTargetsToShow();
+              // do nothing if arc type
+              if ($$.hasArcType(targetsToShow)) {
+                  return;
+              }
+              var mouse = d3.mouse(this);
+              var closest = withName($$.findClosestFromTargets(targetsToShow, mouse));
+              var isMouseCloseToDataPoint = isHoveringDataPoint(mouse, closest);
+              // ensure onmouseout is always called if mousemove switch between 2 targets
+              if ($$.mouseover &&
+                  (!closest ||
+                      closest.id !== $$.mouseover.id ||
+                      closest.index !== $$.mouseover.index)) {
+                  config.data_onmouseout.call($$.api, $$.mouseover);
+                  $$.mouseover = undefined;
+              }
+              if (closest && !$$.mouseover) {
+                  config.data_onmouseover.call($$.api, closest);
+                  $$.mouseover = closest;
+              }
+              // show cursor as pointer if we're hovering a data point close enough
+              $$.svg
+                  .select('.' + CLASS.eventRect)
+                  .style('cursor', isMouseCloseToDataPoint ? 'pointer' : null);
+              // if tooltip not grouped, we want to display only data from closest data point
+              var showSingleDataPoint = !config.tooltip_grouped || $$.hasType('stanford', targetsToShow);
+              // find data to highlight
+              var selectedData;
+              if (showSingleDataPoint) {
+                  if (closest) {
+                      selectedData = [closest];
+                  }
+              }
+              else {
+                  var closestByX = void 0;
+                  if (closest) {
+                      // reuse closest value
+                      closestByX = closest;
+                  }
+                  else {
+                      // try to find the closest value by X values from the mouse position
+                      var mouseX = config.axis_rotated ? mouse[1] : mouse[0];
+                      closestByX = $$.findClosestFromTargetsByX(targetsToShow, $$.x.invert(mouseX));
+                  }
+                  // highlight all data for this 'x' value
+                  if (closestByX) {
+                      selectedData = $$.filterByX(targetsToShow, closestByX.x);
+                  }
+              }
+              // ensure we have data to show
+              if (!selectedData || selectedData.length === 0) {
+                  return mouseout();
+              }
+              // inject names for each point
+              selectedData = selectedData.map(withName);
+              // show tooltip
+              $$.showTooltip(selectedData, this);
+              // expand points
+              if (config.point_focus_expand_enabled) {
+                  $$.unexpandCircles();
+                  selectedData.forEach(function (d) {
+                      $$.expandCircles(d.index, d.id, false);
+                  });
+              }
+              // expand bars
+              $$.unexpandBars();
+              selectedData.forEach(function (d) {
+                  $$.expandBars(d.index, d.id, false);
+              });
+              // Show xgrid focus line
+              $$.showXGridFocus(selectedData);
+          }
+          : null)
+          .on('click', config.interaction_enabled
+          ? function () {
+              var targetsToShow = $$.getTargetsToShow();
+              if ($$.hasArcType(targetsToShow)) {
+                  return;
+              }
+              var mouse = d3.mouse(this);
+              var closest = withName($$.findClosestFromTargets(targetsToShow, mouse));
+              if (!isHoveringDataPoint(mouse, closest)) {
+                  return;
+              }
+              // select if selection enabled
+              var sameXData;
+              if (!config.data_selection_grouped || $$.isStanfordType(closest)) {
+                  sameXData = [closest];
+              }
+              else {
+                  sameXData = $$.filterByX(targetsToShow, closest.x);
+              }
+              // toggle selected state
+              sameXData.forEach(function (d) {
+                  $$.main
+                      .selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(d.id))
+                      .selectAll('.' + CLASS.shape + '-' + d.index)
+                      .each(function () {
+                      if (config.data_selection_grouped ||
+                          $$.isWithinShape(this, d)) {
+                          $$.toggleShape(this, d, d.index);
+                      }
+                  });
+              });
+              // call data_onclick on the closest data point
+              if (closest) {
+                  var shape = $$.main
+                      .selectAll('.' + CLASS.shapes + $$.getTargetSelectorSuffix(closest.id))
+                      .select('.' + CLASS.shape + '-' + closest.index);
+                  config.data_onclick.call($$.api, closest, shape.node());
+              }
+          }
+          : null)
+          .call(config.interaction_enabled && config.data_selection_draggable && $$.drag
+          ? d3
+              .drag()
+              .on('drag', function () {
+              $$.drag(d3.mouse(this));
+          })
+              .on('start', function () {
+              $$.dragstart(d3.mouse(this));
+          })
+              .on('end', function () {
+              $$.dragend();
+          })
+          : function () { });
+  };
+  ChartInternal.prototype.getMousePosition = function (data) {
+      var $$ = this;
+      return [$$.x(data.x), $$.getYScale(data.id)(data.value)];
+  };
+  ChartInternal.prototype.dispatchEvent = function (type, mouse) {
+      var $$ = this, selector = '.' + CLASS.eventRect, eventRect = $$.main.select(selector).node(), box = eventRect.getBoundingClientRect(), x = box.left + (mouse ? mouse[0] : 0), y = box.top + (mouse ? mouse[1] : 0), event = document.createEvent('MouseEvents');
+      event.initMouseEvent(type, true, true, window, 0, x, y, x, y, false, false, false, false, 0, null);
+      eventRect.dispatchEvent(event);
+  };
+
+  ChartInternal.prototype.initLegend = function () {
+      var $$ = this;
+      $$.legendItemTextBox = {};
+      $$.legendHasRendered = false;
+      $$.legend = $$.svg.append('g').attr('transform', $$.getTranslate('legend'));
+      if (!$$.config.legend_show) {
+          $$.legend.style('visibility', 'hidden');
+          $$.hiddenLegendIds = $$.mapToIds($$.data.targets);
+          return;
+      }
+      // MEMO: call here to update legend box and tranlate for all
+      // MEMO: translate will be updated by this, so transform not needed in updateLegend()
+      $$.updateLegendWithDefaults();
+  };
+  ChartInternal.prototype.updateLegendWithDefaults = function () {
+      var $$ = this;
+      $$.updateLegend($$.mapToIds($$.data.targets), {
+          withTransform: false,
+          withTransitionForTransform: false,
+          withTransition: false
+      });
+  };
+  ChartInternal.prototype.updateSizeForLegend = function (legendHeight, legendWidth) {
+      var $$ = this, config = $$.config, insetLegendPosition = {
+          top: $$.isLegendTop
+              ? $$.getCurrentPaddingTop() + config.legend_inset_y + 5.5
+              : $$.currentHeight -
+                  legendHeight -
+                  $$.getCurrentPaddingBottom() -
+                  config.legend_inset_y,
+          left: $$.isLegendLeft
+              ? $$.getCurrentPaddingLeft() + config.legend_inset_x + 0.5
+              : $$.currentWidth -
+                  legendWidth -
+                  $$.getCurrentPaddingRight() -
+                  config.legend_inset_x +
+                  0.5
+      };
+      $$.margin3 = {
+          top: $$.isLegendRight
+              ? 0
+              : $$.isLegendInset
+                  ? insetLegendPosition.top
+                  : $$.currentHeight - legendHeight,
+          right: NaN,
+          bottom: 0,
+          left: $$.isLegendRight
+              ? $$.currentWidth - legendWidth
+              : $$.isLegendInset
+                  ? insetLegendPosition.left
+                  : 0
+      };
+  };
+  ChartInternal.prototype.transformLegend = function (withTransition) {
+      var $$ = this;
+      (withTransition ? $$.legend.transition() : $$.legend).attr('transform', $$.getTranslate('legend'));
+  };
+  ChartInternal.prototype.updateLegendStep = function (step) {
+      this.legendStep = step;
+  };
+  ChartInternal.prototype.updateLegendItemWidth = function (w) {
+      this.legendItemWidth = w;
+  };
+  ChartInternal.prototype.updateLegendItemHeight = function (h) {
+      this.legendItemHeight = h;
+  };
+  ChartInternal.prototype.getLegendWidth = function () {
+      var $$ = this;
+      return $$.config.legend_show
+          ? $$.isLegendRight || $$.isLegendInset
+              ? $$.legendItemWidth * ($$.legendStep + 1)
+              : $$.currentWidth
+          : 0;
+  };
+  ChartInternal.prototype.getLegendHeight = function () {
+      var $$ = this, h = 0;
+      if ($$.config.legend_show) {
+          if ($$.isLegendRight) {
+              h = $$.currentHeight;
+          }
+          else {
+              h = Math.max(20, $$.legendItemHeight) * ($$.legendStep + 1);
+          }
+      }
+      return h;
+  };
+  ChartInternal.prototype.opacityForLegend = function (legendItem) {
+      return legendItem.classed(CLASS.legendItemHidden) ? null : 1;
+  };
+  ChartInternal.prototype.opacityForUnfocusedLegend = function (legendItem) {
+      return legendItem.classed(CLASS.legendItemHidden) ? null : 0.3;
+  };
+  ChartInternal.prototype.toggleFocusLegend = function (targetIds, focus) {
+      var $$ = this;
+      targetIds = $$.mapToTargetIds(targetIds);
+      $$.legend
+          .selectAll('.' + CLASS.legendItem)
+          .filter(function (id) {
+          return targetIds.indexOf(id) >= 0;
+      })
+          .classed(CLASS.legendItemFocused, focus)
+          .transition()
+          .duration(100)
+          .style('opacity', function () {
+          var opacity = focus ? $$.opacityForLegend : $$.opacityForUnfocusedLegend;
+          return opacity.call($$, $$.d3.select(this));
+      });
+  };
+  ChartInternal.prototype.revertLegend = function () {
+      var $$ = this, d3 = $$.d3;
+      $$.legend
+          .selectAll('.' + CLASS.legendItem)
+          .classed(CLASS.legendItemFocused, false)
+          .transition()
+          .duration(100)
+          .style('opacity', function () {
+          return $$.opacityForLegend(d3.select(this));
+      });
+  };
+  ChartInternal.prototype.showLegend = function (targetIds) {
+      var $$ = this, config = $$.config;
+      if (!config.legend_show) {
+          config.legend_show = true;
+          $$.legend.style('visibility', 'visible');
+          if (!$$.legendHasRendered) {
+              $$.updateLegendWithDefaults();
+          }
+      }
+      $$.removeHiddenLegendIds(targetIds);
+      $$.legend
+          .selectAll($$.selectorLegends(targetIds))
+          .style('visibility', 'visible')
+          .transition()
+          .style('opacity', function () {
+          return $$.opacityForLegend($$.d3.select(this));
+      });
+  };
+  ChartInternal.prototype.hideLegend = function (targetIds) {
+      var $$ = this, config = $$.config;
+      if (config.legend_show && isEmpty(targetIds)) {
+          config.legend_show = false;
+          $$.legend.style('visibility', 'hidden');
+      }
+      $$.addHiddenLegendIds(targetIds);
+      $$.legend
+          .selectAll($$.selectorLegends(targetIds))
+          .style('opacity', 0)
+          .style('visibility', 'hidden');
+  };
+  ChartInternal.prototype.clearLegendItemTextBoxCache = function () {
+      this.legendItemTextBox = {};
+  };
+  ChartInternal.prototype.updateLegend = function (targetIds, options, transitions) {
+      var $$ = this, config = $$.config;
+      var xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect, x1ForLegendTile, x2ForLegendTile, yForLegendTile;
+      var paddingTop = 4, paddingRight = 10, maxWidth = 0, maxHeight = 0, posMin = 10, tileWidth = config.legend_item_tile_width + 5;
+      var l, totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = [0], steps = {}, step = 0;
+      var withTransition, withTransitionForTransform;
+      var texts, rects, tiles, background;
+      // Skip elements when their name is set to null
+      targetIds = targetIds.filter(function (id) {
+          return !isDefined(config.data_names[id]) || config.data_names[id] !== null;
+      });
+      options = options || {};
+      withTransition = getOption(options, 'withTransition', true);
+      withTransitionForTransform = getOption(options, 'withTransitionForTransform', true);
+      function getTextBox(textElement, id) {
+          if (!$$.legendItemTextBox[id]) {
+              $$.legendItemTextBox[id] = $$.getTextRect(textElement.textContent, CLASS.legendItem, textElement);
+          }
+          return $$.legendItemTextBox[id];
+      }
+      function updatePositions(textElement, id, index) {
+          var reset = index === 0, isLast = index === targetIds.length - 1, box = getTextBox(textElement, id), itemWidth = box.width +
+              tileWidth +
+              (isLast && !($$.isLegendRight || $$.isLegendInset) ? 0 : paddingRight) +
+              config.legend_padding, itemHeight = box.height + paddingTop, itemLength = $$.isLegendRight || $$.isLegendInset ? itemHeight : itemWidth, areaLength = $$.isLegendRight || $$.isLegendInset
+              ? $$.getLegendHeight()
+              : $$.getLegendWidth(), margin, maxLength;
+          // MEMO: care about condifion of step, totalLength
+          function updateValues(id, withoutStep) {
+              if (!withoutStep) {
+                  margin = (areaLength - totalLength - itemLength) / 2;
+                  if (margin < posMin) {
+                      margin = (areaLength - itemLength) / 2;
+                      totalLength = 0;
+                      step++;
+                  }
+              }
+              steps[id] = step;
+              margins[step] = $$.isLegendInset ? 10 : margin;
+              offsets[id] = totalLength;
+              totalLength += itemLength;
+          }
+          if (reset) {
+              totalLength = 0;
+              step = 0;
+              maxWidth = 0;
+              maxHeight = 0;
+          }
+          if (config.legend_show && !$$.isLegendToShow(id)) {
+              widths[id] = heights[id] = steps[id] = offsets[id] = 0;
+              return;
+          }
+          widths[id] = itemWidth;
+          heights[id] = itemHeight;
+          if (!maxWidth || itemWidth >= maxWidth) {
+              maxWidth = itemWidth;
+          }
+          if (!maxHeight || itemHeight >= maxHeight) {
+              maxHeight = itemHeight;
+          }
+          maxLength = $$.isLegendRight || $$.isLegendInset ? maxHeight : maxWidth;
+          if (config.legend_equally) {
+              Object.keys(widths).forEach(function (id) {
+                  widths[id] = maxWidth;
+              });
+              Object.keys(heights).forEach(function (id) {
+                  heights[id] = maxHeight;
+              });
+              margin = (areaLength - maxLength * targetIds.length) / 2;
+              if (margin < posMin) {
+                  totalLength = 0;
+                  step = 0;
+                  targetIds.forEach(function (id) {
+                      updateValues(id);
+                  });
+              }
+              else {
+                  updateValues(id, true);
+              }
+          }
+          else {
+              updateValues(id);
+          }
+      }
+      if ($$.isLegendInset) {
+          step = config.legend_inset_step
+              ? config.legend_inset_step
+              : targetIds.length;
+          $$.updateLegendStep(step);
+      }
+      if ($$.isLegendRight) {
+          xForLegend = function (id) {
+              return maxWidth * steps[id];
+          };
+          yForLegend = function (id) {
+              return margins[steps[id]] + offsets[id];
+          };
+      }
+      else if ($$.isLegendInset) {
+          xForLegend = function (id) {
+              return maxWidth * steps[id] + 10;
+          };
+          yForLegend = function (id) {
+              return margins[steps[id]] + offsets[id];
+          };
+      }
+      else {
+          xForLegend = function (id) {
+              return margins[steps[id]] + offsets[id];
+          };
+          yForLegend = function (id) {
+              return maxHeight * steps[id];
+          };
+      }
+      xForLegendText = function (id, i) {
+          return xForLegend(id, i) + 4 + config.legend_item_tile_width;
+      };
+      yForLegendText = function (id, i) {
+          return yForLegend(id, i) + 9;
+      };
+      xForLegendRect = function (id, i) {
+          return xForLegend(id, i);
+      };
+      yForLegendRect = function (id, i) {
+          return yForLegend(id, i) - 5;
+      };
+      x1ForLegendTile = function (id, i) {
+          return xForLegend(id, i) - 2;
+      };
+      x2ForLegendTile = function (id, i) {
+          return xForLegend(id, i) - 2 + config.legend_item_tile_width;
+      };
+      yForLegendTile = function (id, i) {
+          return yForLegend(id, i) + 4;
+      };
+      // Define g for legend area
+      l = $$.legend
+          .selectAll('.' + CLASS.legendItem)
+          .data(targetIds)
+          .enter()
+          .append('g')
+          .attr('class', function (id) {
+          return $$.generateClass(CLASS.legendItem, id);
+      })
+          .style('visibility', function (id) {
+          return $$.isLegendToShow(id) ? 'visible' : 'hidden';
+      })
+          .style('cursor', function () {
+          return config.interaction_enabled ? 'pointer' : 'auto';
+      })
+          .on('click', config.interaction_enabled
+          ? function (id) {
+              if (config.legend_item_onclick) {
+                  config.legend_item_onclick.call($$, id);
+              }
+              else {
+                  if ($$.d3.event.altKey) {
+                      $$.api.hide();
+                      $$.api.show(id);
+                  }
+                  else {
+                      $$.api.toggle(id);
+                      $$.isTargetToShow(id) ? $$.api.focus(id) : $$.api.revert();
+                  }
+              }
+          }
+          : null)
+          .on('mouseover', config.interaction_enabled
+          ? function (id) {
+              if (config.legend_item_onmouseover) {
+                  config.legend_item_onmouseover.call($$, id);
+              }
+              else {
+                  $$.d3.select(this).classed(CLASS.legendItemFocused, true);
+                  if (!$$.transiting && $$.isTargetToShow(id)) {
+                      $$.api.focus(id);
+                  }
+              }
+          }
+          : null)
+          .on('mouseout', config.interaction_enabled
+          ? function (id) {
+              if (config.legend_item_onmouseout) {
+                  config.legend_item_onmouseout.call($$, id);
+              }
+              else {
+                  $$.d3.select(this).classed(CLASS.legendItemFocused, false);
+                  $$.api.revert();
+              }
+          }
+          : null);
+      l.append('text')
+          .text(function (id) {
+          return isDefined(config.data_names[id]) ? config.data_names[id] : id;
+      })
+          .each(function (id, i) {
+          updatePositions(this, id, i);
+      })
+          .style('pointer-events', 'none')
+          .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200)
+          .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendText);
+      l.append('rect')
+          .attr('class', CLASS.legendItemEvent)
+          .style('fill-opacity', 0)
+          .attr('x', $$.isLegendRight || $$.isLegendInset ? xForLegendRect : -200)
+          .attr('y', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendRect);
+      l.append('line')
+          .attr('class', CLASS.legendItemTile)
+          .style('stroke', $$.color)
+          .style('pointer-events', 'none')
+          .attr('x1', $$.isLegendRight || $$.isLegendInset ? x1ForLegendTile : -200)
+          .attr('y1', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile)
+          .attr('x2', $$.isLegendRight || $$.isLegendInset ? x2ForLegendTile : -200)
+          .attr('y2', $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendTile)
+          .attr('stroke-width', config.legend_item_tile_height);
+      // Set background for inset legend
+      background = $$.legend.select('.' + CLASS.legendBackground + ' rect');
+      if ($$.isLegendInset && maxWidth > 0 && background.size() === 0) {
+          background = $$.legend
+              .insert('g', '.' + CLASS.legendItem)
+              .attr('class', CLASS.legendBackground)
+              .append('rect');
+      }
+      texts = $$.legend
+          .selectAll('text')
+          .data(targetIds)
+          .text(function (id) {
+          return isDefined(config.data_names[id]) ? config.data_names[id] : id;
+      }) // MEMO: needed for update
+          .each(function (id, i) {
+          updatePositions(this, id, i);
+      });
+      (withTransition ? texts.transition() : texts)
+          .attr('x', xForLegendText)
+          .attr('y', yForLegendText);
+      rects = $$.legend.selectAll('rect.' + CLASS.legendItemEvent).data(targetIds);
+      (withTransition ? rects.transition() : rects)
+          .attr('width', function (id) {
+          return widths[id];
+      })
+          .attr('height', function (id) {
+          return heights[id];
+      })
+          .attr('x', xForLegendRect)
+          .attr('y', yForLegendRect);
+      tiles = $$.legend.selectAll('line.' + CLASS.legendItemTile).data(targetIds);
+      (withTransition ? tiles.transition() : tiles)
+          .style('stroke', $$.levelColor
+          ? function (id) {
+              return $$.levelColor($$.cache[id].values.reduce(function (total, item) {
+                  return total + item.value;
+              }, 0));
+          }
+          : $$.color)
+          .attr('x1', x1ForLegendTile)
+          .attr('y1', yForLegendTile)
+          .attr('x2', x2ForLegendTile)
+          .attr('y2', yForLegendTile);
+      if (background) {
+          (withTransition ? background.transition() : background)
+              .attr('height', $$.getLegendHeight() - 12)
+              .attr('width', maxWidth * (step + 1) + 10);
+      }
+      // toggle legend state
+      $$.legend
+          .selectAll('.' + CLASS.legendItem)
+          .classed(CLASS.legendItemHidden, function (id) {
+          return !$$.isTargetToShow(id);
+      });
+      // Update all to reflect change of legend
+      $$.updateLegendItemWidth(maxWidth);
+      $$.updateLegendItemHeight(maxHeight);
+      $$.updateLegendStep(step);
+      // Update size and scale
+      $$.updateSizes();
+      $$.updateScales();
+      $$.updateSvgSize();
+      // Update g positions
+      $$.transformAll(withTransitionForTransform, transitions);
+      $$.legendHasRendered = true;
+  };
+
+  ChartInternal.prototype.initRegion = function () {
+      var $$ = this;
+      $$.region = $$.main
+          .append('g')
+          .attr('clip-path', $$.clipPath)
+          .attr('class', CLASS.regions);
+  };
+  ChartInternal.prototype.updateRegion = function (duration) {
+      var $$ = this, config = $$.config;
+      // hide if arc type
+      $$.region.style('visibility', $$.hasArcType() ? 'hidden' : 'visible');
+      var mainRegion = $$.main
+          .select('.' + CLASS.regions)
+          .selectAll('.' + CLASS.region)
+          .data(config.regions);
+      var g = mainRegion.enter().append('g');
+      g.append('rect')
+          .attr('x', $$.regionX.bind($$))
+          .attr('y', $$.regionY.bind($$))
+          .attr('width', $$.regionWidth.bind($$))
+          .attr('height', $$.regionHeight.bind($$))
+          .style('fill-opacity', function (d) {
+          return isValue(d.opacity) ? d.opacity : 0.1;
+      });
+      g.append('text').text($$.labelRegion.bind($$));
+      $$.mainRegion = g.merge(mainRegion).attr('class', $$.classRegion.bind($$));
+      mainRegion
+          .exit()
+          .transition()
+          .duration(duration)
+          .style('opacity', 0)
+          .remove();
+  };
+  ChartInternal.prototype.redrawRegion = function (withTransition, transition) {
+      var $$ = this, regions = $$.mainRegion, regionLabels = $$.mainRegion.selectAll('text');
+      return [
+          (withTransition ? regions.transition(transition) : regions)
+              .attr('x', $$.regionX.bind($$))
+              .attr('y', $$.regionY.bind($$))
+              .attr('width', $$.regionWidth.bind($$))
+              .attr('height', $$.regionHeight.bind($$))
+              .style('fill-opacity', function (d) {
+              return isValue(d.opacity) ? d.opacity : 0.1;
+          }),
+          (withTransition ? regionLabels.transition(transition) : regionLabels)
+              .attr('x', $$.labelOffsetX.bind($$))
+              .attr('y', $$.labelOffsetY.bind($$))
+              .attr('transform', $$.labelTransform.bind($$))
+              .attr('style', 'text-anchor: left;')
+      ];
+  };
+  ChartInternal.prototype.regionX = function (d) {
+      var $$ = this, config = $$.config, xPos, yScale = d.axis === 'y' ? $$.y : $$.y2;
+      if (d.axis === 'y' || d.axis === 'y2') {
+          xPos = config.axis_rotated ? ('start' in d ? yScale(d.start) : 0) : 0;
+      }
+      else {
+          xPos = config.axis_rotated
+              ? 0
+              : 'start' in d
+                  ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start)
+                  : 0;
+      }
+      return xPos;
+  };
+  ChartInternal.prototype.regionY = function (d) {
+      var $$ = this, config = $$.config, yPos, yScale = d.axis === 'y' ? $$.y : $$.y2;
+      if (d.axis === 'y' || d.axis === 'y2') {
+          yPos = config.axis_rotated ? 0 : 'end' in d ? yScale(d.end) : 0;
+      }
+      else {
+          yPos = config.axis_rotated
+              ? 'start' in d
+                  ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start)
+                  : 0
+              : 0;
+      }
+      return yPos;
+  };
+  ChartInternal.prototype.regionWidth = function (d) {
+      var $$ = this, config = $$.config, start = $$.regionX(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2;
+      if (d.axis === 'y' || d.axis === 'y2') {
+          end = config.axis_rotated
+              ? 'end' in d
+                  ? yScale(d.end)
+                  : $$.width
+              : $$.width;
+      }
+      else {
+          end = config.axis_rotated
+              ? $$.width
+              : 'end' in d
+                  ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end)
+                  : $$.width;
+      }
+      return end < start ? 0 : end - start;
+  };
+  ChartInternal.prototype.regionHeight = function (d) {
+      var $$ = this, config = $$.config, start = this.regionY(d), end, yScale = d.axis === 'y' ? $$.y : $$.y2;
+      if (d.axis === 'y' || d.axis === 'y2') {
+          end = config.axis_rotated
+              ? $$.height
+              : 'start' in d
+                  ? yScale(d.start)
+                  : $$.height;
+      }
+      else {
+          end = config.axis_rotated
+              ? 'end' in d
+                  ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end)
+                  : $$.height
+              : $$.height;
+      }
+      return end < start ? 0 : end - start;
+  };
+  ChartInternal.prototype.isRegionOnX = function (d) {
+      return !d.axis || d.axis === 'x';
+  };
+  ChartInternal.prototype.labelRegion = function (d) {
+      return 'label' in d ? d.label : '';
+  };
+  ChartInternal.prototype.labelTransform = function (d) {
+      return 'vertical' in d && d.vertical ? 'rotate(90)' : '';
+  };
+  ChartInternal.prototype.labelOffsetX = function (d) {
+      var paddingX = 'paddingX' in d ? d.paddingX : 3;
+      var paddingY = 'paddingY' in d ? d.paddingY : 3;
+      return 'vertical' in d && d.vertical
+          ? this.regionY(d) + paddingY
+          : this.regionX(d) + paddingX;
+  };
+  ChartInternal.prototype.labelOffsetY = function (d) {
+      var paddingX = 'paddingX' in d ? d.paddingX : 3;
+      var paddingY = 'paddingY' in d ? d.paddingY : 3;
+      return 'vertical' in d && d.vertical
+          ? -(this.regionX(d) + paddingX)
+          : this.regionY(d) + 10 + paddingY;
+  };
+
+  function c3LogScale(d3, linearScale, logScale) {
+      var PROJECTION = [0.01, 10];
+      if (!linearScale) {
+          linearScale = d3.scaleLinear();
+          linearScale.range(PROJECTION);
+      }
+      if (!logScale) {
+          logScale = d3.scaleLog();
+          logScale.domain(PROJECTION);
+          logScale.nice();
+      }
+      // copied from https://github.com/compute-io/logspace
+      function logspace(a, b, len) {
+          var arr, end, tmp, d;
+          if (arguments.length < 3) {
+              len = 10;
+          }
+          else {
+              if (len === 0) {
+                  return [];
+              }
+          }
+          // Calculate the increment:
+          end = len - 1;
+          d = (b - a) / end;
+          // Build the output array...
+          arr = new Array(len);
+          tmp = a;
+          arr[0] = Math.pow(10, tmp);
+          for (var i = 1; i < end; i++) {
+              tmp += d;
+              arr[i] = Math.pow(10, tmp);
+          }
+          arr[end] = Math.pow(10, b);
+          return arr;
+      }
+      function scale(x) {
+          return logScale(linearScale(x));
+      }
+      scale.domain = function (x) {
+          if (!arguments.length) {
+              return linearScale.domain();
+          }
+          linearScale.domain(x);
+          return scale;
+      };
+      scale.range = function (x) {
+          if (!arguments.length) {
+              return logScale.range();
+          }
+          logScale.range(x);
+          return scale;
+      };
+      scale.ticks = function (m) {
+          return logspace(-2, 1, m || 10).map(function (v) {
+              return linearScale.invert(v);
+          });
+      };
+      scale.copy = function () {
+          return c3LogScale(d3, linearScale.copy(), logScale.copy());
+      };
+      return scale;
+  }
+  ChartInternal.prototype.getScale = function (min, max, forTimeseries) {
+      return (forTimeseries ? this.d3.scaleTime() : this.d3.scaleLinear()).range([
+          min,
+          max
+      ]);
+  };
+  ChartInternal.prototype.getX = function (min, max, domain, offset) {
+      var $$ = this, scale = $$.getScale(min, max, $$.isTimeSeries()), _scale = domain ? scale.domain(domain) : scale, key;
+      // Define customized scale if categorized axis
+      if ($$.isCategorized()) {
+          offset =
+              offset ||
+                  function () {
+                      return 0;
+                  };
+          scale = function (d, raw) {
+              var v = _scale(d) + offset(d);
+              return raw ? v : Math.ceil(v);
+          };
+      }
+      else {
+          scale = function (d, raw) {
+              var v = _scale(d);
+              return raw ? v : Math.ceil(v);
+          };
+      }
+      // define functions
+      for (key in _scale) {
+          scale[key] = _scale[key];
+      }
+      scale.orgDomain = function () {
+          return _scale.domain();
+      };
+      // define custom domain() for categorized axis
+      if ($$.isCategorized()) {
+          scale.domain = function (domain) {
+              if (!arguments.length) {
+                  domain = this.orgDomain();
+                  return [domain[0], domain[1] + 1];
+              }
+              _scale.domain(domain);
+              return scale;
+          };
+      }
+      return scale;
+  };
+  /**
+   * Creates and configures a D3 scale instance for the given type.
+   *
+   * By defaults it returns a Linear scale.
+   *
+   * @param {String} type Type of d3-scale to create. Type can be 'linear', 'time', 'timeseries' or 'log'.
+   * @param {Array} domain The scale domain such as [from, to]
+   * @param {Array} range The scale's range such as [from, to]
+   *
+   * @return A d3-scale instance
+   */
+  ChartInternal.prototype.getY = function (type, domain, range) {
+      var scale;
+      if (type === 'timeseries' || type === 'time') {
+          scale = this.d3.scaleTime();
+      }
+      else if (type === 'log') {
+          scale = c3LogScale(this.d3);
+      }
+      else if (type === 'linear' || type === undefined) {
+          scale = this.d3.scaleLinear();
+      }
+      else {
+          throw new Error("Invalid Y axis type: \"" + type + "\"");
+      }
+      if (domain) {
+          scale.domain(domain);
+      }
+      if (range) {
+          scale.range(range);
+      }
+      return scale;
+  };
+  ChartInternal.prototype.getYScale = function (id) {
+      return this.axis.getId(id) === 'y2' ? this.y2 : this.y;
+  };
+  ChartInternal.prototype.getSubYScale = function (id) {
+      return this.axis.getId(id) === 'y2' ? this.subY2 : this.subY;
+  };
+  ChartInternal.prototype.updateScales = function () {
+      var $$ = this, config = $$.config, forInit = !$$.x;
+      // update edges
+      $$.xMin = config.axis_rotated ? 1 : 0;
+      $$.xMax = config.axis_rotated ? $$.height : $$.width;
+      $$.yMin = config.axis_rotated ? 0 : $$.height;
+      $$.yMax = config.axis_rotated ? $$.width : 1;
+      $$.subXMin = $$.xMin;
+      $$.subXMax = $$.xMax;
+      $$.subYMin = config.axis_rotated ? 0 : $$.height2;
+      $$.subYMax = config.axis_rotated ? $$.width2 : 1;
+      // update scales
+      $$.x = $$.getX($$.xMin, $$.xMax, forInit ? undefined : $$.x.orgDomain(), function () {
+          return $$.xAxis.tickOffset();
+      });
+      $$.y = $$.getY(config.axis_y_type, forInit ? config.axis_y_default : $$.y.domain(), [$$.yMin, $$.yMax]);
+      $$.y2 = $$.getY(config.axis_y2_type, forInit ? config.axis_y2_default : $$.y2.domain(), [$$.yMin, $$.yMax]);
+      $$.subX = $$.getX($$.xMin, $$.xMax, $$.orgXDomain, function (d) {
+          return d % 1 ? 0 : $$.subXAxis.tickOffset();
+      });
+      $$.subY = $$.getY(config.axis_y_type, forInit ? config.axis_y_default : $$.subY.domain(), [$$.subYMin, $$.subYMax]);
+      $$.subY2 = $$.getY(config.axis_y2_type, forInit ? config.axis_y2_default : $$.subY2.domain(), [$$.subYMin, $$.subYMax]);
+      // update axes
+      $$.xAxisTickFormat = $$.axis.getXAxisTickFormat();
+      $$.xAxisTickValues = $$.axis.getXAxisTickValues();
+      $$.yAxisTickValues = $$.axis.getYAxisTickValues();
+      $$.y2AxisTickValues = $$.axis.getY2AxisTickValues();
+      $$.xAxis = $$.axis.getXAxis($$.x, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);
+      $$.subXAxis = $$.axis.getXAxis($$.subX, $$.subXOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);
+      $$.yAxis = $$.axis.getYAxis('y', $$.y, $$.yOrient, $$.yAxisTickValues, config.axis_y_tick_outer);
+      $$.y2Axis = $$.axis.getYAxis('y2', $$.y2, $$.y2Orient, $$.y2AxisTickValues, config.axis_y2_tick_outer);
+      // Set initialized scales to brush and zoom
+      if (!forInit) {
+          if ($$.brush) {
+              $$.brush.updateScale($$.subX);
+          }
+      }
+      // update for arc
+      if ($$.updateArc) {
+          $$.updateArc();
+      }
+  };
+
+  ChartInternal.prototype.selectPoint = function (target, d, i) {
+      var $$ = this, config = $$.config, cx = (config.axis_rotated ? $$.circleY : $$.circleX).bind($$), cy = (config.axis_rotated ? $$.circleX : $$.circleY).bind($$), r = $$.pointSelectR.bind($$);
+      config.data_onselected.call($$.api, d, target.node());
+      // add selected-circle on low layer g
+      $$.main
+          .select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id))
+          .selectAll('.' + CLASS.selectedCircle + '-' + i)
+          .data([d])
+          .enter()
+          .append('circle')
+          .attr('class', function () {
+          return $$.generateClass(CLASS.selectedCircle, i);
+      })
+          .attr('cx', cx)
+          .attr('cy', cy)
+          .attr('stroke', function () {
+          return $$.color(d);
+      })
+          .attr('r', function (d) {
+          return $$.pointSelectR(d) * 1.4;
+      })
+          .transition()
+          .duration(100)
+          .attr('r', r);
+  };
+  ChartInternal.prototype.unselectPoint = function (target, d, i) {
+      var $$ = this;
+      $$.config.data_onunselected.call($$.api, d, target.node());
+      // remove selected-circle from low layer g
+      $$.main
+          .select('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id))
+          .selectAll('.' + CLASS.selectedCircle + '-' + i)
+          .transition()
+          .duration(100)
+          .attr('r', 0)
+          .remove();
+  };
+  ChartInternal.prototype.togglePoint = function (selected, target, d, i) {
+      selected ? this.selectPoint(target, d, i) : this.unselectPoint(target, d, i);
+  };
+  ChartInternal.prototype.selectPath = function (target, d) {
+      var $$ = this;
+      $$.config.data_onselected.call($$, d, target.node());
+      if ($$.config.interaction_brighten) {
+          target
+              .transition()
+              .duration(100)
+              .style('fill', function () {
+              return $$.d3.rgb($$.color(d)).brighter(0.75);
+          });
+      }
+  };
+  ChartInternal.prototype.unselectPath = function (target, d) {
+      var $$ = this;
+      $$.config.data_onunselected.call($$, d, target.node());
+      if ($$.config.interaction_brighten) {
+          target
+              .transition()
+              .duration(100)
+              .style('fill', function () {
+              return $$.color(d);
+          });
+      }
+  };
+  ChartInternal.prototype.togglePath = function (selected, target, d, i) {
+      selected ? this.selectPath(target, d, i) : this.unselectPath(target, d, i);
+  };
+  ChartInternal.prototype.getToggle = function (that, d) {
+      var $$ = this, toggle;
+      if (that.nodeName === 'circle') {
+          if ($$.isStepType(d)) {
+              // circle is hidden in step chart, so treat as within the click area
+              toggle = function () { }; // TODO: how to select step chart?
+          }
+          else {
+              toggle = $$.togglePoint;
+          }
+      }
+      else if (that.nodeName === 'path') {
+          toggle = $$.togglePath;
+      }
+      return toggle;
+  };
+  ChartInternal.prototype.toggleShape = function (that, d, i) {
+      var $$ = this, d3 = $$.d3, config = $$.config, shape = d3.select(that), isSelected = shape.classed(CLASS.SELECTED), toggle = $$.getToggle(that, d).bind($$);
+      if (config.data_selection_enabled && config.data_selection_isselectable(d)) {
+          if (!config.data_selection_multiple) {
+              $$.main
+                  .selectAll('.' +
+                  CLASS.shapes +
+                  (config.data_selection_grouped
+                      ? $$.getTargetSelectorSuffix(d.id)
+                      : ''))
+                  .selectAll('.' + CLASS.shape)
+                  .each(function (d, i) {
+                  var shape = d3.select(this);
+                  if (shape.classed(CLASS.SELECTED)) {
+                      toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
+                  }
+              });
+          }
+          shape.classed(CLASS.SELECTED, !isSelected);
+          toggle(!isSelected, shape, d, i);
+      }
+  };
+
+  ChartInternal.prototype.initBar = function () {
+      var $$ = this;
+      $$.main
+          .select('.' + CLASS.chart)
+          .append('g')
+          .attr('class', CLASS.chartBars);
+  };
+  ChartInternal.prototype.updateTargetsForBar = function (targets) {
+      var $$ = this, config = $$.config, mainBars, mainBarEnter, classChartBar = $$.classChartBar.bind($$), classBars = $$.classBars.bind($$), classFocus = $$.classFocus.bind($$);
+      mainBars = $$.main
+          .select('.' + CLASS.chartBars)
+          .selectAll('.' + CLASS.chartBar)
+          .data(targets)
+          .attr('class', function (d) {
+          return classChartBar(d) + classFocus(d);
+      });
+      mainBarEnter = mainBars
+          .enter()
+          .append('g')
+          .attr('class', classChartBar)
+          .style('pointer-events', 'none');
+      // Bars for each data
+      mainBarEnter
+          .append('g')
+          .attr('class', classBars)
+          .style('cursor', function (d) {
+          return config.data_selection_isselectable(d) ? 'pointer' : null;
+      });
+  };
+  ChartInternal.prototype.updateBar = function (durationForExit) {
+      var $$ = this, barData = $$.barData.bind($$), classBar = $$.classBar.bind($$), initialOpacity = $$.initialOpacity.bind($$), color = function (d) {
+          return $$.color(d.id);
+      };
+      var mainBar = $$.main
+          .selectAll('.' + CLASS.bars)
+          .selectAll('.' + CLASS.bar)
+          .data(barData);
+      var mainBarEnter = mainBar
+          .enter()
+          .append('path')
+          .attr('class', classBar)
+          .style('stroke', color)
+          .style('fill', color);
+      $$.mainBar = mainBarEnter.merge(mainBar).style('opacity', initialOpacity);
+      mainBar
+          .exit()
+          .transition()
+          .duration(durationForExit)
+          .style('opacity', 0);
+  };
+  ChartInternal.prototype.redrawBar = function (drawBar, withTransition, transition) {
+      var $$ = this;
+      return [
+          (withTransition ? this.mainBar.transition(transition) : this.mainBar)
+              .attr('d', drawBar)
+              .style('stroke', this.color)
+              .style('fill', this.color)
+              .style('opacity', function (d) { return ($$.isTargetToShow(d.id) ? 1 : 0); })
+      ];
+  };
+  ChartInternal.prototype.getBarW = function (axis, barTargetsNum) {
+      var $$ = this, config = $$.config, w = typeof config.bar_width === 'number'
+          ? config.bar_width
+          : barTargetsNum
+              ? (axis.tickInterval() * config.bar_width_ratio) / barTargetsNum
+              : 0;
+      return config.bar_width_max && w > config.bar_width_max
+          ? config.bar_width_max
+          : w;
+  };
+  ChartInternal.prototype.getBars = function (i, id) {
+      var $$ = this;
+      return (id
+          ? $$.main.selectAll('.' + CLASS.bars + $$.getTargetSelectorSuffix(id))
+          : $$.main).selectAll('.' + CLASS.bar + (isValue(i) ? '-' + i : ''));
+  };
+  ChartInternal.prototype.expandBars = function (i, id, reset) {
+      var $$ = this;
+      if (reset) {
+          $$.unexpandBars();
+      }
+      $$.getBars(i, id).classed(CLASS.EXPANDED, true);
+  };
+  ChartInternal.prototype.unexpandBars = function (i) {
+      var $$ = this;
+      $$.getBars(i).classed(CLASS.EXPANDED, false);
+  };
+  ChartInternal.prototype.generateDrawBar = function (barIndices, isSub) {
+      var $$ = this, config = $$.config, getPoints = $$.generateGetBarPoints(barIndices, isSub);
+      return function (d, i) {
+          // 4 points that make a bar
+          var points = getPoints(d, i);
+          // switch points if axis is rotated, not applicable for sub chart
+          var indexX = config.axis_rotated ? 1 : 0;
+          var indexY = config.axis_rotated ? 0 : 1;
+          var path = 'M ' +
+              points[0][indexX] +
+              ',' +
+              points[0][indexY] +
+              ' ' +
+              'L' +
+              points[1][indexX] +
+              ',' +
+              points[1][indexY] +
+              ' ' +
+              'L' +
+              points[2][indexX] +
+              ',' +
+              points[2][indexY] +
+              ' ' +
+              'L' +
+              points[3][indexX] +
+              ',' +
+              points[3][indexY] +
+              ' ' +
+              'z';
+          return path;
+      };
+  };
+  ChartInternal.prototype.generateGetBarPoints = function (barIndices, isSub) {
+      var $$ = this, axis = isSub ? $$.subXAxis : $$.xAxis, barTargetsNum = barIndices.__max__ + 1, barW = $$.getBarW(axis, barTargetsNum), barX = $$.getShapeX(barW, barTargetsNum, barIndices, !!isSub), barY = $$.getShapeY(!!isSub), barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub), barSpaceOffset = barW * ($$.config.bar_space / 2), yScale = isSub ? $$.getSubYScale : $$.getYScale;
+      return function (d, i) {
+          var y0 = yScale.call($$, d.id)(0), offset = barOffset(d, i) || y0, // offset is for stacked bar chart
+          posX = barX(d), posY = barY(d);
+          // fix posY not to overflow opposite quadrant
+          if ($$.config.axis_rotated) {
+              if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) {
+                  posY = y0;
+              }
+          }
+          posY -= y0 - offset;
+          // 4 points that make a bar
+          return [
+              [posX + barSpaceOffset, offset],
+              [posX + barSpaceOffset, posY],
+              [posX + barW - barSpaceOffset, posY],
+              [posX + barW - barSpaceOffset, offset]
+          ];
+      };
+  };
+  /**
+   * Returns whether the data point is within the given bar shape.
+   *
+   * @param mouse
+   * @param barShape
+   * @return {boolean}
+   */
+  ChartInternal.prototype.isWithinBar = function (mouse, barShape) {
+      return isWithinBox(mouse, getBBox(barShape), 2);
+  };
+
+  ChartInternal.prototype.getShapeIndices = function (typeFilter) {
+      var $$ = this, config = $$.config, indices = {}, i = 0, j, k;
+      $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)).forEach(function (d) {
+          for (j = 0; j < config.data_groups.length; j++) {
+              if (config.data_groups[j].indexOf(d.id) < 0) {
+                  continue;
+              }
+              for (k = 0; k < config.data_groups[j].length; k++) {
+                  if (config.data_groups[j][k] in indices) {
+                      indices[d.id] = indices[config.data_groups[j][k]];
+                      break;
+                  }
+              }
+          }
+          if (isUndefined(indices[d.id])) {
+              indices[d.id] = i++;
+          }
+      });
+      indices.__max__ = i - 1;
+      return indices;
+  };
+  ChartInternal.prototype.getShapeX = function (offset, targetsNum, indices, isSub) {
+      var $$ = this, scale = isSub ? $$.subX : $$.x;
+      return function (d) {
+          var index = d.id in indices ? indices[d.id] : 0;
+          return d.x || d.x === 0 ? scale(d.x) - offset * (targetsNum / 2 - index) : 0;
+      };
+  };
+  ChartInternal.prototype.getShapeY = function (isSub) {
+      var $$ = this;
+      return function (d) {
+          var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id);
+          return scale($$.isTargetNormalized(d.id) ? $$.getRatio('index', d, true) : d.value);
+      };
+  };
+  ChartInternal.prototype.getShapeOffset = function (typeFilter, indices, isSub) {
+      var $$ = this, targets = $$.orderTargets($$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))), targetIds = targets.map(function (t) {
+          return t.id;
+      });
+      return function (d, i) {
+          var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id), y0 = scale(0), offset = y0;
+          targets.forEach(function (t) {
+              var rowValues = $$.isStepType(d)
+                  ? $$.convertValuesToStep(t.values)
+                  : t.values;
+              var isTargetNormalized = $$.isTargetNormalized(d.id);
+              var values = rowValues.map(function (v) {
+                  return isTargetNormalized ? $$.getRatio('index', v, true) : v.value;
+              });
+              if (t.id === d.id || indices[t.id] !== indices[d.id]) {
+                  return;
+              }
+              if (targetIds.indexOf(t.id) < targetIds.indexOf(d.id)) {
+                  // check if the x values line up
+                  if (isUndefined(rowValues[i]) || +rowValues[i].x !== +d.x) {
+                      // "+" for timeseries
+                      // if not, try to find the value that does line up
+                      i = -1;
+                      rowValues.forEach(function (v, j) {
+                          var x1 = v.x.constructor === Date ? +v.x : v.x;
+                          var x2 = d.x.constructor === Date ? +d.x : d.x;
+                          if (x1 === x2) {
+                              i = j;
+                          }
+                      });
+                  }
+                  if (i in rowValues && rowValues[i].value * d.value >= 0) {
+                      offset += scale(values[i]) - y0;
+                  }
+              }
+          });
+          return offset;
+      };
+  };
+  ChartInternal.prototype.isWithinShape = function (that, d) {
+      var $$ = this, shape = $$.d3.select(that), isWithin;
+      if (!$$.isTargetToShow(d.id)) {
+          isWithin = false;
+      }
+      else if (that.nodeName === 'circle') {
+          isWithin = $$.isStepType(d)
+              ? $$.isWithinStep(that, $$.getYScale(d.id)(d.value))
+              : $$.isWithinCircle(that, $$.pointSelectR(d) * 1.5);
+      }
+      else if (that.nodeName === 'path') {
+          isWithin = shape.classed(CLASS.bar)
+              ? $$.isWithinBar($$.d3.mouse(that), that)
+              : true;
+      }
+      return isWithin;
+  };
+  ChartInternal.prototype.getInterpolate = function (d) {
+      var $$ = this, d3 = $$.d3, types = {
+          linear: d3.curveLinear,
+          'linear-closed': d3.curveLinearClosed,
+          basis: d3.curveBasis,
+          'basis-open': d3.curveBasisOpen,
+          'basis-closed': d3.curveBasisClosed,
+          bundle: d3.curveBundle,
+          cardinal: d3.curveCardinal,
+          'cardinal-open': d3.curveCardinalOpen,
+          'cardinal-closed': d3.curveCardinalClosed,
+          monotone: d3.curveMonotoneX,
+          step: d3.curveStep,
+          'step-before': d3.curveStepBefore,
+          'step-after': d3.curveStepAfter
+      }, type;
+      if ($$.isSplineType(d)) {
+          type = types[$$.config.spline_interpolation_type] || types.cardinal;
+      }
+      else if ($$.isStepType(d)) {
+          type = types[$$.config.line_step_type];
+      }
+      else {
+          type = types.linear;
+      }
+      return type;
+  };
+
+  ChartInternal.prototype.initLine = function () {
+      var $$ = this;
+      $$.main
+          .select('.' + CLASS.chart)
+          .append('g')
+          .attr('class', CLASS.chartLines);
+  };
+  ChartInternal.prototype.updateTargetsForLine = function (targets) {
+      var $$ = this, config = $$.config, mainLines, mainLineEnter, classChartLine = $$.classChartLine.bind($$), classLines = $$.classLines.bind($$), classAreas = $$.classAreas.bind($$), classCircles = $$.classCircles.bind($$), classFocus = $$.classFocus.bind($$);
+      mainLines = $$.main
+          .select('.' + CLASS.chartLines)
+          .selectAll('.' + CLASS.chartLine)
+          .data(targets)
+          .attr('class', function (d) {
+          return classChartLine(d) + classFocus(d);
+      });
+      mainLineEnter = mainLines
+          .enter()
+          .append('g')
+          .attr('class', classChartLine)
+          .style('opacity', 0)
+          .style('pointer-events', 'none');
+      // Lines for each data
+      mainLineEnter.append('g').attr('class', classLines);
+      // Areas
+      mainLineEnter.append('g').attr('class', classAreas);
+      // Circles for each data point on lines
+      mainLineEnter.append('g').attr('class', function (d) {
+          return $$.generateClass(CLASS.selectedCircles, d.id);
+      });
+      mainLineEnter
+          .append('g')
+          .attr('class', classCircles)
+          .style('cursor', function (d) {
+          return config.data_selection_isselectable(d) ? 'pointer' : null;
+      });
+      // Update date for selected circles
+      targets.forEach(function (t) {
+          $$.main
+              .selectAll('.' + CLASS.selectedCircles + $$.getTargetSelectorSuffix(t.id))
+              .selectAll('.' + CLASS.selectedCircle)
+              .each(function (d) {
+              d.value = t.values[d.index].value;
+          });
+      });
+      // MEMO: can not keep same color...
+      //mainLineUpdate.exit().remove();
+  };
+  ChartInternal.prototype.updateLine = function (durationForExit) {
+      var $$ = this;
+      var mainLine = $$.main
+          .selectAll('.' + CLASS.lines)
+          .selectAll('.' + CLASS.line)
+          .data($$.lineData.bind($$));
+      var mainLineEnter = mainLine
+          .enter()
+          .append('path')
+          .attr('class', $$.classLine.bind($$))
+          .style('stroke', $$.color);
+      $$.mainLine = mainLineEnter
+          .merge(mainLine)
+          .style('opacity', $$.initialOpacity.bind($$))
+          .style('shape-rendering', function (d) {
+          return $$.isStepType(d) ? 'crispEdges' : '';
+      })
+          .attr('transform', null);
+      mainLine
+          .exit()
+          .transition()
+          .duration(durationForExit)
+          .style('opacity', 0);
+  };
+  ChartInternal.prototype.redrawLine = function (drawLine, withTransition, transition) {
+      return [
+          (withTransition ? this.mainLine.transition(transition) : this.mainLine)
+              .attr('d', drawLine)
+              .style('stroke', this.color)
+              .style('opacity', 1)
+      ];
+  };
+  ChartInternal.prototype.generateDrawLine = function (lineIndices, isSub) {
+      var $$ = this, config = $$.config, line = $$.d3.line(), getPoints = $$.generateGetLinePoints(lineIndices, isSub), yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale, xValue = function (d) {
+          return (isSub ? $$.subxx : $$.xx).call($$, d);
+      }, yValue = function (d, i) {
+          return config.data_groups.length > 0
+              ? getPoints(d, i)[0][1]
+              : yScaleGetter.call($$, d.id)(d.value);
+      };
+      line = config.axis_rotated
+          ? line.x(yValue).y(xValue)
+          : line.x(xValue).y(yValue);
+      if (!config.line_connectNull) {
+          line = line.defined(function (d) {
+              return d.value != null;
+          });
+      }
+      return function (d) {
+          var values = config.line_connectNull
+              ? $$.filterRemoveNull(d.values)
+              : d.values, x = isSub ? $$.subX : $$.x, y = yScaleGetter.call($$, d.id), x0 = 0, y0 = 0, path;
+          if ($$.isLineType(d)) {
+              if (config.data_regions[d.id]) {
+                  path = $$.lineWithRegions(values, x, y, config.data_regions[d.id]);
+              }
+              else {
+                  if ($$.isStepType(d)) {
+                      values = $$.convertValuesToStep(values);
+                  }
+                  path = line.curve($$.getInterpolate(d))(values);
+              }
+          }
+          else {
+              if (values[0]) {
+                  x0 = x(values[0].x);
+                  y0 = y(values[0].value);
+              }
+              path = config.axis_rotated ? 'M ' + y0 + ' ' + x0 : 'M ' + x0 + ' ' + y0;
+          }
+          return path ? path : 'M 0 0';
+      };
+  };
+  ChartInternal.prototype.generateGetLinePoints = function (lineIndices, isSub) {
+      // partial duplication of generateGetBarPoints
+      var $$ = this, config = $$.config, lineTargetsNum = lineIndices.__max__ + 1, x = $$.getShapeX(0, lineTargetsNum, lineIndices, !!isSub), y = $$.getShapeY(!!isSub), lineOffset = $$.getShapeOffset($$.isLineType, lineIndices, !!isSub), yScale = isSub ? $$.getSubYScale : $$.getYScale;
+      return function (d, i) {
+          var y0 = yScale.call($$, d.id)(0), offset = lineOffset(d, i) || y0, // offset is for stacked area chart
+          posX = x(d), posY = y(d);
+          // fix posY not to overflow opposite quadrant
+          if (config.axis_rotated) {
+              if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) {
+                  posY = y0;
+              }
+          }
+          // 1 point that marks the line position
+          return [
+              [posX, posY - (y0 - offset)],
+              [posX, posY - (y0 - offset)],
+              [posX, posY - (y0 - offset)],
+              [posX, posY - (y0 - offset)] // needed for compatibility
+          ];
+      };
+  };
+  ChartInternal.prototype.lineWithRegions = function (d, x, y, _regions) {
+      var $$ = this, config = $$.config, prev = -1, i, j, s = 'M', sWithRegion, xp, yp, dx, dy, dd, diff, diffx2, xOffset = $$.isCategorized() ? 0.5 : 0, xValue, yValue, regions = [];
+      function isWithinRegions(x, regions) {
+          var i;
+          for (i = 0; i < regions.length; i++) {
+              if (regions[i].start < x && x <= regions[i].end) {
+                  return true;
+              }
+          }
+          return false;
+      }
+      // Check start/end of regions
+      if (isDefined(_regions)) {
+          for (i = 0; i < _regions.length; i++) {
+              regions[i] = {};
+              if (isUndefined(_regions[i].start)) {
+                  regions[i].start = d[0].x;
+              }
+              else {
+                  regions[i].start = $$.isTimeSeries()
+                      ? $$.parseDate(_regions[i].start)
+                      : _regions[i].start;
+              }
+              if (isUndefined(_regions[i].end)) {
+                  regions[i].end = d[d.length - 1].x;
+              }
+              else {
+                  regions[i].end = $$.isTimeSeries()
+                      ? $$.parseDate(_regions[i].end)
+                      : _regions[i].end;
+              }
+          }
+      }
+      // Set scales
+      xValue = config.axis_rotated
+          ? function (d) {
+              return y(d.value);
+          }
+          : function (d) {
+              return x(d.x);
+          };
+      yValue = config.axis_rotated
+          ? function (d) {
+              return x(d.x);
+          }
+          : function (d) {
+              return y(d.value);
+          };
+      // Define svg generator function for region
+      function generateM(points) {
+          return ('M' +
+              points[0][0] +
+              ' ' +
+              points[0][1] +
+              ' ' +
+              points[1][0] +
+              ' ' +
+              points[1][1]);
+      }
+      if ($$.isTimeSeries()) {
+          sWithRegion = function (d0, d1, j, diff) {
+              var x0 = d0.x.getTime(), x_diff = d1.x - d0.x, xv0 = new Date(x0 + x_diff * j), xv1 = new Date(x0 + x_diff * (j + diff)), points;
+              if (config.axis_rotated) {
+                  points = [
+                      [y(yp(j)), x(xv0)],
+                      [y(yp(j + diff)), x(xv1)]
+                  ];
+              }
+              else {
+                  points = [
+                      [x(xv0), y(yp(j))],
+                      [x(xv1), y(yp(j + diff))]
+                  ];
+              }
+              return generateM(points);
+          };
+      }
+      else {
+          sWithRegion = function (d0, d1, j, diff) {
+              var points;
+              if (config.axis_rotated) {
+                  points = [
+                      [y(yp(j), true), x(xp(j))],
+                      [y(yp(j + diff), true), x(xp(j + diff))]
+                  ];
+              }
+              else {
+                  points = [
+                      [x(xp(j), true), y(yp(j))],
+                      [x(xp(j + diff), true), y(yp(j + diff))]
+                  ];
+              }
+              return generateM(points);
+          };
+      }
+      // Generate
+      for (i = 0; i < d.length; i++) {
+          // Draw as normal
+          if (isUndefined(regions) || !isWithinRegions(d[i].x, regions)) {
+              s += ' ' + xValue(d[i]) + ' ' + yValue(d[i]);
+          }
+          // Draw with region // TODO: Fix for horizotal charts
+          else {
+              xp = $$.getScale(d[i - 1].x + xOffset, d[i].x + xOffset, $$.isTimeSeries());
+              yp = $$.getScale(d[i - 1].value, d[i].value);
+              dx = x(d[i].x) - x(d[i - 1].x);
+              dy = y(d[i].value) - y(d[i - 1].value);
+              dd = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
+              diff = 2 / dd;
+              diffx2 = diff * 2;
+              for (j = diff; j <= 1; j += diffx2) {
+                  s += sWithRegion(d[i - 1], d[i], j, diff);
+              }
+          }
+          prev = d[i].x;
+      }
+      return s;
+  };
+  ChartInternal.prototype.updateArea = function (durationForExit) {
+      var $$ = this, d3 = $$.d3;
+      var mainArea = $$.main
+          .selectAll('.' + CLASS.areas)
+          .selectAll('.' + CLASS.area)
+          .data($$.lineData.bind($$));
+      var mainAreaEnter = mainArea
+          .enter()
+          .append('path')
+          .attr('class', $$.classArea.bind($$))
+          .style('fill', $$.color)
+          .style('opacity', function () {
+          $$.orgAreaOpacity = +d3.select(this).style('opacity');
+          return 0;
+      });
+      $$.mainArea = mainAreaEnter
+          .merge(mainArea)
+          .style('opacity', $$.orgAreaOpacity);
+      mainArea
+          .exit()
+          .transition()
+          .duration(durationForExit)
+          .style('opacity', 0);
+  };
+  ChartInternal.prototype.redrawArea = function (drawArea, withTransition, transition) {
+      return [
+          (withTransition ? this.mainArea.transition(transition) : this.mainArea)
+              .attr('d', drawArea)
+              .style('fill', this.color)
+              .style('opacity', this.orgAreaOpacity)
+      ];
+  };
+  ChartInternal.prototype.generateDrawArea = function (areaIndices, isSub) {
+      var $$ = this, config = $$.config, area = $$.d3.area(), getPoints = $$.generateGetAreaPoints(areaIndices, isSub), yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale, xValue = function (d) {
+          return (isSub ? $$.subxx : $$.xx).call($$, d);
+      }, value0 = function (d, i) {
+          return config.data_groups.length > 0
+              ? getPoints(d, i)[0][1]
+              : yScaleGetter.call($$, d.id)($$.getAreaBaseValue(d.id));
+      }, value1 = function (d, i) {
+          return config.data_groups.length > 0
+              ? getPoints(d, i)[1][1]
+              : yScaleGetter.call($$, d.id)(d.value);
+      };
+      area = config.axis_rotated
+          ? area
+              .x0(value0)
+              .x1(value1)
+              .y(xValue)
+          : area
+              .x(xValue)
+              .y0(config.area_above ? 0 : value0)
+              .y1(value1);
+      if (!config.line_connectNull) {
+          area = area.defined(function (d) {
+              return d.value !== null;
+          });
+      }
+      return function (d) {
+          var values = config.line_connectNull
+              ? $$.filterRemoveNull(d.values)
+              : d.values, x0 = 0, y0 = 0, path;
+          if ($$.isAreaType(d)) {
+              if ($$.isStepType(d)) {
+                  values = $$.convertValuesToStep(values);
+              }
+              path = area.curve($$.getInterpolate(d))(values);
+          }
+          else {
+              if (values[0]) {
+                  x0 = $$.x(values[0].x);
+                  y0 = $$.getYScale(d.id)(values[0].value);
+              }
+              path = config.axis_rotated ? 'M ' + y0 + ' ' + x0 : 'M ' + x0 + ' ' + y0;
+          }
+          return path ? path : 'M 0 0';
+      };
+  };
+  ChartInternal.prototype.getAreaBaseValue = function () {
+      return 0;
+  };
+  ChartInternal.prototype.generateGetAreaPoints = function (areaIndices, isSub) {
+      // partial duplication of generateGetBarPoints
+      var $$ = this, config = $$.config, areaTargetsNum = areaIndices.__max__ + 1, x = $$.getShapeX(0, areaTargetsNum, areaIndices, !!isSub), y = $$.getShapeY(!!isSub), areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, !!isSub), yScale = isSub ? $$.getSubYScale : $$.getYScale;
+      return function (d, i) {
+          var y0 = yScale.call($$, d.id)(0), offset = areaOffset(d, i) || y0, // offset is for stacked area chart
+          posX = x(d), posY = y(d);
+          // fix posY not to overflow opposite quadrant
+          if (config.axis_rotated) {
+              if ((0 < d.value && posY < y0) || (d.value < 0 && y0 < posY)) {
+                  posY = y0;
+              }
+          }
+          // 1 point that marks the area position
+          return [
+              [posX, offset],
+              [posX, posY - (y0 - offset)],
+              [posX, posY - (y0 - offset)],
+              [posX, offset] // needed for compatibility
+          ];
+      };
+  };
+  ChartInternal.prototype.updateCircle = function (cx, cy) {
+      var $$ = this;
+      var mainCircle = $$.main
+          .selectAll('.' + CLASS.circles)
+          .selectAll('.' + CLASS.circle)
+          .data($$.lineOrScatterOrStanfordData.bind($$));
+      var mainCircleEnter = mainCircle
+          .enter()
+          .append('circle')
+          .attr('shape-rendering', $$.isStanfordGraphType() ? 'crispEdges' : '')
+          .attr('class', $$.classCircle.bind($$))
+          .attr('cx', cx)
+          .attr('cy', cy)
+          .attr('r', $$.pointR.bind($$))
+          .style('color', $$.isStanfordGraphType() ? $$.getStanfordPointColor.bind($$) : $$.color);
+      $$.mainCircle = mainCircleEnter
+          .merge(mainCircle)
+          .style('opacity', $$.isStanfordGraphType() ? 1 : $$.initialOpacityForCircle.bind($$));
+      mainCircle.exit().style('opacity', 0);
+  };
+  ChartInternal.prototype.redrawCircle = function (cx, cy, withTransition, transition) {
+      var $$ = this, selectedCircles = $$.main.selectAll('.' + CLASS.selectedCircle);
+      return [
+          (withTransition ? $$.mainCircle.transition(transition) : $$.mainCircle)
+              .style('opacity', this.opacityForCircle.bind($$))
+              .style('color', $$.isStanfordGraphType() ? $$.getStanfordPointColor.bind($$) : $$.color)
+              .attr('cx', cx)
+              .attr('cy', cy),
+          (withTransition ? selectedCircles.transition(transition) : selectedCircles)
+              .attr('cx', cx)
+              .attr('cy', cy)
+      ];
+  };
+  ChartInternal.prototype.circleX = function (d) {
+      return d.x || d.x === 0 ? this.x(d.x) : null;
+  };
+  ChartInternal.prototype.updateCircleY = function () {
+      var $$ = this, lineIndices, getPoints;
+      if ($$.config.data_groups.length > 0) {
+          (lineIndices = $$.getShapeIndices($$.isLineType)),
+              (getPoints = $$.generateGetLinePoints(lineIndices));
+          $$.circleY = function (d, i) {
+              return getPoints(d, i)[0][1];
+          };
+      }
+      else {
+          $$.circleY = function (d) {
+              return $$.getYScale(d.id)(d.value);
+          };
+      }
+  };
+  ChartInternal.prototype.getCircles = function (i, id) {
+      var $$ = this;
+      return (id
+          ? $$.main.selectAll('.' + CLASS.circles + $$.getTargetSelectorSuffix(id))
+          : $$.main).selectAll('.' + CLASS.circle + (isValue(i) ? '-' + i : ''));
+  };
+  ChartInternal.prototype.expandCircles = function (i, id, reset) {
+      var $$ = this, r = $$.pointExpandedR.bind($$);
+      if (reset) {
+          $$.unexpandCircles();
+      }
+      $$.getCircles(i, id)
+          .classed(CLASS.EXPANDED, true)
+          .attr('r', r);
+  };
+  ChartInternal.prototype.unexpandCircles = function (i) {
+      var $$ = this, r = $$.pointR.bind($$);
+      $$.getCircles(i)
+          .filter(function () {
+          return $$.d3.select(this).classed(CLASS.EXPANDED);
+      })
+          .classed(CLASS.EXPANDED, false)
+          .attr('r', r);
+  };
+  ChartInternal.prototype.pointR = function (d) {
+      var $$ = this, config = $$.config;
+      return $$.isStepType(d)
+          ? 0
+          : isFunction(config.point_r)
+              ? config.point_r(d)
+              : config.point_r;
+  };
+  ChartInternal.prototype.pointExpandedR = function (d) {
+      var $$ = this, config = $$.config;
+      if (config.point_focus_expand_enabled) {
+          return isFunction(config.point_focus_expand_r)
+              ? config.point_focus_expand_r(d)
+              : config.point_focus_expand_r
+                  ? config.point_focus_expand_r
+                  : $$.pointR(d) * 1.75;
+      }
+      else {
+          return $$.pointR(d);
+      }
+  };
+  ChartInternal.prototype.pointSelectR = function (d) {
+      var $$ = this, config = $$.config;
+      return isFunction(config.point_select_r)
+          ? config.point_select_r(d)
+          : config.point_select_r
+              ? config.point_select_r
+              : $$.pointR(d) * 4;
+  };
+  ChartInternal.prototype.isWithinCircle = function (that, r) {
+      var d3 = this.d3, mouse = d3.mouse(that), d3_this = d3.select(that), cx = +d3_this.attr('cx'), cy = +d3_this.attr('cy');
+      return Math.sqrt(Math.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)) < r;
+  };
+  ChartInternal.prototype.isWithinStep = function (that, y) {
+      return Math.abs(y - this.d3.mouse(that)[1]) < 30;
+  };
+
+  ChartInternal.prototype.getCurrentWidth = function () {
+      var $$ = this, config = $$.config;
+      return config.size_width ? config.size_width : $$.getParentWidth();
+  };
+  ChartInternal.prototype.getCurrentHeight = function () {
+      var $$ = this, config = $$.config, h = config.size_height ? config.size_height : $$.getParentHeight();
+      return h > 0
+          ? h
+          : 320 / ($$.hasType('gauge') && !config.gauge_fullCircle ? 2 : 1);
+  };
+  ChartInternal.prototype.getCurrentPaddingTop = function () {
+      var $$ = this, config = $$.config, padding = isValue(config.padding_top) ? config.padding_top : 0;
+      if ($$.title && $$.title.node()) {
+          padding += $$.getTitlePadding();
+      }
+      return padding;
+  };
+  ChartInternal.prototype.getCurrentPaddingBottom = function () {
+      var config = this.config;
+      return isValue(config.padding_bottom) ? config.padding_bottom : 0;
+  };
+  ChartInternal.prototype.getCurrentPaddingLeft = function (withoutRecompute) {
+      var $$ = this, config = $$.config;
+      if (isValue(config.padding_left)) {
+          return config.padding_left;
+      }
+      else if (config.axis_rotated) {
+          return !config.axis_x_show || config.axis_x_inner
+              ? 1
+              : Math.max(ceil10($$.getAxisWidthByAxisId('x', withoutRecompute)), 40);
+      }
+      else if (!config.axis_y_show || config.axis_y_inner) {
+          // && !config.axis_rotated
+          return $$.axis.getYAxisLabelPosition().isOuter ? 30 : 1;
+      }
+      else {
+          return ceil10($$.getAxisWidthByAxisId('y', withoutRecompute));
+      }
+  };
+  ChartInternal.prototype.getCurrentPaddingRight = function () {
+      var $$ = this, config = $$.config, padding = 0, defaultPadding = 10, legendWidthOnRight = $$.isLegendRight ? $$.getLegendWidth() + 20 : 0;
+      if (isValue(config.padding_right)) {
+          padding = config.padding_right + 1; // 1 is needed not to hide tick line
+      }
+      else if (config.axis_rotated) {
+          padding = defaultPadding + legendWidthOnRight;
+      }
+      else if (!config.axis_y2_show || config.axis_y2_inner) {
+          // && !config.axis_rotated
+          padding =
+              2 +
+                  legendWidthOnRight +
+                  ($$.axis.getY2AxisLabelPosition().isOuter ? 20 : 0);
+      }
+      else {
+          padding = ceil10($$.getAxisWidthByAxisId('y2')) + legendWidthOnRight;
+      }
+      if ($$.colorScale && $$.colorScale.node()) {
+          padding += $$.getColorScalePadding();
+      }
+      return padding;
+  };
+  ChartInternal.prototype.getParentRectValue = function (key) {
+      var parent = this.selectChart.node(), v;
+      while (parent && parent.tagName !== 'BODY') {
+          try {
+              v = parent.getBoundingClientRect()[key];
+          }
+          catch (e) {
+              if (key === 'width') {
+                  // In IE in certain cases getBoundingClientRect
+                  // will cause an "unspecified error"
+                  v = parent.offsetWidth;
+              }
+          }
+          if (v) {
+              break;
+          }
+          parent = parent.parentNode;
+      }
+      return v;
+  };
+  ChartInternal.prototype.getParentWidth = function () {
+      return this.getParentRectValue('width');
+  };
+  ChartInternal.prototype.getParentHeight = function () {
+      var h = this.selectChart.style('height');
+      return h.indexOf('px') > 0 ? +h.replace('px', '') : 0;
+  };
+  ChartInternal.prototype.getSvgLeft = function (withoutRecompute) {
+      var $$ = this, config = $$.config, hasLeftAxisRect = config.axis_rotated || (!config.axis_rotated && !config.axis_y_inner), leftAxisClass = config.axis_rotated ? CLASS.axisX : CLASS.axisY, leftAxis = $$.main.select('.' + leftAxisClass).node(), svgRect = leftAxis && hasLeftAxisRect
+          ? leftAxis.getBoundingClientRect()
+          : { right: 0 }, chartRect = $$.selectChart.node().getBoundingClientRect(), hasArc = $$.hasArcType(), svgLeft = svgRect.right -
+          chartRect.left -
+          (hasArc ? 0 : $$.getCurrentPaddingLeft(withoutRecompute));
+      return svgLeft > 0 ? svgLeft : 0;
+  };
+  ChartInternal.prototype.getAxisWidthByAxisId = function (id, withoutRecompute) {
+      var $$ = this, position = $$.axis.getLabelPositionById(id);
+      return ($$.axis.getMaxTickWidth(id, withoutRecompute) + (position.isInner ? 20 : 40));
+  };
+  ChartInternal.prototype.getHorizontalAxisHeight = function (axisId, isSubchart) {
+      var $$ = this, config = $$.config, h = 30;
+      if (axisId === 'x' && !(isDefined(isSubchart) && isSubchart ? config.subchart_axis_x_show : config.axis_x_show)) {
+          return 8;
+      }
+      if (axisId === 'x' && config.axis_x_height) {
+          return config.axis_x_height;
+      }
+      if (axisId === 'y' && !config.axis_y_show) {
+          return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1;
+      }
+      if (axisId === 'y2' && !config.axis_y2_show) {
+          return $$.rotated_padding_top;
+      }
+      // Calculate x axis height when tick rotated
+      if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) {
+          h =
+              30 +
+                  $$.axis.getMaxTickWidth(axisId) *
+                      Math.cos((Math.PI * (90 - Math.abs(config.axis_x_tick_rotate))) / 180);
+      }
+      // Calculate y axis height when tick rotated
+      if (axisId === 'y' && config.axis_rotated && config.axis_y_tick_rotate) {
+          h =
+              30 +
+                  $$.axis.getMaxTickWidth(axisId) *
+                      Math.cos((Math.PI * (90 - Math.abs(config.axis_y_tick_rotate))) / 180);
+      }
+      return (h +
+          ($$.axis.getLabelPositionById(axisId).isInner ? 0 : 10) +
+          (axisId === 'y2' ? -10 : 0));
+  };
+
+  ChartInternal.prototype.initBrush = function (scale) {
+      var $$ = this, d3 = $$.d3;
+      // TODO: dynamically change brushY/brushX according to axis_rotated.
+      $$.brush = ($$.config.axis_rotated ? d3.brushY() : d3.brushX())
+          .on('brush', function () {
+          var event = d3.event.sourceEvent;
+          if (event && event.type === 'zoom') {
+              return;
+          }
+          $$.redrawForBrush();
+      })
+          .on('end', function () {
+          var event = d3.event.sourceEvent;
+          if (event && event.type === 'zoom') {
+              return;
+          }
+          if ($$.brush.empty() && event && event.type !== 'end') {
+              $$.brush.clear();
+          }
+      });
+      $$.brush.updateExtent = function () {
+          var range = this.scale.range(), extent;
+          if ($$.config.axis_rotated) {
+              extent = [
+                  [0, range[0]],
+                  [$$.width2, range[1]]
+              ];
+          }
+          else {
+              extent = [
+                  [range[0], 0],
+                  [range[1], $$.height2]
+              ];
+          }
+          this.extent(extent);
+          return this;
+      };
+      $$.brush.updateScale = function (scale) {
+          this.scale = scale;
+          return this;
+      };
+      $$.brush.update = function (scale) {
+          this.updateScale(scale || $$.subX).updateExtent();
+          $$.context.select('.' + CLASS.brush).call(this);
+      };
+      $$.brush.clear = function () {
+          $$.context.select('.' + CLASS.brush).call($$.brush.move, null);
+      };
+      $$.brush.selection = function () {
+          return d3.brushSelection($$.context.select('.' + CLASS.brush).node());
+      };
+      $$.brush.selectionAsValue = function (selectionAsValue, withTransition) {
+          var selection, brush;
+          if (selectionAsValue) {
+              if ($$.context) {
+                  selection = [
+                      this.scale(selectionAsValue[0]),
+                      this.scale(selectionAsValue[1])
+                  ];
+                  brush = $$.context.select('.' + CLASS.brush);
+                  if (withTransition) {
+                      brush = brush.transition();
+                  }
+                  $$.brush.move(brush, selection);
+              }
+              return [];
+          }
+          selection = $$.brush.selection() || [0, 0];
+          return [this.scale.invert(selection[0]), this.scale.invert(selection[1])];
+      };
+      $$.brush.empty = function () {
+          var selection = $$.brush.selection();
+          return !selection || selection[0] === selection[1];
+      };
+      return $$.brush.updateScale(scale);
+  };
+  ChartInternal.prototype.initSubchart = function () {
+      var $$ = this, config = $$.config, context = ($$.context = $$.svg
+          .append('g')
+          .attr('transform', $$.getTranslate('context')));
+      // set style
+      context.style('visibility', 'visible');
+      // Define g for chart area
+      context
+          .append('g')
+          .attr('clip-path', $$.clipPathForSubchart)
+          .attr('class', CLASS.chart);
+      // Define g for bar chart area
+      context
+          .select('.' + CLASS.chart)
+          .append('g')
+          .attr('class', CLASS.chartBars);
+      // Define g for line chart area
+      context
+          .select('.' + CLASS.chart)
+          .append('g')
+          .attr('class', CLASS.chartLines);
+      // Add extent rect for Brush
+      context
+          .append('g')
+          .attr('clip-path', $$.clipPath)
+          .attr('class', CLASS.brush);
+      // ATTENTION: This must be called AFTER chart added
+      // Add Axis
+      $$.axes.subx = context
+          .append('g')
+          .attr('class', CLASS.axisX)
+          .attr('transform', $$.getTranslate('subx'))
+          .attr('clip-path', config.axis_rotated ? '' : $$.clipPathForXAxis)
+          .style('visibility', config.subchart_axis_x_show ? 'visible' : 'hidden');
+  };
+  ChartInternal.prototype.initSubchartBrush = function () {
+      var $$ = this;
+      // Add extent rect for Brush
+      $$.initBrush($$.subX).updateExtent();
+      $$.context.select('.' + CLASS.brush).call($$.brush);
+  };
+  ChartInternal.prototype.updateTargetsForSubchart = function (targets) {
+      var $$ = this, context = $$.context, config = $$.config, contextLineEnter, contextLine, contextBarEnter, contextBar, classChartBar = $$.classChartBar.bind($$), classBars = $$.classBars.bind($$), classChartLine = $$.classChartLine.bind($$), classLines = $$.classLines.bind($$), classAreas = $$.classAreas.bind($$);
+      //-- Bar --//
+      contextBar = context
+          .select('.' + CLASS.chartBars)
+          .selectAll('.' + CLASS.chartBar)
+          .data(targets);
+      contextBarEnter = contextBar
+          .enter()
+          .append('g')
+          .style('opacity', 0);
+      contextBarEnter.merge(contextBar).attr('class', classChartBar);
+      // Bars for each data
+      contextBarEnter.append('g').attr('class', classBars);
+      //-- Line --//
+      contextLine = context
+          .select('.' + CLASS.chartLines)
+          .selectAll('.' + CLASS.chartLine)
+          .data(targets);
+      contextLineEnter = contextLine
+          .enter()
+          .append('g')
+          .style('opacity', 0);
+      contextLineEnter.merge(contextLine).attr('class', classChartLine);
+      // Lines for each data
+      contextLineEnter.append('g').attr('class', classLines);
+      // Area
+      contextLineEnter.append('g').attr('class', classAreas);
+      //-- Brush --//
+      context
+          .selectAll('.' + CLASS.brush + ' rect')
+          .attr(config.axis_rotated ? 'width' : 'height', config.axis_rotated ? $$.width2 : $$.height2);
+  };
+  ChartInternal.prototype.updateBarForSubchart = function (durationForExit) {
+      var $$ = this;
+      var contextBar = $$.context
+          .selectAll('.' + CLASS.bars)
+          .selectAll('.' + CLASS.bar)
+          .data($$.barData.bind($$));
+      var contextBarEnter = contextBar
+          .enter()
+          .append('path')
+          .attr('class', $$.classBar.bind($$))
+          .style('stroke', 'none')
+          .style('fill', $$.color);
+      contextBar
+          .exit()
+          .transition()
+          .duration(durationForExit)
+          .style('opacity', 0)
+          .remove();
+      $$.contextBar = contextBarEnter
+          .merge(contextBar)
+          .style('opacity', $$.initialOpacity.bind($$));
+  };
+  ChartInternal.prototype.redrawBarForSubchart = function (drawBarOnSub, withTransition, duration) {
+      (withTransition
+          ? this.contextBar.transition(Math.random().toString()).duration(duration)
+          : this.contextBar)
+          .attr('d', drawBarOnSub)
+          .style('opacity', 1);
+  };
+  ChartInternal.prototype.updateLineForSubchart = function (durationForExit) {
+      var $$ = this;
+      var contextLine = $$.context
+          .selectAll('.' + CLASS.lines)
+          .selectAll('.' + CLASS.line)
+          .data($$.lineData.bind($$));
+      var contextLineEnter = contextLine
+          .enter()
+          .append('path')
+          .attr('class', $$.classLine.bind($$))
+          .style('stroke', $$.color);
+      contextLine
+          .exit()
+          .transition()
+          .duration(durationForExit)
+          .style('opacity', 0)
+          .remove();
+      $$.contextLine = contextLineEnter
+          .merge(contextLine)
+          .style('opacity', $$.initialOpacity.bind($$));
+  };
+  ChartInternal.prototype.redrawLineForSubchart = function (drawLineOnSub, withTransition, duration) {
+      (withTransition
+          ? this.contextLine.transition(Math.random().toString()).duration(duration)
+          : this.contextLine)
+          .attr('d', drawLineOnSub)
+          .style('opacity', 1);
+  };
+  ChartInternal.prototype.updateAreaForSubchart = function (durationForExit) {
+      var $$ = this, d3 = $$.d3;
+      var contextArea = $$.context
+          .selectAll('.' + CLASS.areas)
+          .selectAll('.' + CLASS.area)
+          .data($$.lineData.bind($$));
+      var contextAreaEnter = contextArea
+          .enter()
+          .append('path')
+          .attr('class', $$.classArea.bind($$))
+          .style('fill', $$.color)
+          .style('opacity', function () {
+          $$.orgAreaOpacity = +d3.select(this).style('opacity');
+          return 0;
+      });
+      contextArea
+          .exit()
+          .transition()
+          .duration(durationForExit)
+          .style('opacity', 0)
+          .remove();
+      $$.contextArea = contextAreaEnter.merge(contextArea).style('opacity', 0);
+  };
+  ChartInternal.prototype.redrawAreaForSubchart = function (drawAreaOnSub, withTransition, duration) {
+      (withTransition
+          ? this.contextArea.transition(Math.random().toString()).duration(duration)
+          : this.contextArea)
+          .attr('d', drawAreaOnSub)
+          .style('fill', this.color)
+          .style('opacity', this.orgAreaOpacity);
+  };
+  ChartInternal.prototype.redrawSubchart = function (withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices) {
+      var $$ = this, d3 = $$.d3, drawAreaOnSub, drawBarOnSub, drawLineOnSub;
+      // reflect main chart to extent on subchart if zoomed
+      if (d3.event && d3.event.type === 'zoom') {
+          $$.brush.selectionAsValue($$.x.orgDomain());
+      }
+      // update subchart elements if needed
+      if (withSubchart) {
+          // extent rect
+          if (!$$.brush.empty()) {
+              $$.brush.selectionAsValue($$.x.orgDomain());
+          }
+          // setup drawer - MEMO: this must be called after axis updated
+          drawAreaOnSub = $$.generateDrawArea(areaIndices, true);
+          drawBarOnSub = $$.generateDrawBar(barIndices, true);
+          drawLineOnSub = $$.generateDrawLine(lineIndices, true);
+          $$.updateBarForSubchart(duration);
+          $$.updateLineForSubchart(duration);
+          $$.updateAreaForSubchart(duration);
+          $$.redrawBarForSubchart(drawBarOnSub, duration, duration);
+          $$.redrawLineForSubchart(drawLineOnSub, duration, duration);
+          $$.redrawAreaForSubchart(drawAreaOnSub, duration, duration);
+      }
+  };
+  ChartInternal.prototype.redrawForBrush = function () {
+      var $$ = this, x = $$.x, d3 = $$.d3, s;
+      $$.redraw({
+          withTransition: false,
+          withY: $$.config.zoom_rescale,
+          withSubchart: false,
+          withUpdateXDomain: true,
+          withEventRect: false,
+          withDimension: false
+      });
+      // update zoom transation binded to event rect
+      s = d3.event.selection || $$.brush.scale.range();
+      $$.main
+          .select('.' + CLASS.eventRect)
+          .call($$.zoom.transform, d3.zoomIdentity.scale($$.width / (s[1] - s[0])).translate(-s[0], 0));
+      $$.config.subchart_onbrush.call($$.api, x.orgDomain());
+  };
+  ChartInternal.prototype.transformContext = function (withTransition, transitions) {
+      var $$ = this, subXAxis;
+      if (transitions && transitions.axisSubX) {
+          subXAxis = transitions.axisSubX;
+      }
+      else {
+          subXAxis = $$.context.select('.' + CLASS.axisX);
+          if (withTransition) {
+              subXAxis = subXAxis.transition();
+          }
+      }
+      $$.context.attr('transform', $$.getTranslate('context'));
+      subXAxis.attr('transform', $$.getTranslate('subx'));
+  };
+  ChartInternal.prototype.getDefaultSelection = function () {
+      var $$ = this, config = $$.config, selection = isFunction(config.axis_x_selection)
+          ? config.axis_x_selection($$.getXDomain($$.data.targets))
+          : config.axis_x_selection;
+      if ($$.isTimeSeries()) {
+          selection = [$$.parseDate(selection[0]), $$.parseDate(selection[1])];
+      }
+      return selection;
+  };
+  ChartInternal.prototype.removeSubchart = function () {
+      var $$ = this;
+      $$.brush = null;
+      $$.context.remove();
+      $$.context = null;
+  };
+
+  ChartInternal.prototype.initText = function () {
+      var $$ = this;
+      $$.main
+          .select('.' + CLASS.chart)
+          .append('g')
+          .attr('class', CLASS.chartTexts);
+      $$.mainText = $$.d3.selectAll([]);
+  };
+  ChartInternal.prototype.updateTargetsForText = function (targets) {
+      var $$ = this, classChartText = $$.classChartText.bind($$), classTexts = $$.classTexts.bind($$), classFocus = $$.classFocus.bind($$);
+      var mainText = $$.main
+          .select('.' + CLASS.chartTexts)
+          .selectAll('.' + CLASS.chartText)
+          .data(targets);
+      var mainTextEnter = mainText
+          .enter()
+          .append('g')
+          .attr('class', classChartText)
+          .style('opacity', 0)
+          .style('pointer-events', 'none');
+      mainTextEnter.append('g').attr('class', classTexts);
+      mainTextEnter.merge(mainText).attr('class', function (d) {
+          return classChartText(d) + classFocus(d);
+      });
+  };
+  ChartInternal.prototype.updateText = function (xForText, yForText, durationForExit) {
+      var $$ = this, config = $$.config, barOrLineData = $$.barOrLineData.bind($$), classText = $$.classText.bind($$);
+      var mainText = $$.main
+          .selectAll('.' + CLASS.texts)
+          .selectAll('.' + CLASS.text)
+          .data(barOrLineData);
+      var mainTextEnter = mainText
+          .enter()
+          .append('text')
+          .attr('class', classText)
+          .attr('text-anchor', function (d) {
+          return config.axis_rotated ? (d.value < 0 ? 'end' : 'start') : 'middle';
+      })
+          .style('stroke', 'none')
+          .attr('x', xForText)
+          .attr('y', yForText)
+          .style('fill', function (d) {
+          return $$.color(d);
+      })
+          .style('fill-opacity', 0);
+      $$.mainText = mainTextEnter.merge(mainText).text(function (d, i, j) {
+          return $$.dataLabelFormat(d.id)(d.value, d.id, i, j);
+      });
+      mainText
+          .exit()
+          .transition()
+          .duration(durationForExit)
+          .style('fill-opacity', 0)
+          .remove();
+  };
+  ChartInternal.prototype.redrawText = function (xForText, yForText, forFlow, withTransition, transition) {
+      return [
+          (withTransition ? this.mainText.transition(transition) : this.mainText)
+              .attr('x', xForText)
+              .attr('y', yForText)
+              .style('fill', this.color)
+              .style('fill-opacity', forFlow ? 0 : this.opacityForText.bind(this))
+      ];
+  };
+  ChartInternal.prototype.getTextRect = function (text, cls, element) {
+      var dummy = this.d3
+          .select('body')
+          .append('div')
+          .classed('c3', true), svg = dummy
+          .append('svg')
+          .style('visibility', 'hidden')
+          .style('position', 'fixed')
+          .style('top', 0)
+          .style('left', 0), font = this.d3.select(element).style('font'), rect;
+      svg
+          .selectAll('.dummy')
+          .data([text])
+          .enter()
+          .append('text')
+          .classed(cls ? cls : '', true)
+          .style('font', font)
+          .text(text)
+          .each(function () {
+          rect = getBBox(this);
+      });
+      dummy.remove();
+      return rect;
+  };
+  ChartInternal.prototype.generateXYForText = function (areaIndices, barIndices, lineIndices, forX) {
+      var $$ = this, getAreaPoints = $$.generateGetAreaPoints(areaIndices, false), getBarPoints = $$.generateGetBarPoints(barIndices, false), getLinePoints = $$.generateGetLinePoints(lineIndices, false), getter = forX ? $$.getXForText : $$.getYForText;
+      return function (d, i) {
+          var getPoints = $$.isAreaType(d)
+              ? getAreaPoints
+              : $$.isBarType(d)
+                  ? getBarPoints
+                  : getLinePoints;
+          return getter.call($$, getPoints(d, i), d, this);
+      };
+  };
+  ChartInternal.prototype.getXForText = function (points, d, textElement) {
+      var $$ = this, box = getBBox(textElement), xPos, padding;
+      if ($$.config.axis_rotated) {
+          padding = $$.isBarType(d) ? 4 : 6;
+          xPos = points[2][1] + padding * (d.value < 0 ? -1 : 1);
+      }
+      else {
+          xPos = $$.hasType('bar') ? (points[2][0] + points[0][0]) / 2 : points[0][0];
+      }
+      // show labels regardless of the domain if value is null
+      if (d.value === null) {
+          if (xPos > $$.width) {
+              xPos = $$.width - box.width;
+          }
+          else if (xPos < 0) {
+              xPos = 4;
+          }
+      }
+      return xPos;
+  };
+  ChartInternal.prototype.getYForText = function (points, d, textElement) {
+      var $$ = this, box = getBBox(textElement), yPos;
+      if ($$.config.axis_rotated) {
+          yPos = (points[0][0] + points[2][0] + box.height * 0.6) / 2;
+      }
+      else {
+          yPos = points[2][1];
+          if (d.value < 0 || (d.value === 0 && !$$.hasPositiveValue)) {
+              yPos += box.height;
+              if ($$.isBarType(d) && $$.isSafari()) {
+                  yPos -= 3;
+              }
+              else if (!$$.isBarType(d) && $$.isChrome()) {
+                  yPos += 3;
+              }
+          }
+          else {
+              yPos += $$.isBarType(d) ? -3 : -6;
+          }
+      }
+      // show labels regardless of the domain if value is null
+      if (d.value === null && !$$.config.axis_rotated) {
+          if (yPos < box.height) {
+              yPos = box.height;
+          }
+          else if (yPos > this.height) {
+              yPos = this.height - 4;
+          }
+      }
+      return yPos;
+  };
+
+  ChartInternal.prototype.initTitle = function () {
+      var $$ = this;
+      $$.title = $$.svg
+          .append('text')
+          .text($$.config.title_text)
+          .attr('class', $$.CLASS.title);
+  };
+  ChartInternal.prototype.redrawTitle = function () {
+      var $$ = this;
+      $$.title.attr('x', $$.xForTitle.bind($$)).attr('y', $$.yForTitle.bind($$));
+  };
+  ChartInternal.prototype.xForTitle = function () {
+      var $$ = this, config = $$.config, position = config.title_position || 'left', x;
+      if (position.indexOf('right') >= 0) {
+          x =
+              $$.currentWidth -
+                  $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width -
+                  config.title_padding.right;
+      }
+      else if (position.indexOf('center') >= 0) {
+          x = Math.max(($$.currentWidth -
+              $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node()).width) /
+              2, 0);
+      }
+      else {
+          // left
+          x = config.title_padding.left;
+      }
+      return x;
+  };
+  ChartInternal.prototype.yForTitle = function () {
+      var $$ = this;
+      return ($$.config.title_padding.top +
+          $$.getTextRect($$.title.node().textContent, $$.CLASS.title, $$.title.node())
+              .height);
+  };
+  ChartInternal.prototype.getTitlePadding = function () {
+      var $$ = this;
+      return $$.yForTitle() + $$.config.title_padding.bottom;
+  };
+
+  function powerOfTen(d) {
+      return d / Math.pow(10, Math.ceil(Math.log(d) / Math.LN10 - 1e-12)) === 1;
+  }
+  ChartInternal.prototype.drawColorScale = function () {
+      var $$ = this, d3 = $$.d3, config = $$.config, target = $$.data.targets[0], barWidth, barHeight, axis, points, legendAxis, axisScale, inverseScale, height;
+      barWidth = !isNaN(config.stanford_scaleWidth)
+          ? config.stanford_scaleWidth
+          : 20;
+      barHeight = 5;
+      if (barHeight < 0 || barWidth < 0) {
+          throw Error("Colorscale's barheight and barwidth must be greater than 0.");
+      }
+      height =
+          $$.height - config.stanford_padding.bottom - config.stanford_padding.top;
+      points = d3.range(config.stanford_padding.bottom, height, barHeight);
+      inverseScale = d3
+          .scaleSequential(target.colors)
+          .domain([points[points.length - 1], points[0]]);
+      if ($$.colorScale) {
+          $$.colorScale.remove();
+      }
+      $$.colorScale = $$.svg
+          .append('g')
+          .attr('width', 50)
+          .attr('height', height)
+          .attr('class', CLASS.colorScale);
+      $$.colorScale
+          .append('g')
+          .attr('transform', "translate(0, " + config.stanford_padding.top + ")")
+          .selectAll('bars')
+          .data(points)
+          .enter()
+          .append('rect')
+          .attr('y', function (d, i) { return i * barHeight; })
+          .attr('x', 0)
+          .attr('width', barWidth)
+          .attr('height', barHeight)
+          .attr('fill', function (d) {
+          return inverseScale(d);
+      });
+      // Legend Axis
+      axisScale = d3
+          .scaleLog()
+          .domain([target.minEpochs, target.maxEpochs])
+          .range([
+          points[0] +
+              config.stanford_padding.top +
+              points[points.length - 1] +
+              barHeight -
+              1,
+          points[0] + config.stanford_padding.top
+      ]);
+      legendAxis = d3.axisRight(axisScale);
+      if (config.stanford_scaleFormat === 'pow10') {
+          legendAxis.tickValues([1, 10, 100, 1000, 10000, 100000, 1000000, 10000000]);
+      }
+      else if (isFunction(config.stanford_scaleFormat)) {
+          legendAxis.tickFormat(config.stanford_scaleFormat);
+      }
+      else {
+          legendAxis.tickFormat(d3.format('d'));
+      }
+      if (isFunction(config.stanford_scaleValues)) {
+          legendAxis.tickValues(config.stanford_scaleValues(target.minEpochs, target.maxEpochs));
+      }
+      // Draw Axis
+      axis = $$.colorScale
+          .append('g')
+          .attr('class', 'legend axis')
+          .attr('transform', "translate(" + barWidth + ",0)")
+          .call(legendAxis);
+      if (config.stanford_scaleFormat === 'pow10') {
+          axis
+              .selectAll('.tick text')
+              .text(null)
+              .filter(powerOfTen)
+              .text(10)
+              .append('tspan')
+              .attr('dy', '-.7em') // https://bl.ocks.org/mbostock/6738229
+              .text(function (d) {
+              return Math.round(Math.log(d) / Math.LN10);
+          });
+      }
+      $$.colorScale.attr('transform', "translate(" + ($$.currentWidth - $$.xForColorScale()) + ", 0)");
+  };
+  ChartInternal.prototype.xForColorScale = function () {
+      var $$ = this;
+      return $$.config.stanford_padding.right + getBBox($$.colorScale.node()).width;
+  };
+  ChartInternal.prototype.getColorScalePadding = function () {
+      var $$ = this;
+      return $$.xForColorScale() + $$.config.stanford_padding.left + 20;
+  };
+
+  ChartInternal.prototype.isStanfordGraphType = function () {
+      var $$ = this;
+      return $$.config.data_type === 'stanford';
+  };
+  ChartInternal.prototype.initStanfordData = function () {
+      var $$ = this, d3 = $$.d3, config = $$.config, target = $$.data.targets[0], epochs, maxEpochs, minEpochs;
+      // Make larger values appear on top
+      target.values.sort(compareEpochs);
+      // Get array of epochs
+      epochs = target.values.map(function (a) { return a.epochs; });
+      minEpochs = !isNaN(config.stanford_scaleMin)
+          ? config.stanford_scaleMin
+          : d3.min(epochs);
+      maxEpochs = !isNaN(config.stanford_scaleMax)
+          ? config.stanford_scaleMax
+          : d3.max(epochs);
+      if (minEpochs > maxEpochs) {
+          throw Error('Number of minEpochs has to be smaller than maxEpochs');
+      }
+      target.colors = isFunction(config.stanford_colors)
+          ? config.stanford_colors
+          : d3.interpolateHslLong(d3.hsl(250, 1, 0.5), d3.hsl(0, 1, 0.5));
+      target.colorscale = d3
+          .scaleSequentialLog(target.colors)
+          .domain([minEpochs, maxEpochs]);
+      target.minEpochs = minEpochs;
+      target.maxEpochs = maxEpochs;
+  };
+  ChartInternal.prototype.getStanfordPointColor = function (d) {
+      var $$ = this, target = $$.data.targets[0];
+      return target.colorscale(d.epochs);
+  };
+  // http://jsfiddle.net/Xotic750/KtzLq/
+  ChartInternal.prototype.getCentroid = function (points) {
+      var area = getRegionArea(points);
+      var x = 0, y = 0, i, j, f, point1, point2;
+      for (i = 0, j = points.length - 1; i < points.length; j = i, i += 1) {
+          point1 = points[i];
+          point2 = points[j];
+          f = point1.x * point2.y - point2.x * point1.y;
+          x += (point1.x + point2.x) * f;
+          y += (point1.y + point2.y) * f;
+      }
+      f = area * 6;
+      return {
+          x: x / f,
+          y: y / f
+      };
+  };
+  ChartInternal.prototype.getStanfordTooltipTitle = function (d) {
+      var $$ = this, labelX = $$.axis.getLabelText('x'), labelY = $$.axis.getLabelText('y');
+      return "\n      <tr><th>" + (labelX ? sanitise(labelX) : 'x') + "</th><th class='value'>" + d.x + "</th></tr>\n      <tr><th>" + (labelY ? sanitise(labelY) : 'y') + "</th><th class='value'>" + d.value + "</th></tr>\n    ";
+  };
+  ChartInternal.prototype.countEpochsInRegion = function (region) {
+      var $$ = this, target = $$.data.targets[0], total, count;
+      total = target.values.reduce(function (accumulator, currentValue) { return accumulator + Number(currentValue.epochs); }, 0);
+      count = target.values.reduce(function (accumulator, currentValue) {
+          if (pointInRegion(currentValue, region)) {
+              return accumulator + Number(currentValue.epochs);
+          }
+          return accumulator;
+      }, 0);
+      return {
+          value: count,
+          percentage: count !== 0 ? ((count / total) * 100).toFixed(1) : 0
+      };
+  };
+  var getRegionArea = function (points) {
+      // thanks to: https://stackoverflow.com/questions/16282330/find-centerpoint-of-polygon-in-javascript
+      var area = 0, i, j, point1, point2;
+      for (i = 0, j = points.length - 1; i < points.length; j = i, i += 1) {
+          point1 = points[i];
+          point2 = points[j];
+          area += point1.x * point2.y;
+          area -= point1.y * point2.x;
+      }
+      area /= 2;
+      return area;
+  };
+  var pointInRegion = function (point, region) {
+      // thanks to: http://bl.ocks.org/bycoffe/5575904
+      // ray-casting algorithm based on
+      // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
+      var xi, yi, yj, xj, intersect, x = point.x, y = point.value, inside = false;
+      for (var i = 0, j = region.length - 1; i < region.length; j = i++) {
+          xi = region[i].x;
+          yi = region[i].y;
+          xj = region[j].x;
+          yj = region[j].y;
+          intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
+          if (intersect) {
+              inside = !inside;
+          }
+      }
+      return inside;
+  };
+  var compareEpochs = function (a, b) {
+      if (a.epochs < b.epochs) {
+          return -1;
+      }
+      if (a.epochs > b.epochs) {
+          return 1;
+      }
+      return 0;
+  };
+
+  ChartInternal.prototype.initStanfordElements = function () {
+      var $$ = this;
+      // Avoid blocking eventRect
+      $$.stanfordElements = $$.main
+          .select('.' + CLASS.chart)
+          .append('g')
+          .attr('class', CLASS.stanfordElements);
+      $$.stanfordElements.append('g').attr('class', CLASS.stanfordLines);
+      $$.stanfordElements.append('g').attr('class', CLASS.stanfordTexts);
+      $$.stanfordElements.append('g').attr('class', CLASS.stanfordRegions);
+  };
+  ChartInternal.prototype.updateStanfordElements = function (duration) {
+      var $$ = this, main = $$.main, config = $$.config, stanfordLine, stanfordLineEnter, stanfordRegion, stanfordRegionEnter, stanfordText, stanfordTextEnter, xvCustom = $$.xvCustom.bind($$), yvCustom = $$.yvCustom.bind($$), countPointsInRegion = $$.countEpochsInRegion.bind($$);
+      // Stanford-Lines
+      stanfordLine = main
+          .select('.' + CLASS.stanfordLines)
+          .style('shape-rendering', 'geometricprecision')
+          .selectAll('.' + CLASS.stanfordLine)
+          .data(config.stanford_lines);
+      // enter
+      stanfordLineEnter = stanfordLine
+          .enter()
+          .append('g')
+          .attr('class', function (d) {
+          return CLASS.stanfordLine + (d['class'] ? ' ' + d['class'] : '');
+      });
+      stanfordLineEnter
+          .append('line')
+          .attr('x1', function (d) {
+          return config.axis_rotated ? yvCustom(d, 'value_y1') : xvCustom(d, 'value_x1');
+      })
+          .attr('x2', function (d) {
+          return config.axis_rotated ? yvCustom(d, 'value_y2') : xvCustom(d, 'value_x2');
+      })
+          .attr('y1', function (d) {
+          return config.axis_rotated ? xvCustom(d, 'value_x1') : yvCustom(d, 'value_y1');
+      })
+          .attr('y2', function (d) {
+          return config.axis_rotated ? xvCustom(d, 'value_x2') : yvCustom(d, 'value_y2');
+      })
+          .style('opacity', 0);
+      // update
+      $$.stanfordLines = stanfordLineEnter.merge(stanfordLine);
+      $$.stanfordLines
+          .select('line')
+          .transition()
+          .duration(duration)
+          .attr('x1', function (d) {
+          return config.axis_rotated ? yvCustom(d, 'value_y1') : xvCustom(d, 'value_x1');
+      })
+          .attr('x2', function (d) {
+          return config.axis_rotated ? yvCustom(d, 'value_y2') : xvCustom(d, 'value_x2');
+      })
+          .attr('y1', function (d) {
+          return config.axis_rotated ? xvCustom(d, 'value_x1') : yvCustom(d, 'value_y1');
+      })
+          .attr('y2', function (d) {
+          return config.axis_rotated ? xvCustom(d, 'value_x2') : yvCustom(d, 'value_y2');
+      })
+          .style('opacity', 1);
+      // exit
+      stanfordLine
+          .exit()
+          .transition()
+          .duration(duration)
+          .style('opacity', 0)
+          .remove();
+      // Stanford-Text
+      stanfordText = main
+          .select('.' + CLASS.stanfordTexts)
+          .selectAll('.' + CLASS.stanfordText)
+          .data(config.stanford_texts);
+      // enter
+      stanfordTextEnter = stanfordText
+          .enter()
+          .append('g')
+          .attr('class', function (d) {
+          return CLASS.stanfordText + (d['class'] ? ' ' + d['class'] : '');
+      });
+      stanfordTextEnter
+          .append('text')
+          .attr('x', function (d) { return (config.axis_rotated ? yvCustom(d, 'y') : xvCustom(d, 'x')); })
+          .attr('y', function (d) { return (config.axis_rotated ? xvCustom(d, 'x') : yvCustom(d, 'y')); })
+          .style('opacity', 0);
+      // update
+      $$.stanfordTexts = stanfordTextEnter.merge(stanfordText);
+      $$.stanfordTexts
+          .select('text')
+          .transition()
+          .duration(duration)
+          .attr('x', function (d) { return (config.axis_rotated ? yvCustom(d, 'y') : xvCustom(d, 'x')); })
+          .attr('y', function (d) { return (config.axis_rotated ? xvCustom(d, 'x') : yvCustom(d, 'y')); })
+          .text(function (d) {
+          return d.content;
+      })
+          .style('opacity', 1);
+      // exit
+      stanfordText
+          .exit()
+          .transition()
+          .duration(duration)
+          .style('opacity', 0)
+          .remove();
+      // Stanford-Regions
+      stanfordRegion = main
+          .select('.' + CLASS.stanfordRegions)
+          .selectAll('.' + CLASS.stanfordRegion)
+          .data(config.stanford_regions);
+      // enter
+      stanfordRegionEnter = stanfordRegion
+          .enter()
+          .append('g')
+          .attr('class', function (d) {
+          return CLASS.stanfordRegion + (d['class'] ? ' ' + d['class'] : '');
+      });
+      stanfordRegionEnter
+          .append('polygon')
+          .attr('points', function (d) {
+          return d.points
+              .map(function (value) {
+              return [
+                  config.axis_rotated ? yvCustom(value, 'y') : xvCustom(value, 'x'),
+                  config.axis_rotated ? xvCustom(value, 'x') : yvCustom(value, 'y')
+              ].join(',');
+          })
+              .join(' ');
+      })
+          .style('opacity', 0);
+      stanfordRegionEnter
+          .append('text')
+          .attr('x', function (d) { return $$.getCentroid(d.points).x; })
+          .attr('y', function (d) { return $$.getCentroid(d.points).y; })
+          .style('opacity', 0);
+      // update
+      $$.stanfordRegions = stanfordRegionEnter.merge(stanfordRegion);
+      $$.stanfordRegions
+          .select('polygon')
+          .transition()
+          .duration(duration)
+          .attr('points', function (d) {
+          return d.points
+              .map(function (value) {
+              return [
+                  config.axis_rotated ? yvCustom(value, 'y') : xvCustom(value, 'x'),
+                  config.axis_rotated ? xvCustom(value, 'x') : yvCustom(value, 'y')
+              ].join(',');
+          })
+              .join(' ');
+      })
+          .style('opacity', function (d) {
+          return d.opacity ? d.opacity : 0.2;
+      });
+      $$.stanfordRegions
+          .select('text')
+          .transition()
+          .duration(duration)
+          .attr('x', function (d) {
+          return config.axis_rotated
+              ? yvCustom($$.getCentroid(d.points), 'y')
+              : xvCustom($$.getCentroid(d.points), 'x');
+      })
+          .attr('y', function (d) {
+          return config.axis_rotated
+              ? xvCustom($$.getCentroid(d.points), 'x')
+              : yvCustom($$.getCentroid(d.points), 'y');
+      })
+          .text(function (d) {
+          if (d.text) {
+              var value, percentage, temp;
+              if ($$.isStanfordGraphType()) {
+                  temp = countPointsInRegion(d.points);
+                  value = temp.value;
+                  percentage = temp.percentage;
+              }
+              return d.text(value, percentage);
+          }
+          return '';
+      })
+          .attr('text-anchor', 'middle')
+          .attr('dominant-baseline', 'middle')
+          .style('opacity', 1);
+      // exit
+      stanfordRegion
+          .exit()
+          .transition()
+          .duration(duration)
+          .style('opacity', 0)
+          .remove();
+  };
+
+  ChartInternal.prototype.initTooltip = function () {
+      var $$ = this, config = $$.config, i;
+      $$.tooltip = $$.selectChart
+          .style('position', 'relative')
+          .append('div')
+          .attr('class', CLASS.tooltipContainer)
+          .style('position', 'absolute')
+          .style('pointer-events', 'none')
+          .style('display', 'none');
+      // Show tooltip if needed
+      if (config.tooltip_init_show) {
+          if ($$.isTimeSeries() && isString(config.tooltip_init_x)) {
+              config.tooltip_init_x = $$.parseDate(config.tooltip_init_x);
+              for (i = 0; i < $$.data.targets[0].values.length; i++) {
+                  if ($$.data.targets[0].values[i].x - config.tooltip_init_x === 0) {
+                      break;
+                  }
+              }
+              config.tooltip_init_x = i;
+          }
+          $$.tooltip.html(config.tooltip_contents.call($$, $$.data.targets.map(function (d) {
+              return $$.addName(d.values[config.tooltip_init_x]);
+          }), $$.axis.getXAxisTickFormat(), $$.getYFormat($$.hasArcType()), $$.color));
+          $$.tooltip
+              .style('top', config.tooltip_init_position.top)
+              .style('left', config.tooltip_init_position.left)
+              .style('display', 'block');
+      }
+  };
+  ChartInternal.prototype.getTooltipSortFunction = function () {
+      var $$ = this, config = $$.config;
+      if (config.data_groups.length === 0 || config.tooltip_order !== undefined) {
+          // if data are not grouped or if an order is specified
+          // for the tooltip values we sort them by their values
+          var order = config.tooltip_order;
+          if (order === undefined) {
+              order = config.data_order;
+          }
+          var valueOf = function (obj) {
+              return obj ? obj.value : null;
+          };
+          // if data are not grouped, we sort them by their value
+          if (isString(order) && order.toLowerCase() === 'asc') {
+              return function (a, b) {
+                  return valueOf(a) - valueOf(b);
+              };
+          }
+          else if (isString(order) && order.toLowerCase() === 'desc') {
+              return function (a, b) {
+                  return valueOf(b) - valueOf(a);
+              };
+          }
+          else if (isFunction(order)) {
+              // if the function is from data_order we need
+              // to wrap the returned function in order to format
+              // the sorted value to the expected format
+              var sortFunction = order;
+              if (config.tooltip_order === undefined) {
+                  sortFunction = function (a, b) {
+                      return order(a
+                          ? {
+                              id: a.id,
+                              values: [a]
+                          }
+                          : null, b
+                          ? {
+                              id: b.id,
+                              values: [b]
+                          }
+                          : null);
+                  };
+              }
+              return sortFunction;
+          }
+          else if (isArray(order)) {
+              return function (a, b) {
+                  return order.indexOf(a.id) - order.indexOf(b.id);
+              };
+          }
+      }
+      else {
+          // if data are grouped, we follow the order of grouped targets
+          var ids = $$.orderTargets($$.data.targets).map(function (i) {
+              return i.id;
+          });
+          // if it was either asc or desc we need to invert the order
+          // returned by orderTargets
+          if ($$.isOrderAsc() || $$.isOrderDesc()) {
+              ids = ids.reverse();
+          }
+          return function (a, b) {
+              return ids.indexOf(a.id) - ids.indexOf(b.id);
+          };
+      }
+  };
+  ChartInternal.prototype.getTooltipContent = function (d, defaultTitleFormat, defaultValueFormat, color) {
+      var $$ = this, config = $$.config, titleFormat = config.tooltip_format_title || defaultTitleFormat, nameFormat = config.tooltip_format_name ||
+          function (name) {
+              return name;
+          }, text, i, title, value, name, bgcolor;
+      var valueFormat = config.tooltip_format_value;
+      if (!valueFormat) {
+          valueFormat = $$.isTargetNormalized(d.id)
+              ? function (v, ratio) { return (ratio * 100).toFixed(2) + "%"; }
+              : defaultValueFormat;
+      }
+      var tooltipSortFunction = this.getTooltipSortFunction();
+      if (tooltipSortFunction) {
+          d.sort(tooltipSortFunction);
+      }
+      for (i = 0; i < d.length; i++) {
+          if (!(d[i] && (d[i].value || d[i].value === 0))) {
+              continue;
+          }
+          if ($$.isStanfordGraphType()) {
+              // Custom tooltip for stanford plots
+              if (!text) {
+                  title = $$.getStanfordTooltipTitle(d[i]);
+                  text = "<table class='" + $$.CLASS.tooltip + "'>" + title;
+              }
+              bgcolor = $$.getStanfordPointColor(d[i]);
+              name = sanitise(config.data_epochs); // Epochs key name
+              value = d[i].epochs;
+          }
+          else {
+              // Regular tooltip
+              if (!text) {
+                  title = sanitise(titleFormat ? titleFormat(d[i].x, d[i].index) : d[i].x);
+                  text =
+                      "<table class='" +
+                          $$.CLASS.tooltip +
+                          "'>" +
+                          (title || title === 0
+                              ? "<tr><th colspan='2'>" + title + '</th></tr>'
+                              : '');
+              }
+              value = sanitise(valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index, d));
+              if (value !== undefined) {
+                  // Skip elements when their name is set to null
+                  if (d[i].name === null) {
+                      continue;
+                  }
+                  name = sanitise(nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index));
+                  bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
+              }
+          }
+          if (value !== undefined) {
+              text +=
+                  "<tr class='" +
+                      $$.CLASS.tooltipName +
+                      '-' +
+                      $$.getTargetSelectorSuffix(d[i].id) +
+                      "'>";
+              text +=
+                  "<td class='name'><span style='background-color:" +
+                      bgcolor +
+                      "'></span>" +
+                      name +
+                      '</td>';
+              text += "<td class='value'>" + value + '</td>';
+              text += '</tr>';
+          }
+      }
+      return text + '</table>';
+  };
+  ChartInternal.prototype.tooltipPosition = function (dataToShow, tWidth, tHeight, element) {
+      var $$ = this, config = $$.config, d3 = $$.d3;
+      var svgLeft, tooltipLeft, tooltipRight, tooltipTop, chartRight;
+      var forArc = $$.hasArcType(), mouse = d3.mouse(element);
+      // Determin tooltip position
+      if (forArc) {
+          tooltipLeft =
+              ($$.width - ($$.isLegendRight ? $$.getLegendWidth() : 0)) / 2 + mouse[0];
+          tooltipTop =
+              ($$.hasType('gauge') ? $$.height : $$.height / 2) + mouse[1] + 20;
+      }
+      else {
+          svgLeft = $$.getSvgLeft(true);
+          if (config.axis_rotated) {
+              tooltipLeft = svgLeft + mouse[0] + 100;
+              tooltipRight = tooltipLeft + tWidth;
+              chartRight = $$.currentWidth - $$.getCurrentPaddingRight();
+              tooltipTop = $$.x(dataToShow[0].x) + 20;
+          }
+          else {
+              tooltipLeft =
+                  svgLeft + $$.getCurrentPaddingLeft(true) + $$.x(dataToShow[0].x) + 20;
+              tooltipRight = tooltipLeft + tWidth;
+              chartRight = svgLeft + $$.currentWidth - $$.getCurrentPaddingRight();
+              tooltipTop = mouse[1] + 15;
+          }
+          if (tooltipRight > chartRight) {
+              // 20 is needed for Firefox to keep tooltip width
+              tooltipLeft -= tooltipRight - chartRight + 20;
+          }
+          if (tooltipTop + tHeight > $$.currentHeight) {
+              tooltipTop -= tHeight + 30;
+          }
+      }
+      if (tooltipTop < 0) {
+          tooltipTop = 0;
+      }
+      return {
+          top: tooltipTop,
+          left: tooltipLeft
+      };
+  };
+  ChartInternal.prototype.showTooltip = function (selectedData, element) {
+      var $$ = this, config = $$.config;
+      var tWidth, tHeight, position;
+      var forArc = $$.hasArcType(), dataToShow = selectedData.filter(function (d) {
+          return d && isValue(d.value);
+      }), positionFunction = config.tooltip_position || ChartInternal.prototype.tooltipPosition;
+      if (dataToShow.length === 0 || !config.tooltip_show) {
+          $$.hideTooltip();
+          return;
+      }
+      $$.tooltip
+          .html(config.tooltip_contents.call($$, selectedData, $$.axis.getXAxisTickFormat(), $$.getYFormat(forArc), $$.color))
+          .style('display', 'block');
+      // Get tooltip dimensions
+      tWidth = $$.tooltip.property('offsetWidth');
+      tHeight = $$.tooltip.property('offsetHeight');
+      position = positionFunction.call(this, dataToShow, tWidth, tHeight, element);
+      // Set tooltip
+      $$.tooltip
+          .style('top', position.top + 'px')
+          .style('left', position.left + 'px');
+  };
+  ChartInternal.prototype.hideTooltip = function () {
+      this.tooltip.style('display', 'none');
+  };
+
+  ChartInternal.prototype.setTargetType = function (targetIds, type) {
+      var $$ = this, config = $$.config;
+      $$.mapToTargetIds(targetIds).forEach(function (id) {
+          $$.withoutFadeIn[id] = type === config.data_types[id];
+          config.data_types[id] = type;
+      });
+      if (!targetIds) {
+          config.data_type = type;
+      }
+  };
+  ChartInternal.prototype.hasType = function (type, targets) {
+      var $$ = this, types = $$.config.data_types, has = false;
+      targets = targets || $$.data.targets;
+      if (targets && targets.length) {
+          targets.forEach(function (target) {
+              var t = types[target.id];
+              if ((t && t.indexOf(type) >= 0) || (!t && type === 'line')) {
+                  has = true;
+              }
+          });
+      }
+      else if (Object.keys(types).length) {
+          Object.keys(types).forEach(function (id) {
+              if (types[id] === type) {
+                  has = true;
+              }
+          });
+      }
+      else {
+          has = $$.config.data_type === type;
+      }
+      return has;
+  };
+  ChartInternal.prototype.hasArcType = function (targets) {
+      return (this.hasType('pie', targets) ||
+          this.hasType('donut', targets) ||
+          this.hasType('gauge', targets));
+  };
+  ChartInternal.prototype.isLineType = function (d) {
+      var config = this.config, id = isString(d) ? d : d.id;
+      return (!config.data_types[id] ||
+          ['line', 'spline', 'area', 'area-spline', 'step', 'area-step'].indexOf(config.data_types[id]) >= 0);
+  };
+  ChartInternal.prototype.isStepType = function (d) {
+      var id = isString(d) ? d : d.id;
+      return ['step', 'area-step'].indexOf(this.config.data_types[id]) >= 0;
+  };
+  ChartInternal.prototype.isSplineType = function (d) {
+      var id = isString(d) ? d : d.id;
+      return ['spline', 'area-spline'].indexOf(this.config.data_types[id]) >= 0;
+  };
+  ChartInternal.prototype.isAreaType = function (d) {
+      var id = isString(d) ? d : d.id;
+      return (['area', 'area-spline', 'area-step'].indexOf(this.config.data_types[id]) >=
+          0);
+  };
+  ChartInternal.prototype.isBarType = function (d) {
+      var id = isString(d) ? d : d.id;
+      return this.config.data_types[id] === 'bar';
+  };
+  ChartInternal.prototype.isScatterType = function (d) {
+      var id = isString(d) ? d : d.id;
+      return this.config.data_types[id] === 'scatter';
+  };
+  ChartInternal.prototype.isStanfordType = function (d) {
+      var id = isString(d) ? d : d.id;
+      return this.config.data_types[id] === 'stanford';
+  };
+  ChartInternal.prototype.isPieType = function (d) {
+      var id = isString(d) ? d : d.id;
+      return this.config.data_types[id] === 'pie';
+  };
+  ChartInternal.prototype.isGaugeType = function (d) {
+      var id = isString(d) ? d : d.id;
+      return this.config.data_types[id] === 'gauge';
+  };
+  ChartInternal.prototype.isDonutType = function (d) {
+      var id = isString(d) ? d : d.id;
+      return this.config.data_types[id] === 'donut';
+  };
+  ChartInternal.prototype.isArcType = function (d) {
+      return this.isPieType(d) || this.isDonutType(d) || this.isGaugeType(d);
+  };
+  ChartInternal.prototype.lineData = function (d) {
+      return this.isLineType(d) ? [d] : [];
+  };
+  ChartInternal.prototype.arcData = function (d) {
+      return this.isArcType(d.data) ? [d] : [];
+  };
+  /* not used
+   function scatterData(d) {
+   return isScatterType(d) ? d.values : [];
+   }
+   */
+  ChartInternal.prototype.barData = function (d) {
+      return this.isBarType(d) ? d.values : [];
+  };
+  ChartInternal.prototype.lineOrScatterOrStanfordData = function (d) {
+      return this.isLineType(d) || this.isScatterType(d) || this.isStanfordType(d)
+          ? d.values
+          : [];
+  };
+  ChartInternal.prototype.barOrLineData = function (d) {
+      return this.isBarType(d) || this.isLineType(d) ? d.values : [];
+  };
+
+  ChartInternal.prototype.isSafari = function () {
+      var ua = window.navigator.userAgent;
+      return ua.indexOf('Safari') >= 0 && ua.indexOf('Chrome') < 0;
+  };
+  ChartInternal.prototype.isChrome = function () {
+      var ua = window.navigator.userAgent;
+      return ua.indexOf('Chrome') >= 0;
+  };
+
+  ChartInternal.prototype.initZoom = function () {
+      var $$ = this, d3 = $$.d3, config = $$.config, startEvent;
+      $$.zoom = d3
+          .zoom()
+          .on('start', function () {
+          if (config.zoom_type !== 'scroll') {
+              return;
+          }
+          var e = d3.event.sourceEvent;
+          if (e && e.type === 'brush') {
+              return;
+          }
+          startEvent = e;
+          config.zoom_onzoomstart.call($$.api, e);
+      })
+          .on('zoom', function () {
+          if (config.zoom_type !== 'scroll') {
+              return;
+          }
+          var e = d3.event.sourceEvent;
+          if (e && e.type === 'brush') {
+              return;
+          }
+          $$.redrawForZoom();
+          config.zoom_onzoom.call($$.api, $$.x.orgDomain());
+      })
+          .on('end', function () {
+          if (config.zoom_type !== 'scroll') {
+              return;
+          }
+          var e = d3.event.sourceEvent;
+          if (e && e.type === 'brush') {
+              return;
+          }
+          // if click, do nothing. otherwise, click interaction will be canceled.
+          if (e &&
+              startEvent.clientX === e.clientX &&
+              startEvent.clientY === e.clientY) {
+              return;
+          }
+          config.zoom_onzoomend.call($$.api, $$.x.orgDomain());
+      });
+      $$.zoom.updateDomain = function () {
+          if (d3.event && d3.event.transform) {
+              if (config.axis_rotated && config.zoom_type === 'scroll' && d3.event.sourceEvent.type === 'mousemove') {
+                  // we're moving the mouse in a rotated chart with zoom = "scroll", so we need rescaleY (i.e. vertical)
+                  $$.x.domain(d3.event.transform.rescaleY($$.subX).domain());
+              }
+              else {
+                  $$.x.domain(d3.event.transform.rescaleX($$.subX).domain());
+              }
+          }
+          return this;
+      };
+      $$.zoom.updateExtent = function () {
+          this.scaleExtent([1, Infinity])
+              .translateExtent([
+              [0, 0],
+              [$$.width, $$.height]
+          ])
+              .extent([
+              [0, 0],
+              [$$.width, $$.height]
+          ]);
+          return this;
+      };
+      $$.zoom.update = function () {
+          return this.updateExtent().updateDomain();
+      };
+      return $$.zoom.updateExtent();
+  };
+  ChartInternal.prototype.zoomTransform = function (range) {
+      var $$ = this, s = [$$.x(range[0]), $$.x(range[1])];
+      return $$.d3.zoomIdentity.scale($$.width / (s[1] - s[0])).translate(-s[0], 0);
+  };
+  ChartInternal.prototype.initDragZoom = function () {
+      var $$ = this;
+      var d3 = $$.d3;
+      var config = $$.config;
+      var context = ($$.context = $$.svg);
+      var brushXPos = $$.margin.left + 20.5;
+      var brushYPos = $$.margin.top + 0.5;
+      if (!(config.zoom_type === 'drag' && config.zoom_enabled)) {
+          return;
+      }
+      var getZoomedDomain = function (selection) {
+          return selection && selection.map(function (x) { return $$.x.invert(x); });
+      };
+      var brush = ($$.dragZoomBrush = d3
+          .brushX()
+          .on('start', function () {
+          $$.api.unzoom();
+          $$.svg.select('.' + CLASS.dragZoom).classed('disabled', false);
+          config.zoom_onzoomstart.call($$.api, d3.event.sourceEvent);
+      })
+          .on('brush', function () {
+          config.zoom_onzoom.call($$.api, getZoomedDomain(d3.event.selection));
+      })
+          .on('end', function () {
+          if (d3.event.selection == null) {
+              return;
+          }
+          var zoomedDomain = getZoomedDomain(d3.event.selection);
+          if (!config.zoom_disableDefaultBehavior) {
+              $$.api.zoom(zoomedDomain);
+          }
+          $$.svg.select('.' + CLASS.dragZoom).classed('disabled', true);
+          config.zoom_onzoomend.call($$.api, zoomedDomain);
+      }));
+      context
+          .append('g')
+          .classed(CLASS.dragZoom, true)
+          .attr('clip-path', $$.clipPath)
+          .attr('transform', 'translate(' + brushXPos + ',' + brushYPos + ')')
+          .call(brush);
+  };
+  ChartInternal.prototype.getZoomDomain = function () {
+      var $$ = this, config = $$.config, d3 = $$.d3, min = d3.min([$$.orgXDomain[0], config.zoom_x_min]), max = d3.max([$$.orgXDomain[1], config.zoom_x_max]);
+      return [min, max];
+  };
+  ChartInternal.prototype.redrawForZoom = function () {
+      var $$ = this, d3 = $$.d3, config = $$.config, zoom = $$.zoom, x = $$.x;
+      if (!config.zoom_enabled) {
+          return;
+      }
+      if ($$.filterTargetsToShow($$.data.targets).length === 0) {
+          return;
+      }
+      zoom.update();
+      if (config.zoom_disableDefaultBehavior) {
+          return;
+      }
+      if ($$.isCategorized() && x.orgDomain()[0] === $$.orgXDomain[0]) {
+          x.domain([$$.orgXDomain[0] - 1e-10, x.orgDomain()[1]]);
+      }
+      $$.redraw({
+          withTransition: false,
+          withY: config.zoom_rescale,
+          withSubchart: false,
+          withEventRect: false,
+          withDimension: false
+      });
+      if (d3.event.sourceEvent && d3.event.sourceEvent.type === 'mousemove') {
+          $$.cancelClick = true;
+      }
+  };
+
+  return c3;
+
+})));

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
public/plugin/c3-0.7.20/c3.min.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 1 - 0
public/plugin/c3-0.7.20/c3.min.js


+ 2 - 0
public/plugin/c3-0.7.20/codecov.yml

@@ -0,0 +1,2 @@
+coverage:
+  status: no

+ 15 - 0
public/plugin/c3-0.7.20/component.json

@@ -0,0 +1,15 @@
+{
+  "name": "c3",
+  "repo": "masayuki0812/c3",
+  "description": "A D3-based reusable chart library",
+  "version": "0.7.20",
+  "keywords": [],
+  "dependencies": {
+    "mbostock/d3": "v5.0.0"
+  },
+  "development": {},
+  "license": "MIT",
+  "main": "c3.js",
+  "scripts": ["c3.js"],
+  "styles": ["c3.css"]
+}

+ 33 - 0
public/plugin/c3-0.7.20/config.rb

@@ -0,0 +1,33 @@
+helpers do
+  def js_as_plain(id)
+    f = open("docs/js/samples/" + id + ".js")
+    js = f.read
+    f.close
+    js
+  end
+  def data_as_plain(name)
+    f = open("docs/data/" + name)
+    data = f.read
+    f.close
+    data
+  end
+  def css_as_plain(name)
+    f = open("docs/css/samples/" + name)
+    css = f.read
+    f.close
+    css
+  end
+  def get_css_name(path)
+    path.gsub('.html', '')
+  end
+end
+
+set :source, 'docs'
+set :haml, { :ugly => true, :format => :html5 }
+set :css_dir, 'css'
+set :js_dir, 'js'
+set :images_dir, 'img'
+
+configure :build do
+  activate :asset_hash, :ignore => %r{^js/ace/.*}
+end

+ 327 - 0
public/plugin/c3-0.7.20/data/samples.yml

@@ -0,0 +1,327 @@
+simple_multiple:
+  title: 'Line Chart'
+  desc: 'Line chart with sequential data.'
+
+timeseries:
+  title: Timeseries Chart
+  desc: Simple line chart with timeseries data.
+
+chart_spline:
+  title: Spline Chart
+  desc: Display as Spline Chart.
+
+simple_xy:
+  title: Simple XY Line Chart
+  desc: Simple line chart with custom x.
+
+simple_xy_multiple:
+  title: Multiple XY Line Chart
+  desc: Multiple line chart with multiple custom x.
+
+simple_regions:
+  title: Line Chart with Regions
+  desc: Set regions for each data with style.
+
+chart_bar:
+  title: Bar Chart
+  desc: Display as Bar Chart.
+
+chart_bar_stacked:
+  title: Stacked Bar Chart
+  desc: Display as Stacked Bar Chart.
+
+chart_scatter:
+  title: Scatter Plot
+  desc: Display as Scatter Plot.
+
+chart_pie:
+  title: Pie Chart
+  desc: Display as Pie Chart.
+
+chart_donut:
+  title: Donut Chart
+  desc: Display as Donut Chart.
+
+chart_gauge:
+  title: Gauge Chart
+  desc: Display as Gauge Chart.
+
+chart_step:
+  title: Step Chart
+  desc: Display as Step Chart.
+
+chart_area:
+  title: Area Chart
+  desc: Display as Area Chart.
+
+chart_area_stacked:
+  title: Stacked Area Chart
+  desc: Display as Stacked Area Chart.
+
+chart_stanford:
+  title: Stanford Chart
+  desc: Display as Stanford Chart.
+
+chart_combination:
+  title: Combination Chart
+  desc: Display all kinda charts up in here.
+
+categorized:
+  title: Category Axis
+  desc: Show ticks as categorized by each data.
+
+axes_y2:
+  title: Additional Y Axis
+  desc: Additional y axis can be added.
+
+axes_rotated:
+  title: Rotated Axis
+  desc: Switch x and y axis position.
+
+axes_x_localtime:
+  title: X Axis Timezone
+  desc: Convert time to UTC.
+
+axes_x_tick_rotate:
+  title: Rotate X Axis Tick Text
+  desc: Rotate x axis tick text.
+
+axes_x_tick_format:
+  title: X Axis Tick Format
+  desc: Format x axis tick text.
+
+axes_y_tick_format:
+  title: Y Axis Tick Format
+  desc: Format y axis tick text.
+
+axes_x_tick_culling:
+  title: X Axis Tick Culling
+  desc: Set cull ticks or not on X Axis.
+
+axes_x_tick_values:
+  title: X Axis Tick Values
+  desc: Set tick texts on X Axis.
+
+axes_x_tick_count:
+  title: X Axis Tick Count
+  desc: Set the number of ticks on X Axis.
+
+axes_x_tick_fit:
+  title: X Axis Tick Fitting
+  desc: Set ticks position to x of data.
+
+axes_label:
+  title: Axis Label
+  desc: Set label for axis.
+
+axes_label_position:
+  title: Axis Label Position
+  desc: Set axis label position.
+
+axes_y_padding:
+  title: Padding for Y Axis
+  desc: Set padding for y axis.
+
+axes_y_range:
+  title: Range for Y Axis
+  desc: Set range for y axis.
+
+data_columned:
+  title: Column Oriented Data
+  desc: Column-oriented data can be used as input.
+
+data_rowed:
+  title: Row Oriented Data
+  desc: Row-oriented data can be used as input.
+
+data_json:
+  title: JSON Data
+  desc: JSON can be used as input.
+
+data_url:
+  title: Data from URL
+  desc: Data from URL can be used as input.
+
+data_load:
+  title: Load Data
+  desc: Load data dynamically.
+
+data_name:
+  title: Data Name
+  desc: Set name for each data.
+
+data_stringx:
+  title: Category Data
+  desc: Load data with x values on category axis.
+
+data_order:
+  title: Data Order
+  desc: Define data order. This will be used for stacked bar chart.
+
+data_label:
+  title: Data Label
+  desc: Show label of data.
+
+data_label_format:
+  title: Data Label Format
+  desc: Format label of data.
+
+data_number_format_l10n:
+  title: Number Format Localization
+  desc: Number format localization using D3 locale settings.
+
+data_color:
+  title: Data Color
+  desc: Set color according to data.
+
+options_legend:
+  title: Hide Legend
+  desc: Set visibility of legend.
+
+legend_position:
+  title: Legend Position
+  desc: Show legend on bottom or right side.
+
+legend_custom:
+  title: Custom Legend
+  desc: Build custom legend
+
+tooltip_show:
+  title: Hide Tooltip
+  desc: Set visibility of tooltip.
+
+tooltip_grouped:
+  title: Tooltip Grouping
+  desc: Show tooltips as grouped or not.
+
+tooltip_format:
+  title: Tooltip Format
+  desc: Set format for title and value on tooltip.
+
+tooltip_horizontal:
+  title: Horizontal Tooltip
+  desc: Show tooltips based on the horizontal position of the mouse.
+
+options_gridline:
+  title: Grid Lines
+  desc: Show grid lines for x and y axis.
+
+grid_x_lines:
+  title: Optional X Grid Lines
+  desc: Add optional grid lines on x grid.
+
+grid_y_lines:
+  title: Optional Y Grid Lines
+  desc: Add optional grid lines on y grid.
+
+options_subchart:
+  title: Sub Chart
+  desc: Show sub chart for zoom and selection range.
+
+interaction_zoom:
+  title: Zoom
+  desc: Zoom by mouse wheel event and slide by drag.
+
+interaction_zoom_by_drag:
+  title: Zoom by Drag
+  desc: Zoom by dragging area.
+
+region:
+  title: Region
+  desc: Show rects on chart.
+
+region_timeseries:
+  title: Region with Timeseries
+  desc: Show rects on timeseries chart.
+
+options_size:
+  title: Chart Size
+  desc: Set chart size in px.
+
+options_color:
+  title: Color Pattern
+  desc: Set custom color pattern.
+
+options_padding:
+  title: Padding
+  desc: Change padding for the chart.
+
+point_show:
+  title: Hide points
+  desc: Hide points on line chart
+
+pie_label_format:
+  title: Pie Label Format
+  desc: Change label format on Pie chart
+
+transition_duration:
+  title: Duration of Transition
+  desc: Set duration of transition for chart animation.
+
+api_flow:
+  title: Flow
+  desc: Load/Unload data as flowing
+
+api_resize:
+  title: Resize
+  desc: Resize chart.
+
+api_data_name:
+  title: Data Name
+  desc: Update data names.
+
+api_data_color:
+  title: Data Color
+  desc: Update data colors.
+
+api_axis_label:
+  title: Axis Label
+  desc: Update axis labels.
+
+api_axis_range:
+  title: Axis Range
+  desc: Update axis range.
+
+api_grid_x:
+  title: X Grid
+  desc: Update custom x grids.
+
+transform_line:
+  title: To Line Chart
+  desc: Transform to line chart.
+
+transform_spline:
+  title: To Spline Chart
+  desc: Transform to spline chart.
+
+transform_bar:
+  title: To Bar Chart
+  desc: Transform to bar chart.
+
+transform_area:
+  title: To Area Chart
+  desc: Transform to area chart.
+
+transform_areaspline:
+  title: To Area Spline Chart
+  desc: Transform to area spline chart.
+
+transform_scatter:
+  title: To Scatter Plot
+  desc: Transform to scatter plot.
+
+transform_pie:
+  title: To Pie Chart
+  desc: Transform to pie chart.
+
+transform_donut:
+  title: To Donut Chart
+  desc: Transform to donut chart.
+
+style_region:
+  title: Style for Region
+  desc: Set style for regions.
+
+style_grid:
+  title: Style for Grid
+  desc: Set style for grids.

BIN
public/plugin/c3-0.7.20/design/c3-logo.sketch


+ 157 - 0
public/plugin/c3-0.7.20/docs/404.html

@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Page Not Found :(</title>
+        <style>
+            ::-moz-selection {
+                background: #b3d4fc;
+                text-shadow: none;
+            }
+
+            ::selection {
+                background: #b3d4fc;
+                text-shadow: none;
+            }
+
+            html {
+                padding: 30px 10px;
+                font-size: 20px;
+                line-height: 1.4;
+                color: #737373;
+                background: #f0f0f0;
+                -webkit-text-size-adjust: 100%;
+                -ms-text-size-adjust: 100%;
+            }
+
+            html,
+            input {
+                font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+            }
+
+            body {
+                max-width: 500px;
+                _width: 500px;
+                padding: 30px 20px 50px;
+                border: 1px solid #b3b3b3;
+                border-radius: 4px;
+                margin: 0 auto;
+                box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;
+                background: #fcfcfc;
+            }
+
+            h1 {
+                margin: 0 10px;
+                font-size: 50px;
+                text-align: center;
+            }
+
+            h1 span {
+                color: #bbb;
+            }
+
+            h3 {
+                margin: 1.5em 0 0.5em;
+            }
+
+            p {
+                margin: 1em 0;
+            }
+
+            ul {
+                padding: 0 0 0 40px;
+                margin: 1em 0;
+            }
+
+            .container {
+                max-width: 380px;
+                _width: 380px;
+                margin: 0 auto;
+            }
+
+            /* google search */
+
+            #goog-fixurl ul {
+                list-style: none;
+                padding: 0;
+                margin: 0;
+            }
+
+            #goog-fixurl form {
+                margin: 0;
+            }
+
+            #goog-wm-qt,
+            #goog-wm-sb {
+                border: 1px solid #bbb;
+                font-size: 16px;
+                line-height: normal;
+                vertical-align: top;
+                color: #444;
+                border-radius: 2px;
+            }
+
+            #goog-wm-qt {
+                width: 220px;
+                height: 20px;
+                padding: 5px;
+                margin: 5px 10px 0 0;
+                box-shadow: inset 0 1px 1px #ccc;
+            }
+
+            #goog-wm-sb {
+                display: inline-block;
+                height: 32px;
+                padding: 0 10px;
+                margin: 5px 0 0;
+                white-space: nowrap;
+                cursor: pointer;
+                background-color: #f5f5f5;
+                background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);
+                background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);
+                background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);
+                background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);
+                -webkit-appearance: none;
+                -moz-appearance: none;
+                appearance: none;
+                *overflow: visible;
+                *display: inline;
+                *zoom: 1;
+            }
+
+            #goog-wm-sb:hover,
+            #goog-wm-sb:focus {
+                border-color: #aaa;
+                box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+                background-color: #f8f8f8;
+            }
+
+            #goog-wm-qt:hover,
+            #goog-wm-qt:focus {
+                border-color: #105cb6;
+                outline: 0;
+                color: #222;
+            }
+
+            input::-moz-focus-inner {
+                padding: 0;
+                border: 0;
+            }
+        </style>
+    </head>
+    <body>
+        <div class="container">
+            <h1>Not found <span>:(</span></h1>
+            <p>Sorry, but the page you were trying to view does not exist.</p>
+            <p>It looks like this was the result of either:</p>
+            <ul>
+                <li>a mistyped address</li>
+                <li>an out-of-date link</li>
+            </ul>
+            <script>
+                var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host;
+            </script>
+            <script src="http://linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js"></script>
+        </div>
+    </body>
+</html>

+ 1 - 0
public/plugin/c3-0.7.20/docs/CNAME

@@ -0,0 +1 @@
+c3js.org

+ 3 - 0
public/plugin/c3-0.7.20/docs/_footer.haml

@@ -0,0 +1,3 @@
+%footer
+  %hr
+  %p &copy Masayuki Tanaka 2014

+ 4 - 0
public/plugin/c3-0.7.20/docs/_index_item.haml

@@ -0,0 +1,4 @@
+.large-4.columns
+  %h3 #{data.samples[id].title}
+  %p.margin-small-bottom #{data.samples[id].desc}
+  %a.btn.btn-default( href="/samples/#{id}.html" role="button" ) View details &raquo;

+ 4 - 0
public/plugin/c3-0.7.20/docs/_index_item_title.haml

@@ -0,0 +1,4 @@
+%a( href="/examples.html##{id}" name="#{id}" )
+  %h2<
+    \#
+    %span #{name}

+ 3 - 0
public/plugin/c3-0.7.20/docs/_reference_item_link.haml

@@ -0,0 +1,3 @@
+%a( href="##{ id.gsub(/\./, '-') }")< #{ id.gsub(/(api|class)\./, '') }
+- if defined? experimental
+  <span class="secondary label">Experimental</span>

+ 5 - 0
public/plugin/c3-0.7.20/docs/_reference_menu_item.haml

@@ -0,0 +1,5 @@
+%li
+  - if defined? experimental
+    = partial :reference_item_link, locals: { id: id, experimental: experimental }
+  - else
+    = partial :reference_item_link, locals: { id: id }

+ 34 - 0
public/plugin/c3-0.7.20/docs/_sample.haml

@@ -0,0 +1,34 @@
+.container
+
+  %h1.title #{data.samples[id].title}
+
+  .chart
+    #chart
+
+  #ace-error
+
+  .sourcecode.margin-medium-v.margin-small-h
+    %h3 # #{id}.js
+    #javascript-editor.c3-editor
+      = js_as_plain id
+
+  - if defined? other_css
+    .sourcecode
+      %h3 # #{other_css}
+      %pre
+        %code.css
+          = css_as_plain other_css
+
+  - if defined? other_files
+    - other_files.each do |f|
+      .sourcecode
+        %h3 # #{f}
+        %pre
+          %code.html
+            = data_as_plain f
+
+  = partial :footer
+
+= partial :script
+= partial :sample_editor, locals: { type: 'javascript' }
+= javascript_include_tag "samples/#{id}.js"

+ 36 - 0
public/plugin/c3-0.7.20/docs/_sample_editor.haml

@@ -0,0 +1,36 @@
+= javascript_include_tag "ace/ace.js"
+= javascript_include_tag "ace/mode-javascript.js"
+= javascript_include_tag "ace/theme-tomorrow.js"
+:javascript
+  var editor = ace.edit('#{type}-editor'),
+      error  = document.getElementById('ace-error');
+
+  function debounce(func, wait) {
+    var timeout;
+    return function() {
+      var context = this, args = arguments;
+      var later = function() {
+        func.apply(context, args);
+      };
+      clearTimeout(timeout);
+      timeout = setTimeout(later, wait);
+    };
+  };
+
+  editor.on('change', debounce(function(e) {
+    try {
+      eval(editor.getValue());
+      error.innerHTML = '';
+    }
+    catch(e) {
+      error.innerHTML = e;
+    }
+  }, 300));
+
+  editor.setOption("maxLines", 100);
+  editor.setOption("showLineNumbers", false);
+  editor.setOption("showGutter", false);
+
+  editor.setTheme("ace/theme/tomorrow");
+  editor.getSession().setMode("ace/mode/#{type}");
+  editor.commands.removeCommand('gotoline') // Disables the override of Command-L

+ 17 - 0
public/plugin/c3-0.7.20/docs/_samples_header.haml

@@ -0,0 +1,17 @@
+.nav
+  %a( href="/") Home
+
+.page-header.title
+  %h1 #{data.samples[id].title}
+
+.chart
+  #chart
+
+.sourcecode
+  %h3 # #{id}.js
+  %pre
+    %code.html.javascript
+      = js_as_plain id
+
+= partial :script
+= javascript_include_tag "samples/#{id}.js"

+ 8 - 0
public/plugin/c3-0.7.20/docs/_script.haml

@@ -0,0 +1,8 @@
+= javascript_include_tag 'jquery-1.11.0.min.js'
+= javascript_include_tag 'foundation.min.js'
+= javascript_include_tag 'highlight.pack.js'
+= javascript_include_tag 'd3-5.8.2.min.js'
+= javascript_include_tag 'c3.min.js'
+:javascript
+  hljs.initHighlightingOnLoad();
+  $(document).foundation();

+ 22 - 0
public/plugin/c3-0.7.20/docs/_script_scroll.haml

@@ -0,0 +1,22 @@
+:javascript
+  $(function(){
+    function scrollToHash() {
+      var hash = document.location.hash,
+          target = $('.column-content h3 a[href^=' + hash + ']'),
+          position;
+      if (target.length) {
+        position = target.offset().top - 60;
+        $("html, body").animate({scrollTop:position}, 250, "swing");
+      }
+    }
+    $(window).on('hashchange', scrollToHash);
+
+    // When clicked
+    $('a[href^=#]').click(function(){
+      document.location.hash = $(this).attr("href");
+      return false;
+    });
+
+    // When loaded
+    $(window).trigger('hashchange');
+  });

+ 2 - 0
public/plugin/c3-0.7.20/docs/_sidemenu_item.haml

@@ -0,0 +1,2 @@
+%li
+  %a( href="##{ id }") #{ name }

BIN
public/plugin/c3-0.7.20/docs/apple-touch-icon-114x114-precomposed.png


BIN
public/plugin/c3-0.7.20/docs/apple-touch-icon-144x144-precomposed.png


BIN
public/plugin/c3-0.7.20/docs/apple-touch-icon-57x57-precomposed.png


BIN
public/plugin/c3-0.7.20/docs/apple-touch-icon-72x72-precomposed.png


BIN
public/plugin/c3-0.7.20/docs/apple-touch-icon-precomposed.png


BIN
public/plugin/c3-0.7.20/docs/apple-touch-icon.png


+ 15 - 0
public/plugin/c3-0.7.20/docs/crossdomain.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
+<cross-domain-policy>
+    <!-- Read this: www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html -->
+
+    <!-- Most restrictive policy: -->
+    <site-control permitted-cross-domain-policies="none"/>
+
+    <!-- Least restrictive policy: -->
+    <!--
+    <site-control permitted-cross-domain-policies="all"/>
+    <allow-access-from domain="*" to-ports="*" secure="false"/>
+    <allow-http-request-headers-from domain="*" headers="*" secure="false"/>
+    -->
+</cross-domain-policy>

Diferenças do arquivo suprimidas por serem muito extensas
+ 7 - 0
public/plugin/c3-0.7.20/docs/css/bootstrap.min.css


+ 241 - 0
public/plugin/c3-0.7.20/docs/css/c3.css

@@ -0,0 +1,241 @@
+/*-- Chart --*/
+.c3 svg {
+  font: 10px sans-serif;
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+
+.c3 path, .c3 line {
+  fill: none;
+  stroke: #000;
+}
+
+.c3 text {
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  user-select: none;
+}
+
+.c3-legend-item-tile,
+.c3-xgrid-focus,
+.c3-ygrid,
+.c3-event-rect,
+.c3-bars path {
+  shape-rendering: crispEdges;
+}
+
+.c3-chart-arc path {
+  stroke: #fff;
+}
+
+.c3-chart-arc rect {
+  stroke: white;
+  stroke-width: 1;
+}
+
+.c3-chart-arc text {
+  fill: #fff;
+  font-size: 13px;
+}
+
+/*-- Axis --*/
+/*-- Grid --*/
+.c3-grid line {
+  stroke: #aaa;
+}
+
+.c3-grid text {
+  fill: #aaa;
+}
+
+.c3-xgrid, .c3-ygrid {
+  stroke-dasharray: 3 3;
+}
+
+/*-- Text on Chart --*/
+.c3-text.c3-empty {
+  fill: #808080;
+  font-size: 2em;
+}
+
+/*-- Line --*/
+.c3-line {
+  stroke-width: 1px;
+}
+
+/*-- Point --*/
+.c3-circle {
+  fill: currentColor;
+}
+
+.c3-circle._expanded_ {
+  stroke-width: 1px;
+  stroke: white;
+}
+
+.c3-selected-circle {
+  fill: white;
+  stroke-width: 2px;
+}
+
+/*-- Bar --*/
+.c3-bar {
+  stroke-width: 0;
+}
+
+.c3-bar._expanded_ {
+  fill-opacity: 1;
+  fill-opacity: 0.75;
+}
+
+/*-- Focus --*/
+.c3-target.c3-focused {
+  opacity: 1;
+}
+
+.c3-target.c3-focused path.c3-line, .c3-target.c3-focused path.c3-step {
+  stroke-width: 2px;
+}
+
+.c3-target.c3-defocused {
+  opacity: 0.3 !important;
+}
+
+/*-- Region --*/
+.c3-region {
+  fill: steelblue;
+  fill-opacity: 0.1;
+}
+.c3-region text {
+  fill-opacity: 1;
+}
+
+/*-- Brush --*/
+.c3-brush .extent {
+  fill-opacity: 0.1;
+}
+
+/*-- Select - Drag --*/
+/*-- Legend --*/
+.c3-legend-item {
+  font-size: 12px;
+}
+
+.c3-legend-item-hidden {
+  opacity: 0.15;
+}
+
+.c3-legend-background {
+  opacity: 0.75;
+  fill: white;
+  stroke: lightgray;
+  stroke-width: 1;
+}
+
+/*-- Title --*/
+.c3-title {
+  font: 14px sans-serif;
+}
+
+/*-- Tooltip --*/
+.c3-tooltip-container {
+  z-index: 10;
+}
+
+.c3-tooltip {
+  border-collapse: collapse;
+  border-spacing: 0;
+  background-color: #fff;
+  empty-cells: show;
+  -webkit-box-shadow: 7px 7px 12px -9px #777777;
+  -moz-box-shadow: 7px 7px 12px -9px #777777;
+  box-shadow: 7px 7px 12px -9px #777777;
+  opacity: 0.9;
+}
+
+.c3-tooltip tr {
+  border: 1px solid #CCC;
+}
+
+.c3-tooltip th {
+  background-color: #aaa;
+  font-size: 14px;
+  padding: 2px 5px;
+  text-align: left;
+  color: #FFF;
+}
+
+.c3-tooltip td {
+  font-size: 13px;
+  padding: 3px 6px;
+  background-color: #fff;
+  border-left: 1px dotted #999;
+}
+
+.c3-tooltip td > span {
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  margin-right: 6px;
+}
+
+.c3-tooltip .value {
+  text-align: right;
+}
+
+/*-- Area --*/
+.c3-area {
+  stroke-width: 0;
+  opacity: 0.2;
+}
+
+/*-- Arc --*/
+.c3-chart-arcs-title {
+  dominant-baseline: middle;
+  font-size: 1.3em;
+}
+
+.c3-chart-arcs .c3-chart-arcs-background {
+  fill: #e0e0e0;
+  stroke: #FFF;
+}
+
+.c3-chart-arcs .c3-chart-arcs-gauge-unit {
+  fill: #000;
+  font-size: 16px;
+}
+
+.c3-chart-arcs .c3-chart-arcs-gauge-max {
+  fill: #777;
+}
+
+.c3-chart-arcs .c3-chart-arcs-gauge-min {
+  fill: #777;
+}
+
+.c3-chart-arc .c3-gauge-value {
+  fill: #000;
+  /*  font-size: 28px !important;*/
+}
+
+.c3-chart-arc.c3-target g path {
+  opacity: 1;
+}
+
+.c3-chart-arc.c3-target.c3-focused g path {
+  opacity: 1;
+}
+
+/*-- Zoom --*/
+.c3-drag-zoom.enabled {
+  pointer-events: all !important;
+  visibility: visible;
+}
+
+.c3-drag-zoom.disabled {
+  pointer-events: none !important;
+  visibility: hidden;
+}
+
+.c3-drag-zoom .extent {
+  fill-opacity: 0.1;
+}

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
public/plugin/c3-0.7.20/docs/css/c3.min.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/examples.css


+ 5264 - 0
public/plugin/c3-0.7.20/docs/css/foundation.css

@@ -0,0 +1,5264 @@
+meta.foundation-version {
+  font-family: "/5.2.2/"; }
+
+meta.foundation-mq-small {
+  font-family: "/only screen/";
+  width: 0em; }
+
+meta.foundation-mq-medium {
+  font-family: "/only screen and (min-width:40.063em)/";
+  width: 40.063em; }
+
+meta.foundation-mq-large {
+  font-family: "/only screen and (min-width:64.063em)/";
+  width: 64.063em; }
+
+meta.foundation-mq-xlarge {
+  font-family: "/only screen and (min-width:90.063em)/";
+  width: 90.063em; }
+
+meta.foundation-mq-xxlarge {
+  font-family: "/only screen and (min-width:120.063em)/";
+  width: 120.063em; }
+
+meta.foundation-data-attribute-namespace {
+  font-family: false; }
+
+html, body {
+  height: 100%; }
+
+*,
+*:before,
+*:after {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box; }
+
+html,
+body {
+  font-size: 100%; }
+
+body {
+  background: white;
+  color: #222222;
+  padding: 0;
+  margin: 0;
+  font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
+  font-weight: normal;
+  font-style: normal;
+  line-height: 1;
+  position: relative;
+  cursor: default; }
+
+a:hover {
+  cursor: pointer; }
+
+img {
+  max-width: 100%;
+  height: auto; }
+
+img {
+  -ms-interpolation-mode: bicubic; }
+
+#map_canvas img,
+#map_canvas embed,
+#map_canvas object,
+.map_canvas img,
+.map_canvas embed,
+.map_canvas object {
+  max-width: none !important; }
+
+.left {
+  float: left !important; }
+
+.right {
+  float: right !important; }
+
+.clearfix {
+  *zoom: 1; }
+  .clearfix:before, .clearfix:after {
+    content: " ";
+    display: table; }
+  .clearfix:after {
+    clear: both; }
+
+.hide {
+  display: none; }
+
+.antialiased {
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale; }
+
+img {
+  display: inline-block;
+  vertical-align: middle; }
+
+textarea {
+  height: auto;
+  min-height: 50px; }
+
+select {
+  width: 100%; }
+
+.row {
+  width: 100%;
+  margin-left: auto;
+  margin-right: auto;
+  margin-top: 0;
+  margin-bottom: 0;
+  max-width: 62.5rem;
+  *zoom: 1; }
+  .row:before, .row:after {
+    content: " ";
+    display: table; }
+  .row:after {
+    clear: both; }
+  .row.collapse > .column,
+  .row.collapse > .columns {
+    padding-left: 0;
+    padding-right: 0; }
+  .row.collapse .row {
+    margin-left: 0;
+    margin-right: 0; }
+  .row .row {
+    width: auto;
+    margin-left: -0.9375rem;
+    margin-right: -0.9375rem;
+    margin-top: 0;
+    margin-bottom: 0;
+    max-width: none;
+    *zoom: 1; }
+    .row .row:before, .row .row:after {
+      content: " ";
+      display: table; }
+    .row .row:after {
+      clear: both; }
+    .row .row.collapse {
+      width: auto;
+      margin: 0;
+      max-width: none;
+      *zoom: 1; }
+      .row .row.collapse:before, .row .row.collapse:after {
+        content: " ";
+        display: table; }
+      .row .row.collapse:after {
+        clear: both; }
+
+.column,
+.columns {
+  padding-left: 0.9375rem;
+  padding-right: 0.9375rem;
+  width: 100%;
+  float: left; }
+
+@media only screen {
+  .small-push-0 {
+    position: relative;
+    left: 0%;
+    right: auto; }
+
+  .small-pull-0 {
+    position: relative;
+    right: 0%;
+    left: auto; }
+
+  .small-push-1 {
+    position: relative;
+    left: 8.33333%;
+    right: auto; }
+
+  .small-pull-1 {
+    position: relative;
+    right: 8.33333%;
+    left: auto; }
+
+  .small-push-2 {
+    position: relative;
+    left: 16.66667%;
+    right: auto; }
+
+  .small-pull-2 {
+    position: relative;
+    right: 16.66667%;
+    left: auto; }
+
+  .small-push-3 {
+    position: relative;
+    left: 25%;
+    right: auto; }
+
+  .small-pull-3 {
+    position: relative;
+    right: 25%;
+    left: auto; }
+
+  .small-push-4 {
+    position: relative;
+    left: 33.33333%;
+    right: auto; }
+
+  .small-pull-4 {
+    position: relative;
+    right: 33.33333%;
+    left: auto; }
+
+  .small-push-5 {
+    position: relative;
+    left: 41.66667%;
+    right: auto; }
+
+  .small-pull-5 {
+    position: relative;
+    right: 41.66667%;
+    left: auto; }
+
+  .small-push-6 {
+    position: relative;
+    left: 50%;
+    right: auto; }
+
+  .small-pull-6 {
+    position: relative;
+    right: 50%;
+    left: auto; }
+
+  .small-push-7 {
+    position: relative;
+    left: 58.33333%;
+    right: auto; }
+
+  .small-pull-7 {
+    position: relative;
+    right: 58.33333%;
+    left: auto; }
+
+  .small-push-8 {
+    position: relative;
+    left: 66.66667%;
+    right: auto; }
+
+  .small-pull-8 {
+    position: relative;
+    right: 66.66667%;
+    left: auto; }
+
+  .small-push-9 {
+    position: relative;
+    left: 75%;
+    right: auto; }
+
+  .small-pull-9 {
+    position: relative;
+    right: 75%;
+    left: auto; }
+
+  .small-push-10 {
+    position: relative;
+    left: 83.33333%;
+    right: auto; }
+
+  .small-pull-10 {
+    position: relative;
+    right: 83.33333%;
+    left: auto; }
+
+  .small-push-11 {
+    position: relative;
+    left: 91.66667%;
+    right: auto; }
+
+  .small-pull-11 {
+    position: relative;
+    right: 91.66667%;
+    left: auto; }
+
+  .column,
+  .columns {
+    position: relative;
+    padding-left: 0.9375rem;
+    padding-right: 0.9375rem;
+    float: left; }
+
+  .small-1 {
+    width: 8.33333%; }
+
+  .small-2 {
+    width: 16.66667%; }
+
+  .small-3 {
+    width: 25%; }
+
+  .small-4 {
+    width: 33.33333%; }
+
+  .small-5 {
+    width: 41.66667%; }
+
+  .small-6 {
+    width: 50%; }
+
+  .small-7 {
+    width: 58.33333%; }
+
+  .small-8 {
+    width: 66.66667%; }
+
+  .small-9 {
+    width: 75%; }
+
+  .small-10 {
+    width: 83.33333%; }
+
+  .small-11 {
+    width: 91.66667%; }
+
+  .small-12 {
+    width: 100%; }
+
+  [class*="column"] + [class*="column"]:last-child {
+    float: right; }
+
+  [class*="column"] + [class*="column"].end {
+    float: left; }
+
+  .small-offset-0 {
+    margin-left: 0% !important; }
+
+  .small-offset-1 {
+    margin-left: 8.33333% !important; }
+
+  .small-offset-2 {
+    margin-left: 16.66667% !important; }
+
+  .small-offset-3 {
+    margin-left: 25% !important; }
+
+  .small-offset-4 {
+    margin-left: 33.33333% !important; }
+
+  .small-offset-5 {
+    margin-left: 41.66667% !important; }
+
+  .small-offset-6 {
+    margin-left: 50% !important; }
+
+  .small-offset-7 {
+    margin-left: 58.33333% !important; }
+
+  .small-offset-8 {
+    margin-left: 66.66667% !important; }
+
+  .small-offset-9 {
+    margin-left: 75% !important; }
+
+  .small-offset-10 {
+    margin-left: 83.33333% !important; }
+
+  .small-offset-11 {
+    margin-left: 91.66667% !important; }
+
+  .small-reset-order,
+  .small-reset-order {
+    margin-left: 0;
+    margin-right: 0;
+    left: auto;
+    right: auto;
+    float: left; }
+
+  .column.small-centered,
+  .columns.small-centered {
+    margin-left: auto;
+    margin-right: auto;
+    float: none; }
+
+  .column.small-uncentered,
+  .columns.small-uncentered {
+    margin-left: 0;
+    margin-right: 0;
+    float: left !important; }
+
+  .column.small-uncentered.opposite,
+  .columns.small-uncentered.opposite {
+    float: right; } }
+@media only screen and (min-width: 40.063em) {
+  .medium-push-0 {
+    position: relative;
+    left: 0%;
+    right: auto; }
+
+  .medium-pull-0 {
+    position: relative;
+    right: 0%;
+    left: auto; }
+
+  .medium-push-1 {
+    position: relative;
+    left: 8.33333%;
+    right: auto; }
+
+  .medium-pull-1 {
+    position: relative;
+    right: 8.33333%;
+    left: auto; }
+
+  .medium-push-2 {
+    position: relative;
+    left: 16.66667%;
+    right: auto; }
+
+  .medium-pull-2 {
+    position: relative;
+    right: 16.66667%;
+    left: auto; }
+
+  .medium-push-3 {
+    position: relative;
+    left: 25%;
+    right: auto; }
+
+  .medium-pull-3 {
+    position: relative;
+    right: 25%;
+    left: auto; }
+
+  .medium-push-4 {
+    position: relative;
+    left: 33.33333%;
+    right: auto; }
+
+  .medium-pull-4 {
+    position: relative;
+    right: 33.33333%;
+    left: auto; }
+
+  .medium-push-5 {
+    position: relative;
+    left: 41.66667%;
+    right: auto; }
+
+  .medium-pull-5 {
+    position: relative;
+    right: 41.66667%;
+    left: auto; }
+
+  .medium-push-6 {
+    position: relative;
+    left: 50%;
+    right: auto; }
+
+  .medium-pull-6 {
+    position: relative;
+    right: 50%;
+    left: auto; }
+
+  .medium-push-7 {
+    position: relative;
+    left: 58.33333%;
+    right: auto; }
+
+  .medium-pull-7 {
+    position: relative;
+    right: 58.33333%;
+    left: auto; }
+
+  .medium-push-8 {
+    position: relative;
+    left: 66.66667%;
+    right: auto; }
+
+  .medium-pull-8 {
+    position: relative;
+    right: 66.66667%;
+    left: auto; }
+
+  .medium-push-9 {
+    position: relative;
+    left: 75%;
+    right: auto; }
+
+  .medium-pull-9 {
+    position: relative;
+    right: 75%;
+    left: auto; }
+
+  .medium-push-10 {
+    position: relative;
+    left: 83.33333%;
+    right: auto; }
+
+  .medium-pull-10 {
+    position: relative;
+    right: 83.33333%;
+    left: auto; }
+
+  .medium-push-11 {
+    position: relative;
+    left: 91.66667%;
+    right: auto; }
+
+  .medium-pull-11 {
+    position: relative;
+    right: 91.66667%;
+    left: auto; }
+
+  .column,
+  .columns {
+    position: relative;
+    padding-left: 0.9375rem;
+    padding-right: 0.9375rem;
+    float: left; }
+
+  .medium-1 {
+    width: 8.33333%; }
+
+  .medium-2 {
+    width: 16.66667%; }
+
+  .medium-3 {
+    width: 25%; }
+
+  .medium-4 {
+    width: 33.33333%; }
+
+  .medium-5 {
+    width: 41.66667%; }
+
+  .medium-6 {
+    width: 50%; }
+
+  .medium-7 {
+    width: 58.33333%; }
+
+  .medium-8 {
+    width: 66.66667%; }
+
+  .medium-9 {
+    width: 75%; }
+
+  .medium-10 {
+    width: 83.33333%; }
+
+  .medium-11 {
+    width: 91.66667%; }
+
+  .medium-12 {
+    width: 100%; }
+
+  [class*="column"] + [class*="column"]:last-child {
+    float: right; }
+
+  [class*="column"] + [class*="column"].end {
+    float: left; }
+
+  .medium-offset-0 {
+    margin-left: 0% !important; }
+
+  .medium-offset-1 {
+    margin-left: 8.33333% !important; }
+
+  .medium-offset-2 {
+    margin-left: 16.66667% !important; }
+
+  .medium-offset-3 {
+    margin-left: 25% !important; }
+
+  .medium-offset-4 {
+    margin-left: 33.33333% !important; }
+
+  .medium-offset-5 {
+    margin-left: 41.66667% !important; }
+
+  .medium-offset-6 {
+    margin-left: 50% !important; }
+
+  .medium-offset-7 {
+    margin-left: 58.33333% !important; }
+
+  .medium-offset-8 {
+    margin-left: 66.66667% !important; }
+
+  .medium-offset-9 {
+    margin-left: 75% !important; }
+
+  .medium-offset-10 {
+    margin-left: 83.33333% !important; }
+
+  .medium-offset-11 {
+    margin-left: 91.66667% !important; }
+
+  .medium-reset-order,
+  .medium-reset-order {
+    margin-left: 0;
+    margin-right: 0;
+    left: auto;
+    right: auto;
+    float: left; }
+
+  .column.medium-centered,
+  .columns.medium-centered {
+    margin-left: auto;
+    margin-right: auto;
+    float: none; }
+
+  .column.medium-uncentered,
+  .columns.medium-uncentered {
+    margin-left: 0;
+    margin-right: 0;
+    float: left !important; }
+
+  .column.medium-uncentered.opposite,
+  .columns.medium-uncentered.opposite {
+    float: right; }
+
+  .push-0 {
+    position: relative;
+    left: 0%;
+    right: auto; }
+
+  .pull-0 {
+    position: relative;
+    right: 0%;
+    left: auto; }
+
+  .push-1 {
+    position: relative;
+    left: 8.33333%;
+    right: auto; }
+
+  .pull-1 {
+    position: relative;
+    right: 8.33333%;
+    left: auto; }
+
+  .push-2 {
+    position: relative;
+    left: 16.66667%;
+    right: auto; }
+
+  .pull-2 {
+    position: relative;
+    right: 16.66667%;
+    left: auto; }
+
+  .push-3 {
+    position: relative;
+    left: 25%;
+    right: auto; }
+
+  .pull-3 {
+    position: relative;
+    right: 25%;
+    left: auto; }
+
+  .push-4 {
+    position: relative;
+    left: 33.33333%;
+    right: auto; }
+
+  .pull-4 {
+    position: relative;
+    right: 33.33333%;
+    left: auto; }
+
+  .push-5 {
+    position: relative;
+    left: 41.66667%;
+    right: auto; }
+
+  .pull-5 {
+    position: relative;
+    right: 41.66667%;
+    left: auto; }
+
+  .push-6 {
+    position: relative;
+    left: 50%;
+    right: auto; }
+
+  .pull-6 {
+    position: relative;
+    right: 50%;
+    left: auto; }
+
+  .push-7 {
+    position: relative;
+    left: 58.33333%;
+    right: auto; }
+
+  .pull-7 {
+    position: relative;
+    right: 58.33333%;
+    left: auto; }
+
+  .push-8 {
+    position: relative;
+    left: 66.66667%;
+    right: auto; }
+
+  .pull-8 {
+    position: relative;
+    right: 66.66667%;
+    left: auto; }
+
+  .push-9 {
+    position: relative;
+    left: 75%;
+    right: auto; }
+
+  .pull-9 {
+    position: relative;
+    right: 75%;
+    left: auto; }
+
+  .push-10 {
+    position: relative;
+    left: 83.33333%;
+    right: auto; }
+
+  .pull-10 {
+    position: relative;
+    right: 83.33333%;
+    left: auto; }
+
+  .push-11 {
+    position: relative;
+    left: 91.66667%;
+    right: auto; }
+
+  .pull-11 {
+    position: relative;
+    right: 91.66667%;
+    left: auto; } }
+@media only screen and (min-width: 64.063em) {
+  .large-push-0 {
+    position: relative;
+    left: 0%;
+    right: auto; }
+
+  .large-pull-0 {
+    position: relative;
+    right: 0%;
+    left: auto; }
+
+  .large-push-1 {
+    position: relative;
+    left: 8.33333%;
+    right: auto; }
+
+  .large-pull-1 {
+    position: relative;
+    right: 8.33333%;
+    left: auto; }
+
+  .large-push-2 {
+    position: relative;
+    left: 16.66667%;
+    right: auto; }
+
+  .large-pull-2 {
+    position: relative;
+    right: 16.66667%;
+    left: auto; }
+
+  .large-push-3 {
+    position: relative;
+    left: 25%;
+    right: auto; }
+
+  .large-pull-3 {
+    position: relative;
+    right: 25%;
+    left: auto; }
+
+  .large-push-4 {
+    position: relative;
+    left: 33.33333%;
+    right: auto; }
+
+  .large-pull-4 {
+    position: relative;
+    right: 33.33333%;
+    left: auto; }
+
+  .large-push-5 {
+    position: relative;
+    left: 41.66667%;
+    right: auto; }
+
+  .large-pull-5 {
+    position: relative;
+    right: 41.66667%;
+    left: auto; }
+
+  .large-push-6 {
+    position: relative;
+    left: 50%;
+    right: auto; }
+
+  .large-pull-6 {
+    position: relative;
+    right: 50%;
+    left: auto; }
+
+  .large-push-7 {
+    position: relative;
+    left: 58.33333%;
+    right: auto; }
+
+  .large-pull-7 {
+    position: relative;
+    right: 58.33333%;
+    left: auto; }
+
+  .large-push-8 {
+    position: relative;
+    left: 66.66667%;
+    right: auto; }
+
+  .large-pull-8 {
+    position: relative;
+    right: 66.66667%;
+    left: auto; }
+
+  .large-push-9 {
+    position: relative;
+    left: 75%;
+    right: auto; }
+
+  .large-pull-9 {
+    position: relative;
+    right: 75%;
+    left: auto; }
+
+  .large-push-10 {
+    position: relative;
+    left: 83.33333%;
+    right: auto; }
+
+  .large-pull-10 {
+    position: relative;
+    right: 83.33333%;
+    left: auto; }
+
+  .large-push-11 {
+    position: relative;
+    left: 91.66667%;
+    right: auto; }
+
+  .large-pull-11 {
+    position: relative;
+    right: 91.66667%;
+    left: auto; }
+
+  .column,
+  .columns {
+    position: relative;
+    padding-left: 0.9375rem;
+    padding-right: 0.9375rem;
+    float: left; }
+
+  .large-1 {
+    width: 8.33333%; }
+
+  .large-2 {
+    width: 16.66667%; }
+
+  .large-3 {
+    width: 25%; }
+
+  .large-4 {
+    width: 33.33333%; }
+
+  .large-5 {
+    width: 41.66667%; }
+
+  .large-6 {
+    width: 50%; }
+
+  .large-7 {
+    width: 58.33333%; }
+
+  .large-8 {
+    width: 66.66667%; }
+
+  .large-9 {
+    width: 75%; }
+
+  .large-10 {
+    width: 83.33333%; }
+
+  .large-11 {
+    width: 91.66667%; }
+
+  .large-12 {
+    width: 100%; }
+
+  [class*="column"] + [class*="column"]:last-child {
+    float: right; }
+
+  [class*="column"] + [class*="column"].end {
+    float: left; }
+
+  .large-offset-0 {
+    margin-left: 0% !important; }
+
+  .large-offset-1 {
+    margin-left: 8.33333% !important; }
+
+  .large-offset-2 {
+    margin-left: 16.66667% !important; }
+
+  .large-offset-3 {
+    margin-left: 25% !important; }
+
+  .large-offset-4 {
+    margin-left: 33.33333% !important; }
+
+  .large-offset-5 {
+    margin-left: 41.66667% !important; }
+
+  .large-offset-6 {
+    margin-left: 50% !important; }
+
+  .large-offset-7 {
+    margin-left: 58.33333% !important; }
+
+  .large-offset-8 {
+    margin-left: 66.66667% !important; }
+
+  .large-offset-9 {
+    margin-left: 75% !important; }
+
+  .large-offset-10 {
+    margin-left: 83.33333% !important; }
+
+  .large-offset-11 {
+    margin-left: 91.66667% !important; }
+
+  .large-reset-order,
+  .large-reset-order {
+    margin-left: 0;
+    margin-right: 0;
+    left: auto;
+    right: auto;
+    float: left; }
+
+  .column.large-centered,
+  .columns.large-centered {
+    margin-left: auto;
+    margin-right: auto;
+    float: none; }
+
+  .column.large-uncentered,
+  .columns.large-uncentered {
+    margin-left: 0;
+    margin-right: 0;
+    float: left !important; }
+
+  .column.large-uncentered.opposite,
+  .columns.large-uncentered.opposite {
+    float: right; }
+
+  .push-0 {
+    position: relative;
+    left: 0%;
+    right: auto; }
+
+  .pull-0 {
+    position: relative;
+    right: 0%;
+    left: auto; }
+
+  .push-1 {
+    position: relative;
+    left: 8.33333%;
+    right: auto; }
+
+  .pull-1 {
+    position: relative;
+    right: 8.33333%;
+    left: auto; }
+
+  .push-2 {
+    position: relative;
+    left: 16.66667%;
+    right: auto; }
+
+  .pull-2 {
+    position: relative;
+    right: 16.66667%;
+    left: auto; }
+
+  .push-3 {
+    position: relative;
+    left: 25%;
+    right: auto; }
+
+  .pull-3 {
+    position: relative;
+    right: 25%;
+    left: auto; }
+
+  .push-4 {
+    position: relative;
+    left: 33.33333%;
+    right: auto; }
+
+  .pull-4 {
+    position: relative;
+    right: 33.33333%;
+    left: auto; }
+
+  .push-5 {
+    position: relative;
+    left: 41.66667%;
+    right: auto; }
+
+  .pull-5 {
+    position: relative;
+    right: 41.66667%;
+    left: auto; }
+
+  .push-6 {
+    position: relative;
+    left: 50%;
+    right: auto; }
+
+  .pull-6 {
+    position: relative;
+    right: 50%;
+    left: auto; }
+
+  .push-7 {
+    position: relative;
+    left: 58.33333%;
+    right: auto; }
+
+  .pull-7 {
+    position: relative;
+    right: 58.33333%;
+    left: auto; }
+
+  .push-8 {
+    position: relative;
+    left: 66.66667%;
+    right: auto; }
+
+  .pull-8 {
+    position: relative;
+    right: 66.66667%;
+    left: auto; }
+
+  .push-9 {
+    position: relative;
+    left: 75%;
+    right: auto; }
+
+  .pull-9 {
+    position: relative;
+    right: 75%;
+    left: auto; }
+
+  .push-10 {
+    position: relative;
+    left: 83.33333%;
+    right: auto; }
+
+  .pull-10 {
+    position: relative;
+    right: 83.33333%;
+    left: auto; }
+
+  .push-11 {
+    position: relative;
+    left: 91.66667%;
+    right: auto; }
+
+  .pull-11 {
+    position: relative;
+    right: 91.66667%;
+    left: auto; } }
+button, .button {
+  border-style: solid;
+  border-width: 0px;
+  cursor: pointer;
+  font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
+  font-weight: normal;
+  line-height: normal;
+  margin: 0 0 1.25rem;
+  position: relative;
+  text-decoration: none;
+  text-align: center;
+  -webkit-appearance: none;
+  -webkit-border-radius: 0;
+  display: inline-block;
+  padding-top: 1rem;
+  padding-right: 2rem;
+  padding-bottom: 1.0625rem;
+  padding-left: 2rem;
+  font-size: 1rem;
+  background-color: #008cba;
+  border-color: #007095;
+  color: white;
+  transition: background-color 300ms ease-out; }
+  button:hover, button:focus, .button:hover, .button:focus {
+    background-color: #007095; }
+  button:hover, button:focus, .button:hover, .button:focus {
+    color: white; }
+  button.secondary, .button.secondary {
+    background-color: #e7e7e7;
+    border-color: #b9b9b9;
+    color: #333333; }
+    button.secondary:hover, button.secondary:focus, .button.secondary:hover, .button.secondary:focus {
+      background-color: #b9b9b9; }
+    button.secondary:hover, button.secondary:focus, .button.secondary:hover, .button.secondary:focus {
+      color: #333333; }
+  button.success, .button.success {
+    background-color: #43ac6a;
+    border-color: #368a55;
+    color: white; }
+    button.success:hover, button.success:focus, .button.success:hover, .button.success:focus {
+      background-color: #368a55; }
+    button.success:hover, button.success:focus, .button.success:hover, .button.success:focus {
+      color: white; }
+  button.alert, .button.alert {
+    background-color: #f04124;
+    border-color: #cf2a0e;
+    color: white; }
+    button.alert:hover, button.alert:focus, .button.alert:hover, .button.alert:focus {
+      background-color: #cf2a0e; }
+    button.alert:hover, button.alert:focus, .button.alert:hover, .button.alert:focus {
+      color: white; }
+  button.large, .button.large {
+    padding-top: 1.125rem;
+    padding-right: 2.25rem;
+    padding-bottom: 1.1875rem;
+    padding-left: 2.25rem;
+    font-size: 1.25rem; }
+  button.small, .button.small {
+    padding-top: 0.875rem;
+    padding-right: 1.75rem;
+    padding-bottom: 0.9375rem;
+    padding-left: 1.75rem;
+    font-size: 0.8125rem; }
+  button.tiny, .button.tiny {
+    padding-top: 0.625rem;
+    padding-right: 1.25rem;
+    padding-bottom: 0.6875rem;
+    padding-left: 1.25rem;
+    font-size: 0.6875rem; }
+  button.expand, .button.expand {
+    padding-right: 0;
+    padding-left: 0;
+    width: 100%; }
+  button.left-align, .button.left-align {
+    text-align: left;
+    text-indent: 0.75rem; }
+  button.right-align, .button.right-align {
+    text-align: right;
+    padding-right: 0.75rem; }
+  button.radius, .button.radius {
+    border-radius: 3px; }
+  button.round, .button.round {
+    border-radius: 1000px; }
+  button.disabled, button[disabled], .button.disabled, .button[disabled] {
+    background-color: #008cba;
+    border-color: #007095;
+    color: white;
+    cursor: default;
+    opacity: 0.7;
+    box-shadow: none; }
+    button.disabled:hover, button.disabled:focus, button[disabled]:hover, button[disabled]:focus, .button.disabled:hover, .button.disabled:focus, .button[disabled]:hover, .button[disabled]:focus {
+      background-color: #007095; }
+    button.disabled:hover, button.disabled:focus, button[disabled]:hover, button[disabled]:focus, .button.disabled:hover, .button.disabled:focus, .button[disabled]:hover, .button[disabled]:focus {
+      color: white; }
+    button.disabled:hover, button.disabled:focus, button[disabled]:hover, button[disabled]:focus, .button.disabled:hover, .button.disabled:focus, .button[disabled]:hover, .button[disabled]:focus {
+      background-color: #008cba; }
+    button.disabled.secondary, button[disabled].secondary, .button.disabled.secondary, .button[disabled].secondary {
+      background-color: #e7e7e7;
+      border-color: #b9b9b9;
+      color: #333333;
+      cursor: default;
+      opacity: 0.7;
+      box-shadow: none; }
+      button.disabled.secondary:hover, button.disabled.secondary:focus, button[disabled].secondary:hover, button[disabled].secondary:focus, .button.disabled.secondary:hover, .button.disabled.secondary:focus, .button[disabled].secondary:hover, .button[disabled].secondary:focus {
+        background-color: #b9b9b9; }
+      button.disabled.secondary:hover, button.disabled.secondary:focus, button[disabled].secondary:hover, button[disabled].secondary:focus, .button.disabled.secondary:hover, .button.disabled.secondary:focus, .button[disabled].secondary:hover, .button[disabled].secondary:focus {
+        color: #333333; }
+      button.disabled.secondary:hover, button.disabled.secondary:focus, button[disabled].secondary:hover, button[disabled].secondary:focus, .button.disabled.secondary:hover, .button.disabled.secondary:focus, .button[disabled].secondary:hover, .button[disabled].secondary:focus {
+        background-color: #e7e7e7; }
+    button.disabled.success, button[disabled].success, .button.disabled.success, .button[disabled].success {
+      background-color: #43ac6a;
+      border-color: #368a55;
+      color: white;
+      cursor: default;
+      opacity: 0.7;
+      box-shadow: none; }
+      button.disabled.success:hover, button.disabled.success:focus, button[disabled].success:hover, button[disabled].success:focus, .button.disabled.success:hover, .button.disabled.success:focus, .button[disabled].success:hover, .button[disabled].success:focus {
+        background-color: #368a55; }
+      button.disabled.success:hover, button.disabled.success:focus, button[disabled].success:hover, button[disabled].success:focus, .button.disabled.success:hover, .button.disabled.success:focus, .button[disabled].success:hover, .button[disabled].success:focus {
+        color: white; }
+      button.disabled.success:hover, button.disabled.success:focus, button[disabled].success:hover, button[disabled].success:focus, .button.disabled.success:hover, .button.disabled.success:focus, .button[disabled].success:hover, .button[disabled].success:focus {
+        background-color: #43ac6a; }
+    button.disabled.alert, button[disabled].alert, .button.disabled.alert, .button[disabled].alert {
+      background-color: #f04124;
+      border-color: #cf2a0e;
+      color: white;
+      cursor: default;
+      opacity: 0.7;
+      box-shadow: none; }
+      button.disabled.alert:hover, button.disabled.alert:focus, button[disabled].alert:hover, button[disabled].alert:focus, .button.disabled.alert:hover, .button.disabled.alert:focus, .button[disabled].alert:hover, .button[disabled].alert:focus {
+        background-color: #cf2a0e; }
+      button.disabled.alert:hover, button.disabled.alert:focus, button[disabled].alert:hover, button[disabled].alert:focus, .button.disabled.alert:hover, .button.disabled.alert:focus, .button[disabled].alert:hover, .button[disabled].alert:focus {
+        color: white; }
+      button.disabled.alert:hover, button.disabled.alert:focus, button[disabled].alert:hover, button[disabled].alert:focus, .button.disabled.alert:hover, .button.disabled.alert:focus, .button[disabled].alert:hover, .button[disabled].alert:focus {
+        background-color: #f04124; }
+
+@media only screen and (min-width: 40.063em) {
+  button, .button {
+    display: inline-block; } }
+meta.foundation-mq-topbar {
+  font-family: "/only screen and (min-width:40.063em)/";
+  width: 40.063em; }
+
+/* Wrapped around .top-bar to contain to grid width */
+.contain-to-grid {
+  width: 100%;
+  background: #333333; }
+  .contain-to-grid .top-bar {
+    margin-bottom: 0; }
+
+.fixed {
+  width: 100%;
+  left: 0;
+  position: fixed;
+  top: 0;
+  z-index: 99; }
+  .fixed.expanded:not(.top-bar) {
+    overflow-y: auto;
+    height: auto;
+    width: 100%;
+    max-height: 100%; }
+    .fixed.expanded:not(.top-bar) .title-area {
+      position: fixed;
+      width: 100%;
+      z-index: 99; }
+    .fixed.expanded:not(.top-bar) .top-bar-section {
+      z-index: 98;
+      margin-top: 45px; }
+
+.top-bar {
+  overflow: hidden;
+  height: 45px;
+  line-height: 45px;
+  position: relative;
+  background: #333333;
+  margin-bottom: 0; }
+  .top-bar ul {
+    margin-bottom: 0;
+    list-style: none; }
+  .top-bar .row {
+    max-width: none; }
+  .top-bar form,
+  .top-bar input {
+    margin-bottom: 0; }
+  .top-bar input {
+    height: auto;
+    padding-top: .35rem;
+    padding-bottom: .35rem;
+    font-size: 0.75rem; }
+  .top-bar .button, .top-bar button {
+    padding-top: .45rem;
+    padding-bottom: .35rem;
+    margin-bottom: 0;
+    font-size: 0.75rem; }
+  .top-bar .title-area {
+    position: relative;
+    margin: 0; }
+  .top-bar .name {
+    height: 45px;
+    margin: 0;
+    font-size: 16px; }
+    .top-bar .name h1 {
+      line-height: 45px;
+/*      font-size: 1.0625rem;*/
+      font-size: 0.94444rem;
+      margin: 0; }
+      .top-bar .name h1 a {
+        font-weight: normal;
+        color: white;
+        width: 75%;
+        display: block;
+        padding: 0 15px; }
+  .top-bar .toggle-topbar {
+    position: absolute;
+    right: 0;
+    top: 0; }
+    .top-bar .toggle-topbar a {
+      color: white;
+      text-transform: uppercase;
+      font-size: 0.8125rem;
+      font-weight: bold;
+      position: relative;
+      display: block;
+      padding: 0 15px;
+      height: 45px;
+      line-height: 45px; }
+    .top-bar .toggle-topbar.menu-icon {
+      right: 15px;
+      top: 50%;
+      margin-top: -16px;
+      padding-left: 40px; }
+      .top-bar .toggle-topbar.menu-icon a {
+        height: 34px;
+        line-height: 33px;
+        padding: 0;
+        padding-right: 25px;
+        color: white;
+        position: relative; }
+        .top-bar .toggle-topbar.menu-icon a::after {
+          content: "";
+          position: absolute;
+          right: 0;
+          display: block;
+          width: 16px;
+          top: 0;
+          height: 0;
+          box-shadow: 0 10px 0 1px white, 0 16px 0 1px white, 0 22px 0 1px white; }
+  .top-bar.expanded {
+    height: auto;
+    background: transparent; }
+    .top-bar.expanded .title-area {
+      background: #333333; }
+    .top-bar.expanded .toggle-topbar a {
+      color: #888888; }
+      .top-bar.expanded .toggle-topbar a::after {
+        box-shadow: 0 10px 0 1px #888888, 0 16px 0 1px #888888, 0 22px 0 1px #888888; }
+
+.top-bar-section {
+  left: 0;
+  position: relative;
+  width: auto;
+  transition: left 300ms ease-out; }
+  .top-bar-section ul {
+    width: 100%;
+    height: auto;
+    display: block;
+    background: #333333;
+    font-size: 16px;
+    margin: 0; }
+  .top-bar-section .divider,
+  .top-bar-section [role="separator"] {
+    border-top: solid 1px #1a1a1a;
+    clear: both;
+    height: 1px;
+    width: 100%; }
+  .top-bar-section ul li > a {
+    display: block;
+    width: 100%;
+    color: white;
+    padding: 12px 0 12px 0;
+    padding-left: 15px;
+    font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
+    font-size: 0.8125rem;
+    font-weight: normal;
+    text-transform: none;
+    background: #333333; }
+    .top-bar-section ul li > a.button {
+      font-size: 0.8125rem;
+      padding-right: 15px;
+      padding-left: 15px;
+      background-color: #008cba;
+      border-color: #007095;
+      color: white; }
+      .top-bar-section ul li > a.button:hover, .top-bar-section ul li > a.button:focus {
+        background-color: #007095; }
+      .top-bar-section ul li > a.button:hover, .top-bar-section ul li > a.button:focus {
+        color: white; }
+    .top-bar-section ul li > a.button.secondary {
+      background-color: #e7e7e7;
+      border-color: #b9b9b9;
+      color: #333333; }
+      .top-bar-section ul li > a.button.secondary:hover, .top-bar-section ul li > a.button.secondary:focus {
+        background-color: #b9b9b9; }
+      .top-bar-section ul li > a.button.secondary:hover, .top-bar-section ul li > a.button.secondary:focus {
+        color: #333333; }
+    .top-bar-section ul li > a.button.success {
+      background-color: #43ac6a;
+      border-color: #368a55;
+      color: white; }
+      .top-bar-section ul li > a.button.success:hover, .top-bar-section ul li > a.button.success:focus {
+        background-color: #368a55; }
+      .top-bar-section ul li > a.button.success:hover, .top-bar-section ul li > a.button.success:focus {
+        color: white; }
+    .top-bar-section ul li > a.button.alert {
+      background-color: #f04124;
+      border-color: #cf2a0e;
+      color: white; }
+      .top-bar-section ul li > a.button.alert:hover, .top-bar-section ul li > a.button.alert:focus {
+        background-color: #cf2a0e; }
+      .top-bar-section ul li > a.button.alert:hover, .top-bar-section ul li > a.button.alert:focus {
+        color: white; }
+  .top-bar-section ul li > button {
+    font-size: 0.8125rem;
+    padding-right: 15px;
+    padding-left: 15px;
+    background-color: #008cba;
+    border-color: #007095;
+    color: white; }
+    .top-bar-section ul li > button:hover, .top-bar-section ul li > button:focus {
+      background-color: #007095; }
+    .top-bar-section ul li > button:hover, .top-bar-section ul li > button:focus {
+      color: white; }
+    .top-bar-section ul li > button.secondary {
+      background-color: #e7e7e7;
+      border-color: #b9b9b9;
+      color: #333333; }
+      .top-bar-section ul li > button.secondary:hover, .top-bar-section ul li > button.secondary:focus {
+        background-color: #b9b9b9; }
+      .top-bar-section ul li > button.secondary:hover, .top-bar-section ul li > button.secondary:focus {
+        color: #333333; }
+    .top-bar-section ul li > button.success {
+      background-color: #43ac6a;
+      border-color: #368a55;
+      color: white; }
+      .top-bar-section ul li > button.success:hover, .top-bar-section ul li > button.success:focus {
+        background-color: #368a55; }
+      .top-bar-section ul li > button.success:hover, .top-bar-section ul li > button.success:focus {
+        color: white; }
+    .top-bar-section ul li > button.alert {
+      background-color: #f04124;
+      border-color: #cf2a0e;
+      color: white; }
+      .top-bar-section ul li > button.alert:hover, .top-bar-section ul li > button.alert:focus {
+        background-color: #cf2a0e; }
+      .top-bar-section ul li > button.alert:hover, .top-bar-section ul li > button.alert:focus {
+        color: white; }
+  .top-bar-section ul li:hover:not(.has-form) > a {
+    background: #272727;
+    color: white; }
+  .top-bar-section ul li.active > a {
+    background: #008cba;
+    color: white; }
+    .top-bar-section ul li.active > a:hover {
+      background: #0078a0;
+      color: white; }
+  .top-bar-section .has-form {
+    padding: 15px; }
+  .top-bar-section .has-dropdown {
+    position: relative; }
+    .top-bar-section .has-dropdown > a:after {
+      content: "";
+      display: block;
+      width: 0;
+      height: 0;
+      border: inset 5px;
+      border-color: transparent transparent transparent rgba(255, 255, 255, 0.4);
+      border-left-style: solid;
+      margin-right: 15px;
+      margin-top: -4.5px;
+      position: absolute;
+      top: 50%;
+      right: 0; }
+    .top-bar-section .has-dropdown.moved {
+      position: static; }
+      .top-bar-section .has-dropdown.moved > .dropdown {
+        display: block;
+        position: static !important;
+        height: auto;
+        width: auto;
+        overflow: visible;
+        clip: auto;
+        position: absolute !important;
+        width: 100%; }
+      .top-bar-section .has-dropdown.moved > a:after {
+        display: none; }
+  .top-bar-section .dropdown {
+    position: absolute;
+    left: 100%;
+    top: 0;
+    z-index: 99;
+    display: block;
+    position: absolute !important;
+    height: 1px;
+    width: 1px;
+    overflow: hidden;
+    clip: rect(1px, 1px, 1px, 1px); }
+    .top-bar-section .dropdown li {
+      width: 100%;
+      height: auto; }
+      .top-bar-section .dropdown li a {
+        font-weight: normal;
+        padding: 8px 15px; }
+        .top-bar-section .dropdown li a.parent-link {
+          font-weight: normal; }
+      .top-bar-section .dropdown li.title h5 {
+        margin-bottom: 0; }
+        .top-bar-section .dropdown li.title h5 a {
+          color: white;
+          line-height: 22.5px;
+          display: block; }
+      .top-bar-section .dropdown li.has-form {
+        padding: 8px 15px; }
+      .top-bar-section .dropdown li .button, .top-bar-section .dropdown li button {
+        top: auto; }
+    .top-bar-section .dropdown label {
+      padding: 8px 15px 2px;
+      margin-bottom: 0;
+      text-transform: uppercase;
+      color: #777777;
+      font-weight: bold;
+      font-size: 0.625rem; }
+
+.js-generated {
+  display: block; }
+
+@media only screen and (min-width: 40.063em) {
+  .top-bar {
+    background: #333333;
+    *zoom: 1;
+    overflow: visible; }
+    .top-bar:before, .top-bar:after {
+      content: " ";
+      display: table; }
+    .top-bar:after {
+      clear: both; }
+    .top-bar .toggle-topbar {
+      display: none; }
+    .top-bar .title-area {
+      float: left; }
+    .top-bar .name h1 a {
+      width: auto; }
+    .top-bar input,
+    .top-bar .button,
+    .top-bar button {
+      font-size: 0.875rem;
+      position: relative;
+      top: 7px; }
+    .top-bar.expanded {
+      background: #333333; }
+
+  .contain-to-grid .top-bar {
+    max-width: 62.5rem;
+    margin: 0 auto;
+    margin-bottom: 0; }
+
+  .top-bar-section {
+    transition: none 0 0;
+    left: 0 !important; }
+    .top-bar-section ul {
+      width: auto;
+      height: auto !important;
+      display: inline; }
+      .top-bar-section ul li {
+        float: left; }
+        .top-bar-section ul li .js-generated {
+          display: none; }
+    .top-bar-section li.hover > a:not(.button) {
+      background: #272727;
+      color: white; }
+    .top-bar-section li:not(.has-form) a:not(.button) {
+      padding: 0 15px;
+      line-height: 45px;
+      background: #333333; }
+      .top-bar-section li:not(.has-form) a:not(.button):hover {
+        background: #272727; }
+    .top-bar-section li.active:not(.has-form) a:not(.button) {
+      padding: 0 15px;
+      line-height: 45px;
+      color: white;
+      background: #008cba; }
+      .top-bar-section li.active:not(.has-form) a:not(.button):hover {
+        background: #0078a0; }
+    .top-bar-section .has-dropdown > a {
+      padding-right: 35px !important; }
+      .top-bar-section .has-dropdown > a:after {
+        content: "";
+        display: block;
+        width: 0;
+        height: 0;
+        border: inset 5px;
+        border-color: rgba(255, 255, 255, 0.4) transparent transparent transparent;
+        border-top-style: solid;
+        margin-top: -2.5px;
+        top: 22.5px; }
+    .top-bar-section .has-dropdown.moved {
+      position: relative; }
+      .top-bar-section .has-dropdown.moved > .dropdown {
+        display: block;
+        position: absolute !important;
+        height: 1px;
+        width: 1px;
+        overflow: hidden;
+        clip: rect(1px, 1px, 1px, 1px); }
+    .top-bar-section .has-dropdown.hover > .dropdown, .top-bar-section .has-dropdown.not-click:hover > .dropdown {
+      display: block;
+      position: static !important;
+      height: auto;
+      width: auto;
+      overflow: visible;
+      clip: auto;
+      position: absolute !important; }
+    .top-bar-section .has-dropdown .dropdown li.has-dropdown > a:after {
+      border: none;
+      content: "\00bb";
+      top: 1rem;
+      margin-top: -1px;
+      right: 5px;
+      line-height: 1.2; }
+    .top-bar-section .dropdown {
+      left: 0;
+      top: auto;
+      background: transparent;
+      min-width: 100%; }
+      .top-bar-section .dropdown li a {
+        color: white;
+        line-height: 1;
+        white-space: nowrap;
+        padding: 12px 15px;
+        background: #333333; }
+      .top-bar-section .dropdown li:not(.has-form) a:not(.button) {
+        color: white;
+        background: #333333; }
+      .top-bar-section .dropdown li:not(.has-form):hover > a:not(.button) {
+        color: white;
+        background: #272727; }
+      .top-bar-section .dropdown li label {
+        white-space: nowrap;
+        background: #333333; }
+      .top-bar-section .dropdown li .dropdown {
+        left: 100%;
+        top: 0; }
+    .top-bar-section > ul > .divider, .top-bar-section > ul > [role="separator"] {
+      border-bottom: none;
+      border-top: none;
+      border-right: solid 1px #4e4e4e;
+      clear: none;
+      height: 45px;
+      width: 0; }
+    .top-bar-section .has-form {
+      background: #333333;
+      padding: 0 15px;
+      height: 45px; }
+    .top-bar-section .right li .dropdown {
+      left: auto;
+      right: 0; }
+      .top-bar-section .right li .dropdown li .dropdown {
+        right: 100%; }
+    .top-bar-section .left li .dropdown {
+      right: auto;
+      left: 0; }
+      .top-bar-section .left li .dropdown li .dropdown {
+        left: 100%; }
+
+  .no-js .top-bar-section ul li:hover > a {
+    background: #272727;
+    color: white; }
+  .no-js .top-bar-section ul li:active > a {
+    background: #008cba;
+    color: white; }
+  .no-js .top-bar-section .has-dropdown:hover > .dropdown {
+    display: block;
+    position: static !important;
+    height: auto;
+    width: auto;
+    overflow: visible;
+    clip: auto;
+    position: absolute !important; } }
+.breadcrumbs {
+  display: block;
+  padding: 0.5625rem 0.875rem 0.5625rem;
+  overflow: hidden;
+  margin-left: 0;
+  list-style: none;
+  border-style: solid;
+  border-width: 1px;
+  background-color: #f4f4f4;
+  border-color: gainsboro;
+  border-radius: 3px; }
+  .breadcrumbs > * {
+    margin: 0;
+    float: left;
+    font-size: 0.6875rem;
+    line-height: 0.6875rem;
+    text-transform: uppercase;
+    color: #008cba; }
+    .breadcrumbs > *:hover a, .breadcrumbs > *:focus a {
+      text-decoration: underline; }
+    .breadcrumbs > * a {
+      color: #008cba; }
+    .breadcrumbs > *.current {
+      cursor: default;
+      color: #333333; }
+      .breadcrumbs > *.current a {
+        cursor: default;
+        color: #333333; }
+      .breadcrumbs > *.current:hover, .breadcrumbs > *.current:hover a, .breadcrumbs > *.current:focus, .breadcrumbs > *.current:focus a {
+        text-decoration: none; }
+    .breadcrumbs > *.unavailable {
+      color: #999999; }
+      .breadcrumbs > *.unavailable a {
+        color: #999999; }
+      .breadcrumbs > *.unavailable:hover, .breadcrumbs > *.unavailable:hover a, .breadcrumbs > *.unavailable:focus,
+      .breadcrumbs > *.unavailable a:focus {
+        text-decoration: none;
+        color: #999999;
+        cursor: default; }
+    .breadcrumbs > *:before {
+      content: "/";
+      color: #aaaaaa;
+      margin: 0 0.75rem;
+      position: relative;
+      top: 1px; }
+    .breadcrumbs > *:first-child:before {
+      content: " ";
+      margin: 0; }
+
+.alert-box {
+  border-style: solid;
+  border-width: 1px;
+  display: block;
+  font-weight: normal;
+  margin-bottom: 1.25rem;
+  position: relative;
+  padding: 0.875rem 1.5rem 0.875rem 0.875rem;
+  font-size: 0.8125rem;
+  transition: opacity 300ms ease-out;
+  background-color: #008cba;
+  border-color: #0078a0;
+  color: white; }
+  .alert-box .close {
+    font-size: 1.375rem;
+    padding: 9px 6px 4px;
+    line-height: 0;
+    position: absolute;
+    top: 50%;
+    margin-top: -0.6875rem;
+    right: 0.25rem;
+    color: #333333;
+    opacity: 0.3; }
+    .alert-box .close:hover, .alert-box .close:focus {
+      opacity: 0.5; }
+  .alert-box.radius {
+    border-radius: 3px; }
+  .alert-box.round {
+    border-radius: 1000px; }
+  .alert-box.success {
+    background-color: #43ac6a;
+    border-color: #3a945b;
+    color: white; }
+  .alert-box.alert {
+    background-color: #f04124;
+    border-color: #de2d0f;
+    color: white; }
+  .alert-box.secondary {
+    background-color: #e7e7e7;
+    border-color: #c7c7c7;
+    color: #4f4f4f; }
+  .alert-box.warning {
+    background-color: #f08a24;
+    border-color: #de770f;
+    color: white; }
+  .alert-box.info {
+    background-color: #a0d3e8;
+    border-color: #74bfdd;
+    color: #4f4f4f; }
+  .alert-box.alert-close {
+    opacity: 0; }
+
+.inline-list {
+  margin: 0 auto 1.0625rem auto;
+  margin-left: -1.375rem;
+  margin-right: 0;
+  padding: 0;
+  list-style: none;
+  overflow: hidden; }
+  .inline-list > li {
+    list-style: none;
+    float: left;
+    margin-left: 1.375rem;
+    display: block; }
+    .inline-list > li > * {
+      display: block; }
+
+.button-group {
+  list-style: none;
+  margin: 0;
+  left: 0;
+  *zoom: 1; }
+  .button-group:before, .button-group:after {
+    content: " ";
+    display: table; }
+  .button-group:after {
+    clear: both; }
+  .button-group li {
+    margin: 0;
+    float: left; }
+    .button-group li > button, .button-group li .button {
+      border-left: 1px solid;
+      border-color: rgba(255, 255, 255, 0.5); }
+    .button-group li:first-child button, .button-group li:first-child .button {
+      border-left: 0; }
+    .button-group li:first-child {
+      margin-left: 0; }
+  .button-group.radius > * > button, .button-group.radius > * .button {
+    border-left: 1px solid;
+    border-color: rgba(255, 255, 255, 0.5); }
+  .button-group.radius > *:first-child button, .button-group.radius > *:first-child .button {
+    border-left: 0; }
+  .button-group.radius > *:first-child, .button-group.radius > *:first-child > a, .button-group.radius > *:first-child > button, .button-group.radius > *:first-child > .button {
+    border-bottom-left-radius: 3px;
+    border-top-left-radius: 3px; }
+  .button-group.radius > *:last-child, .button-group.radius > *:last-child > a, .button-group.radius > *:last-child > button, .button-group.radius > *:last-child > .button {
+    border-bottom-right-radius: 3px;
+    border-top-right-radius: 3px; }
+  .button-group.round > * > button, .button-group.round > * .button {
+    border-left: 1px solid;
+    border-color: rgba(255, 255, 255, 0.5); }
+  .button-group.round > *:first-child button, .button-group.round > *:first-child .button {
+    border-left: 0; }
+  .button-group.round > *:first-child, .button-group.round > *:first-child > a, .button-group.round > *:first-child > button, .button-group.round > *:first-child > .button {
+    border-bottom-left-radius: 1000px;
+    border-top-left-radius: 1000px; }
+  .button-group.round > *:last-child, .button-group.round > *:last-child > a, .button-group.round > *:last-child > button, .button-group.round > *:last-child > .button {
+    border-bottom-right-radius: 1000px;
+    border-top-right-radius: 1000px; }
+  .button-group.even-2 li {
+    width: 50%; }
+    .button-group.even-2 li > button, .button-group.even-2 li .button {
+      border-left: 1px solid;
+      border-color: rgba(255, 255, 255, 0.5); }
+    .button-group.even-2 li:first-child button, .button-group.even-2 li:first-child .button {
+      border-left: 0; }
+    .button-group.even-2 li button, .button-group.even-2 li .button {
+      width: 100%; }
+  .button-group.even-3 li {
+    width: 33.33333%; }
+    .button-group.even-3 li > button, .button-group.even-3 li .button {
+      border-left: 1px solid;
+      border-color: rgba(255, 255, 255, 0.5); }
+    .button-group.even-3 li:first-child button, .button-group.even-3 li:first-child .button {
+      border-left: 0; }
+    .button-group.even-3 li button, .button-group.even-3 li .button {
+      width: 100%; }
+  .button-group.even-4 li {
+    width: 25%; }
+    .button-group.even-4 li > button, .button-group.even-4 li .button {
+      border-left: 1px solid;
+      border-color: rgba(255, 255, 255, 0.5); }
+    .button-group.even-4 li:first-child button, .button-group.even-4 li:first-child .button {
+      border-left: 0; }
+    .button-group.even-4 li button, .button-group.even-4 li .button {
+      width: 100%; }
+  .button-group.even-5 li {
+    width: 20%; }
+    .button-group.even-5 li > button, .button-group.even-5 li .button {
+      border-left: 1px solid;
+      border-color: rgba(255, 255, 255, 0.5); }
+    .button-group.even-5 li:first-child button, .button-group.even-5 li:first-child .button {
+      border-left: 0; }
+    .button-group.even-5 li button, .button-group.even-5 li .button {
+      width: 100%; }
+  .button-group.even-6 li {
+    width: 16.66667%; }
+    .button-group.even-6 li > button, .button-group.even-6 li .button {
+      border-left: 1px solid;
+      border-color: rgba(255, 255, 255, 0.5); }
+    .button-group.even-6 li:first-child button, .button-group.even-6 li:first-child .button {
+      border-left: 0; }
+    .button-group.even-6 li button, .button-group.even-6 li .button {
+      width: 100%; }
+  .button-group.even-7 li {
+    width: 14.28571%; }
+    .button-group.even-7 li > button, .button-group.even-7 li .button {
+      border-left: 1px solid;
+      border-color: rgba(255, 255, 255, 0.5); }
+    .button-group.even-7 li:first-child button, .button-group.even-7 li:first-child .button {
+      border-left: 0; }
+    .button-group.even-7 li button, .button-group.even-7 li .button {
+      width: 100%; }
+  .button-group.even-8 li {
+    width: 12.5%; }
+    .button-group.even-8 li > button, .button-group.even-8 li .button {
+      border-left: 1px solid;
+      border-color: rgba(255, 255, 255, 0.5); }
+    .button-group.even-8 li:first-child button, .button-group.even-8 li:first-child .button {
+      border-left: 0; }
+    .button-group.even-8 li button, .button-group.even-8 li .button {
+      width: 100%; }
+
+.button-bar {
+  *zoom: 1; }
+  .button-bar:before, .button-bar:after {
+    content: " ";
+    display: table; }
+  .button-bar:after {
+    clear: both; }
+  .button-bar .button-group {
+    float: left;
+    margin-right: 0.625rem; }
+    .button-bar .button-group div {
+      overflow: hidden; }
+
+/* Panels */
+.panel {
+  border-style: solid;
+  border-width: 1px;
+  border-color: #d8d8d8;
+  margin-bottom: 1.25rem;
+  padding: 1.25rem;
+  background: #f2f2f2; }
+  .panel > :first-child {
+    margin-top: 0; }
+  .panel > :last-child {
+    margin-bottom: 0; }
+  .panel h1, .panel h2, .panel h3, .panel h4, .panel h5, .panel h6, .panel p {
+    color: #333333; }
+  .panel h1, .panel h2, .panel h3, .panel h4, .panel h5, .panel h6 {
+    line-height: 1;
+    margin-bottom: 0.625rem; }
+    .panel h1.subheader, .panel h2.subheader, .panel h3.subheader, .panel h4.subheader, .panel h5.subheader, .panel h6.subheader {
+      line-height: 1.4; }
+  .panel.callout {
+    border-style: solid;
+    border-width: 1px;
+    border-color: #b6edff;
+    margin-bottom: 1.25rem;
+    padding: 1.25rem;
+    background: #ecfaff; }
+    .panel.callout > :first-child {
+      margin-top: 0; }
+    .panel.callout > :last-child {
+      margin-bottom: 0; }
+    .panel.callout h1, .panel.callout h2, .panel.callout h3, .panel.callout h4, .panel.callout h5, .panel.callout h6, .panel.callout p {
+      color: #333333; }
+    .panel.callout h1, .panel.callout h2, .panel.callout h3, .panel.callout h4, .panel.callout h5, .panel.callout h6 {
+      line-height: 1;
+      margin-bottom: 0.625rem; }
+      .panel.callout h1.subheader, .panel.callout h2.subheader, .panel.callout h3.subheader, .panel.callout h4.subheader, .panel.callout h5.subheader, .panel.callout h6.subheader {
+        line-height: 1.4; }
+    .panel.callout a:not(.button) {
+      color: #008cba; }
+  .panel.radius {
+    border-radius: 3px; }
+
+.dropdown.button, button.dropdown {
+  position: relative;
+  padding-right: 3.5625rem; }
+  .dropdown.button:before, button.dropdown:before {
+    position: absolute;
+    content: "";
+    width: 0;
+    height: 0;
+    display: block;
+    border-style: solid;
+    border-color: white transparent transparent transparent;
+    top: 50%; }
+  .dropdown.button:before, button.dropdown:before {
+    border-width: 0.375rem;
+    right: 1.40625rem;
+    margin-top: -0.15625rem; }
+  .dropdown.button:before, button.dropdown:before {
+    border-color: white transparent transparent transparent; }
+  .dropdown.button.tiny, button.dropdown.tiny {
+    padding-right: 2.625rem; }
+    .dropdown.button.tiny:before, button.dropdown.tiny:before {
+      border-width: 0.375rem;
+      right: 1.125rem;
+      margin-top: -0.125rem; }
+    .dropdown.button.tiny:before, button.dropdown.tiny:before {
+      border-color: white transparent transparent transparent; }
+  .dropdown.button.small, button.dropdown.small {
+    padding-right: 3.0625rem; }
+    .dropdown.button.small:before, button.dropdown.small:before {
+      border-width: 0.4375rem;
+      right: 1.3125rem;
+      margin-top: -0.15625rem; }
+    .dropdown.button.small:before, button.dropdown.small:before {
+      border-color: white transparent transparent transparent; }
+  .dropdown.button.large, button.dropdown.large {
+    padding-right: 3.625rem; }
+    .dropdown.button.large:before, button.dropdown.large:before {
+      border-width: 0.3125rem;
+      right: 1.71875rem;
+      margin-top: -0.15625rem; }
+    .dropdown.button.large:before, button.dropdown.large:before {
+      border-color: white transparent transparent transparent; }
+  .dropdown.button.secondary:before, button.dropdown.secondary:before {
+    border-color: #333333 transparent transparent transparent; }
+
+div.switch {
+  position: relative;
+  padding: 0;
+  display: block;
+  overflow: hidden;
+  border-style: solid;
+  border-width: 1px;
+  margin-bottom: 1.25rem;
+  height: 2.25rem;
+  background: white;
+  border-color: #cccccc; }
+  div.switch label {
+    position: relative;
+    left: 0;
+    z-index: 2;
+    float: left;
+    width: 50%;
+    height: 100%;
+    margin: 0;
+    font-weight: bold;
+    text-align: left;
+    transition: all 0.1s ease-out; }
+  div.switch input {
+    position: absolute;
+    z-index: 3;
+    opacity: 0;
+    width: 100%;
+    height: 100%;
+    -moz-appearance: none; }
+    div.switch input:hover, div.switch input:focus {
+      cursor: pointer; }
+  div.switch span:last-child {
+    position: absolute;
+    top: -1px;
+    left: -1px;
+    z-index: 1;
+    display: block;
+    padding: 0;
+    border-width: 1px;
+    border-style: solid;
+    transition: all 0.1s ease-out; }
+  div.switch input:not(:checked) + label {
+    opacity: 0; }
+  div.switch input:checked {
+    display: none !important; }
+  div.switch input {
+    left: 0;
+    display: block !important; }
+  div.switch input:first-of-type + label,
+  div.switch input:first-of-type + span + label {
+    left: -50%; }
+  div.switch input:first-of-type:checked + label,
+  div.switch input:first-of-type:checked + span + label {
+    left: 0%; }
+  div.switch input:last-of-type + label,
+  div.switch input:last-of-type + span + label {
+    right: -50%;
+    left: auto;
+    text-align: right; }
+  div.switch input:last-of-type:checked + label,
+  div.switch input:last-of-type:checked + span + label {
+    right: 0%;
+    left: auto; }
+  div.switch span.custom {
+    display: none !important; }
+  form.custom div.switch .hidden-field {
+    margin-left: auto;
+    position: absolute;
+    visibility: visible; }
+  div.switch label {
+    padding: 0;
+    line-height: 2.3rem;
+    font-size: 0.875rem; }
+  div.switch input:first-of-type:checked ~ span:last-child {
+    left: 100%;
+    margin-left: -2.1875rem; }
+  div.switch span:last-child {
+    width: 2.25rem;
+    height: 2.25rem; }
+  div.switch span:last-child {
+    border-color: #b3b3b3;
+    background: white;
+    background: linear-gradient(to bottom, white 0%, #f2f2f2 100%);
+    box-shadow: 2px 0 10px 0 rgba(0, 0, 0, 0.07), 1000px 0 0 980px #f3faf6, -2px 0 10px 0 rgba(0, 0, 0, 0.07), -1000px 0 0 1000px whitesmoke; }
+  div.switch:hover span:last-child, div.switch:focus span:last-child {
+    background: white;
+    background: linear-gradient(to bottom, white 0%, #e6e6e6 100%); }
+  div.switch:active {
+    background: transparent; }
+  div.switch.large {
+    height: 2.75rem; }
+    div.switch.large label {
+      padding: 0;
+      line-height: 2.3rem;
+      font-size: 1.0625rem; }
+    div.switch.large input:first-of-type:checked ~ span:last-child {
+      left: 100%;
+      margin-left: -2.6875rem; }
+    div.switch.large span:last-child {
+      width: 2.75rem;
+      height: 2.75rem; }
+  div.switch.small {
+    height: 1.75rem; }
+    div.switch.small label {
+      padding: 0;
+      line-height: 2.1rem;
+      font-size: 0.75rem; }
+    div.switch.small input:first-of-type:checked ~ span:last-child {
+      left: 100%;
+      margin-left: -1.6875rem; }
+    div.switch.small span:last-child {
+      width: 1.75rem;
+      height: 1.75rem; }
+  div.switch.tiny {
+    height: 1.375rem; }
+    div.switch.tiny label {
+      padding: 0;
+      line-height: 1.9rem;
+      font-size: 0.6875rem; }
+    div.switch.tiny input:first-of-type:checked ~ span:last-child {
+      left: 100%;
+      margin-left: -1.3125rem; }
+    div.switch.tiny span:last-child {
+      width: 1.375rem;
+      height: 1.375rem; }
+  div.switch.radius {
+    border-radius: 4px; }
+    div.switch.radius span:last-child {
+      border-radius: 3px; }
+  div.switch.round {
+    border-radius: 1000px; }
+    div.switch.round span:last-child {
+      border-radius: 999px; }
+    div.switch.round label {
+      padding: 0 0.5625rem; }
+
+/* Image Thumbnails */
+.th {
+  line-height: 0;
+  display: inline-block;
+  border: solid 4px white;
+  max-width: 100%;
+  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2);
+  transition: all 200ms ease-out; }
+  .th:hover, .th:focus {
+    box-shadow: 0 0 6px 1px rgba(0, 140, 186, 0.5); }
+  .th.radius {
+    border-radius: 3px; }
+
+/* Pricing Tables */
+.pricing-table {
+  border: solid 1px #dddddd;
+  margin-left: 0;
+  margin-bottom: 1.25rem; }
+  .pricing-table * {
+    list-style: none;
+    line-height: 1; }
+  .pricing-table .title {
+    background-color: #333333;
+    padding: 0.9375rem 1.25rem;
+    text-align: center;
+    color: #eeeeee;
+    font-weight: normal;
+    font-size: 1rem;
+    font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; }
+  .pricing-table .price {
+    background-color: #f6f6f6;
+    padding: 0.9375rem 1.25rem;
+    text-align: center;
+    color: #333333;
+    font-weight: normal;
+    font-size: 2rem;
+    font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; }
+  .pricing-table .description {
+    background-color: white;
+    padding: 0.9375rem;
+    text-align: center;
+    color: #777777;
+    font-size: 0.75rem;
+    font-weight: normal;
+    line-height: 1.4;
+    border-bottom: dotted 1px #dddddd; }
+  .pricing-table .bullet-item {
+    background-color: white;
+    padding: 0.9375rem;
+    text-align: center;
+    color: #333333;
+    font-size: 0.875rem;
+    font-weight: normal;
+    border-bottom: dotted 1px #dddddd; }
+  .pricing-table .cta-button {
+    background-color: white;
+    text-align: center;
+    padding: 1.25rem 1.25rem 0; }
+
+@keyframes rotate {
+  from {
+    -webkit-transform: rotate(0deg);
+    -moz-transform: rotate(0deg);
+    -ms-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    transform: rotate(0deg); }
+
+  to {
+    -webkit-transform: rotate(360deg);
+    -moz-transform: rotate(360deg);
+    -ms-transform: rotate(360deg);
+    -o-transform: rotate(360deg);
+    transform: rotate(360deg); } }
+
+/* Orbit Graceful Loading */
+.slideshow-wrapper {
+  position: relative; }
+  .slideshow-wrapper ul {
+    list-style-type: none;
+    margin: 0; }
+    .slideshow-wrapper ul li,
+    .slideshow-wrapper ul li .orbit-caption {
+      display: none; }
+    .slideshow-wrapper ul li:first-child {
+      display: block; }
+  .slideshow-wrapper .orbit-container {
+    background-color: transparent; }
+    .slideshow-wrapper .orbit-container li {
+      display: block; }
+      .slideshow-wrapper .orbit-container li .orbit-caption {
+        display: block; }
+  .slideshow-wrapper .preloader {
+    display: block;
+    width: 40px;
+    height: 40px;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    margin-top: -20px;
+    margin-left: -20px;
+    border: solid 3px;
+    border-color: #555555 white;
+    border-radius: 1000px;
+    animation-name: rotate;
+    animation-duration: 1.5s;
+    animation-iteration-count: infinite;
+    animation-timing-function: linear; }
+
+.orbit-container {
+  overflow: hidden;
+  width: 100%;
+  position: relative;
+  background: none; }
+  .orbit-container .orbit-slides-container {
+    list-style: none;
+    margin: 0;
+    padding: 0;
+    position: relative;
+    -webkit-transform: translateZ(0); }
+    .orbit-container .orbit-slides-container img {
+      display: block;
+      max-width: 100%; }
+    .orbit-container .orbit-slides-container.fade li {
+      opacity: 0;
+      transition: opacity 500ms ease-in-out;
+      -ms-transform: translate(0, 0);
+      -webkit-transform: translate3d(0, 0, 0);
+      -moz-transform: translate3d(0, 0, 0);
+      -o-transform: translate3d(0, 0, 0);
+      transform: translate3d(0, 0, 0); }
+      .orbit-container .orbit-slides-container.fade li.animate-in {
+        opacity: 1;
+        z-index: 20;
+        transition: opacity 500ms ease-in-out; }
+      .orbit-container .orbit-slides-container.fade li.animate-out {
+        z-index: 10;
+        transition: opacity 500ms ease-in-out; }
+    .orbit-container .orbit-slides-container.swipe-next li {
+      -ms-transform: translate(100%, 0);
+      -webkit-transform: translate3d(100%, 0, 0);
+      -moz-transform: translate3d(100%, 0, 0);
+      -o-transform: translate3d(100%, 0, 0);
+      transform: translate3d(100%, 0, 0); }
+      .orbit-container .orbit-slides-container.swipe-next li.animate-in {
+        -ms-transform: translate(0, 0);
+        -webkit-transform: translate3d(0, 0, 0);
+        -moz-transform: translate3d(0, 0, 0);
+        -o-transform: translate3d(0, 0, 0);
+        transform: translate3d(0, 0, 0);
+        transition-duration: 500ms; }
+      .orbit-container .orbit-slides-container.swipe-next li.animate-out {
+        -ms-transform: translate(-100%, 0);
+        -webkit-transform: translate3d(-100%, 0, 0);
+        -moz-transform: translate3d(-100%, 0, 0);
+        -o-transform: translate3d(-100%, 0, 0);
+        transform: translate3d(-100%, 0, 0);
+        transition-duration: 500ms; }
+    .orbit-container .orbit-slides-container.swipe-prev li {
+      -ms-transform: translate(-100%, 0);
+      -webkit-transform: translate3d(-100%, 0, 0);
+      -moz-transform: translate3d(-100%, 0, 0);
+      -o-transform: translate3d(-100%, 0, 0);
+      transform: translate3d(-100%, 0, 0); }
+      .orbit-container .orbit-slides-container.swipe-prev li.animate-in {
+        -ms-transform: translate(0, 0);
+        -webkit-transform: translate3d(0, 0, 0);
+        -moz-transform: translate3d(0, 0, 0);
+        -o-transform: translate3d(0, 0, 0);
+        transform: translate3d(0, 0, 0);
+        transition-duration: 500ms; }
+      .orbit-container .orbit-slides-container.swipe-prev li.animate-out {
+        -ms-transform: translate(100%, 0);
+        -webkit-transform: translate3d(100%, 0, 0);
+        -moz-transform: translate3d(100%, 0, 0);
+        -o-transform: translate3d(100%, 0, 0);
+        transform: translate3d(100%, 0, 0);
+        transition-duration: 500ms; }
+    .orbit-container .orbit-slides-container li {
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100%;
+      -ms-transform: translate(100%, 0);
+      -webkit-transform: translate3d(100%, 0, 0);
+      -moz-transform: translate3d(100%, 0, 0);
+      -o-transform: translate3d(100%, 0, 0);
+      transform: translate3d(100%, 0, 0); }
+      .orbit-container .orbit-slides-container li.active {
+        opacity: 1;
+        top: 0;
+        left: 0;
+        -ms-transform: translate(0, 0);
+        -webkit-transform: translate3d(0, 0, 0);
+        -moz-transform: translate3d(0, 0, 0);
+        -o-transform: translate3d(0, 0, 0);
+        transform: translate3d(0, 0, 0); }
+      .orbit-container .orbit-slides-container li .orbit-caption {
+        position: absolute;
+        bottom: 0;
+        background-color: rgba(51, 51, 51, 0.8);
+        color: white;
+        width: 100%;
+        padding: 0.625rem 0.875rem;
+        font-size: 0.875rem; }
+  .orbit-container .orbit-slide-number {
+    position: absolute;
+    top: 10px;
+    left: 10px;
+    font-size: 12px;
+    color: white;
+    background: rgba(0, 0, 0, 0);
+    z-index: 10; }
+    .orbit-container .orbit-slide-number span {
+      font-weight: 700;
+      padding: 0.3125rem; }
+  .orbit-container .orbit-timer {
+    position: absolute;
+    top: 12px;
+    right: 10px;
+    height: 6px;
+    width: 100px;
+    z-index: 10; }
+    .orbit-container .orbit-timer .orbit-progress {
+      height: 3px;
+      background-color: rgba(255, 255, 255, 0.3);
+      display: block;
+      width: 0%;
+      position: relative;
+      right: 20px;
+      top: 5px; }
+    .orbit-container .orbit-timer > span {
+      display: none;
+      position: absolute;
+      top: 0px;
+      right: 0;
+      width: 11px;
+      height: 14px;
+      border: solid 4px white;
+      border-top: none;
+      border-bottom: none; }
+    .orbit-container .orbit-timer.paused > span {
+      right: -4px;
+      top: 0px;
+      width: 11px;
+      height: 14px;
+      border: inset 8px;
+      border-left-style: solid;
+      -webkit-transform: rotate(180deg);
+      -moz-transform: rotate(180deg);
+      -ms-transform: rotate(180deg);
+      -o-transform: rotate(180deg);
+      transform: rotate(180deg);
+      border-color: transparent white transparent transparent; }
+      .orbit-container .orbit-timer.paused > span.dark {
+        border-color: transparent #333333 transparent transparent; }
+  .orbit-container:hover .orbit-timer > span {
+    display: block; }
+  .orbit-container .orbit-prev,
+  .orbit-container .orbit-next {
+    position: absolute;
+    top: 45%;
+    margin-top: -25px;
+    width: 36px;
+    height: 60px;
+    line-height: 50px;
+    color: white;
+    background-color: transparent;
+    text-indent: -9999px !important;
+    z-index: 10; }
+    .orbit-container .orbit-prev:hover,
+    .orbit-container .orbit-next:hover {
+      background-color: rgba(0, 0, 0, 0.3); }
+    .orbit-container .orbit-prev > span,
+    .orbit-container .orbit-next > span {
+      position: absolute;
+      top: 50%;
+      margin-top: -10px;
+      display: block;
+      width: 0;
+      height: 0;
+      border: inset 10px; }
+  .orbit-container .orbit-prev {
+    left: 0; }
+    .orbit-container .orbit-prev > span {
+      border-right-style: solid;
+      border-color: transparent;
+      border-right-color: white; }
+    .orbit-container .orbit-prev:hover > span {
+      border-right-color: white; }
+  .orbit-container .orbit-next {
+    right: 0; }
+    .orbit-container .orbit-next > span {
+      border-color: transparent;
+      border-left-style: solid;
+      border-left-color: white;
+      left: 50%;
+      margin-left: -4px; }
+    .orbit-container .orbit-next:hover > span {
+      border-left-color: white; }
+  .orbit-container .orbit-bullets-container {
+    text-align: center; }
+  .orbit-container .orbit-bullets {
+    margin: 0 auto 30px auto;
+    overflow: hidden;
+    position: relative;
+    top: 10px;
+    float: none;
+    text-align: center;
+    display: block; }
+    .orbit-container .orbit-bullets li {
+      display: inline-block;
+      width: 0.5625rem;
+      height: 0.5625rem;
+      background: #cccccc;
+      float: none;
+      margin-right: 6px;
+      border-radius: 1000px; }
+      .orbit-container .orbit-bullets li.active {
+        background: #999999; }
+      .orbit-container .orbit-bullets li:last-child {
+        margin-right: 0; }
+
+.touch .orbit-container .orbit-prev,
+.touch .orbit-container .orbit-next {
+  display: none; }
+.touch .orbit-bullets {
+  display: none; }
+
+@media only screen and (min-width: 40.063em) {
+  .touch .orbit-container .orbit-prev,
+  .touch .orbit-container .orbit-next {
+    display: inherit; }
+  .touch .orbit-bullets {
+    display: block; } }
+@media only screen and (max-width: 40em) {
+  .orbit-stack-on-small .orbit-slides-container {
+    height: auto !important; }
+  .orbit-stack-on-small .orbit-slides-container > * {
+    position: relative;
+    margin-left: 0% !important;
+    opacity: 1 !important;
+    -webkit-transform: none !important;
+    -moz-transform: none !important;
+    -ms-transform: none !important;
+    -o-transform: none !important;
+    transform: none !important;
+    transition: none !important; }
+  .orbit-stack-on-small .orbit-timer {
+    display: none; }
+  .orbit-stack-on-small .orbit-next, .orbit-stack-on-small .orbit-prev {
+    display: none; }
+  .orbit-stack-on-small .orbit-bullets {
+    display: none; } }
+[data-magellan-expedition], [data-magellan-expedition-clone] {
+  background: white;
+  z-index: 50;
+  min-width: 100%;
+  padding: 10px; }
+  [data-magellan-expedition] .sub-nav, [data-magellan-expedition-clone] .sub-nav {
+    margin-bottom: 0; }
+    [data-magellan-expedition] .sub-nav dd, [data-magellan-expedition-clone] .sub-nav dd {
+      margin-bottom: 0; }
+    [data-magellan-expedition] .sub-nav a, [data-magellan-expedition-clone] .sub-nav a {
+      line-height: 1.8em; }
+
+.tabs {
+  *zoom: 1;
+  margin-bottom: 0 !important; }
+  .tabs:before, .tabs:after {
+    content: " ";
+    display: table; }
+  .tabs:after {
+    clear: both; }
+  .tabs dd {
+    position: relative;
+    margin-bottom: 0 !important;
+    float: left; }
+    .tabs dd > a {
+      display: block;
+      background: #efefef;
+      color: #222222;
+      padding: 1rem 2rem;
+      font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
+      font-size: 1rem; }
+      .tabs dd > a:hover {
+        background: #e1e1e1; }
+    .tabs dd.active a {
+      background: white; }
+  .tabs.radius dd:first-child a {
+    border-bottom-left-radius: 3px;
+    border-top-left-radius: 3px; }
+  .tabs.radius dd:last-child a {
+    border-bottom-right-radius: 3px;
+    border-top-right-radius: 3px; }
+  .tabs.vertical dd {
+    position: inherit;
+    float: none;
+    display: block;
+    top: auto; }
+
+.tabs-content {
+  *zoom: 1;
+  margin-bottom: 1.5rem;
+  width: 100%; }
+  .tabs-content:before, .tabs-content:after {
+    content: " ";
+    display: table; }
+  .tabs-content:after {
+    clear: both; }
+  .tabs-content > .content {
+    display: none;
+    float: left;
+    padding: 0.9375rem 0;
+    width: 100%; }
+    .tabs-content > .content.active {
+      display: block;
+      float: none; }
+    .tabs-content > .content.contained {
+      padding: 0.9375rem; }
+  .tabs-content.vertical {
+    display: block; }
+    .tabs-content.vertical > .content {
+      padding: 0 0.9375rem; }
+
+@media only screen and (min-width: 40.063em) {
+  .tabs.vertical {
+    width: 20%;
+    float: left;
+    margin-bottom: 1.25rem; }
+
+  .tabs-content.vertical {
+    width: 80%;
+    float: left;
+    margin-left: -1px; } }
+.no-js .tabs-content > .content {
+  display: block;
+  float: none; }
+
+ul.pagination {
+  display: block;
+  height: 1.5rem;
+  margin-left: -0.3125rem; }
+  ul.pagination li {
+    height: 1.5rem;
+    color: #222222;
+    font-size: 0.875rem;
+    margin-left: 0.3125rem; }
+    ul.pagination li a {
+      display: block;
+      padding: 0.0625rem 0.625rem 0.0625rem;
+      color: #999999;
+      border-radius: 3px; }
+    ul.pagination li:hover a,
+    ul.pagination li a:focus {
+      background: #e6e6e6; }
+    ul.pagination li.unavailable a {
+      cursor: default;
+      color: #999999; }
+    ul.pagination li.unavailable:hover a, ul.pagination li.unavailable a:focus {
+      background: transparent; }
+    ul.pagination li.current a {
+      background: #008cba;
+      color: white;
+      font-weight: bold;
+      cursor: default; }
+      ul.pagination li.current a:hover, ul.pagination li.current a:focus {
+        background: #008cba; }
+  ul.pagination li {
+    float: left;
+    display: block; }
+
+/* Pagination centred wrapper */
+.pagination-centered {
+  text-align: center; }
+  .pagination-centered ul.pagination li {
+    float: none;
+    display: inline-block; }
+
+.side-nav {
+  display: block;
+  margin: 0;
+  padding: 0.875rem 0;
+  list-style-type: none;
+  list-style-position: inside;
+  font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; }
+  .side-nav li {
+    margin: 0 0 0.4375rem 0;
+    font-size: 0.875rem; }
+    .side-nav li a:not(.button) {
+      display: block;
+      color: #008cba; }
+      .side-nav li a:not(.button):hover, .side-nav li a:not(.button):focus {
+        color: #1cc7ff; }
+    .side-nav li.active > a:first-child:not(.button) {
+      color: #1cc7ff;
+      font-weight: normal;
+      font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; }
+    .side-nav li.divider {
+      border-top: 1px solid;
+      height: 0;
+      padding: 0;
+      list-style: none;
+      border-top-color: white; }
+
+.accordion {
+  *zoom: 1;
+  margin-bottom: 0; }
+  .accordion:before, .accordion:after {
+    content: " ";
+    display: table; }
+  .accordion:after {
+    clear: both; }
+  .accordion dd {
+    display: block;
+    margin-bottom: 0 !important; }
+    .accordion dd.active > a {
+      background: #e8e8e8; }
+    .accordion dd > a {
+      background: #efefef;
+      color: #222222;
+      padding: 1rem;
+      display: block;
+      font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
+      font-size: 1rem; }
+      .accordion dd > a:hover {
+        background: #e3e3e3; }
+  .accordion .content {
+    display: none;
+    padding: 0.9375rem; }
+    .accordion .content.active {
+      display: block;
+      background: white; }
+
+.text-left {
+  text-align: left !important; }
+
+.text-right {
+  text-align: right !important; }
+
+.text-center {
+  text-align: center !important; }
+
+.text-justify {
+  text-align: justify !important; }
+
+@media only screen and (max-width: 40em) {
+  .small-only-text-left {
+    text-align: left !important; }
+
+  .small-only-text-right {
+    text-align: right !important; }
+
+  .small-only-text-center {
+    text-align: center !important; }
+
+  .small-only-text-justify {
+    text-align: justify !important; } }
+@media only screen {
+  .small-text-left {
+    text-align: left !important; }
+
+  .small-text-right {
+    text-align: right !important; }
+
+  .small-text-center {
+    text-align: center !important; }
+
+  .small-text-justify {
+    text-align: justify !important; } }
+@media only screen and (min-width: 40.063em) and (max-width: 64em) {
+  .medium-only-text-left {
+    text-align: left !important; }
+
+  .medium-only-text-right {
+    text-align: right !important; }
+
+  .medium-only-text-center {
+    text-align: center !important; }
+
+  .medium-only-text-justify {
+    text-align: justify !important; } }
+@media only screen and (min-width: 40.063em) {
+  .medium-text-left {
+    text-align: left !important; }
+
+  .medium-text-right {
+    text-align: right !important; }
+
+  .medium-text-center {
+    text-align: center !important; }
+
+  .medium-text-justify {
+    text-align: justify !important; } }
+@media only screen and (min-width: 64.063em) and (max-width: 90em) {
+  .large-only-text-left {
+    text-align: left !important; }
+
+  .large-only-text-right {
+    text-align: right !important; }
+
+  .large-only-text-center {
+    text-align: center !important; }
+
+  .large-only-text-justify {
+    text-align: justify !important; } }
+@media only screen and (min-width: 64.063em) {
+  .large-text-left {
+    text-align: left !important; }
+
+  .large-text-right {
+    text-align: right !important; }
+
+  .large-text-center {
+    text-align: center !important; }
+
+  .large-text-justify {
+    text-align: justify !important; } }
+@media only screen and (min-width: 90.063em) and (max-width: 120em) {
+  .xlarge-only-text-left {
+    text-align: left !important; }
+
+  .xlarge-only-text-right {
+    text-align: right !important; }
+
+  .xlarge-only-text-center {
+    text-align: center !important; }
+
+  .xlarge-only-text-justify {
+    text-align: justify !important; } }
+@media only screen and (min-width: 90.063em) {
+  .xlarge-text-left {
+    text-align: left !important; }
+
+  .xlarge-text-right {
+    text-align: right !important; }
+
+  .xlarge-text-center {
+    text-align: center !important; }
+
+  .xlarge-text-justify {
+    text-align: justify !important; } }
+@media only screen and (min-width: 120.063em) and (max-width: 99999999em) {
+  .xxlarge-only-text-left {
+    text-align: left !important; }
+
+  .xxlarge-only-text-right {
+    text-align: right !important; }
+
+  .xxlarge-only-text-center {
+    text-align: center !important; }
+
+  .xxlarge-only-text-justify {
+    text-align: justify !important; } }
+@media only screen and (min-width: 120.063em) {
+  .xxlarge-text-left {
+    text-align: left !important; }
+
+  .xxlarge-text-right {
+    text-align: right !important; }
+
+  .xxlarge-text-center {
+    text-align: center !important; }
+
+  .xxlarge-text-justify {
+    text-align: justify !important; } }
+/* Typography resets */
+div,
+dl,
+dt,
+dd,
+ul,
+ol,
+li,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+pre,
+form,
+p,
+blockquote,
+th,
+td {
+  margin: 0;
+  padding: 0; }
+
+/* Default Link Styles */
+a {
+  color: #008cba;
+  text-decoration: none;
+  line-height: inherit; }
+  a:hover, a:focus {
+    color: #0078a0; }
+  a img {
+    border: none; }
+
+/* Default paragraph styles */
+p {
+  font-family: inherit;
+  font-weight: normal;
+  font-size: 1rem;
+  line-height: 1.6;
+  margin-bottom: 1.25rem;
+  text-rendering: optimizeLegibility; }
+  p.lead {
+    font-size: 1.21875rem;
+    line-height: 1.6; }
+  p aside {
+    font-size: 0.875rem;
+    line-height: 1.35;
+    font-style: italic; }
+
+/* Default header styles */
+h1, h2, h3, h4, h5, h6 {
+  font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif !important;
+  font-weight: normal;
+  font-style: normal;
+  color: #222222;
+  text-rendering: optimizeLegibility;
+  margin-top: 0.2rem;
+  margin-bottom: 0.5rem;
+  line-height: 1.4; }
+  h1 small, h2 small, h3 small, h4 small, h5 small, h6 small {
+    font-size: 60%;
+    color: #6f6f6f;
+    line-height: 0; }
+
+h1 {
+  font-size: 2.125rem; }
+
+h2 {
+  font-size: 1.6875rem; }
+
+h3 {
+  font-size: 1.375rem; }
+
+h4 {
+  font-size: 1.125rem; }
+
+h5 {
+  font-size: 1.125rem; }
+
+h6 {
+  font-size: 1rem; }
+
+.subheader {
+  line-height: 1.4;
+  color: #6f6f6f;
+  font-weight: normal;
+  margin-top: 0.2rem;
+  margin-bottom: 0.5rem; }
+
+hr {
+  border: solid #dddddd;
+  border-width: 1px 0 0;
+  clear: both;
+  margin: 1.25rem 0 1.1875rem;
+  height: 0; }
+
+/* Helpful Typography Defaults */
+em,
+i {
+  font-style: italic;
+  line-height: inherit; }
+
+strong,
+b {
+  font-weight: bold;
+  line-height: inherit; }
+
+small {
+  font-size: 60%;
+  line-height: inherit; }
+
+code {
+  font-family: Consolas, "Liberation Mono", Courier, monospace;
+  font-weight: bold;
+  color: #bd260d; }
+
+/* Lists */
+ul,
+ol,
+dl {
+  font-size: 1rem;
+  line-height: 1.6;
+  margin-bottom: 1.25rem;
+  list-style-position: outside;
+  font-family: inherit; }
+
+ul {
+  margin-left: 1.1rem; }
+  ul.no-bullet {
+    margin-left: 0; }
+    ul.no-bullet li ul,
+    ul.no-bullet li ol {
+      margin-left: 1.25rem;
+      margin-bottom: 0;
+      list-style: none; }
+
+/* Unordered Lists */
+ul li ul,
+ul li ol {
+  margin-left: 1.25rem;
+  margin-bottom: 0; }
+ul.square li ul, ul.circle li ul, ul.disc li ul {
+  list-style: inherit; }
+ul.square {
+  list-style-type: square;
+  margin-left: 1.1rem; }
+ul.circle {
+  list-style-type: circle;
+  margin-left: 1.1rem; }
+ul.disc {
+  list-style-type: disc;
+  margin-left: 1.1rem; }
+ul.no-bullet {
+  list-style: none; }
+
+/* Ordered Lists */
+ol {
+  margin-left: 1.4rem; }
+  ol li ul,
+  ol li ol {
+    margin-left: 1.25rem;
+    margin-bottom: 0; }
+
+/* Definition Lists */
+dl dt {
+  margin-bottom: 0.3rem;
+  font-weight: bold; }
+dl dd {
+  margin-bottom: 0.75rem; }
+
+/* Abbreviations */
+abbr,
+acronym {
+  text-transform: uppercase;
+  font-size: 90%;
+  color: #222222;
+  border-bottom: 1px dotted #dddddd;
+  cursor: help; }
+
+abbr {
+  text-transform: none; }
+
+/* Blockquotes */
+blockquote {
+  margin: 0 0 1.25rem;
+  padding: 0.5625rem 1.25rem 0 1.1875rem;
+  border-left: 1px solid #dddddd; }
+  blockquote cite {
+    display: block;
+    font-size: 0.8125rem;
+    color: #555555; }
+    blockquote cite:before {
+      content: "\2014 \0020"; }
+    blockquote cite a,
+    blockquote cite a:visited {
+      color: #555555; }
+
+blockquote,
+blockquote p {
+  line-height: 1.6;
+  color: #6f6f6f; }
+
+/* Microformats */
+.vcard {
+  display: inline-block;
+  margin: 0 0 1.25rem 0;
+  border: 1px solid #dddddd;
+  padding: 0.625rem 0.75rem; }
+  .vcard li {
+    margin: 0;
+    display: block; }
+  .vcard .fn {
+    font-weight: bold;
+    font-size: 0.9375rem; }
+
+.vevent .summary {
+  font-weight: bold; }
+.vevent abbr {
+  cursor: default;
+  text-decoration: none;
+  font-weight: bold;
+  border: none;
+  padding: 0 0.0625rem; }
+
+@media only screen and (min-width: 40.063em) {
+  h1, h2, h3, h4, h5, h6 {
+    line-height: 1.4; }
+
+  h1 {
+    font-size: 2.75rem; }
+
+  h2 {
+    font-size: 2.3125rem; }
+
+  h3 {
+    font-size: 1.6875rem; }
+
+  h4 {
+    font-size: 1.4375rem; } }
+/*
+ * Print styles.
+ *
+ * Inlined to avoid required HTTP connection: www.phpied.com/delay-loading-your-print-css/
+ * Credit to Paul Irish and HTML5 Boilerplate (html5boilerplate.com)
+*/
+.print-only {
+  display: none !important; }
+
+@media print {
+  * {
+    background: transparent !important;
+    color: black !important;
+    /* Black prints faster: h5bp.com/s */
+    box-shadow: none !important;
+    text-shadow: none !important; }
+
+  a,
+  a:visited {
+    text-decoration: underline; }
+
+  a[href]:after {
+    content: " (" attr(href) ")"; }
+
+  abbr[title]:after {
+    content: " (" attr(title) ")"; }
+
+  .ir a:after,
+  a[href^="javascript:"]:after,
+  a[href^="#"]:after {
+    content: ""; }
+
+  pre,
+  blockquote {
+    border: 1px solid #999999;
+    page-break-inside: avoid; }
+
+  thead {
+    display: table-header-group;
+    /* h5bp.com/t */ }
+
+  tr,
+  img {
+    page-break-inside: avoid; }
+
+  img {
+    max-width: 100% !important; }
+
+  @page {
+    margin: 0.5cm; }
+
+  p,
+  h2,
+  h3 {
+    orphans: 3;
+    widows: 3; }
+
+  h2,
+  h3 {
+    page-break-after: avoid; }
+
+  .hide-on-print {
+    display: none !important; }
+
+  .print-only {
+    display: block !important; }
+
+  .hide-for-print {
+    display: none !important; }
+
+  .show-for-print {
+    display: inherit !important; } }
+.split.button {
+  position: relative;
+  padding-right: 5.0625rem; }
+  .split.button span {
+    display: block;
+    height: 100%;
+    position: absolute;
+    right: 0;
+    top: 0;
+    border-left: solid 1px; }
+    .split.button span:before {
+      position: absolute;
+      content: "";
+      width: 0;
+      height: 0;
+      display: block;
+      border-style: inset;
+      top: 50%;
+      left: 50%; }
+    .split.button span:active {
+      background-color: rgba(0, 0, 0, 0.1); }
+  .split.button span {
+    border-left-color: rgba(255, 255, 255, 0.5); }
+  .split.button span {
+    width: 3.09375rem; }
+    .split.button span:before {
+      border-top-style: solid;
+      border-width: 0.375rem;
+      top: 48%;
+      margin-left: -0.375rem; }
+  .split.button span:before {
+    border-color: white transparent transparent transparent; }
+  .split.button.secondary span {
+    border-left-color: rgba(255, 255, 255, 0.5); }
+  .split.button.secondary span:before {
+    border-color: white transparent transparent transparent; }
+  .split.button.alert span {
+    border-left-color: rgba(255, 255, 255, 0.5); }
+  .split.button.success span {
+    border-left-color: rgba(255, 255, 255, 0.5); }
+  .split.button.tiny {
+    padding-right: 3.75rem; }
+    .split.button.tiny span {
+      width: 2.25rem; }
+      .split.button.tiny span:before {
+        border-top-style: solid;
+        border-width: 0.375rem;
+        top: 48%;
+        margin-left: -0.375rem; }
+  .split.button.small {
+    padding-right: 4.375rem; }
+    .split.button.small span {
+      width: 2.625rem; }
+      .split.button.small span:before {
+        border-top-style: solid;
+        border-width: 0.4375rem;
+        top: 48%;
+        margin-left: -0.375rem; }
+  .split.button.large {
+    padding-right: 5.5rem; }
+    .split.button.large span {
+      width: 3.4375rem; }
+      .split.button.large span:before {
+        border-top-style: solid;
+        border-width: 0.3125rem;
+        top: 48%;
+        margin-left: -0.375rem; }
+  .split.button.expand {
+    padding-left: 2rem; }
+  .split.button.secondary span:before {
+    border-color: #333333 transparent transparent transparent; }
+  .split.button.radius span {
+    border-bottom-right-radius: 3px;
+    border-top-right-radius: 3px; }
+  .split.button.round span {
+    border-bottom-right-radius: 1000px;
+    border-top-right-radius: 1000px; }
+
+.reveal-modal-bg {
+  position: fixed;
+  height: 100%;
+  width: 100%;
+  background: black;
+  background: rgba(0, 0, 0, 0.45);
+  z-index: 99;
+  display: none;
+  top: 0;
+  left: 0; }
+
+dialog, .reveal-modal {
+  visibility: hidden;
+  display: none;
+  position: absolute;
+  z-index: 100;
+  width: 100vw;
+  top: 0;
+  left: 0;
+  background-color: white;
+  padding: 1.25rem;
+  border: solid 1px #666666;
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); }
+  @media only screen and (max-width: 40em) {
+    dialog, .reveal-modal {
+      min-height: 100vh; } }
+  @media only screen and (min-width: 40.063em) {
+    dialog, .reveal-modal {
+      left: 50%; } }
+  dialog .column,
+  dialog .columns, .reveal-modal .column,
+  .reveal-modal .columns {
+    min-width: 0; }
+  dialog > :first-child, .reveal-modal > :first-child {
+    margin-top: 0; }
+  dialog > :last-child, .reveal-modal > :last-child {
+    margin-bottom: 0; }
+  @media only screen and (min-width: 40.063em) {
+    dialog, .reveal-modal {
+      margin-left: -40%;
+      width: 80%; } }
+  @media only screen and (min-width: 40.063em) {
+    dialog, .reveal-modal {
+      top: 6.25rem; } }
+  dialog .close-reveal-modal, .reveal-modal .close-reveal-modal {
+    font-size: 2.5rem;
+    line-height: 1;
+    position: absolute;
+    top: 0.5rem;
+    right: 0.6875rem;
+    color: #aaaaaa;
+    font-weight: bold;
+    cursor: pointer; }
+
+dialog[open] {
+  display: block;
+  visibility: visible; }
+
+@media only screen and (min-width: 40.063em) {
+  dialog, .reveal-modal {
+    padding: 1.875rem; }
+    dialog.radius, .reveal-modal.radius {
+      border-radius: 3px; }
+    dialog.round, .reveal-modal.round {
+      border-radius: 1000px; }
+    dialog.collapse, .reveal-modal.collapse {
+      padding: 0; }
+  dialog.full, .reveal-modal.full {
+    top: 0;
+    left: 0;
+    height: 100vh;
+    min-height: 100vh;
+    margin-left: 0 !important; } }
+  @media only screen and (min-width: 40.063em) and (min-width: 40.063em) {
+    dialog.tiny, .reveal-modal.tiny {
+      margin-left: -15%;
+      width: 30%; } }
+  @media only screen and (min-width: 40.063em) and (min-width: 40.063em) {
+    dialog.small, .reveal-modal.small {
+      margin-left: -20%;
+      width: 40%; } }
+  @media only screen and (min-width: 40.063em) and (min-width: 40.063em) {
+    dialog.medium, .reveal-modal.medium {
+      margin-left: -30%;
+      width: 60%; } }
+  @media only screen and (min-width: 40.063em) and (min-width: 40.063em) {
+    dialog.large, .reveal-modal.large {
+      margin-left: -35%;
+      width: 70%; } }
+  @media only screen and (min-width: 40.063em) and (min-width: 40.063em) {
+    dialog.xlarge, .reveal-modal.xlarge {
+      margin-left: -47.5%;
+      width: 95%; } }
+
+  @media only screen and (min-width: 40.063em) and (min-width: 40.063em) {
+    dialog.full, .reveal-modal.full {
+      margin-left: -50vw;
+      width: 100vw; } }
+
+@media print {
+  dialog, .reveal-modal {
+    background: white !important; } }
+/* Tooltips */
+.has-tip {
+  border-bottom: dotted 1px #cccccc;
+  cursor: help;
+  font-weight: bold;
+  color: #333333; }
+  .has-tip:hover, .has-tip:focus {
+    border-bottom: dotted 1px #003f54;
+    color: #008cba; }
+  .has-tip.tip-left, .has-tip.tip-right {
+    float: none !important; }
+
+.tooltip {
+  display: none;
+  position: absolute;
+  z-index: 999;
+  font-weight: normal;
+  font-size: 0.875rem;
+  line-height: 1.3;
+  padding: 0.75rem;
+  max-width: 85%;
+  left: 50%;
+  width: 100%;
+  color: white;
+  background: #333333; }
+  .tooltip > .nub {
+    display: block;
+    left: 5px;
+    position: absolute;
+    width: 0;
+    height: 0;
+    border: solid 5px;
+    border-color: transparent transparent #333333 transparent;
+    top: -10px; }
+    .tooltip > .nub.rtl {
+      left: auto;
+      right: 5px; }
+  .tooltip.radius {
+    border-radius: 3px; }
+  .tooltip.round {
+    border-radius: 1000px; }
+    .tooltip.round > .nub {
+      left: 2rem; }
+  .tooltip.opened {
+    color: #008cba !important;
+    border-bottom: dotted 1px #003f54 !important; }
+
+.tap-to-close {
+  display: block;
+  font-size: 0.625rem;
+  color: #777777;
+  font-weight: normal; }
+
+@media only screen and (min-width: 40.063em) {
+  .tooltip > .nub {
+    border-color: transparent transparent #333333 transparent;
+    top: -10px; }
+  .tooltip.tip-top > .nub {
+    border-color: #333333 transparent transparent transparent;
+    top: auto;
+    bottom: -10px; }
+  .tooltip.tip-left, .tooltip.tip-right {
+    float: none !important; }
+  .tooltip.tip-left > .nub {
+    border-color: transparent transparent transparent #333333;
+    right: -10px;
+    left: auto;
+    top: 50%;
+    margin-top: -5px; }
+  .tooltip.tip-right > .nub {
+    border-color: transparent #333333 transparent transparent;
+    right: auto;
+    left: -10px;
+    top: 50%;
+    margin-top: -5px; } }
+/* Clearing Styles */
+.clearing-thumbs, [data-clearing] {
+  *zoom: 1;
+  margin-bottom: 0;
+  margin-left: 0;
+  list-style: none; }
+  .clearing-thumbs:before, .clearing-thumbs:after, [data-clearing]:before, [data-clearing]:after {
+    content: " ";
+    display: table; }
+  .clearing-thumbs:after, [data-clearing]:after {
+    clear: both; }
+  .clearing-thumbs li, [data-clearing] li {
+    float: left;
+    margin-right: 10px; }
+  .clearing-thumbs[class*="block-grid-"] li, [data-clearing][class*="block-grid-"] li {
+    margin-right: 0; }
+
+.clearing-blackout {
+  background: #333333;
+  position: fixed;
+  width: 100%;
+  height: 100%;
+  top: 0;
+  left: 0;
+  z-index: 998; }
+  .clearing-blackout .clearing-close {
+    display: block; }
+
+.clearing-container {
+  position: relative;
+  z-index: 998;
+  height: 100%;
+  overflow: hidden;
+  margin: 0; }
+
+.clearing-touch-label {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  color: #aaa;
+  font-size: 0.6em; }
+
+.visible-img {
+  height: 95%;
+  position: relative; }
+  .visible-img img {
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    margin-left: -50%;
+    max-height: 100%;
+    max-width: 100%; }
+
+.clearing-caption {
+  color: #cccccc;
+  font-size: 0.875em;
+  line-height: 1.3;
+  margin-bottom: 0;
+  text-align: center;
+  bottom: 0;
+  background: #333333;
+  width: 100%;
+  padding: 10px 30px 20px;
+  position: absolute;
+  left: 0; }
+
+.clearing-close {
+  z-index: 999;
+  padding-left: 20px;
+  padding-top: 10px;
+  font-size: 30px;
+  line-height: 1;
+  color: #cccccc;
+  display: none; }
+  .clearing-close:hover, .clearing-close:focus {
+    color: #ccc; }
+
+.clearing-assembled .clearing-container {
+  height: 100%; }
+  .clearing-assembled .clearing-container .carousel > ul {
+    display: none; }
+
+.clearing-feature li {
+  display: none; }
+  .clearing-feature li.clearing-featured-img {
+    display: block; }
+
+@media only screen and (min-width: 40.063em) {
+  .clearing-main-prev,
+  .clearing-main-next {
+    position: absolute;
+    height: 100%;
+    width: 40px;
+    top: 0; }
+    .clearing-main-prev > span,
+    .clearing-main-next > span {
+      position: absolute;
+      top: 50%;
+      display: block;
+      width: 0;
+      height: 0;
+      border: solid 12px; }
+      .clearing-main-prev > span:hover,
+      .clearing-main-next > span:hover {
+        opacity: 0.8; }
+
+  .clearing-main-prev {
+    left: 0; }
+    .clearing-main-prev > span {
+      left: 5px;
+      border-color: transparent;
+      border-right-color: #cccccc; }
+
+  .clearing-main-next {
+    right: 0; }
+    .clearing-main-next > span {
+      border-color: transparent;
+      border-left-color: #cccccc; }
+
+  .clearing-main-prev.disabled,
+  .clearing-main-next.disabled {
+    opacity: 0.3; }
+
+  .clearing-assembled .clearing-container .carousel {
+    background: rgba(51, 51, 51, 0.8);
+    height: 120px;
+    margin-top: 10px;
+    text-align: center; }
+    .clearing-assembled .clearing-container .carousel > ul {
+      display: inline-block;
+      z-index: 999;
+      height: 100%;
+      position: relative;
+      float: none; }
+      .clearing-assembled .clearing-container .carousel > ul li {
+        display: block;
+        width: 120px;
+        min-height: inherit;
+        float: left;
+        overflow: hidden;
+        margin-right: 0;
+        padding: 0;
+        position: relative;
+        cursor: pointer;
+        opacity: 0.4;
+        clear: none; }
+        .clearing-assembled .clearing-container .carousel > ul li.fix-height img {
+          height: 100%;
+          max-width: none; }
+        .clearing-assembled .clearing-container .carousel > ul li a.th {
+          border: none;
+          box-shadow: none;
+          display: block; }
+        .clearing-assembled .clearing-container .carousel > ul li img {
+          cursor: pointer !important;
+          width: 100% !important; }
+        .clearing-assembled .clearing-container .carousel > ul li.visible {
+          opacity: 1; }
+        .clearing-assembled .clearing-container .carousel > ul li:hover {
+          opacity: 0.8; }
+  .clearing-assembled .clearing-container .visible-img {
+    background: #333333;
+    overflow: hidden;
+    height: 85%; }
+
+  .clearing-close {
+    position: absolute;
+    top: 10px;
+    right: 20px;
+    padding-left: 0;
+    padding-top: 0; } }
+/* Progress Bar */
+.progress {
+  background-color: #f6f6f6;
+  height: 1.5625rem;
+  border: 1px solid white;
+  padding: 0.125rem;
+  margin-bottom: 0.625rem; }
+  .progress .meter {
+    background: #008cba;
+    height: 100%;
+    display: block; }
+  .progress.secondary .meter {
+    background: #e7e7e7;
+    height: 100%;
+    display: block; }
+  .progress.success .meter {
+    background: #43ac6a;
+    height: 100%;
+    display: block; }
+  .progress.alert .meter {
+    background: #f04124;
+    height: 100%;
+    display: block; }
+  .progress.radius {
+    border-radius: 3px; }
+    .progress.radius .meter {
+      border-radius: 2px; }
+  .progress.round {
+    border-radius: 1000px; }
+    .progress.round .meter {
+      border-radius: 999px; }
+
+.sub-nav {
+  display: block;
+  width: auto;
+  overflow: hidden;
+  margin: -0.25rem 0 1.125rem;
+  padding-top: 0.25rem;
+  margin-right: 0;
+  margin-left: -0.75rem; }
+  .sub-nav dt {
+    text-transform: uppercase; }
+  .sub-nav dt,
+  .sub-nav dd,
+  .sub-nav li {
+    float: left;
+    display: inline;
+    margin-left: 1rem;
+    margin-bottom: 0.625rem;
+    font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
+    font-weight: normal;
+    font-size: 0.875rem;
+    color: #999999; }
+    .sub-nav dt a,
+    .sub-nav dd a,
+    .sub-nav li a {
+      text-decoration: none;
+      color: #999999;
+      padding: 0.1875rem 1rem; }
+      .sub-nav dt a:hover,
+      .sub-nav dd a:hover,
+      .sub-nav li a:hover {
+        color: #737373; }
+    .sub-nav dt.active a,
+    .sub-nav dd.active a,
+    .sub-nav li.active a {
+      border-radius: 3px;
+      font-weight: normal;
+      background: #008cba;
+      padding: 0.1875rem 1rem;
+      cursor: default;
+      color: white; }
+      .sub-nav dt.active a:hover,
+      .sub-nav dd.active a:hover,
+      .sub-nav li.active a:hover {
+        background: #0078a0; }
+
+/* Foundation Joyride */
+.joyride-list {
+  display: none; }
+
+/* Default styles for the container */
+.joyride-tip-guide {
+  display: none;
+  position: absolute;
+  background: #333333;
+  color: white;
+  z-index: 101;
+  top: 0;
+  left: 2.5%;
+  font-family: inherit;
+  font-weight: normal;
+  width: 95%; }
+
+.lt-ie9 .joyride-tip-guide {
+  max-width: 800px;
+  left: 50%;
+  margin-left: -400px; }
+
+.joyride-content-wrapper {
+  width: 100%;
+  padding: 1.125rem 1.25rem 1.5rem; }
+  .joyride-content-wrapper .button {
+    margin-bottom: 0 !important; }
+
+/* Add a little css triangle pip, older browser just miss out on the fanciness of it */
+.joyride-tip-guide .joyride-nub {
+  display: block;
+  position: absolute;
+  left: 22px;
+  width: 0;
+  height: 0;
+  border: 10px solid #333333; }
+  .joyride-tip-guide .joyride-nub.top {
+    border-top-style: solid;
+    border-color: #333333;
+    border-top-color: transparent !important;
+    border-left-color: transparent !important;
+    border-right-color: transparent !important;
+    top: -20px; }
+  .joyride-tip-guide .joyride-nub.bottom {
+    border-bottom-style: solid;
+    border-color: #333333 !important;
+    border-bottom-color: transparent !important;
+    border-left-color: transparent !important;
+    border-right-color: transparent !important;
+    bottom: -20px; }
+  .joyride-tip-guide .joyride-nub.right {
+    right: -20px; }
+  .joyride-tip-guide .joyride-nub.left {
+    left: -20px; }
+
+/* Typography */
+.joyride-tip-guide h1,
+.joyride-tip-guide h2,
+.joyride-tip-guide h3,
+.joyride-tip-guide h4,
+.joyride-tip-guide h5,
+.joyride-tip-guide h6 {
+  line-height: 1.25;
+  margin: 0;
+  font-weight: bold;
+  color: white; }
+
+.joyride-tip-guide p {
+  margin: 0 0 1.125rem 0;
+  font-size: 0.875rem;
+  line-height: 1.3; }
+
+.joyride-timer-indicator-wrap {
+  width: 50px;
+  height: 3px;
+  border: solid 1px #555555;
+  position: absolute;
+  right: 1.0625rem;
+  bottom: 1rem; }
+
+.joyride-timer-indicator {
+  display: block;
+  width: 0;
+  height: inherit;
+  background: #666666; }
+
+.joyride-close-tip {
+  position: absolute;
+  right: 12px;
+  top: 10px;
+  color: #777777 !important;
+  text-decoration: none;
+  font-size: 24px;
+  font-weight: normal;
+  line-height: 0.5 !important; }
+  .joyride-close-tip:hover, .joyride-close-tip:focus {
+    color: #eeeeee !important; }
+
+.joyride-modal-bg {
+  position: fixed;
+  height: 100%;
+  width: 100%;
+  background: transparent;
+  background: rgba(0, 0, 0, 0.5);
+  z-index: 100;
+  display: none;
+  top: 0;
+  left: 0;
+  cursor: pointer; }
+
+.joyride-expose-wrapper {
+  background-color: #ffffff;
+  position: absolute;
+  border-radius: 3px;
+  z-index: 102;
+  box-shadow: 0 0 15px white; }
+
+.joyride-expose-cover {
+  background: transparent;
+  border-radius: 3px;
+  position: absolute;
+  z-index: 9999;
+  top: 0;
+  left: 0; }
+
+/* Styles for screens that are at least 768px; */
+@media only screen and (min-width: 40.063em) {
+  .joyride-tip-guide {
+    width: 300px;
+    left: inherit; }
+    .joyride-tip-guide .joyride-nub.bottom {
+      border-color: #333333 !important;
+      border-bottom-color: transparent !important;
+      border-left-color: transparent !important;
+      border-right-color: transparent !important;
+      bottom: -20px; }
+    .joyride-tip-guide .joyride-nub.right {
+      border-color: #333333 !important;
+      border-top-color: transparent !important;
+      border-right-color: transparent !important;
+      border-bottom-color: transparent !important;
+      top: 22px;
+      left: auto;
+      right: -20px; }
+    .joyride-tip-guide .joyride-nub.left {
+      border-color: #333333 !important;
+      border-top-color: transparent !important;
+      border-left-color: transparent !important;
+      border-bottom-color: transparent !important;
+      top: 22px;
+      left: -20px;
+      right: auto; } }
+.label {
+  font-weight: normal;
+  font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
+  text-align: center;
+  text-decoration: none;
+  line-height: 1;
+  white-space: nowrap;
+  display: inline-block;
+  position: relative;
+  margin-bottom: inherit;
+  padding: 0.25rem 0.5rem 0.375rem;
+  font-size: 0.6875rem;
+  background-color: #008cba;
+  color: white; }
+  .label.radius {
+    border-radius: 3px; }
+  .label.round {
+    border-radius: 1000px; }
+  .label.alert {
+    background-color: #f04124;
+    color: white; }
+  .label.success {
+    background-color: #43ac6a;
+    color: white; }
+  .label.secondary {
+    background-color: #e7e7e7;
+    color: #333333; }
+
+.off-canvas-wrap {
+  -webkit-backface-visibility: hidden;
+  position: relative;
+  width: 100%;
+  overflow: hidden; }
+  .off-canvas-wrap.move-right, .off-canvas-wrap.move-left {
+    min-height: 100%;
+    -webkit-overflow-scrolling: touch; }
+
+.inner-wrap {
+  -webkit-backface-visibility: hidden;
+  position: relative;
+  width: 100%;
+  *zoom: 1;
+  -webkit-transition: -webkit-transform 500ms ease;
+  -moz-transition: -moz-transform 500ms ease;
+  -ms-transition: -ms-transform 500ms ease;
+  -o-transition: -o-transform 500ms ease;
+  transition: transform 500ms ease; }
+  .inner-wrap:before, .inner-wrap:after {
+    content: " ";
+    display: table; }
+  .inner-wrap:after {
+    clear: both; }
+
+.tab-bar {
+  -webkit-backface-visibility: hidden;
+  background: #333333;
+  color: white;
+  height: 2.8125rem;
+  line-height: 2.8125rem;
+  position: relative; }
+  .tab-bar h1, .tab-bar h2, .tab-bar h3, .tab-bar h4, .tab-bar h5, .tab-bar h6 {
+    color: white;
+    font-weight: bold;
+    line-height: 2.8125rem;
+    margin: 0; }
+  .tab-bar h1, .tab-bar h2, .tab-bar h3, .tab-bar h4 {
+    font-size: 1.125rem; }
+
+.left-small {
+  width: 2.8125rem;
+  height: 2.8125rem;
+  position: absolute;
+  top: 0;
+  border-right: solid 1px #1a1a1a;
+  left: 0; }
+
+.right-small {
+  width: 2.8125rem;
+  height: 2.8125rem;
+  position: absolute;
+  top: 0;
+  border-left: solid 1px #1a1a1a;
+  right: 0; }
+
+.tab-bar-section {
+  padding: 0 0.625rem;
+  position: absolute;
+  text-align: center;
+  height: 2.8125rem;
+  top: 0; }
+  @media only screen and (min-width: 40.063em) {
+    .tab-bar-section {
+      text-align: left; } }
+  .tab-bar-section.left {
+    left: 0;
+    right: 2.8125rem; }
+  .tab-bar-section.right {
+    left: 2.8125rem;
+    right: 0; }
+  .tab-bar-section.middle {
+    left: 2.8125rem;
+    right: 2.8125rem; }
+
+.tab-bar .menu-icon {
+  text-indent: 2.1875rem;
+  width: 2.8125rem;
+  height: 2.8125rem;
+  display: block;
+  line-height: 2.0625rem;
+  padding: 0;
+  color: white;
+  position: relative;
+  -ms-transform: translate(0, 0);
+  -webkit-transform: translate3d(0, 0, 0);
+  -moz-transform: translate3d(0, 0, 0);
+  -ms-transform: translate3d(0, 0, 0);
+  -o-transform: translate3d(0, 0, 0);
+  transform: translate3d(0, 0, 0); }
+  .tab-bar .menu-icon span {
+    position: absolute;
+    display: block;
+    height: 0;
+    width: 1rem;
+    line-height: 1;
+    top: 0.9375rem;
+    left: 0.90625rem;
+    box-shadow: 0 0px 0 1px white, 0 7px 0 1px white, 0 14px 0 1px white; }
+  .tab-bar .menu-icon:hover span {
+    box-shadow: 0 0px 0 1px #b3b3b3, 0 7px 0 1px #b3b3b3, 0 14px 0 1px #b3b3b3; }
+
+.left-off-canvas-menu {
+  -webkit-backface-visibility: hidden;
+  width: 15.625rem;
+  top: 0;
+  bottom: 0;
+  position: absolute;
+  overflow-y: auto;
+  background: #333333;
+  z-index: 1001;
+  box-sizing: content-box;
+  -webkit-overflow-scrolling: touch;
+  -ms-transform: translate(-100%, 0);
+  -webkit-transform: translate3d(-100%, 0, 0);
+  -moz-transform: translate3d(-100%, 0, 0);
+  -ms-transform: translate3d(-100%, 0, 0);
+  -o-transform: translate3d(-100%, 0, 0);
+  transform: translate3d(-100%, 0, 0);
+  left: 0; }
+  .left-off-canvas-menu * {
+    -webkit-backface-visibility: hidden; }
+
+.right-off-canvas-menu {
+  -webkit-backface-visibility: hidden;
+  width: 15.625rem;
+  top: 0;
+  bottom: 0;
+  position: absolute;
+  overflow-y: auto;
+  background: #333333;
+  z-index: 1001;
+  box-sizing: content-box;
+  -webkit-overflow-scrolling: touch;
+  -ms-transform: translate(100%, 0);
+  -webkit-transform: translate3d(100%, 0, 0);
+  -moz-transform: translate3d(100%, 0, 0);
+  -ms-transform: translate3d(100%, 0, 0);
+  -o-transform: translate3d(100%, 0, 0);
+  transform: translate3d(100%, 0, 0);
+  right: 0; }
+  .right-off-canvas-menu * {
+    -webkit-backface-visibility: hidden; }
+
+ul.off-canvas-list {
+  list-style-type: none;
+  padding: 0;
+  margin: 0; }
+  ul.off-canvas-list li label {
+    padding: 0.3rem 0.9375rem;
+    color: #999999;
+    text-transform: uppercase;
+    font-weight: bold;
+    background: #444444;
+    border-top: 1px solid #5e5e5e;
+    border-bottom: none;
+    margin: 0; }
+  ul.off-canvas-list li a {
+    display: block;
+    padding: 0.66667rem;
+    color: rgba(255, 255, 255, 0.7);
+    border-bottom: 1px solid #262626;
+    transition: background 300ms ease; }
+    ul.off-canvas-list li a:hover {
+      background: #242424; }
+
+.move-right > .inner-wrap {
+  -ms-transform: translate(15.625rem, 0);
+  -webkit-transform: translate3d(15.625rem, 0, 0);
+  -moz-transform: translate3d(15.625rem, 0, 0);
+  -ms-transform: translate3d(15.625rem, 0, 0);
+  -o-transform: translate3d(15.625rem, 0, 0);
+  transform: translate3d(15.625rem, 0, 0); }
+.move-right .exit-off-canvas {
+  -webkit-backface-visibility: hidden;
+  transition: background 300ms ease;
+  cursor: pointer;
+  box-shadow: -4px 0 4px rgba(0, 0, 0, 0.5), 4px 0 4px rgba(0, 0, 0, 0.5);
+  display: block;
+  position: absolute;
+  background: rgba(255, 255, 255, 0.2);
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  z-index: 1002;
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
+  @media only screen and (min-width: 40.063em) {
+    .move-right .exit-off-canvas:hover {
+      background: rgba(255, 255, 255, 0.05); } }
+
+.move-left > .inner-wrap {
+  -ms-transform: translate(-15.625rem, 0);
+  -webkit-transform: translate3d(-15.625rem, 0, 0);
+  -moz-transform: translate3d(-15.625rem, 0, 0);
+  -ms-transform: translate3d(-15.625rem, 0, 0);
+  -o-transform: translate3d(-15.625rem, 0, 0);
+  transform: translate3d(-15.625rem, 0, 0); }
+.move-left .exit-off-canvas {
+  -webkit-backface-visibility: hidden;
+  transition: background 300ms ease;
+  cursor: pointer;
+  box-shadow: -4px 0 4px rgba(0, 0, 0, 0.5), 4px 0 4px rgba(0, 0, 0, 0.5);
+  display: block;
+  position: absolute;
+  background: rgba(255, 255, 255, 0.2);
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  z-index: 1002;
+  -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
+  @media only screen and (min-width: 40.063em) {
+    .move-left .exit-off-canvas:hover {
+      background: rgba(255, 255, 255, 0.05); } }
+
+.no-csstransforms .left-off-canvas-menu {
+  left: -15.625rem; }
+.no-csstransforms .right-off-canvas-menu {
+  right: -15.625rem; }
+.no-csstransforms .move-left > .inner-wrap {
+  right: 15.625rem; }
+.no-csstransforms .move-right > .inner-wrap {
+  left: 15.625rem; }
+
+/* Foundation Dropdowns */
+.f-dropdown {
+  position: absolute;
+  left: -9999px;
+  list-style: none;
+  margin-left: 0;
+  width: 100%;
+  max-height: none;
+  height: auto;
+  background: white;
+  border: solid 1px #cccccc;
+  font-size: 0.875rem;
+  z-index: 99;
+  margin-top: 2px;
+  max-width: 200px; }
+  .f-dropdown > *:first-child {
+    margin-top: 0; }
+  .f-dropdown > *:last-child {
+    margin-bottom: 0; }
+  .f-dropdown:before {
+    content: "";
+    display: block;
+    width: 0;
+    height: 0;
+    border: inset 6px;
+    border-color: transparent transparent white transparent;
+    border-bottom-style: solid;
+    position: absolute;
+    top: -12px;
+    left: 10px;
+    z-index: 99; }
+  .f-dropdown:after {
+    content: "";
+    display: block;
+    width: 0;
+    height: 0;
+    border: inset 7px;
+    border-color: transparent transparent #cccccc transparent;
+    border-bottom-style: solid;
+    position: absolute;
+    top: -14px;
+    left: 9px;
+    z-index: 98; }
+  .f-dropdown.right:before {
+    left: auto;
+    right: 10px; }
+  .f-dropdown.right:after {
+    left: auto;
+    right: 9px; }
+  .f-dropdown.drop-right {
+    position: absolute;
+    left: -9999px;
+    list-style: none;
+    margin-left: 0;
+    width: 100%;
+    max-height: none;
+    height: auto;
+    background: white;
+    border: solid 1px #cccccc;
+    font-size: 0.875rem;
+    z-index: 99;
+    margin-top: 0;
+    margin-left: 2px;
+    max-width: 200px; }
+    .f-dropdown.drop-right > *:first-child {
+      margin-top: 0; }
+    .f-dropdown.drop-right > *:last-child {
+      margin-bottom: 0; }
+    .f-dropdown.drop-right:before {
+      content: "";
+      display: block;
+      width: 0;
+      height: 0;
+      border: inset 6px;
+      border-color: transparent white transparent transparent;
+      border-right-style: solid;
+      position: absolute;
+      top: 10px;
+      left: -12px;
+      z-index: 99; }
+    .f-dropdown.drop-right:after {
+      content: "";
+      display: block;
+      width: 0;
+      height: 0;
+      border: inset 7px;
+      border-color: transparent #cccccc transparent transparent;
+      border-right-style: solid;
+      position: absolute;
+      top: 9px;
+      left: -14px;
+      z-index: 98; }
+  .f-dropdown.drop-left {
+    position: absolute;
+    left: -9999px;
+    list-style: none;
+    margin-left: 0;
+    width: 100%;
+    max-height: none;
+    height: auto;
+    background: white;
+    border: solid 1px #cccccc;
+    font-size: 0.875rem;
+    z-index: 99;
+    margin-top: 0;
+    margin-left: -2px;
+    max-width: 200px; }
+    .f-dropdown.drop-left > *:first-child {
+      margin-top: 0; }
+    .f-dropdown.drop-left > *:last-child {
+      margin-bottom: 0; }
+    .f-dropdown.drop-left:before {
+      content: "";
+      display: block;
+      width: 0;
+      height: 0;
+      border: inset 6px;
+      border-color: transparent transparent transparent white;
+      border-left-style: solid;
+      position: absolute;
+      top: 10px;
+      right: -12px;
+      left: auto;
+      z-index: 99; }
+    .f-dropdown.drop-left:after {
+      content: "";
+      display: block;
+      width: 0;
+      height: 0;
+      border: inset 7px;
+      border-color: transparent transparent transparent #cccccc;
+      border-left-style: solid;
+      position: absolute;
+      top: 9px;
+      right: -14px;
+      left: auto;
+      z-index: 98; }
+  .f-dropdown.drop-top {
+    position: absolute;
+    left: -9999px;
+    list-style: none;
+    margin-left: 0;
+    width: 100%;
+    max-height: none;
+    height: auto;
+    background: white;
+    border: solid 1px #cccccc;
+    font-size: 0.875rem;
+    z-index: 99;
+    margin-top: -2px;
+    margin-left: 0;
+    max-width: 200px; }
+    .f-dropdown.drop-top > *:first-child {
+      margin-top: 0; }
+    .f-dropdown.drop-top > *:last-child {
+      margin-bottom: 0; }
+    .f-dropdown.drop-top:before {
+      content: "";
+      display: block;
+      width: 0;
+      height: 0;
+      border: inset 6px;
+      border-color: white transparent transparent transparent;
+      border-top-style: solid;
+      position: absolute;
+      top: auto;
+      bottom: -12px;
+      left: 10px;
+      right: auto;
+      z-index: 99; }
+    .f-dropdown.drop-top:after {
+      content: "";
+      display: block;
+      width: 0;
+      height: 0;
+      border: inset 7px;
+      border-color: #cccccc transparent transparent transparent;
+      border-top-style: solid;
+      position: absolute;
+      top: auto;
+      bottom: -14px;
+      left: 9px;
+      right: auto;
+      z-index: 98; }
+  .f-dropdown li {
+    font-size: 0.875rem;
+    cursor: pointer;
+    line-height: 1.125rem;
+    margin: 0; }
+    .f-dropdown li:hover, .f-dropdown li:focus {
+      background: #eeeeee; }
+    .f-dropdown li a {
+      display: block;
+      padding: 0.5rem;
+      color: #555555; }
+  .f-dropdown.content {
+    position: absolute;
+    left: -9999px;
+    list-style: none;
+    margin-left: 0;
+    padding: 1.25rem;
+    width: 100%;
+    height: auto;
+    max-height: none;
+    background: white;
+    border: solid 1px #cccccc;
+    font-size: 0.875rem;
+    z-index: 99;
+    max-width: 200px; }
+    .f-dropdown.content > *:first-child {
+      margin-top: 0; }
+    .f-dropdown.content > *:last-child {
+      margin-bottom: 0; }
+  .f-dropdown.tiny {
+    max-width: 200px; }
+  .f-dropdown.small {
+    max-width: 300px; }
+  .f-dropdown.medium {
+    max-width: 500px; }
+  .f-dropdown.large {
+    max-width: 800px; }
+
+table {
+  background: white;
+  margin-bottom: 1.25rem;
+  border: solid 1px #dddddd; }
+  table thead,
+  table tfoot {
+    background: whitesmoke; }
+    table thead tr th,
+    table thead tr td,
+    table tfoot tr th,
+    table tfoot tr td {
+      padding: 0.5rem 0.625rem 0.625rem;
+      font-size: 0.875rem;
+      font-weight: bold;
+      color: #222222;
+      text-align: left; }
+  table tr th,
+  table tr td {
+    padding: 0.5625rem 0.625rem;
+    font-size: 0.875rem;
+    color: #222222; }
+  table tr.even, table tr.alt, table tr:nth-of-type(even) {
+    background: #f9f9f9; }
+  table thead tr th,
+  table tfoot tr th,
+  table tbody tr td,
+  table tr td,
+  table tfoot tr td {
+    display: table-cell;
+    line-height: 1.125rem; }
+
+/* Standard Forms */
+form {
+  margin: 0 0 1rem; }
+
+/* Using forms within rows, we need to set some defaults */
+form .row .row {
+  margin: 0 -0.5rem; }
+  form .row .row .column,
+  form .row .row .columns {
+    padding: 0 0.5rem; }
+  form .row .row.collapse {
+    margin: 0; }
+    form .row .row.collapse .column,
+    form .row .row.collapse .columns {
+      padding: 0; }
+    form .row .row.collapse input {
+      border-bottom-right-radius: 0;
+      border-top-right-radius: 0; }
+form .row input.column,
+form .row input.columns,
+form .row textarea.column,
+form .row textarea.columns {
+  padding-left: 0.5rem; }
+
+/* Label Styles */
+label {
+  font-size: 0.875rem;
+  color: #4d4d4d;
+  cursor: pointer;
+  display: block;
+  font-weight: normal;
+  line-height: 1.5;
+  margin-bottom: 0;
+  /* Styles for required inputs */ }
+  label.right {
+    float: none;
+    text-align: right; }
+  label.inline {
+    margin: 0 0 1rem 0;
+    padding: 0.5625rem 0; }
+  label small {
+    text-transform: capitalize;
+    color: #676767; }
+
+select::-ms-expand {
+  display: none; }
+
+@-moz-document url-prefix() {
+  select {
+    background: #fafafa; }
+
+  select:hover {
+    background: #f3f3f3; } }
+
+/* Attach elements to the beginning or end of an input */
+.prefix,
+.postfix {
+  display: block;
+  position: relative;
+  z-index: 2;
+  text-align: center;
+  width: 100%;
+  padding-top: 0;
+  padding-bottom: 0;
+  border-style: solid;
+  border-width: 1px;
+  overflow: hidden;
+  font-size: 0.875rem;
+  height: 2.3125rem;
+  line-height: 2.3125rem; }
+
+/* Adjust padding, alignment and radius if pre/post element is a button */
+.postfix.button {
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  padding-bottom: 0;
+  text-align: center;
+  line-height: 2.125rem;
+  border: none; }
+
+.prefix.button {
+  padding-left: 0;
+  padding-right: 0;
+  padding-top: 0;
+  padding-bottom: 0;
+  text-align: center;
+  line-height: 2.125rem;
+  border: none; }
+
+.prefix.button.radius {
+  border-radius: 0;
+  border-bottom-left-radius: 3px;
+  border-top-left-radius: 3px; }
+
+.postfix.button.radius {
+  border-radius: 0;
+  border-bottom-right-radius: 3px;
+  border-top-right-radius: 3px; }
+
+.prefix.button.round {
+  border-radius: 0;
+  border-bottom-left-radius: 1000px;
+  border-top-left-radius: 1000px; }
+
+.postfix.button.round {
+  border-radius: 0;
+  border-bottom-right-radius: 1000px;
+  border-top-right-radius: 1000px; }
+
+/* Separate prefix and postfix styles when on span or label so buttons keep their own */
+span.prefix, label.prefix {
+  background: #f2f2f2;
+  border-right: none;
+  color: #333333;
+  border-color: #cccccc; }
+  span.prefix.radius, label.prefix.radius {
+    border-radius: 0;
+    border-bottom-left-radius: 3px;
+    border-top-left-radius: 3px; }
+
+span.postfix, label.postfix {
+  background: #f2f2f2;
+  border-left: none;
+  color: #333333;
+  border-color: #cccccc; }
+  span.postfix.radius, label.postfix.radius {
+    border-radius: 0;
+    border-bottom-right-radius: 3px;
+    border-top-right-radius: 3px; }
+
+/* We use this to get basic styling on all basic form elements */
+input[type="text"],
+input[type="password"],
+input[type="date"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="month"],
+input[type="week"],
+input[type="email"],
+input[type="number"],
+input[type="search"],
+input[type="tel"],
+input[type="time"],
+input[type="url"],
+textarea {
+  -webkit-appearance: none;
+  background-color: white;
+  font-family: inherit;
+  border: 1px solid #cccccc;
+  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+  color: rgba(0, 0, 0, 0.75);
+  display: block;
+  font-size: 0.875rem;
+  margin: 0 0 1rem 0;
+  padding: 0.5rem;
+  height: 2.3125rem;
+  width: 100%;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+  transition: box-shadow 0.45s, border-color 0.45s ease-in-out; }
+  input[type="text"]:focus,
+  input[type="password"]:focus,
+  input[type="date"]:focus,
+  input[type="datetime"]:focus,
+  input[type="datetime-local"]:focus,
+  input[type="month"]:focus,
+  input[type="week"]:focus,
+  input[type="email"]:focus,
+  input[type="number"]:focus,
+  input[type="search"]:focus,
+  input[type="tel"]:focus,
+  input[type="time"]:focus,
+  input[type="url"]:focus,
+  textarea:focus {
+    box-shadow: 0 0 5px #999999;
+    border-color: #999999; }
+  input[type="text"]:focus,
+  input[type="password"]:focus,
+  input[type="date"]:focus,
+  input[type="datetime"]:focus,
+  input[type="datetime-local"]:focus,
+  input[type="month"]:focus,
+  input[type="week"]:focus,
+  input[type="email"]:focus,
+  input[type="number"]:focus,
+  input[type="search"]:focus,
+  input[type="tel"]:focus,
+  input[type="time"]:focus,
+  input[type="url"]:focus,
+  textarea:focus {
+    background: #fafafa;
+    border-color: #999999;
+    outline: none; }
+  input[type="text"][disabled], fieldset[disabled] input[type="text"],
+  input[type="password"][disabled], fieldset[disabled]
+  input[type="password"],
+  input[type="date"][disabled], fieldset[disabled]
+  input[type="date"],
+  input[type="datetime"][disabled], fieldset[disabled]
+  input[type="datetime"],
+  input[type="datetime-local"][disabled], fieldset[disabled]
+  input[type="datetime-local"],
+  input[type="month"][disabled], fieldset[disabled]
+  input[type="month"],
+  input[type="week"][disabled], fieldset[disabled]
+  input[type="week"],
+  input[type="email"][disabled], fieldset[disabled]
+  input[type="email"],
+  input[type="number"][disabled], fieldset[disabled]
+  input[type="number"],
+  input[type="search"][disabled], fieldset[disabled]
+  input[type="search"],
+  input[type="tel"][disabled], fieldset[disabled]
+  input[type="tel"],
+  input[type="time"][disabled], fieldset[disabled]
+  input[type="time"],
+  input[type="url"][disabled], fieldset[disabled]
+  input[type="url"],
+  textarea[disabled], fieldset[disabled]
+  textarea {
+    background-color: #dddddd; }
+  input[type="text"].radius,
+  input[type="password"].radius,
+  input[type="date"].radius,
+  input[type="datetime"].radius,
+  input[type="datetime-local"].radius,
+  input[type="month"].radius,
+  input[type="week"].radius,
+  input[type="email"].radius,
+  input[type="number"].radius,
+  input[type="search"].radius,
+  input[type="tel"].radius,
+  input[type="time"].radius,
+  input[type="url"].radius,
+  textarea.radius {
+    border-radius: 3px; }
+
+input[type="submit"] {
+  -webkit-appearance: none; }
+
+/* Respect enforced amount of rows for textarea */
+textarea[rows] {
+  height: auto; }
+
+/* Add height value for select elements to match text input height */
+select {
+  -webkit-appearance: none !important;
+  background-color: #fafafa;
+  background-image: url("data:image/svg+xml;base64, PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI2cHgiIGhlaWdodD0iM3B4IiB2aWV3Qm94PSIwIDAgNiAzIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA2IDMiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxwb2x5Z29uIHBvaW50cz0iNS45OTIsMCAyLjk5MiwzIC0wLjAwOCwwICIvPjwvc3ZnPg==");
+  background-repeat: no-repeat;
+  background-position: 97% center;
+  border: 1px solid #cccccc;
+  padding: 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0;
+  height: 2.3125rem; }
+  select.radius {
+    border-radius: 3px; }
+  select:hover {
+    background-color: #f3f3f3;
+    border-color: #999999; }
+
+/* Adjust margin for form elements below */
+input[type="file"],
+input[type="checkbox"],
+input[type="radio"],
+select {
+  margin: 0 0 1rem 0; }
+
+input[type="checkbox"] + label,
+input[type="radio"] + label {
+  display: inline-block;
+  margin-left: 0.5rem;
+  margin-right: 1rem;
+  margin-bottom: 0;
+  vertical-align: baseline; }
+
+/* Normalize file input width */
+input[type="file"] {
+  width: 100%; }
+
+/* We add basic fieldset styling */
+fieldset {
+  border: 1px solid #dddddd;
+  padding: 1.25rem;
+  margin: 1.125rem 0; }
+  fieldset legend {
+    font-weight: bold;
+    background: white;
+    padding: 0 0.1875rem;
+    margin: 0;
+    margin-left: -0.1875rem; }
+
+/* Error Handling */
+[data-abide] .error small.error, [data-abide] span.error, [data-abide] small.error {
+  display: block;
+  padding: 0.375rem 0.5625rem 0.5625rem;
+  margin-top: -1px;
+  margin-bottom: 1rem;
+  font-size: 0.75rem;
+  font-weight: normal;
+  font-style: italic;
+  background: #f04124;
+  color: white; }
+[data-abide] span.error, [data-abide] small.error {
+  display: none; }
+
+span.error, small.error {
+  display: block;
+  padding: 0.375rem 0.5625rem 0.5625rem;
+  margin-top: -1px;
+  margin-bottom: 1rem;
+  font-size: 0.75rem;
+  font-weight: normal;
+  font-style: italic;
+  background: #f04124;
+  color: white; }
+
+.error input,
+.error textarea,
+.error select {
+  margin-bottom: 0; }
+.error input[type="checkbox"],
+.error input[type="radio"] {
+  margin-bottom: 1rem; }
+.error label,
+.error label.error {
+  color: #f04124; }
+.error small.error {
+  display: block;
+  padding: 0.375rem 0.5625rem 0.5625rem;
+  margin-top: -1px;
+  margin-bottom: 1rem;
+  font-size: 0.75rem;
+  font-weight: normal;
+  font-style: italic;
+  background: #f04124;
+  color: white; }
+.error > label > small {
+  color: #676767;
+  background: transparent;
+  padding: 0;
+  text-transform: capitalize;
+  font-style: normal;
+  font-size: 60%;
+  margin: 0;
+  display: inline; }
+.error span.error-message {
+  display: block; }
+
+input.error,
+textarea.error {
+  margin-bottom: 0; }
+
+label.error {
+  color: #f04124; }
+
+.range-slider {
+  display: block;
+  position: relative;
+  width: 100%;
+  height: 1rem;
+  border: 1px solid #dddddd;
+  margin: 1.25rem 0;
+  -ms-touch-action: none;
+  touch-action: none;
+  background: #fafafa; }
+  .range-slider.vertical-range {
+    display: block;
+    position: relative;
+    width: 100%;
+    height: 1rem;
+    border: 1px solid #dddddd;
+    margin: 1.25rem 0;
+    -ms-touch-action: none;
+    touch-action: none;
+    display: inline-block;
+    width: 1rem;
+    height: 12.5rem; }
+    .range-slider.vertical-range .range-slider-handle {
+      margin-top: 0;
+      margin-left: -0.5rem;
+      position: absolute;
+      bottom: -10.5rem; }
+    .range-slider.vertical-range .range-slider-active-segment {
+      width: 0.875rem;
+      height: auto;
+      bottom: 0; }
+  .range-slider.radius {
+    background: #fafafa;
+    border-radius: 3px; }
+    .range-slider.radius .range-slider-handle {
+      background: #008cba;
+      border-radius: 3px; }
+      .range-slider.radius .range-slider-handle:hover {
+        background: #007ba4; }
+  .range-slider.round {
+    background: #fafafa;
+    border-radius: 1000px; }
+    .range-slider.round .range-slider-handle {
+      background: #008cba;
+      border-radius: 1000px; }
+      .range-slider.round .range-slider-handle:hover {
+        background: #007ba4; }
+
+.range-slider-active-segment {
+  display: inline-block;
+  position: absolute;
+  height: 0.875rem;
+  background: #e5e5e5; }
+
+.range-slider-handle {
+  display: inline-block;
+  position: absolute;
+  z-index: 1;
+  top: -0.3125rem;
+  width: 2rem;
+  height: 1.375rem;
+  border: 1px solid none;
+  cursor: pointer;
+  background: #008cba; }
+  .range-slider-handle:hover {
+    background: #007ba4; }
+
+[class*="block-grid-"] {
+  display: block;
+  padding: 0;
+  margin: 0 -0.625rem;
+  *zoom: 1; }
+  [class*="block-grid-"]:before, [class*="block-grid-"]:after {
+    content: " ";
+    display: table; }
+  [class*="block-grid-"]:after {
+    clear: both; }
+  [class*="block-grid-"] > li {
+    display: block;
+    height: auto;
+    float: left;
+    padding: 0 0.625rem 1.25rem; }
+
+@media only screen {
+  .small-block-grid-1 > li {
+    width: 100%;
+    list-style: none; }
+    .small-block-grid-1 > li:nth-of-type(n) {
+      clear: none; }
+    .small-block-grid-1 > li:nth-of-type(1n+1) {
+      clear: both; }
+
+  .small-block-grid-2 > li {
+    width: 50%;
+    list-style: none; }
+    .small-block-grid-2 > li:nth-of-type(n) {
+      clear: none; }
+    .small-block-grid-2 > li:nth-of-type(2n+1) {
+      clear: both; }
+
+  .small-block-grid-3 > li {
+    width: 33.33333%;
+    list-style: none; }
+    .small-block-grid-3 > li:nth-of-type(n) {
+      clear: none; }
+    .small-block-grid-3 > li:nth-of-type(3n+1) {
+      clear: both; }
+
+  .small-block-grid-4 > li {
+    width: 25%;
+    list-style: none; }
+    .small-block-grid-4 > li:nth-of-type(n) {
+      clear: none; }
+    .small-block-grid-4 > li:nth-of-type(4n+1) {
+      clear: both; }
+
+  .small-block-grid-5 > li {
+    width: 20%;
+    list-style: none; }
+    .small-block-grid-5 > li:nth-of-type(n) {
+      clear: none; }
+    .small-block-grid-5 > li:nth-of-type(5n+1) {
+      clear: both; }
+
+  .small-block-grid-6 > li {
+    width: 16.66667%;
+    list-style: none; }
+    .small-block-grid-6 > li:nth-of-type(n) {
+      clear: none; }
+    .small-block-grid-6 > li:nth-of-type(6n+1) {
+      clear: both; }
+
+  .small-block-grid-7 > li {
+    width: 14.28571%;
+    list-style: none; }
+    .small-block-grid-7 > li:nth-of-type(n) {
+      clear: none; }
+    .small-block-grid-7 > li:nth-of-type(7n+1) {
+      clear: both; }
+
+  .small-block-grid-8 > li {
+    width: 12.5%;
+    list-style: none; }
+    .small-block-grid-8 > li:nth-of-type(n) {
+      clear: none; }
+    .small-block-grid-8 > li:nth-of-type(8n+1) {
+      clear: both; }
+
+  .small-block-grid-9 > li {
+    width: 11.11111%;
+    list-style: none; }
+    .small-block-grid-9 > li:nth-of-type(n) {
+      clear: none; }
+    .small-block-grid-9 > li:nth-of-type(9n+1) {
+      clear: both; }
+
+  .small-block-grid-10 > li {
+    width: 10%;
+    list-style: none; }
+    .small-block-grid-10 > li:nth-of-type(n) {
+      clear: none; }
+    .small-block-grid-10 > li:nth-of-type(10n+1) {
+      clear: both; }
+
+  .small-block-grid-11 > li {
+    width: 9.09091%;
+    list-style: none; }
+    .small-block-grid-11 > li:nth-of-type(n) {
+      clear: none; }
+    .small-block-grid-11 > li:nth-of-type(11n+1) {
+      clear: both; }
+
+  .small-block-grid-12 > li {
+    width: 8.33333%;
+    list-style: none; }
+    .small-block-grid-12 > li:nth-of-type(n) {
+      clear: none; }
+    .small-block-grid-12 > li:nth-of-type(12n+1) {
+      clear: both; } }
+@media only screen and (min-width: 40.063em) {
+  .medium-block-grid-1 > li {
+    width: 100%;
+    list-style: none; }
+    .medium-block-grid-1 > li:nth-of-type(n) {
+      clear: none; }
+    .medium-block-grid-1 > li:nth-of-type(1n+1) {
+      clear: both; }
+
+  .medium-block-grid-2 > li {
+    width: 50%;
+    list-style: none; }
+    .medium-block-grid-2 > li:nth-of-type(n) {
+      clear: none; }
+    .medium-block-grid-2 > li:nth-of-type(2n+1) {
+      clear: both; }
+
+  .medium-block-grid-3 > li {
+    width: 33.33333%;
+    list-style: none; }
+    .medium-block-grid-3 > li:nth-of-type(n) {
+      clear: none; }
+    .medium-block-grid-3 > li:nth-of-type(3n+1) {
+      clear: both; }
+
+  .medium-block-grid-4 > li {
+    width: 25%;
+    list-style: none; }
+    .medium-block-grid-4 > li:nth-of-type(n) {
+      clear: none; }
+    .medium-block-grid-4 > li:nth-of-type(4n+1) {
+      clear: both; }
+
+  .medium-block-grid-5 > li {
+    width: 20%;
+    list-style: none; }
+    .medium-block-grid-5 > li:nth-of-type(n) {
+      clear: none; }
+    .medium-block-grid-5 > li:nth-of-type(5n+1) {
+      clear: both; }
+
+  .medium-block-grid-6 > li {
+    width: 16.66667%;
+    list-style: none; }
+    .medium-block-grid-6 > li:nth-of-type(n) {
+      clear: none; }
+    .medium-block-grid-6 > li:nth-of-type(6n+1) {
+      clear: both; }
+
+  .medium-block-grid-7 > li {
+    width: 14.28571%;
+    list-style: none; }
+    .medium-block-grid-7 > li:nth-of-type(n) {
+      clear: none; }
+    .medium-block-grid-7 > li:nth-of-type(7n+1) {
+      clear: both; }
+
+  .medium-block-grid-8 > li {
+    width: 12.5%;
+    list-style: none; }
+    .medium-block-grid-8 > li:nth-of-type(n) {
+      clear: none; }
+    .medium-block-grid-8 > li:nth-of-type(8n+1) {
+      clear: both; }
+
+  .medium-block-grid-9 > li {
+    width: 11.11111%;
+    list-style: none; }
+    .medium-block-grid-9 > li:nth-of-type(n) {
+      clear: none; }
+    .medium-block-grid-9 > li:nth-of-type(9n+1) {
+      clear: both; }
+
+  .medium-block-grid-10 > li {
+    width: 10%;
+    list-style: none; }
+    .medium-block-grid-10 > li:nth-of-type(n) {
+      clear: none; }
+    .medium-block-grid-10 > li:nth-of-type(10n+1) {
+      clear: both; }
+
+  .medium-block-grid-11 > li {
+    width: 9.09091%;
+    list-style: none; }
+    .medium-block-grid-11 > li:nth-of-type(n) {
+      clear: none; }
+    .medium-block-grid-11 > li:nth-of-type(11n+1) {
+      clear: both; }
+
+  .medium-block-grid-12 > li {
+    width: 8.33333%;
+    list-style: none; }
+    .medium-block-grid-12 > li:nth-of-type(n) {
+      clear: none; }
+    .medium-block-grid-12 > li:nth-of-type(12n+1) {
+      clear: both; } }
+@media only screen and (min-width: 64.063em) {
+  .large-block-grid-1 > li {
+    width: 100%;
+    list-style: none; }
+    .large-block-grid-1 > li:nth-of-type(n) {
+      clear: none; }
+    .large-block-grid-1 > li:nth-of-type(1n+1) {
+      clear: both; }
+
+  .large-block-grid-2 > li {
+    width: 50%;
+    list-style: none; }
+    .large-block-grid-2 > li:nth-of-type(n) {
+      clear: none; }
+    .large-block-grid-2 > li:nth-of-type(2n+1) {
+      clear: both; }
+
+  .large-block-grid-3 > li {
+    width: 33.33333%;
+    list-style: none; }
+    .large-block-grid-3 > li:nth-of-type(n) {
+      clear: none; }
+    .large-block-grid-3 > li:nth-of-type(3n+1) {
+      clear: both; }
+
+  .large-block-grid-4 > li {
+    width: 25%;
+    list-style: none; }
+    .large-block-grid-4 > li:nth-of-type(n) {
+      clear: none; }
+    .large-block-grid-4 > li:nth-of-type(4n+1) {
+      clear: both; }
+
+  .large-block-grid-5 > li {
+    width: 20%;
+    list-style: none; }
+    .large-block-grid-5 > li:nth-of-type(n) {
+      clear: none; }
+    .large-block-grid-5 > li:nth-of-type(5n+1) {
+      clear: both; }
+
+  .large-block-grid-6 > li {
+    width: 16.66667%;
+    list-style: none; }
+    .large-block-grid-6 > li:nth-of-type(n) {
+      clear: none; }
+    .large-block-grid-6 > li:nth-of-type(6n+1) {
+      clear: both; }
+
+  .large-block-grid-7 > li {
+    width: 14.28571%;
+    list-style: none; }
+    .large-block-grid-7 > li:nth-of-type(n) {
+      clear: none; }
+    .large-block-grid-7 > li:nth-of-type(7n+1) {
+      clear: both; }
+
+  .large-block-grid-8 > li {
+    width: 12.5%;
+    list-style: none; }
+    .large-block-grid-8 > li:nth-of-type(n) {
+      clear: none; }
+    .large-block-grid-8 > li:nth-of-type(8n+1) {
+      clear: both; }
+
+  .large-block-grid-9 > li {
+    width: 11.11111%;
+    list-style: none; }
+    .large-block-grid-9 > li:nth-of-type(n) {
+      clear: none; }
+    .large-block-grid-9 > li:nth-of-type(9n+1) {
+      clear: both; }
+
+  .large-block-grid-10 > li {
+    width: 10%;
+    list-style: none; }
+    .large-block-grid-10 > li:nth-of-type(n) {
+      clear: none; }
+    .large-block-grid-10 > li:nth-of-type(10n+1) {
+      clear: both; }
+
+  .large-block-grid-11 > li {
+    width: 9.09091%;
+    list-style: none; }
+    .large-block-grid-11 > li:nth-of-type(n) {
+      clear: none; }
+    .large-block-grid-11 > li:nth-of-type(11n+1) {
+      clear: both; }
+
+  .large-block-grid-12 > li {
+    width: 8.33333%;
+    list-style: none; }
+    .large-block-grid-12 > li:nth-of-type(n) {
+      clear: none; }
+    .large-block-grid-12 > li:nth-of-type(12n+1) {
+      clear: both; } }
+.flex-video {
+  position: relative;
+  padding-top: 1.5625rem;
+  padding-bottom: 67.5%;
+  height: 0;
+  margin-bottom: 1rem;
+  overflow: hidden; }
+  .flex-video.widescreen {
+    padding-bottom: 56.34%; }
+  .flex-video.vimeo {
+    padding-top: 0; }
+  .flex-video iframe,
+  .flex-video object,
+  .flex-video embed,
+  .flex-video video {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%; }
+
+.keystroke,
+kbd {
+  background-color: #ededed;
+  border-color: #dddddd;
+  color: #222222;
+  border-style: solid;
+  border-width: 1px;
+  margin: 0;
+  font-family: "Consolas", "Menlo", "Courier", monospace;
+  font-size: inherit;
+  padding: 0.125rem 0.25rem 0;
+  border-radius: 3px; }
+
+/* small displays */
+@media only screen {
+  .show-for-small-only, .show-for-small-up, .show-for-small, .show-for-small-down, .hide-for-medium-only, .hide-for-medium-up, .hide-for-medium, .show-for-medium-down, .hide-for-large-only, .hide-for-large-up, .hide-for-large, .show-for-large-down, .hide-for-xlarge-only, .hide-for-xlarge-up, .hide-for-xxlarge-only, .hide-for-xxlarge-up {
+    display: inherit !important; }
+
+  .hide-for-small-only, .hide-for-small-up, .hide-for-small, .hide-for-small-down, .show-for-medium-only, .show-for-medium-up, .show-for-medium, .hide-for-medium-down, .show-for-large-only, .show-for-large-up, .show-for-large, .hide-for-large-down, .show-for-xlarge-only, .show-for-xlarge-up, .show-for-xxlarge-only, .show-for-xxlarge-up {
+    display: none !important; }
+
+  table.show-for-small-only, table.show-for-small-up, table.show-for-small, table.show-for-small-down, table.hide-for-medium-only, table.hide-for-medium-up, table.hide-for-medium, table.show-for-medium-down, table.hide-for-large-only, table.hide-for-large-up, table.hide-for-large, table.show-for-large-down, table.hide-for-xlarge-only, table.hide-for-xlarge-up, table.hide-for-xxlarge-only, table.hide-for-xxlarge-up {
+    display: table; }
+
+  thead.show-for-small-only, thead.show-for-small-up, thead.show-for-small, thead.show-for-small-down, thead.hide-for-medium-only, thead.hide-for-medium-up, thead.hide-for-medium, thead.show-for-medium-down, thead.hide-for-large-only, thead.hide-for-large-up, thead.hide-for-large, thead.show-for-large-down, thead.hide-for-xlarge-only, thead.hide-for-xlarge-up, thead.hide-for-xxlarge-only, thead.hide-for-xxlarge-up {
+    display: table-header-group !important; }
+
+  tbody.show-for-small-only, tbody.show-for-small-up, tbody.show-for-small, tbody.show-for-small-down, tbody.hide-for-medium-only, tbody.hide-for-medium-up, tbody.hide-for-medium, tbody.show-for-medium-down, tbody.hide-for-large-only, tbody.hide-for-large-up, tbody.hide-for-large, tbody.show-for-large-down, tbody.hide-for-xlarge-only, tbody.hide-for-xlarge-up, tbody.hide-for-xxlarge-only, tbody.hide-for-xxlarge-up {
+    display: table-row-group !important; }
+
+  tr.show-for-small-only, tr.show-for-small-up, tr.show-for-small, tr.show-for-small-down, tr.hide-for-medium-only, tr.hide-for-medium-up, tr.hide-for-medium, tr.show-for-medium-down, tr.hide-for-large-only, tr.hide-for-large-up, tr.hide-for-large, tr.show-for-large-down, tr.hide-for-xlarge-only, tr.hide-for-xlarge-up, tr.hide-for-xxlarge-only, tr.hide-for-xxlarge-up {
+    display: table-row !important; }
+
+  th.show-for-small-only, td.show-for-small-only, th.show-for-small-up, td.show-for-small-up, th.show-for-small, td.show-for-small, th.show-for-small-down, td.show-for-small-down, th.hide-for-medium-only, td.hide-for-medium-only, th.hide-for-medium-up, td.hide-for-medium-up, th.hide-for-medium, td.hide-for-medium, th.show-for-medium-down, td.show-for-medium-down, th.hide-for-large-only, td.hide-for-large-only, th.hide-for-large-up, td.hide-for-large-up, th.hide-for-large, td.hide-for-large, th.show-for-large-down, td.show-for-large-down, th.hide-for-xlarge-only, td.hide-for-xlarge-only, th.hide-for-xlarge-up, td.hide-for-xlarge-up, th.hide-for-xxlarge-only, td.hide-for-xxlarge-only, th.hide-for-xxlarge-up, td.hide-for-xxlarge-up {
+    display: table-cell !important; } }
+/* medium displays */
+@media only screen and (min-width: 40.063em) {
+  .hide-for-small-only, .show-for-small-up, .hide-for-small, .hide-for-small-down, .show-for-medium-only, .show-for-medium-up, .show-for-medium, .show-for-medium-down, .hide-for-large-only, .hide-for-large-up, .hide-for-large, .show-for-large-down, .hide-for-xlarge-only, .hide-for-xlarge-up, .hide-for-xxlarge-only, .hide-for-xxlarge-up {
+    display: inherit !important; }
+
+  .show-for-small-only, .hide-for-small-up, .show-for-small, .show-for-small-down, .hide-for-medium-only, .hide-for-medium-up, .hide-for-medium, .hide-for-medium-down, .show-for-large-only, .show-for-large-up, .show-for-large, .hide-for-large-down, .show-for-xlarge-only, .show-for-xlarge-up, .show-for-xxlarge-only, .show-for-xxlarge-up {
+    display: none !important; }
+
+  table.hide-for-small-only, table.show-for-small-up, table.hide-for-small, table.hide-for-small-down, table.show-for-medium-only, table.show-for-medium-up, table.show-for-medium, table.show-for-medium-down, table.hide-for-large-only, table.hide-for-large-up, table.hide-for-large, table.show-for-large-down, table.hide-for-xlarge-only, table.hide-for-xlarge-up, table.hide-for-xxlarge-only, table.hide-for-xxlarge-up {
+    display: table; }
+
+  thead.hide-for-small-only, thead.show-for-small-up, thead.hide-for-small, thead.hide-for-small-down, thead.show-for-medium-only, thead.show-for-medium-up, thead.show-for-medium, thead.show-for-medium-down, thead.hide-for-large-only, thead.hide-for-large-up, thead.hide-for-large, thead.show-for-large-down, thead.hide-for-xlarge-only, thead.hide-for-xlarge-up, thead.hide-for-xxlarge-only, thead.hide-for-xxlarge-up {
+    display: table-header-group !important; }
+
+  tbody.hide-for-small-only, tbody.show-for-small-up, tbody.hide-for-small, tbody.hide-for-small-down, tbody.show-for-medium-only, tbody.show-for-medium-up, tbody.show-for-medium, tbody.show-for-medium-down, tbody.hide-for-large-only, tbody.hide-for-large-up, tbody.hide-for-large, tbody.show-for-large-down, tbody.hide-for-xlarge-only, tbody.hide-for-xlarge-up, tbody.hide-for-xxlarge-only, tbody.hide-for-xxlarge-up {
+    display: table-row-group !important; }
+
+  tr.hide-for-small-only, tr.show-for-small-up, tr.hide-for-small, tr.hide-for-small-down, tr.show-for-medium-only, tr.show-for-medium-up, tr.show-for-medium, tr.show-for-medium-down, tr.hide-for-large-only, tr.hide-for-large-up, tr.hide-for-large, tr.show-for-large-down, tr.hide-for-xlarge-only, tr.hide-for-xlarge-up, tr.hide-for-xxlarge-only, tr.hide-for-xxlarge-up {
+    display: table-row !important; }
+
+  th.hide-for-small-only, td.hide-for-small-only, th.show-for-small-up, td.show-for-small-up, th.hide-for-small, td.hide-for-small, th.hide-for-small-down, td.hide-for-small-down, th.show-for-medium-only, td.show-for-medium-only, th.show-for-medium-up, td.show-for-medium-up, th.show-for-medium, td.show-for-medium, th.show-for-medium-down, td.show-for-medium-down, th.hide-for-large-only, td.hide-for-large-only, th.hide-for-large-up, td.hide-for-large-up, th.hide-for-large, td.hide-for-large, th.show-for-large-down, td.show-for-large-down, th.hide-for-xlarge-only, td.hide-for-xlarge-only, th.hide-for-xlarge-up, td.hide-for-xlarge-up, th.hide-for-xxlarge-only, td.hide-for-xxlarge-only, th.hide-for-xxlarge-up, td.hide-for-xxlarge-up {
+    display: table-cell !important; } }
+/* large displays */
+@media only screen and (min-width: 64.063em) {
+  .hide-for-small-only, .show-for-small-up, .hide-for-small, .hide-for-small-down, .hide-for-medium-only, .show-for-medium-up, .hide-for-medium, .hide-for-medium-down, .show-for-large-only, .show-for-large-up, .show-for-large, .show-for-large-down, .hide-for-xlarge-only, .hide-for-xlarge-up, .hide-for-xxlarge-only, .hide-for-xxlarge-up {
+    display: inherit !important; }
+
+  .show-for-small-only, .hide-for-small-up, .show-for-small, .show-for-small-down, .show-for-medium-only, .hide-for-medium-up, .show-for-medium, .show-for-medium-down, .hide-for-large-only, .hide-for-large-up, .hide-for-large, .hide-for-large-down, .show-for-xlarge-only, .show-for-xlarge-up, .show-for-xxlarge-only, .show-for-xxlarge-up {
+    display: none !important; }
+
+  table.hide-for-small-only, table.show-for-small-up, table.hide-for-small, table.hide-for-small-down, table.hide-for-medium-only, table.show-for-medium-up, table.hide-for-medium, table.hide-for-medium-down, table.show-for-large-only, table.show-for-large-up, table.show-for-large, table.show-for-large-down, table.hide-for-xlarge-only, table.hide-for-xlarge-up, table.hide-for-xxlarge-only, table.hide-for-xxlarge-up {
+    display: table; }
+
+  thead.hide-for-small-only, thead.show-for-small-up, thead.hide-for-small, thead.hide-for-small-down, thead.hide-for-medium-only, thead.show-for-medium-up, thead.hide-for-medium, thead.hide-for-medium-down, thead.show-for-large-only, thead.show-for-large-up, thead.show-for-large, thead.show-for-large-down, thead.hide-for-xlarge-only, thead.hide-for-xlarge-up, thead.hide-for-xxlarge-only, thead.hide-for-xxlarge-up {
+    display: table-header-group !important; }
+
+  tbody.hide-for-small-only, tbody.show-for-small-up, tbody.hide-for-small, tbody.hide-for-small-down, tbody.hide-for-medium-only, tbody.show-for-medium-up, tbody.hide-for-medium, tbody.hide-for-medium-down, tbody.show-for-large-only, tbody.show-for-large-up, tbody.show-for-large, tbody.show-for-large-down, tbody.hide-for-xlarge-only, tbody.hide-for-xlarge-up, tbody.hide-for-xxlarge-only, tbody.hide-for-xxlarge-up {
+    display: table-row-group !important; }
+
+  tr.hide-for-small-only, tr.show-for-small-up, tr.hide-for-small, tr.hide-for-small-down, tr.hide-for-medium-only, tr.show-for-medium-up, tr.hide-for-medium, tr.hide-for-medium-down, tr.show-for-large-only, tr.show-for-large-up, tr.show-for-large, tr.show-for-large-down, tr.hide-for-xlarge-only, tr.hide-for-xlarge-up, tr.hide-for-xxlarge-only, tr.hide-for-xxlarge-up {
+    display: table-row !important; }
+
+  th.hide-for-small-only, td.hide-for-small-only, th.show-for-small-up, td.show-for-small-up, th.hide-for-small, td.hide-for-small, th.hide-for-small-down, td.hide-for-small-down, th.hide-for-medium-only, td.hide-for-medium-only, th.show-for-medium-up, td.show-for-medium-up, th.hide-for-medium, td.hide-for-medium, th.hide-for-medium-down, td.hide-for-medium-down, th.show-for-large-only, td.show-for-large-only, th.show-for-large-up, td.show-for-large-up, th.show-for-large, td.show-for-large, th.show-for-large-down, td.show-for-large-down, th.hide-for-xlarge-only, td.hide-for-xlarge-only, th.hide-for-xlarge-up, td.hide-for-xlarge-up, th.hide-for-xxlarge-only, td.hide-for-xxlarge-only, th.hide-for-xxlarge-up, td.hide-for-xxlarge-up {
+    display: table-cell !important; } }
+/* xlarge displays */
+@media only screen and (min-width: 90.063em) {
+  .hide-for-small-only, .show-for-small-up, .hide-for-small, .hide-for-small-down, .hide-for-medium-only, .show-for-medium-up, .hide-for-medium, .hide-for-medium-down, .hide-for-large-only, .show-for-large-up, .hide-for-large, .hide-for-large-down, .show-for-xlarge-only, .show-for-xlarge-up, .hide-for-xxlarge-only, .hide-for-xxlarge-up {
+    display: inherit !important; }
+
+  .show-for-small-only, .hide-for-small-up, .show-for-small, .show-for-small-down, .show-for-medium-only, .hide-for-medium-up, .show-for-medium, .show-for-medium-down, .show-for-large-only, .hide-for-large-up, .show-for-large, .show-for-large-down, .hide-for-xlarge-only, .hide-for-xlarge-up, .show-for-xxlarge-only, .show-for-xxlarge-up {
+    display: none !important; }
+
+  table.hide-for-small-only, table.show-for-small-up, table.hide-for-small, table.hide-for-small-down, table.hide-for-medium-only, table.show-for-medium-up, table.hide-for-medium, table.hide-for-medium-down, table.hide-for-large-only, table.show-for-large-up, table.hide-for-large, table.hide-for-large-down, table.show-for-xlarge-only, table.show-for-xlarge-up, table.hide-for-xxlarge-only, table.hide-for-xxlarge-up {
+    display: table; }
+
+  thead.hide-for-small-only, thead.show-for-small-up, thead.hide-for-small, thead.hide-for-small-down, thead.hide-for-medium-only, thead.show-for-medium-up, thead.hide-for-medium, thead.hide-for-medium-down, thead.hide-for-large-only, thead.show-for-large-up, thead.hide-for-large, thead.hide-for-large-down, thead.show-for-xlarge-only, thead.show-for-xlarge-up, thead.hide-for-xxlarge-only, thead.hide-for-xxlarge-up {
+    display: table-header-group !important; }
+
+  tbody.hide-for-small-only, tbody.show-for-small-up, tbody.hide-for-small, tbody.hide-for-small-down, tbody.hide-for-medium-only, tbody.show-for-medium-up, tbody.hide-for-medium, tbody.hide-for-medium-down, tbody.hide-for-large-only, tbody.show-for-large-up, tbody.hide-for-large, tbody.hide-for-large-down, tbody.show-for-xlarge-only, tbody.show-for-xlarge-up, tbody.hide-for-xxlarge-only, tbody.hide-for-xxlarge-up {
+    display: table-row-group !important; }
+
+  tr.hide-for-small-only, tr.show-for-small-up, tr.hide-for-small, tr.hide-for-small-down, tr.hide-for-medium-only, tr.show-for-medium-up, tr.hide-for-medium, tr.hide-for-medium-down, tr.hide-for-large-only, tr.show-for-large-up, tr.hide-for-large, tr.hide-for-large-down, tr.show-for-xlarge-only, tr.show-for-xlarge-up, tr.hide-for-xxlarge-only, tr.hide-for-xxlarge-up {
+    display: table-row !important; }
+
+  th.hide-for-small-only, td.hide-for-small-only, th.show-for-small-up, td.show-for-small-up, th.hide-for-small, td.hide-for-small, th.hide-for-small-down, td.hide-for-small-down, th.hide-for-medium-only, td.hide-for-medium-only, th.show-for-medium-up, td.show-for-medium-up, th.hide-for-medium, td.hide-for-medium, th.hide-for-medium-down, td.hide-for-medium-down, th.hide-for-large-only, td.hide-for-large-only, th.show-for-large-up, td.show-for-large-up, th.hide-for-large, td.hide-for-large, th.hide-for-large-down, td.hide-for-large-down, th.show-for-xlarge-only, td.show-for-xlarge-only, th.show-for-xlarge-up, td.show-for-xlarge-up, th.hide-for-xxlarge-only, td.hide-for-xxlarge-only, th.hide-for-xxlarge-up, td.hide-for-xxlarge-up {
+    display: table-cell !important; } }
+/* xxlarge displays */
+@media only screen and (min-width: 120.063em) {
+  .hide-for-small-only, .show-for-small-up, .hide-for-small, .hide-for-small-down, .hide-for-medium-only, .show-for-medium-up, .hide-for-medium, .hide-for-medium-down, .hide-for-large-only, .show-for-large-up, .hide-for-large, .hide-for-large-down, .hide-for-xlarge-only, .show-for-xlarge-up, .show-for-xxlarge-only, .show-for-xxlarge-up {
+    display: inherit !important; }
+
+  .show-for-small-only, .hide-for-small-up, .show-for-small, .show-for-small-down, .show-for-medium-only, .hide-for-medium-up, .show-for-medium, .show-for-medium-down, .show-for-large-only, .hide-for-large-up, .show-for-large, .show-for-large-down, .show-for-xlarge-only, .hide-for-xlarge-up, .hide-for-xxlarge-only, .hide-for-xxlarge-up {
+    display: none !important; }
+
+  table.hide-for-small-only, table.show-for-small-up, table.hide-for-small, table.hide-for-small-down, table.hide-for-medium-only, table.show-for-medium-up, table.hide-for-medium, table.hide-for-medium-down, table.hide-for-large-only, table.show-for-large-up, table.hide-for-large, table.hide-for-large-down, table.hide-for-xlarge-only, table.show-for-xlarge-up, table.show-for-xxlarge-only, table.show-for-xxlarge-up {
+    display: table; }
+
+  thead.hide-for-small-only, thead.show-for-small-up, thead.hide-for-small, thead.hide-for-small-down, thead.hide-for-medium-only, thead.show-for-medium-up, thead.hide-for-medium, thead.hide-for-medium-down, thead.hide-for-large-only, thead.show-for-large-up, thead.hide-for-large, thead.hide-for-large-down, thead.hide-for-xlarge-only, thead.show-for-xlarge-up, thead.show-for-xxlarge-only, thead.show-for-xxlarge-up {
+    display: table-header-group !important; }
+
+  tbody.hide-for-small-only, tbody.show-for-small-up, tbody.hide-for-small, tbody.hide-for-small-down, tbody.hide-for-medium-only, tbody.show-for-medium-up, tbody.hide-for-medium, tbody.hide-for-medium-down, tbody.hide-for-large-only, tbody.show-for-large-up, tbody.hide-for-large, tbody.hide-for-large-down, tbody.hide-for-xlarge-only, tbody.show-for-xlarge-up, tbody.show-for-xxlarge-only, tbody.show-for-xxlarge-up {
+    display: table-row-group !important; }
+
+  tr.hide-for-small-only, tr.show-for-small-up, tr.hide-for-small, tr.hide-for-small-down, tr.hide-for-medium-only, tr.show-for-medium-up, tr.hide-for-medium, tr.hide-for-medium-down, tr.hide-for-large-only, tr.show-for-large-up, tr.hide-for-large, tr.hide-for-large-down, tr.hide-for-xlarge-only, tr.show-for-xlarge-up, tr.show-for-xxlarge-only, tr.show-for-xxlarge-up {
+    display: table-row !important; }
+
+  th.hide-for-small-only, td.hide-for-small-only, th.show-for-small-up, td.show-for-small-up, th.hide-for-small, td.hide-for-small, th.hide-for-small-down, td.hide-for-small-down, th.hide-for-medium-only, td.hide-for-medium-only, th.show-for-medium-up, td.show-for-medium-up, th.hide-for-medium, td.hide-for-medium, th.hide-for-medium-down, td.hide-for-medium-down, th.hide-for-large-only, td.hide-for-large-only, th.show-for-large-up, td.show-for-large-up, th.hide-for-large, td.hide-for-large, th.hide-for-large-down, td.hide-for-large-down, th.hide-for-xlarge-only, td.hide-for-xlarge-only, th.show-for-xlarge-up, td.show-for-xlarge-up, th.show-for-xxlarge-only, td.show-for-xxlarge-only, th.show-for-xxlarge-up, td.show-for-xxlarge-up {
+    display: table-cell !important; } }
+/* Orientation targeting */
+.show-for-landscape,
+.hide-for-portrait {
+  display: inherit !important; }
+
+.hide-for-landscape,
+.show-for-portrait {
+  display: none !important; }
+
+/* Specific visibility for tables */
+table.hide-for-landscape, table.show-for-portrait {
+  display: table; }
+
+thead.hide-for-landscape, thead.show-for-portrait {
+  display: table-header-group !important; }
+
+tbody.hide-for-landscape, tbody.show-for-portrait {
+  display: table-row-group !important; }
+
+tr.hide-for-landscape, tr.show-for-portrait {
+  display: table-row !important; }
+
+td.hide-for-landscape, td.show-for-portrait,
+th.hide-for-landscape,
+th.show-for-portrait {
+  display: table-cell !important; }
+
+@media only screen and (orientation: landscape) {
+  .show-for-landscape,
+  .hide-for-portrait {
+    display: inherit !important; }
+
+  .hide-for-landscape,
+  .show-for-portrait {
+    display: none !important; }
+
+  /* Specific visibility for tables */
+  table.show-for-landscape, table.hide-for-portrait {
+    display: table; }
+
+  thead.show-for-landscape, thead.hide-for-portrait {
+    display: table-header-group !important; }
+
+  tbody.show-for-landscape, tbody.hide-for-portrait {
+    display: table-row-group !important; }
+
+  tr.show-for-landscape, tr.hide-for-portrait {
+    display: table-row !important; }
+
+  td.show-for-landscape, td.hide-for-portrait,
+  th.show-for-landscape,
+  th.hide-for-portrait {
+    display: table-cell !important; } }
+@media only screen and (orientation: portrait) {
+  .show-for-portrait,
+  .hide-for-landscape {
+    display: inherit !important; }
+
+  .hide-for-portrait,
+  .show-for-landscape {
+    display: none !important; }
+
+  /* Specific visibility for tables */
+  table.show-for-portrait, table.hide-for-landscape {
+    display: table; }
+
+  thead.show-for-portrait, thead.hide-for-landscape {
+    display: table-header-group !important; }
+
+  tbody.show-for-portrait, tbody.hide-for-landscape {
+    display: table-row-group !important; }
+
+  tr.show-for-portrait, tr.hide-for-landscape {
+    display: table-row !important; }
+
+  td.show-for-portrait, td.hide-for-landscape,
+  th.show-for-portrait,
+  th.hide-for-landscape {
+    display: table-cell !important; } }
+/* Touch-enabled device targeting */
+.show-for-touch {
+  display: none !important; }
+
+.hide-for-touch {
+  display: inherit !important; }
+
+.touch .show-for-touch {
+  display: inherit !important; }
+
+.touch .hide-for-touch {
+  display: none !important; }
+
+/* Specific visibility for tables */
+table.hide-for-touch {
+  display: table; }
+
+.touch table.show-for-touch {
+  display: table; }
+
+thead.hide-for-touch {
+  display: table-header-group !important; }
+
+.touch thead.show-for-touch {
+  display: table-header-group !important; }
+
+tbody.hide-for-touch {
+  display: table-row-group !important; }
+
+.touch tbody.show-for-touch {
+  display: table-row-group !important; }
+
+tr.hide-for-touch {
+  display: table-row !important; }
+
+.touch tr.show-for-touch {
+  display: table-row !important; }
+
+td.hide-for-touch {
+  display: table-cell !important; }
+
+.touch td.show-for-touch {
+  display: table-cell !important; }
+
+th.hide-for-touch {
+  display: table-cell !important; }
+
+.touch th.show-for-touch {
+  display: table-cell !important; }

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
public/plugin/c3-0.7.20/docs/css/foundation.min.css


+ 3 - 0
public/plugin/c3-0.7.20/docs/css/gettingstarted.css

@@ -0,0 +1,3 @@
+#chart5_1 .c3-line-data2 {
+  stroke-width: 5px;
+}

+ 0 - 0
public/plugin/c3-0.7.20/docs/css/index.css


+ 423 - 0
public/plugin/c3-0.7.20/docs/css/normalize.css

@@ -0,0 +1,423 @@
+/*! normalize.css v3.0.0 | MIT License | git.io/normalize */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
+ *    user zoom.
+ */
+
+html {
+  font-family: sans-serif; /* 1 */
+  -ms-text-size-adjust: 100%; /* 2 */
+  -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+  margin: 0;
+}
+
+/* HTML5 display definitions
+   ========================================================================== */
+
+/**
+ * Correct `block` display not defined in IE 8/9.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+nav,
+section,
+summary {
+  display: block;
+}
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+
+audio,
+canvas,
+progress,
+video {
+  display: inline-block; /* 1 */
+  vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9.
+ * Hide the `template` element in IE, Safari, and Firefox < 22.
+ */
+
+[hidden],
+template {
+  display: none;
+}
+
+/* Links
+   ========================================================================== */
+
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+
+a {
+  background: transparent;
+}
+
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
+ */
+
+a:active,
+a:hover {
+  outline: 0;
+}
+
+/* Text-level semantics
+   ========================================================================== */
+
+/**
+ * Address styling not present in IE 8/9, Safari 5, and Chrome.
+ */
+
+abbr[title] {
+  border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
+ */
+
+b,
+strong {
+  font-weight: bold;
+}
+
+/**
+ * Address styling not present in Safari 5 and Chrome.
+ */
+
+dfn {
+  font-style: italic;
+}
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari 5, and Chrome.
+ */
+
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
+mark {
+  background: #ff0;
+  color: #000;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+  font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+
+sup {
+  top: -0.5em;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+/* Embedded content
+   ========================================================================== */
+
+/**
+ * Remove border when inside `a` element in IE 8/9.
+ */
+
+img {
+  border: 0;
+}
+
+/**
+ * Correct overflow displayed oddly in IE 9.
+ */
+
+svg:not(:root) {
+  overflow: hidden;
+}
+
+/* Grouping content
+   ========================================================================== */
+
+/**
+ * Address margin not present in IE 8/9 and Safari 5.
+ */
+
+figure {
+  margin: 1em 40px;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+  -moz-box-sizing: content-box;
+  box-sizing: content-box;
+  height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+  overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, monospace;
+  font-size: 1em;
+}
+
+/* Forms
+   ========================================================================== */
+
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+
+/**
+ * 1. Correct color not being inherited.
+ *    Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+  color: inherit; /* 1 */
+  font: inherit; /* 2 */
+  margin: 0; /* 3 */
+}
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10.
+ */
+
+button {
+  overflow: visible;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8+, and Opera
+ * Correct `select` style inheritance in Firefox.
+ */
+
+button,
+select {
+  text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ *    and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ *    `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+  -webkit-appearance: button; /* 2 */
+  cursor: pointer; /* 3 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+  cursor: default;
+}
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+  border: 0;
+  padding: 0;
+}
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+input {
+  line-height: normal;
+}
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+  box-sizing: border-box; /* 1 */
+  padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
+ *    (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+  -webkit-appearance: textfield; /* 1 */
+  -moz-box-sizing: content-box;
+  -webkit-box-sizing: content-box; /* 2 */
+  box-sizing: content-box;
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+  border: 1px solid #c0c0c0;
+  margin: 0 2px;
+  padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+  border: 0; /* 1 */
+  padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9.
+ */
+
+textarea {
+  overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+  font-weight: bold;
+}
+
+/* Tables
+   ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+
+td,
+th {
+  padding: 0;
+}

+ 21 - 0
public/plugin/c3-0.7.20/docs/css/reference.css

@@ -0,0 +1,21 @@
+section p {
+    margin-bottom: 0;
+}
+section h5 {
+    margin-top: 1rem;
+}
+section code {
+    padding-left: 0;
+}
+.sourcecode {
+    margin-bottom: 1.25rem;
+    padding: 6px 10px;
+    background-color: #f4f4f4;
+}
+.sourcecode pre {
+    padding: 0;
+    font-size: 1em;
+}
+.sourcecode pre code {
+    background-color: #f4f4f4;
+}

+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/api_axis_label.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/api_axis_range.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/api_data_color.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/api_data_name.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/api_flow.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/api_grid_x.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/api_resize.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_label.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_label_position.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_rotated.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_x_localtime.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_x_tick_count.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_x_tick_culling.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_x_tick_fit.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_x_tick_format.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_x_tick_rotate.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_x_tick_values.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_y2.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_y_padding.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_y_range.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/axes_y_tick_format.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/categorized.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/chart_area.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/chart_area_stacked.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/chart_bar.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/chart_bar_negative.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/chart_bar_stacked.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/chart_combination.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/chart_donut.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/chart_gauge.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/chart_pie.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/chart_scatter.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/chart_spline.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/chart_stanford.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/chart_step.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/data_color.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/data_columned.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/data_json.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/data_label.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/data_label_format.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/data_load.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/data_name.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/data_order.css


+ 0 - 0
public/plugin/c3-0.7.20/docs/css/samples/data_rowed.css


Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff