Browse Source

Merge remote-tracking branch 'upstream/master' into feature/multi-arc-gauge

# Conflicts:
#	src/arc.js
#	src/data.js
pull/1355/head
Gökhan Özen 8 years ago
parent
commit
013f0666a7
  1. 7
      .bmp.yml
  2. 3
      .editorconfig
  3. 4
      .gitignore
  4. 16
      .jshintrc
  5. 24
      .travis.yml
  6. 44
      CONTRIBUTING.md
  7. 114
      Gruntfile.coffee
  8. 20
      README.md
  9. 4
      bower.json
  10. 12
      c3.css
  11. 14841
      c3.js
  12. 2
      c3.min.css
  13. 6
      c3.min.js
  14. 9
      circle.yml
  15. 7
      codecov.yml
  16. 4
      component.json
  17. 6
      htdocs/index.html
  18. 3
      htdocs/samples/chart_gauge.html
  19. 32
      htdocs/samples/different_category_datasets.html
  20. 27
      htdocs/samples/point_show.html
  21. 27
      karma.conf.js
  22. 4388
      package-lock.json
  23. 60
      package.json
  24. 7
      spec/api.axis-spec.js
  25. 53
      spec/api.data-spec.js
  26. 3
      spec/api.focus-spec.js
  27. 7
      spec/api.grid-spec.js
  28. 6
      spec/api.load-spec.js
  29. 247
      spec/api.region-spec.js
  30. 76
      spec/api.zoom-spec.js
  31. 186
      spec/arc-spec.js
  32. 495
      spec/axis-spec.js
  33. 19
      spec/c3-helper.js
  34. 88
      spec/core-spec.js
  35. 1361
      spec/data-spec.js
  36. 164
      spec/domain-spec.js
  37. 301
      spec/grid-spec.js
  38. 90
      spec/interaction-spec.js
  39. 213
      spec/legend-spec.js
  40. 16
      spec/shape.bar-spec.js
  41. 183
      spec/shape.line-spec.js
  42. 50
      spec/svg-helper.js
  43. 362
      spec/tooltip-spec.js
  44. 88
      spec/type-spec.js
  45. 3
      src/api.axis.js
  46. 2
      src/api.category.js
  47. 2
      src/api.chart.js
  48. 2
      src/api.color.js
  49. 2
      src/api.data.js
  50. 6
      src/api.flow.js
  51. 3
      src/api.focus.js
  52. 2
      src/api.grid.js
  53. 3
      src/api.group.js
  54. 2
      src/api.legend.js
  55. 6
      src/api.load.js
  56. 3
      src/api.region.js
  57. 4
      src/api.selection.js
  58. 2
      src/api.show.js
  59. 3
      src/api.tooltip.js
  60. 2
      src/api.transform.js
  61. 2
      src/api.x.js
  62. 3
      src/api.zoom.js
  63. 55
      src/arc.js
  64. 30
      src/axis.js
  65. 2
      src/c3.axis.js
  66. 2
      src/cache.js
  67. 2
      src/category.js
  68. 101
      src/class-utils.js
  69. 100
      src/class.js
  70. 2
      src/clip.js
  71. 3
      src/color.js
  72. 14
      src/config.js
  73. 46
      src/core.js
  74. 57
      src/data.convert.js
  75. 26
      src/data.js
  76. 5
      src/data.load.js
  77. 3
      src/domain.js
  78. 4
      src/drag.js
  79. 3
      src/format.js
  80. 4
      src/grid.js
  81. 4
      src/head.js
  82. 58
      src/index.js
  83. 3
      src/interaction.js
  84. 4
      src/legend.js
  85. 849
      src/polyfill.js
  86. 15
      src/region.js
  87. 2
      src/scale.js
  88. 15
      src/selection.js
  89. 6
      src/shape.bar.js
  90. 4
      src/shape.js
  91. 16
      src/shape.line.js
  92. 14
      src/size.js
  93. 10
      src/subchart.js
  94. 9
      src/tail.js
  95. 3
      src/text.js
  96. 2
      src/title.js
  97. 100
      src/tooltip.js
  98. 3
      src/type.js
  99. 2
      src/ua.js
  100. 98
      src/util.js
  101. Some files were not shown because too many files have changed in this diff Show More

7
.bmp.yml

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

3
.editorconfig

@ -8,3 +8,6 @@ end_of_line = lf
charset = utf-8 charset = utf-8
trim_trailing_whitespace = true trim_trailing_whitespace = true
insert_final_newline = true insert_final_newline = true
[*.yml]
indent_size = 2

4
.gitignore vendored

@ -6,3 +6,7 @@ d3.min.js
components components
build build
.sass-cache .sass-cache
.idea/
# coverage report
/coverage

16
.jshintrc

@ -1,15 +1,14 @@
{ {
"bitwise": true, "esversion": 6,
"eqeqeq": true, "eqeqeq": true,
"curly": true, "curly": true,
"strict": true, "strict": false,
"trailing": true, "trailing": true,
"white": true, "white": true,
"maxlen": 210, "maxlen": 210,
"undef": true, "undef": true,
"unused": true, "unused": true,
"indent": 4, "indent": 4,
"eqnull": true, "eqnull": true,
"expr": true, "expr": true,
"newcap": false, "newcap": false,
@ -17,15 +16,10 @@
"bitwise": false, "bitwise": false,
"browser": true, "browser": true,
"jasmine": true,
"globals": { "globals": {
"jasmine": false, "d3": false,
"describe": false, "require": false
"beforeEach": false,
"beforeAll": false,
"it": false,
"expect": false,
"d3": false
} }
} }

24
.travis.yml

@ -1,5 +1,25 @@
language: node_js language: node_js
node_js:
- 6
dist: trusty
sudo: false
addons:
apt:
packages:
- google-chrome-stable
before_script: before_script:
- npm install -g grunt-cli - export DISPLAY=:99.0
- gem install sass - sh -e /etc/init.d/xvfb start &
- sleep 3
after_success:
- npm run codecov
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/b90b361c0bc91a778bcc
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: never # options: [always|never|change] default: always

44
CONTRIBUTING.md

@ -0,0 +1,44 @@
## 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.
## 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

114
Gruntfile.coffee

@ -1,114 +0,0 @@
module.exports = (grunt) ->
require('load-grunt-tasks') grunt, pattern: ['grunt-contrib-*', 'grunt-sass']
grunt.initConfig
watch:
concat:
tasks: 'concat'
files: ['src/*.js']
sass:
tasks: 'sass'
files: ['src/scss/*.scss']
concat:
dist:
options:
process: (src, filepath) ->
if filepath != 'src/head.js' && filepath != 'src/tail.js'
lines = []
src.split('\n').forEach (line) ->
lines.push( (if line.length > 0 then ' ' else '') + line)
src = lines.join('\n')
return src
src: [
'src/head.js',
'src/core.js',
'src/config.js',
'src/scale.js',
'src/domain.js',
'src/data.js',
'src/data.convert.js',
'src/data.load.js',
'src/category.js',
'src/interaction.js',
'src/size.js',
'src/shape.js',
'src/shape.line.js',
'src/shape.bar.js',
'src/text.js',
'src/type.js',
'src/grid.js',
'src/tooltip.js',
'src/legend.js',
'src/title.js',
'src/axis.js',
'src/clip.js',
'src/arc.js',
'src/region.js',
'src/drag.js',
'src/selection.js',
'src/subchart.js',
'src/zoom.js',
'src/color.js',
'src/format.js',
'src/cache.js',
'src/class.js',
'src/util.js',
'src/api.focus.js',
'src/api.show.js',
'src/api.zoom.js',
'src/api.load.js',
'src/api.flow.js',
'src/api.selection.js',
'src/api.transform.js',
'src/api.group.js',
'src/api.grid.js',
'src/api.region.js',
'src/api.data.js',
'src/api.category.js',
'src/api.color.js',
'src/api.x.js',
'src/api.axis.js',
'src/api.legend.js',
'src/api.chart.js',
'src/api.tooltip.js',
'src/c3.axis.js',
'src/ua.js',
'src/polyfill.js',
'src/tail.js'
]
dest: 'c3.js'
jshint:
c3: 'c3.js'
spec: 'spec/*.js'
options:
jshintrc: '.jshintrc'
jasmine:
c3:
src: 'c3.js'
options:
specs: 'spec/*-spec.js'
helpers: 'spec/*-helper.js'
styles: 'c3.css'
vendor: 'https://rawgit.com/mbostock/d3/v3.5.0/d3.min.js'
uglify:
c3:
files:
'c3.min.js': 'c3.js'
cssmin:
c3:
src: 'c3.css'
dest: 'c3.min.css'
sass:
options:
sourcemap: 'none'
c3:
files:
'c3.css': 'src/scss/main.scss'
grunt.registerTask 'default', ['concat', 'jshint', 'jasmine', 'sass', 'cssmin', 'uglify']

20
README.md

@ -1,4 +1,4 @@
c3 [![Build Status](https://travis-ci.org/masayuki0812/c3.svg?branch=master)](https://travis-ci.org/masayuki0812/c3) [![Dependency Status](https://david-dm.org/masayuki0812/c3.svg)](https://david-dm.org/masayuki0812/c3) [![devDependency Status](https://david-dm.org/masayuki0812/c3/dev-status.svg)](https://david-dm.org/masayuki0812/c3#info=devDependencies) [![license](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](https://github.com/masayuki0812/c3/blob/master/LICENSE) c3 [![Build Status](https://travis-ci.org/c3js/c3.svg?branch=master)](https://travis-ci.org/c3js/c3) [![Dependency Status](https://david-dm.org/c3js/c3.svg)](https://david-dm.org/c3js/c3) [![devDependency Status](https://david-dm.org/c3js/c3/dev-status.svg)](https://david-dm.org/c3js/c3#info=devDependencies) [![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)
== ==
c3 is a D3-based reusable chart library that enables deeper integration of charts into web applications. c3 is a D3-based reusable chart library that enables deeper integration of charts into web applications.
@ -11,25 +11,25 @@ Follow the link for more information: [http://c3js.org](http://c3js.org/)
+ [Examples](http://c3js.org/examples.html) + [Examples](http://c3js.org/examples.html)
Additional samples can be found in this repository: Additional samples can be found in this repository:
+ [https://github.com/masayuki0812/c3/tree/master/htdocs/samples](https://github.com/masayuki0812/c3/tree/master/htdocs/samples) + [https://github.com/c3js/c3/tree/master/htdocs/samples](https://github.com/c3js/c3/tree/master/htdocs/samples)
You can run these samples as: You can run these samples as:
``` ```
$ cd c3/htdocs $ npm run serve
$ python -m SimpleHTTPServer 8080
``` ```
## Google Group ## 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). 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 ## Gitter
[![Join the chat at https://gitter.im/masayuki0812/c3](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/masayuki0812/c3?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![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 ## Using the issue queue
The [issue queue](https://github.com/masayuki0812/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! 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: Before reporting an issue, please do the following:
1. [Search for existing issues](https://github.com/masayuki0812/c3/issues) to ensure you're not posting a duplicate.
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. [Search the Google Group](https://groups.google.com/forum/#!forum/c3js) to ensure it hasn't been addressed there already.
@ -39,16 +39,14 @@ Before reporting an issue, please do the following:
## Pull requests ## Pull requests
Pull requests are welcome, though please post an issue first to see whether such a change is desirable. 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! 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 ## Playground
Please fork this fiddle: Please fork this fiddle:
+ [http://jsfiddle.net/masayuki0812/7kYJu/](http://jsfiddle.net/masayuki0812/7kYJu/) + [http://jsfiddle.net/masayuki0812/7kYJu/](http://jsfiddle.net/masayuki0812/7kYJu/)
## Dependency ## Dependency
+ [D3.js](https://github.com/mbostock/d3) `<=3.5.0` + [D3.js](https://github.com/mbostock/d3) `~3.5.0`
## License ## License
MIT MIT
[![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=masayuki0812&url=https://github.com/masayuki0812/c3&title=c3&language=javascript&tags=github&category=software)

4
bower.json

@ -20,12 +20,12 @@
"bower_components", "bower_components",
"htdocs", "htdocs",
"spec", "spec",
"src", "src/**/*.js",
"package.json", "package.json",
"component.json", "component.json",
"Gruntfile.*" "Gruntfile.*"
], ],
"dependencies": { "dependencies": {
"d3": "<=3.5.0" "d3": "~3.5.0"
} }
} }

12
c3.css

@ -1,7 +1,7 @@
/*-- Chart --*/ /*-- Chart --*/
.c3 svg { .c3 svg {
font: 10px sans-serif; font: 10px sans-serif;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); } -webkit-tap-highlight-color: transparent; }
.c3 path, .c3 line { .c3 path, .c3 line {
fill: none; fill: none;
@ -12,7 +12,11 @@
-moz-user-select: none; -moz-user-select: none;
user-select: none; } user-select: none; }
.c3-legend-item-tile, .c3-xgrid-focus, .c3-ygrid, .c3-event-rect, .c3-bars path { .c3-legend-item-tile,
.c3-xgrid-focus,
.c3-ygrid,
.c3-event-rect,
.c3-bars path {
shape-rendering: crispEdges; } shape-rendering: crispEdges; }
.c3-chart-arc path { .c3-chart-arc path {
@ -71,11 +75,11 @@
/*-- Region --*/ /*-- Region --*/
.c3-region { .c3-region {
fill: steelblue; fill: steelblue;
fill-opacity: 0.1; } fill-opacity: .1; }
/*-- Brush --*/ /*-- Brush --*/
.c3-brush .extent { .c3-brush .extent {
fill-opacity: 0.1; } fill-opacity: .1; }
/*-- Select - Drag --*/ /*-- Select - Drag --*/
/*-- Legend --*/ /*-- Legend --*/

14841
c3.js

File diff suppressed because it is too large Load Diff

2
c3.min.css vendored

@ -1 +1 @@
.c3 svg{font:10px sans-serif;-webkit-tap-highlight-color:transparent}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:gray;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:.75}.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:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-title{font:14px sans-serif}.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 #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777;opacity:.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 td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max,.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000} .c3 svg{font:10px sans-serif;-webkit-tap-highlight-color:transparent}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:grey;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:.75}.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:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-title{font:14px sans-serif}.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 #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777;opacity:.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 td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.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}

6
c3.min.js vendored

File diff suppressed because one or more lines are too long

9
circle.yml

@ -0,0 +1,9 @@
machine:
node:
verison: 6
dependencies:
pre:
- curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
- sudo dpkg -i google-chrome.deb
- sudo sed -i 's|HERE/chrome\"|HERE/chrome\" --disable-setuid-sandbox|g' /opt/google/chrome/google-chrome
- rm google-chrome.deb

7
codecov.yml

@ -0,0 +1,7 @@
coverage:
status:
project:
default:
threshold: 0.4
patch: no
change: no

4
component.json

@ -2,10 +2,10 @@
"name": "c3", "name": "c3",
"repo": "masayuki0812/c3", "repo": "masayuki0812/c3",
"description": "A D3-based reusable chart library", "description": "A D3-based reusable chart library",
"version": "0.4.11-rc4", "version": "0.4.13",
"keywords": [], "keywords": [],
"dependencies": { "dependencies": {
"mbostock/d3": "v3.5.0" "mbostock/d3": "v3.5.6"
}, },
"development": {}, "development": {},
"license": "MIT", "license": "MIT",

6
htdocs/index.html

@ -119,6 +119,9 @@
<a href="./samples/custom_x_categorized.html"> <a href="./samples/custom_x_categorized.html">
Chart with category data on category axis Chart with category data on category axis
</a> </a>
<a href="./samples/different_category_datasets.html">
Chart with different category datasets
</a>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<h3>Additional Axis</h3> <h3>Additional Axis</h3>
@ -330,6 +333,9 @@
<a href="./samples/point_r.html"> <a href="./samples/point_r.html">
Change radius of data point Change radius of data point
</a> </a>
<a href="./samples/point_show.html">
Show points based on condition
</a>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<h3>Bar</h3> <h3>Bar</h3>

3
htdocs/samples/chart_gauge.html

@ -26,6 +26,9 @@
// format: function(value, ratio) { // format: function(value, ratio) {
// return value; // return value;
// }, // },
// extents: function (value, isMax) {
// return value + '%';
// },
// show: false // to turn off the min/max labels. // show: false // to turn off the min/max labels.
}, },
// min: 0, // 0 is default, //can handle negative min e.g. vacuum / voltage / current flow / rate of change // min: 0, // 0 is default, //can handle negative min e.g. vacuum / voltage / current flow / rate of change

32
htdocs/samples/different_category_datasets.html

@ -0,0 +1,32 @@
<html>
<head>
<link href="/css/c3.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="chart"></div>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="/js/c3.min.js"></script>
<script>
var chart = c3.generate({
data: {
xs: {
data1: "cat1",
data2: "cat2",
},
columns: [
["cat1", "a", "b", "c", "d"],
["data1", 30, 200, 100, 400],
["cat2", "b", "a", "c", "d", "e", "f"],
["data2", 400, 60, 200, 800, 10, 10]
]
},
axis: {
x: {
type: "category"
}
}
});
</script>
</body>
</html>

27
htdocs/samples/point_show.html

@ -0,0 +1,27 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="/css/c3.css">
</head>
<body>
<div id="chart"></div>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="/js/c3.min.js"></script>
<script>
var chart = c3.generate({
bindto: '#chart',
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 300, 200, 600, 250, 150]
]
},
point: {
show: function(d) {
return d.value > 200;
}
}
});
</script>
</body>
</html>

27
karma.conf.js

@ -0,0 +1,27 @@
const path = require('path');
module.exports = function(config) {
config.set({
frameworks: ['jasmine', 'browserify'],
files: [
'c3.css',
'spec/*-helper.js',
'spec/*-spec.js'
],
preprocessors: {
'spec/c3-helper.js': ['browserify']
},
browserify: {
debug: true,
transform: [['babelify', { presets: ['es2015'], plugins: ['istanbul'] }]]
},
reporters: ['spec', 'coverage-istanbul'],
coverageIstanbulReporter: {
reports: ['html', 'lcovonly', 'text-summary']
},
autoWatch: true,
browsers: ['Chrome'],
singleRun: true,
browserNoActivityTimeout: 120000,
})
};

4388
package-lock.json generated

File diff suppressed because it is too large Load Diff

60
package.json

@ -1,36 +1,68 @@
{ {
"name": "c3", "name": "c3",
"version": "0.4.11-rc4", "version": "0.4.13",
"description": "D3-based reusable chart library", "description": "D3-based reusable chart library",
"main": "c3.js", "main": "c3.js",
"scripts": { "scripts": {
"test": "grunt" "serve": "static -p 8080 htdocs/",
"prepublish": "npm run dist",
"lint": "jshint --reporter=node_modules/jshint-stylish src/ spec/",
"build": "npm run build:js && npm run build:css",
"build:js": "npm run build:js:rollup && npm run build:js:uglify",
"build:js:rollup": "rollup -f umd --name c3 --globals d3:d3 src/index.js > c3.js",
"build:js:uglify": "uglifyjs c3.js --compress --mangle -o c3.min.js",
"build:css": "npm run build:css:sass && npm run build:css:min",
"build:css:sass": "node-sass src/scss/main.scss > c3.css",
"build:css:min": "cleancss -o c3.min.css c3.css",
"test": "npm run build && npm run lint && karma start karma.conf.js",
"dist": "npm run build",
"codecov": "codecov"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://github.com/masayuki0812/c3.git" "url": "git://github.com/c3js/c3.git"
}, },
"keywords": [ "keywords": [
"d3", "d3",
"chart", "chart",
"graph" "graph"
], ],
"author": "Masayuki Tanaka", "authors": [
"Masayuki Tanaka",
"Ændrew Rininsland",
"Yoshiya Hinosawa"
],
"license": "MIT", "license": "MIT",
"gitHead": "84e03109d9a590f9c8ef687c03d751f666080c6f", "gitHead": "84e03109d9a590f9c8ef687c03d751f666080c6f",
"readmeFilename": "README.md", "readmeFilename": "README.md",
"dependencies": { "dependencies": {
"d3": "<=3.5.0" "d3": "~3.5.0"
}, },
"devDependencies": { "devDependencies": {
"grunt": "^0.4.5", "babel-plugin-istanbul": "^4.1.4",
"grunt-contrib-concat": "~0.5.0", "babel-preset-es2015": "^6.24.1",
"grunt-contrib-cssmin": "^0.10.0", "babelify": "^7.3.0",
"grunt-contrib-jasmine": "~0.8.0", "browserify": "^14.4.0",
"grunt-contrib-jshint": "~0.10.0", "clean-css-cli": "^4.1.3",
"grunt-contrib-uglify": "~0.4.0", "codecov": "^2.2.0",
"grunt-contrib-watch": "^0.6.1", "jasmine-core": "^2.3.4",
"grunt-sass": "^0.17.0", "jshint": "^2.9.4",
"load-grunt-tasks": "~0.2.0" "jshint-stylish": "^2.1.0",
"karma": "^1.7.0",
"karma-browserify": "^5.1.1",
"karma-chrome-launcher": "^2.1.1",
"karma-coverage-istanbul-reporter": "^1.3.0",
"karma-jasmine": "^1.1.0",
"karma-spec-reporter": "0.0.31",
"node-sass": "^4.5.3",
"node-static": "^0.7.9",
"rollup": "^0.41.6",
"uglify-js": "^3.0.15",
"watchify": "^3.9.0"
},
"nyc": {
"exclude": [
"src/polyfill.js"
]
} }
} }

7
spec/api.axis-spec.js

@ -9,7 +9,7 @@ describe('c3 api axis', function () {
describe('axis.labels', function () { describe('axis.labels', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -31,10 +31,9 @@ describe('c3 api axis', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('should update y axis label', function () { it('updates y axis label', function () {
chart.axis.labels({y: 'New Y Axis Label'}); chart.axis.labels({y: 'New Y Axis Label'});
var label = d3.select('.c3-axis-y-label'); var label = d3.select('.c3-axis-y-label');
expect(label.text()).toBe('New Y Axis Label'); expect(label.text()).toBe('New Y Axis Label');
@ -42,7 +41,7 @@ describe('c3 api axis', function () {
expect(label.attr('dy')).toBe('1.2em'); expect(label.attr('dy')).toBe('1.2em');
}); });
it('should update y axis label', function () { it('updates y axis label', function () {
chart.axis.labels({y2: 'New Y2 Axis Label'}); chart.axis.labels({y2: 'New Y2 Axis Label'});
var label = d3.select('.c3-axis-y2-label'); var label = d3.select('.c3-axis-y2-label');
expect(label.text()).toBe('New Y2 Axis Label'); expect(label.text()).toBe('New Y2 Axis Label');

53
spec/api.data-spec.js

@ -30,6 +30,7 @@ describe('c3 api data', function () {
}; };
beforeEach(function (done) { beforeEach(function (done) {
jasmine.addMatchers(customMatchers);
chart = window.initChart(chart, args, done); chart = window.initChart(chart, args, done);
}); });
@ -116,8 +117,8 @@ describe('c3 api data', function () {
it('should return data.colors specified as argument', function () { it('should return data.colors specified as argument', function () {
var results = chart.data.colors(); var results = chart.data.colors();
expect(results.data1).toBe('#FF0000'); expect(results.data1).toBeHexOrRGB('#FF0000');
expect(results.data2).toBe('#00FF00'); expect(results.data2).toBeHexOrRGB('#00FF00');
}); });
it('should return data.colors specified as api', function () { it('should return data.colors specified as api', function () {
@ -125,15 +126,15 @@ describe('c3 api data', function () {
data1: '#00FF00', data1: '#00FF00',
data2: '#FF0000' data2: '#FF0000'
}); });
expect(results.data1).toBe('#00FF00'); expect(results.data1).toBeHexOrRGB('#00FF00');
expect(results.data2).toBe('#FF0000'); expect(results.data2).toBeHexOrRGB('#FF0000');
}); });
it('should set data.colors specified as api', function () { it('should set data.colors specified as api', function () {
expect(d3.select('.c3-line-data1').style('stroke')).toBe("#00ff00"); expect(d3.select('.c3-line-data1').style('stroke')).toBeHexOrRGB("#00ff00");
expect(d3.select('.c3-line-data2').style('stroke')).toBe("#ff0000"); expect(d3.select('.c3-line-data2').style('stroke')).toBeHexOrRGB("#ff0000");
expect(d3.select('.c3-legend-item-data1 .c3-legend-item-tile').style('stroke')).toBe("#00ff00"); expect(d3.select('.c3-legend-item-data1 .c3-legend-item-tile').style('stroke')).toBeHexOrRGB("#00ff00");
expect(d3.select('.c3-legend-item-data2 .c3-legend-item-tile').style('stroke')).toBe("#ff0000"); expect(d3.select('.c3-legend-item-data2 .c3-legend-item-tile').style('stroke')).toBeHexOrRGB("#ff0000");
}); });
}); });
@ -162,3 +163,39 @@ describe('c3 api data', function () {
}); });
}); });
var customMatchers = {
toBeHexOrRGB: function(util, customEqualityTesters) {
'use strict';
function rgb2hex(rgb){
rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
return (rgb && rgb.length === 4) ? "#" +
("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[3],10).toString(16)).slice(-2) : '';
}
return {
compare: function(actual, expected){
if (expected === undefined) {
expected = '';
}
var result = {};
actual = actual.match('rgb') ? rgb2hex(actual) : actual;
expected = expected.match('rgb') ? rgb2hex(expected) : expected;
result.pass = util.equals(actual, expected, customEqualityTesters);
if (result.pass) {
result.message = "Expected " + actual + " not to be quite so goofy";
} else {
result.message = "Expected " + actual + " to be goofy, but it was not very goofy";
}
return result;
}
};
}
};

3
spec/api.focus-spec.js

@ -378,11 +378,10 @@ describe('c3 api focus', function () {
describe('when legend.show = false', function () { describe('when legend.show = false', function () {
it('should update args to hide legend', function () { beforeAll(function () {
args.legend = { args.legend = {
show: false show: false
}; };
expect(true).toBeTruthy();
}); });
it('should focus all targets without showing legend', function (done) { it('should focus all targets without showing legend', function (done) {

7
spec/api.grid-spec.js

@ -9,7 +9,7 @@ describe('c3 api grid', function () {
describe('ygrid.add and ygrid.remove', function () { describe('ygrid.add and ygrid.remove', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -17,10 +17,9 @@ describe('c3 api grid', function () {
] ]
} }
}; };
expect(true).toBeTruthy();
}); });
it('should update y grids', function (done) { it('updates y grids', function (done) {
var main = chart.internal.main, var main = chart.internal.main,
expectedGrids = [ expectedGrids = [
{ {
@ -62,7 +61,7 @@ describe('c3 api grid', function () {
}, 1200); }, 1200);
}); });
it("should update x ygrids even if it's zoomed", function (done) { it('updates x ygrids even if zoomed', function (done) {
var main = chart.internal.main, var main = chart.internal.main,
expectedGrids = [ expectedGrids = [
{ {

6
spec/api.load-spec.js

@ -11,7 +11,7 @@ describe('c3 api load', function () {
describe('as column', function () { describe('as column', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -20,7 +20,6 @@ describe('c3 api load', function () {
] ]
} }
}; };
expect(true).toBeTruthy();
}); });
it('should load additional data', function (done) { it('should load additional data', function (done) {
@ -46,7 +45,7 @@ describe('c3 api load', function () {
describe('category data', function () { describe('category data', function () {
it('should update arg to category data', function () { beforeAll(function () {
args = { args = {
data: { data: {
x: 'x', x: 'x',
@ -62,7 +61,6 @@ describe('c3 api load', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
describe('as column', function () { describe('as column', function () {

247
spec/api.region-spec.js

@ -0,0 +1,247 @@
describe('c3 api region', function () {
'use strict';
var chart, args;
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('api.region', function () {
beforeAll(function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
]
},
regions: [
{
axis: 'y',
start: 300,
end: 400,
class: 'green',
},
{
axis: 'y',
start: 0,
end: 100,
class: 'green',
}
]
};
});
it('updates regions', function (done) {
var main = chart.internal.main,
expectedRegions = [
{
axis: 'y',
start: 250,
end: 350,
class: 'red'
},
{
axis: 'y',
start: 25,
end: 75,
class: 'red'
}
],
regions;
// Call regions API
chart.regions(expectedRegions);
setTimeout(function () {
regions = main.selectAll('.c3-region');
expect(regions.size()).toBe(expectedRegions.length);
regions.each(function (d, i) {
var region = d3.select(this),
rect = region.select('rect'),
y = +rect.attr('y'),
height = +rect.attr('height'),
expectedClass = 'red',
unexpectedClass = 'green',
expectedStart = Math.round(chart.internal.y(expectedRegions[i].start)),
expectedEnd = Math.round(chart.internal.y(expectedRegions[i].end)),
expectedY = expectedEnd,
expectedHeight = expectedStart - expectedEnd;
expect(y).toBeCloseTo(expectedY, -1);
expect(height).toBeCloseTo(expectedHeight, -1);
expect(region.classed(expectedClass)).toBeTruthy();
expect(region.classed(unexpectedClass)).toBeFalsy();
});
}, 500);
setTimeout(function () {
done();
}, 1000);
});
});
describe('api.region.add', function () {
beforeAll(function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
]
},
regions: [
{
axis: 'y',
start: 300,
end: 400,
class: 'green',
},
{
axis: 'y',
start: 0,
end: 100,
class: 'green',
}
]
};
});
it('should add regions', function (done) {
var main = chart.internal.main,
expectedRegions = [
{
axis: 'y',
start: 300,
end: 400,
class: 'green',
},
{
axis: 'y',
start: 0,
end: 100,
class: 'green',
},
{
axis: 'y',
start: 250,
end: 350,
class: 'red'
},
{
axis: 'y',
start: 25,
end: 75,
class: 'red'
}
],
expectedClasses = [
'green',
'green',
'red',
'red',
],
regions;
// Call regions API
chart.regions(expectedRegions);
setTimeout(function () {
regions = main.selectAll('.c3-region');
expect(regions.size()).toBe(expectedRegions.length);
regions.each(function (d, i) {
var region = d3.select(this),
rect = region.select('rect'),
y = +rect.attr('y'),
height = +rect.attr('height'),
expectedClass = expectedClasses[i],
expectedStart = Math.round(chart.internal.y(expectedRegions[i].start)),
expectedEnd = Math.round(chart.internal.y(expectedRegions[i].end)),
expectedY = expectedEnd,
expectedHeight = expectedStart - expectedEnd;
expect(y).toBeCloseTo(expectedY, -1);
expect(height).toBeCloseTo(expectedHeight, -1);
expect(region.classed(expectedClass)).toBeTruthy();
});
}, 500);
setTimeout(function () {
done();
}, 1000);
});
});
describe('api.region.remove', function () {
beforeAll(function () {
args = {
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
]
},
regions: [
{
axis: 'y',
start: 300,
end: 400,
class: 'green',
},
{
axis: 'y',
start: 0,
end: 100,
class: 'green',
},
{
axis: 'y',
start: 250,
end: 350,
class: 'red'
},
]
};
});
it('should remove regions', function (done) {
var main = chart.internal.main,
expectedRegions = [
{
axis: 'y',
start: 250,
end: 350,
class: 'red'
},
],
expectedClasses = ['red'],
regions;
// Call regions API
chart.regions(expectedRegions);
setTimeout(function () {
regions = main.selectAll('.c3-region');
expect(regions.size()).toBe(expectedRegions.length);
regions.each(function (d, i) {
var region = d3.select(this),
rect = region.select('rect'),
y = +rect.attr('y'),
height = +rect.attr('height'),
expectedClass = expectedClasses[i],
expectedStart = Math.round(chart.internal.y(expectedRegions[i].start)),
expectedEnd = Math.round(chart.internal.y(expectedRegions[i].end)),
expectedY = expectedEnd,
expectedHeight = expectedStart - expectedEnd;
expect(y).toBeCloseTo(expectedY, -1);
expect(height).toBeCloseTo(expectedHeight, -1);
expect(region.classed(expectedClass)).toBeTruthy();
});
}, 500);
setTimeout(function () {
done();
}, 1000);
});
});
});

76
spec/api.zoom-spec.js

@ -9,7 +9,7 @@ describe('c3 api zoom', function () {
describe('zoom', function () { describe('zoom', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -22,7 +22,6 @@ describe('c3 api zoom', function () {
enabled: true enabled: true
} }
}; };
expect(true).toBeTruthy();
}); });
it('should be zoomed properly', function () { it('should be zoomed properly', function () {
@ -41,48 +40,48 @@ describe('c3 api zoom', function () {
expect(domain[1]).toBe(target[1]); expect(domain[1]).toBe(target[1]);
}); });
it('should load timeseries data', function () { describe('with timeseries data', function () {
args = { beforeAll(function(){
data: { args = {
x: 'date', data: {
columns: [ x: 'date',
['date', '2014-01-01', '2014-01-02', '2014-08-01', '2014-10-19'], columns: [
['data1', 30, 200, 100, 400] ['date', '2014-01-01', '2014-01-02', '2014-08-01', '2014-10-19'],
] ['data1', 30, 200, 100, 400]
}, ]
axis: { },
x: { axis: {
type: 'timeseries' x: {
type: 'timeseries'
}
},
zoom: {
enabled: true
} }
}, };
zoom: { });
enabled: true
} it('should be zoomed properly', function () {
}; var target = [new Date(2014, 7, 1), new Date(2014, 8, 1)], domain;
expect(true).toBeTruthy(); chart.zoom(target);
domain = chart.internal.x.domain();
expect(+domain[0]).toBe(+target[0]);
expect(+domain[1]).toBe(+target[1]);
});
it('should be zoomed properly', function () {
var target = ['2014-08-01', '2014-09-01'], domain;
chart.zoom(target);
domain = chart.internal.x.domain();
expect(+domain[0]).toBe(+chart.internal.parseDate(target[0]));
expect(+domain[1]).toBe(+chart.internal.parseDate(target[1]));
});
}); });
it('should be zoomed properly', function () {
var target = [new Date(2014, 7, 1), new Date(2014, 8, 1)], domain;
chart.zoom(target);
domain = chart.internal.x.domain();
expect(+domain[0]).toBe(+target[0]);
expect(+domain[1]).toBe(+target[1]);
});
it('should be zoomed properly', function () {
var target = ['2014-08-01', '2014-09-01'], domain;
chart.zoom(target);
domain = chart.internal.x.domain();
expect(+domain[0]).toBe(+chart.internal.parseDate(target[0]));
expect(+domain[1]).toBe(+chart.internal.parseDate(target[1]));
});
}); });
describe('unzoom', function () { describe('unzoom', function () {
it('should load indexed data', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -93,7 +92,6 @@ describe('c3 api zoom', function () {
enabled: true enabled: true
} }
}; };
expect(true).toBeTruthy();
}); });
it('should be unzoomed properly', function () { it('should be unzoomed properly', function () {

186
spec/arc-spec.js

@ -9,7 +9,7 @@ describe('c3 chart arc', function () {
describe('show pie chart', function () { describe('show pie chart', function () {
it('should update args to have pie chart', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -20,7 +20,6 @@ describe('c3 chart arc', function () {
type: 'pie' type: 'pie'
} }
}; };
expect(true).toBeTruthy();
}); });
it('should have correct classes', function () { it('should have correct classes', function () {
@ -47,54 +46,153 @@ describe('c3 chart arc', function () {
expect(d3.select('.c3-arc-data3').attr('d')).toMatch(/M1\..+,211\..+A211\..+,211\..+ 0 0,1 -124\..+,-171\..+L0,0Z/); expect(d3.select('.c3-arc-data3').attr('d')).toMatch(/M1\..+,211\..+A211\..+,211\..+ 0 0,1 -124\..+,-171\..+L0,0Z/);
}); });
it('should set args with data id that can be converted to a color', function () { describe('with data id that can be converted to a color', function () {
args.data.columns = [ beforeAll(function(){
['black', 30], args.data.columns = [
['data2', 150], ['black', 30],
['data3', 120] ['data2', 150],
]; ['data3', 120]
expect(true).toBeTruthy(); ];
}); });
it('should have correct d even if data id can be converted to a color', function (done) { it('should have correct d even if data id can be converted to a color', function (done) {
setTimeout(function () { setTimeout(function () {
expect(d3.select('.c3-arc-black').attr('d')).toMatch(/M-124\..+,-171\..+A211\..+,211\..+ 0 0,1 -3\..+,-211\..+L0,0Z/); expect(d3.select('.c3-arc-black').attr('d')).toMatch(/M-124\..+,-171\..+A211\..+,211\..+ 0 0,1 -3\..+,-211\..+L0,0Z/);
done(); done();
}, 500); }, 500);
}); });
it('should update args to have empty pie chart', function () { describe('with empty pie chart', function(){
args = { beforeAll(function () {
data: { args = {
columns: [ data: {
['data1', null], columns: [
['data2', null], ['data1', null],
['data3', null] ['data2', null],
], ['data3', null]
type: 'pie' ],
} type: 'pie'
}; }
expect(true).toBeTruthy(); };
});
it('should have correct d attribute', function () {
var chartArc = d3.select('.c3-chart-arcs'),
arcs = {
data1: chartArc.select('.c3-chart-arc.c3-target.c3-target-data1')
.select('g.c3-shapes.c3-shapes-data1.c3-arcs.c3-arcs-data1')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data1'),
data2: chartArc.select('.c3-chart-arc.c3-target.c3-target-data2')
.select('g.c3-shapes.c3-shapes-data2.c3-arcs.c3-arcs-data2')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data2'),
data3: chartArc.select('.c3-chart-arc.c3-target.c3-target-data3')
.select('g.c3-shapes.c3-shapes-data3.c3-arcs.c3-arcs-data3')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data3')
};
expect(arcs.data1.attr('d').indexOf('NaN')).toBe(-1);
expect(arcs.data2.attr('d').indexOf('NaN')).toBe(-1);
expect(arcs.data3.attr('d').indexOf('NaN')).toBe(-1);
});
});
}); });
});
it('should have correct d attribute', function () { describe('show gauge', function () {
var chartArc = d3.select('.c3-chart-arcs'),
arcs = { describe('with a 180 degree gauge', function(){
data1: chartArc.select('.c3-chart-arc.c3-target.c3-target-data1') beforeAll(function () {
.select('g.c3-shapes.c3-shapes-data1.c3-arcs.c3-arcs-data1') args = {
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data1'), gauge: {
data2: chartArc.select('.c3-chart-arc.c3-target.c3-target-data2') width: 10,
.select('g.c3-shapes.c3-shapes-data2.c3-arcs.c3-arcs-data2') max: 10,
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data2'), expand: true
data3: chartArc.select('.c3-chart-arc.c3-target.c3-target-data3') },
.select('g.c3-shapes.c3-shapes-data3.c3-arcs.c3-arcs-data3') data: {
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data3') columns: [
}; ['data', 8]
expect(arcs.data1.attr('d').indexOf('NaN')).toBe(-1); ],
expect(arcs.data2.attr('d').indexOf('NaN')).toBe(-1); type: 'gauge'
expect(arcs.data3.attr('d').indexOf('NaN')).toBe(-1); }
};
});
it('should have correct d for Pi radian gauge', function () {
var chartArc = d3.select('.c3-chart-arcs'),
data = chartArc.select('.c3-chart-arc.c3-target.c3-target-data')
.select('g.c3-shapes.c3-shapes-data.c3-arcs.c3-arcs-data')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data');
expect(data.attr('d')).toMatch(/M-304,-3\..+A304,304 0 0,1 245\..+,-178\..+L237\..+,-172\..+A294,294 0 0,0 -294,-3\..+Z/);
});
}); });
describe('with a 2 Pi radian gauge that starts at Pi/2', function() {
beforeAll(function(){
args = {
gauge: {
width: 10,
max: 10,
expand: true,
fullCircle: true
},
data: {
columns: [
['data', 8]
],
type: 'gauge',
fullCircle: true,
startingAngle: Math.PI/2
}
};
});
it('should have correct d for 2 Pi radian gauge starting at Pi/2', function() {
var chartArc = d3.select('.c3-chart-arcs'),
data = chartArc.select('.c3-chart-arc.c3-target.c3-target-data')
.select('g.c3-shapes.c3-shapes-data.c3-arcs.c3-arcs-data')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data');
// This test has bee updated to make tests pass. @TODO double-check this test is accurate.
expect(data.attr('d')).toMatch(/M-221.*?,-2\..+A221.*?,221.*? 0 1,1 -68.*?,210.*?L-65.*?,201.*?A211.*?,211.*? 0 1,0 -211.*?,-2.*?Z/);
});
describe('with labels use custom text', function() {
beforeAll(function(){
args = {
gauge: {
width: 10,
max: 100,
expand: true,
label: {
extents: function (value, isMax) {
if (isMax) {
return 'Max: ' + value + '%';
}
return 'Min: ' + value + '%';
}
}
},
data: {
columns: [
['data', 8]
],
type: 'gauge',
fullCircle: true,
startingAngle: Math.PI/2
}
};
});
it('should show custom min/max guage labels', function () {
var chartArc = d3.select('.c3-chart-arcs'),
min = chartArc.select('.c3-chart-arcs-gauge-min'),
max = chartArc.select('.c3-chart-arcs-gauge-max');
expect(min.text()).toMatch('Min: 0%');
expect(max.text()).toMatch('Max: 100%');
});
});
});
}); });
}); });

495
spec/axis-spec.js

@ -33,64 +33,65 @@ describe('c3 chart axis', function () {
describe('axis.y.tick.count', function () { describe('axis.y.tick.count', function () {
it('should update args to have only 1 tick on y axis', function () { describe('with only 1 tick on y axis', function () {
args.axis.y.tick.count = 1; beforeAll(function(){
expect(true).toBeTruthy(); args.axis.y.tick.count = 1;
}); });
it('should have only 1 tick on y axis', function () { it('should have only 1 tick on y axis', function () {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size(); var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).toBe(1); expect(ticksSize).toBe(1);
});
}); });
it('should update args to have 2 ticks on y axis', function () { describe('with 2 ticks on y axis', function () {
args.axis.y.tick.count = 2; beforeAll(function(){
expect(true).toBeTruthy(); args.axis.y.tick.count = 2;
}); });
it('should have 2 ticks on y axis', function () { it('should have 2 ticks on y axis', function () {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size(); var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).toBe(2); expect(ticksSize).toBe(2);
});
}); });
it('should update args to have 3 ticks on y axis', function () { describe('with 3 ticks on y axis', function () {
args.axis.y.tick.count = 3; beforeAll(function(){
expect(true).toBeTruthy(); args.axis.y.tick.count = 3;
}); });
it('should have 3 ticks on y axis', function () { it('should have 3 ticks on y axis', function () {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size(); var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).toBe(3); expect(ticksSize).toBe(3);
});
}); });
}); });
describe('axis.y.tick.values', function () { describe('axis.y.tick.values', function () {
var values = [100, 500]; var values = [100, 500];
it('should update args to have only 2 ticks on y axis', function () { describe('with only 2 ticks on y axis', function () {
args.axis.y.tick.values = values; beforeAll(function(){
expect(true).toBeTruthy(); args.axis.y.tick.values = values;
}); });
it('should have only 2 tick on y axis', function () { it('should have only 2 tick on y axis', function () {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size(); var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).toBe(2); expect(ticksSize).toBe(2);
}); });
it('should have specified tick texts', function () { it('should have specified tick texts', function () {
d3.select('.c3-axis-y').selectAll('g.tick').each(function (d, i) { d3.select('.c3-axis-y').selectAll('g.tick').each(function (d, i) {
var text = d3.select(this).select('text').text(); var text = d3.select(this).select('text').text();
expect(+text).toBe(values[i]); expect(+text).toBe(values[i]);
});
}); });
}); });
}); });
describe('axis y timeseries', function () { describe('axis y timeseries', function () {
beforeAll(function () {
it('should update args', function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -107,7 +108,6 @@ describe('c3 chart axis', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('should have 7 ticks on y axis', function () { it('should have 7 ticks on y axis', function () {
@ -126,34 +126,35 @@ describe('c3 chart axis', function () {
}); });
}); });
it('should update args to set axis.y.time', function () { describe('with axis.y.time', function () {
args.axis.y.tick.time = { beforeAll(function(){
value : 'seconds', args.axis.y.tick.time = {
interval : 60 value : 'seconds',
}; interval : 60
expect(true).toBeTruthy(); };
}); });
it('should have 4 ticks on y axis', function () { it('should have 4 ticks on y axis', function () {
var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size(); var ticksSize = d3.select('.c3-axis-y').selectAll('g.tick').size();
expect(ticksSize).toBe(4); // the count starts at initial value and increments by the set interval expect(ticksSize).toBe(4); // the count starts at initial value and increments by the set interval
}); });
it('should have specified 60 second intervals', function () { it('should have specified 60 second intervals', function () {
var prevValue; var prevValue;
d3.select('.c3-axis-y').selectAll('g.tick').each(function (d, i) { d3.select('.c3-axis-y').selectAll('g.tick').each(function (d, i) {
if (i !== 0) { if (i !== 0) {
var result = d - prevValue; var result = d - prevValue;
expect(result).toEqual(60000); // expressed in milliseconds expect(result).toEqual(60000); // expressed in milliseconds
} }
prevValue = d; prevValue = d;
});
}); });
}); });
}); });
describe('axis.x.tick.values', function () { describe('axis.x.tick.values', function () {
describe('function is provided', function () { describe('function is provided', function () {
var tickGenerator = function (/*domain*/) { var tickGenerator = function () {
var values = []; var values = [];
for (var i = 0; i <= 300; i += 50) { for (var i = 0; i <= 300; i += 50) {
values.push(i); values.push(i);
@ -167,7 +168,7 @@ describe('c3 chart axis', function () {
} }
}; };
chart = window.c3.generate(args); chart = window.c3.generate(args);
window.generatedTicks = tickGenerator(); window.generatedTicks = tickGenerator(); // This should be removed from window
}); });
it('should use function to generate ticks', function () { it('should use function to generate ticks', function () {
@ -185,7 +186,7 @@ describe('c3 chart axis', function () {
describe('not rotated', function () { describe('not rotated', function () {
it('should update args successfully', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -202,7 +203,6 @@ describe('c3 chart axis', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('should construct indexed x axis properly', function () { it('should construct indexed x axis properly', function () {
@ -222,95 +222,95 @@ describe('c3 chart axis', function () {
}); });
}); });
it('should set axis.x.tick.format', function () { describe('should set axis.x.tick.format', function () {
args.axis.x = { beforeAll(function(){
tick: { args.axis.x = {
format: function () { tick: {
return 'very long tick text on x axis'; format: function () {
return 'very long tick text on x axis';
}
} }
} };
}; });
expect(true).toBeTruthy();
});
it('should split x axis tick text to multiple lines', function () { it('should split x axis tick text to multiple lines', function () {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'), var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'),
expectedTexts = ['very long tick text', 'on x axis'], expectedTexts = ['very long tick text', 'on x axis'],
expectedX = '0'; expectedX = '0';
expect(ticks.size()).toBe(6); expect(ticks.size()).toBe(6);
ticks.each(function () { ticks.each(function () {
var tspans = d3.select(this).selectAll('tspan'); var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).toBe(2); expect(tspans.size()).toBe(2);
tspans.each(function (d, i) { tspans.each(function (d, i) {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(expectedTexts[i]); expect(tspan.text()).toBe(expectedTexts[i]);
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
if (i === 0) { if (i === 0) {
expect(tspan.attr('dy')).toBe('.71em'); expect(tspan.attr('dy')).toBe('.71em');
} else { } else {
expect(tspan.attr('dy')).toBeGreaterThan(8); expect(tspan.attr('dy')).toBeGreaterThan(8);
} }
});
}); });
}); });
});
it('should construct y axis properly', function () { it('should construct y axis properly', function () {
var ticks = chart.internal.main.select('.c3-axis-y').selectAll('g.tick'), var ticks = chart.internal.main.select('.c3-axis-y').selectAll('g.tick'),
expectedX = '-9', expectedX = '-9',
expectedDy = '3'; expectedDy = '3';
expect(ticks.size()).toBe(9); expect(ticks.size()).toBe(9);
ticks.each(function (d) { ticks.each(function (d) {
var tspans = d3.select(this).selectAll('tspan'); var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).toBe(1); expect(tspans.size()).toBe(1);
tspans.each(function () { tspans.each(function () {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(d + ''); expect(tspan.text()).toBe(d + '');
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
expect(tspan.attr('dy')).toBe(expectedDy); expect(tspan.attr('dy')).toBe(expectedDy);
});
}); });
}); });
});
it('should construct y2 axis properly', function () { it('should construct y2 axis properly', function () {
var ticks = chart.internal.main.select('.c3-axis-y2').selectAll('g.tick'), var ticks = chart.internal.main.select('.c3-axis-y2').selectAll('g.tick'),
expectedX = '9', expectedX = '9',
expectedDy = '3'; expectedDy = '3';
expect(ticks.size()).toBe(9); expect(ticks.size()).toBe(9);
ticks.each(function (d) { ticks.each(function (d) {
var tspans = d3.select(this).selectAll('tspan'); var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).toBe(1); expect(tspans.size()).toBe(1);
tspans.each(function () { tspans.each(function () {
var tspan = d3.select(this); var tspan = d3.select(this);
expect(tspan.text()).toBe(d + ''); expect(tspan.text()).toBe(d + '');
expect(tspan.attr('x')).toBe(expectedX); expect(tspan.attr('x')).toBe(expectedX);
expect(tspan.attr('dy')).toBe(expectedDy); expect(tspan.attr('dy')).toBe(expectedDy);
});
}); });
}); });
}); });
it('should set big values in y', function () { describe('should set big values in y', function () {
args.data.columns = [ beforeAll(function(){
['data1', 3000000000000000, 200, 100, 400, 150, 250], args.data.columns = [
['data2', 50, 20, 10, 40, 15, 25] ['data1', 3000000000000000, 200, 100, 400, 150, 250],
]; ['data2', 50, 20, 10, 40, 15, 25]
expect(true).toBeTruthy(); ];
}); });
it('should not split y axis tick text to multiple lines', function () { it('should not split y axis tick text to multiple lines', function () {
var ticks = chart.internal.main.select('.c3-axis-y2').selectAll('g.tick'); var ticks = chart.internal.main.select('.c3-axis-y2').selectAll('g.tick');
ticks.each(function () { ticks.each(function () {
var tspans = d3.select(this).selectAll('tspan'); var tspans = d3.select(this).selectAll('tspan');
expect(tspans.size()).toBe(1); expect(tspans.size()).toBe(1);
});
}); });
}); });
}); });
describe('rotated', function () { describe('rotated', function () {
it('should update args to rotate axis', function () { beforeAll(function () {
args.axis.rotated = true; args.axis.rotated = true;
expect(true).toBeTruthy();
}); });
it('should split x axis tick text to multiple lines', function () { it('should split x axis tick text to multiple lines', function () {
@ -367,7 +367,7 @@ describe('c3 chart axis', function () {
describe('not rotated', function () { describe('not rotated', function () {
it('should update args successfully', function () { beforeAll(function () {
args = { args = {
data: { data: {
x: 'x', x: 'x',
@ -383,7 +383,6 @@ describe('c3 chart axis', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('should locate ticks properly', function () { it('should locate ticks properly', function () {
@ -429,9 +428,8 @@ describe('c3 chart axis', function () {
describe('rotated', function () { describe('rotated', function () {
it('should update args to rotate axis', function () { beforeAll(function () {
args.axis.rotated = true; args.axis.rotated = true;
expect(true).toBeTruthy();
}); });
it('should locate ticks on rotated axis properly', function () { it('should locate ticks on rotated axis properly', function () {
@ -480,11 +478,10 @@ describe('c3 chart axis', function () {
describe('as null', function () { describe('as null', function () {
it('should update args not to split ticks', function () { beforeAll(function () { //'without split ticks',
args.axis.x.tick = { args.axis.x.tick = {
multiline: false multiline: false
}; };
expect(true).toBeTruthy();
}); });
it('should split x tick', function () { it('should split x tick', function () {
@ -497,11 +494,10 @@ describe('c3 chart axis', function () {
describe('as value', function () { describe('as value', function () {
it('should update args not to split ticks', function () { beforeAll(function () { // 'without split ticks',
args.axis.x.tick = { args.axis.x.tick = {
width: 150 width: 150
}; };
expect(true).toBeTruthy();
}); });
it('should split x tick to 2 lines properly', function () { it('should split x tick to 2 lines properly', function () {
@ -531,11 +527,10 @@ describe('c3 chart axis', function () {
describe('with axis.x.tick.format', function () { describe('with axis.x.tick.format', function () {
it('should update args to use axis.x.tick.format', function () { beforeAll(function () { // 'with axis.x.tick.format',
args.axis.x.tick.format = function () { args.axis.x.tick.format = function () {
return ['this is a very long tick text', 'on category axis']; return ['this is a very long tick text', 'on category axis'];
}; };
expect(true).toBeTruthy();
}); });
it('should have multiline tick text', function () { it('should have multiline tick text', function () {
@ -556,7 +551,7 @@ describe('c3 chart axis', function () {
describe('not rotated', function () { describe('not rotated', function () {
it('should update args successfully', function () { beforeAll(function () {
args = { args = {
data: { data: {
x: 'x', x: 'x',
@ -575,7 +570,6 @@ describe('c3 chart axis', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('should rotate tick texts', function () { it('should rotate tick texts', function () {
@ -593,47 +587,68 @@ describe('c3 chart axis', function () {
var box = chart.internal.main.select('.c3-axis-x').node().getBoundingClientRect(), var box = chart.internal.main.select('.c3-axis-x').node().getBoundingClientRect(),
height = chart.internal.getHorizontalAxisHeight('x'); height = chart.internal.getHorizontalAxisHeight('x');
expect(box.height).toBeGreaterThan(50); expect(box.height).toBeGreaterThan(50);
expect(height).toBeCloseTo(70, -1); expect(height).toBeCloseTo(76, -1.3); // @TODO make this test better
}); });
}); });
}); });
describe('axis.x.tick.fit', function () { describe('axis.y.tick.rotate', function () {
describe('axis.x.tick.fit = true', function () { describe('not rotated', function () {
it('should set args for indexed data', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
['data1', 30, 200, 100, 400, 150, 250], ['data1', 30, 200, 100, 400, 150, 250, 100, 600],
['data2', 50, 20, 10, 40, 15, 25], ['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
] ]
},
axis: {
rotated: true,
y: {
tick: {
rotate: 45
}
}
} }
}; };
expect(true).toBeTruthy();
}); });
it('should show fitted ticks on indexed data', function () { it('should rotate tick texts', function () {
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick'); chart.internal.main.selectAll('.c3-axis-y g.tick').each(function () {
expect(ticks.size()).toBe(6); var tick = d3.select(this),
text = tick.select('text'),
tspan = text.select('tspan');
expect(text.attr('transform')).toBe('rotate(45)');
expect(text.attr('y')).toBe('4');
expect(tspan.attr('dx')).toBeCloseTo('5.6', 0);
});
}); });
it('should set args for x-based data', function () { it('should have automatically calculated y axis width', function () {
var box = chart.internal.main.select('.c3-axis-y').node().getBoundingClientRect();
expect(box.width).toBeCloseTo(590, 1);
});
});
});
describe('axis.x.tick.fit', function () {
describe('axis.x.tick.fit = true', function () {
beforeAll(function () { // 'should set args for indexed data',
args = { args = {
data: { data: {
x: 'x',
columns: [ columns: [
['x', 10, 20, 100, 110, 200, 1000],
['data1', 30, 200, 100, 400, 150, 250], ['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25], ['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125] ['data3', 150, 120, 110, 140, 115, 125]
] ]
} }
}; };
expect(true).toBeTruthy();
}); });
it('should show fitted ticks on indexed data', function () { it('should show fitted ticks on indexed data', function () {
@ -641,73 +656,95 @@ describe('c3 chart axis', function () {
expect(ticks.size()).toBe(6); expect(ticks.size()).toBe(6);
}); });
it('should show fitted ticks after hide and show', function () { describe('should set args for x-based data', function () {
chart.hide(); beforeAll(function(){
chart.show(); args = {
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick'); data: {
expect(ticks.size()).toBe(6); x: 'x',
}); columns: [
['x', 10, 20, 100, 110, 200, 1000],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
]
}
};
});
it('should show fitted ticks on indexed data', function () {
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).toBe(6);
});
it('should show fitted ticks after hide and show', function () {
chart.hide();
chart.show();
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).toBe(6);
});
});
}); });
describe('axis.x.tick.fit = false', function () { describe('axis.x.tick.fit = false', function () {
it('should set args for indexed data', function () { describe('should set args for indexed data', function () {
args = { beforeAll(function(){
data: { args = {
columns: [ data: {
['data1', 30, 200, 100, 400, 150, 250], columns: [
['data2', 50, 20, 10, 40, 15, 25], ['data1', 30, 200, 100, 400, 150, 250],
['data3', 150, 120, 110, 140, 115, 125] ['data2', 50, 20, 10, 40, 15, 25],
] ['data3', 150, 120, 110, 140, 115, 125]
}, ]
axis: { },
x: { axis: {
tick: { x: {
fit: false tick: {
fit: false
}
} }
} }
} };
}; });
expect(true).toBeTruthy();
});
it('should show fitted ticks on indexed data', function () { it('should show fitted ticks on indexed data', function () {
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick'); var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).toBe(11); expect(ticks.size()).toBe(11);
});
}); });
it('should set args for x-based data', function () {
args.data = {
x: 'x',
columns: [
['x', 10, 20, 100, 110, 200, 1000],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
]
};
expect(true).toBeTruthy();
});
it('should show fitted ticks on indexed data', function () { describe('should set args for x-based data', function () {
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick'); beforeAll(function(){
expect(ticks.size()).toBe(10); args.data = {
}); x: 'x',
columns: [
['x', 10, 20, 100, 110, 200, 1000],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25],
['data3', 150, 120, 110, 140, 115, 125]
]
};
});
it('should show fitted ticks after hide and show', function () { it('should show fitted ticks on indexed data', function () {
chart.hide(); var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
chart.show(); expect(ticks.size()).toBe(10);
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick'); });
expect(ticks.size()).toBe(10);
});
it('should show fitted ticks after hide and show', function () {
chart.hide();
chart.show();
var ticks = chart.internal.main.selectAll('.c3-axis-x g.tick');
expect(ticks.size()).toBe(10);
});
});
}); });
}); });
describe('axis.y.inner', function () { describe('axis.y.inner', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -721,7 +758,6 @@ describe('c3 chart axis', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('should not have inner y axis', function () { it('should not have inner y axis', function () {
@ -733,25 +769,25 @@ describe('c3 chart axis', function () {
}); });
}); });
it('should update args to have inner y axis', function () { describe('with inner y axis', function () {
args.axis.y.inner = true; beforeAll(function(){
expect(true).toBeTruthy(); args.axis.y.inner = true;
}); });
it('should have inner y axis', function () { it('should have inner y axis', function () {
var paddingLeft = chart.internal.getCurrentPaddingLeft(), var paddingLeft = chart.internal.getCurrentPaddingLeft(),
tickTexts = chart.internal.main.selectAll('.c3-axis-y g.tick text'); tickTexts = chart.internal.main.selectAll('.c3-axis-y g.tick text');
expect(paddingLeft).toBe(1); expect(paddingLeft).toBe(1);
tickTexts.each(function () { tickTexts.each(function () {
expect(+d3.select(this).attr('x')).toBeGreaterThan(0); expect(+d3.select(this).attr('x')).toBeGreaterThan(0);
});
}); });
}); });
}); });
describe('axis.y2.inner', function () { describe('axis.y2.inner', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -766,7 +802,6 @@ describe('c3 chart axis', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('should not have inner y axis', function () { it('should not have inner y axis', function () {
@ -778,20 +813,20 @@ describe('c3 chart axis', function () {
}); });
}); });
it('should update args to have inner y axis', function () { describe('with inner y axis', function () {
args.axis.y2.inner = true; beforeAll(function(){
expect(true).toBeTruthy(); args.axis.y2.inner = true;
}); });
it('should have inner y axis', function () { it('should have inner y axis', function () {
var paddingRight = chart.internal.getCurrentPaddingRight(), var paddingRight = chart.internal.getCurrentPaddingRight(),
tickTexts = chart.internal.main.selectAll('.c3-axis-2y g.tick text'); tickTexts = chart.internal.main.selectAll('.c3-axis-2y g.tick text');
expect(paddingRight).toBe(2); expect(paddingRight).toBe(2);
tickTexts.each(function () { tickTexts.each(function () {
expect(+d3.select(this).attr('x')).toBeLessThan(0); expect(+d3.select(this).attr('x')).toBeLessThan(0);
});
}); });
}); });
}); });
}); });

19
spec/c3-helper.js

@ -1,4 +1,8 @@
function initDom() { import c3 from '../src';
window.c3 = c3;
window.initDom = function () {
'use strict'; 'use strict';
var div = document.createElement('div'); var div = document.createElement('div');
@ -7,10 +11,9 @@ function initDom() {
div.style.height = '480px'; div.style.height = '480px';
document.body.appendChild(div); document.body.appendChild(div);
document.body.style.margin = '0px'; document.body.style.margin = '0px';
} };
typeof initDom !== 'undefined';
function setMouseEvent(chart, name, x, y, element) { window.setMouseEvent = function(chart, name, x, y, element) {
'use strict'; 'use strict';
var paddingLeft = chart.internal.main.node().transform.baseVal.getItem(0).matrix.e, var paddingLeft = chart.internal.main.node().transform.baseVal.getItem(0).matrix.e,
@ -20,10 +23,9 @@ function setMouseEvent(chart, name, x, y, element) {
false, false, false, false, 0, null); false, false, false, false, 0, null);
chart.internal.d3.event = event; chart.internal.d3.event = event;
if (element) { element.dispatchEvent(event); } if (element) { element.dispatchEvent(event); }
} };
typeof setMouseEvent !== 'undefined';
function initChart(chart, args, done) { window.initChart = function (chart, args, done) {
'use strict'; 'use strict';
if (typeof chart === 'undefined') { if (typeof chart === 'undefined') {
@ -43,5 +45,4 @@ function initChart(chart, args, done) {
}, 10); }, 10);
return chart; return chart;
} };
typeof initChart !== 'undefined';

88
spec/core-spec.js

@ -4,6 +4,9 @@ describe('c3 chart', function () {
var chart; var chart;
var args = { var args = {
svg: {
classname: 'customclass'
},
data: { data: {
columns: [ columns: [
['data1', 30, 200, 100, 400, 150, 250], ['data1', 30, 200, 100, 400, 150, 250],
@ -24,16 +27,23 @@ describe('c3 chart', function () {
expect(svg).not.toBeNull(); expect(svg).not.toBeNull();
}); });
it('should set 3rd party property to Function', function () { describe('should set 3rd party property to Function', function () {
Function.prototype.$extIsFunction = true; beforeAll(function(){
expect(true).toBeTruthy(); Function.prototype.$extIsFunction = true;
}); });
it('should be created even if 3rd party property has been set', function () {
var svg = d3.select('#chart svg');
expect(svg).not.toBeNull();
});
it('should be created even if 3rd party property has been set', function () {
var svg = d3.select('#chart svg');
expect(svg).not.toBeNull();
});
it('should be created with a custom class', function () {
var svg = d3.select('#chart svg');
expect(svg.attr('class')).not.toBeNull();
expect(svg.attr('class')).toBe('customclass');
});
});
}); });
describe('size', function () { describe('size', function () {
@ -53,11 +63,11 @@ describe('c3 chart', function () {
describe('bindto', function () { describe('bindto', function () {
describe('selector', function () { describe('selector', function () {
it('update args', function () { beforeAll(function(){
d3.select('#chart').html(''); d3.select('#chart').html('');
args.bindto = '#chart'; args.bindto = '#chart';
expect(true).toBeTruthy();
}); });
it('should be created', function () { it('should be created', function () {
var svg = d3.select('#chart svg'); var svg = d3.select('#chart svg');
expect(svg.size()).toBe(1); expect(svg.size()).toBe(1);
@ -65,10 +75,9 @@ describe('c3 chart', function () {
}); });
describe('d3.selection object', function () { describe('d3.selection object', function () {
it('update args', function () { beforeAll(function () {
d3.select('#chart').html(''); d3.select('#chart').html('');
args.bindto = d3.select('#chart'); args.bindto = d3.select('#chart');
expect(true).toBeTruthy();
}); });
it('should be created', function () { it('should be created', function () {
var svg = d3.select('#chart svg'); var svg = d3.select('#chart svg');
@ -77,11 +86,11 @@ describe('c3 chart', function () {
}); });
describe('null', function () { describe('null', function () {
it('update args', function () { beforeAll(function () {
d3.select('#chart').html(''); d3.select('#chart').html('');
args.bindto = null; args.bindto = null;
expect(true).toBeTruthy();
}); });
it('should not be created', function () { it('should not be created', function () {
var svg = d3.select('#chart svg'); var svg = d3.select('#chart svg');
expect(svg.size()).toBe(0); expect(svg.size()).toBe(0);
@ -89,22 +98,20 @@ describe('c3 chart', function () {
}); });
describe('empty string', function () { describe('empty string', function () {
it('update args', function () { beforeAll(function () {
d3.select('#chart').html(''); d3.select('#chart').html('');
args.bindto = ''; args.bindto = '';
expect(true).toBeTruthy();
}); });
it('should not be created', function () { it('should not be created', function () {
var svg = d3.select('#chart svg'); var svg = d3.select('#chart svg');
expect(svg.size()).toBe(0); expect(svg.size()).toBe(0);
}); });
}); });
}); });
describe('empty data', function () { describe('empty data', function () {
beforeAll(function () {
it('should upaate args for empty data', function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -113,7 +120,6 @@ describe('c3 chart', function () {
] ]
} }
}; };
expect(true).toBeTruthy();
}); });
it('should generate a chart', function () { it('should generate a chart', function () {
@ -121,30 +127,30 @@ describe('c3 chart', function () {
expect(ticks.size()).toBe(0); expect(ticks.size()).toBe(0);
}); });
it('should upaate args for empty data', function () { describe('more empty data', function () {
args = { beforeAll(function(){
data: { args = {
x: 'x', data: {
columns: [ x: 'x',
['x'], columns: [
['data1'], ['x'],
['data2'] ['data1'],
] ['data2']
}, ]
axis: { },
x: { axis: {
type: 'timeseries' x: {
type: 'timeseries'
}
} }
} };
}; });
expect(true).toBeTruthy();
});
it('should generate a chart', function () { it('should generate a chart', function () {
var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick'); var ticks = chart.internal.main.select('.c3-axis-x').selectAll('g.tick');
expect(ticks.size()).toBe(0); expect(ticks.size()).toBe(0);
});
}); });
}); });
}); });

1361
spec/data-spec.js

File diff suppressed because it is too large Load Diff

164
spec/domain-spec.js

@ -22,112 +22,114 @@ describe('c3 chart domain', function () {
describe('axis.y.min', function () { describe('axis.y.min', function () {
it('should change axis.y.min to -100', function () { describe('should change axis.y.min to -100', function () {
args.axis.y.min = -100; beforeAll(function(){
expect(true).toBeTruthy(); args.axis.y.min = -100;
});
it('should be set properly when smaller than max of data', function () {
var domain = chart.internal.y.domain();
expect(domain[0]).toBe(-150);
expect(domain[1]).toBe(450);
});
}); });
it('should be set properly when smaller than max of data', function () { describe('should change axis.y.min to 500', function () {
var domain = chart.internal.y.domain(); beforeAll(function(){
expect(domain[0]).toBe(-150); args.axis.y.min = 500;
expect(domain[1]).toBe(450); });
});
it('should change axis.y.min to 500', function () {
args.axis.y.min = 500;
expect(true).toBeTruthy();
});
it('should be set properly when bigger than max of data', function () { it('should be set properly when bigger than max of data', function () {
var domain = chart.internal.y.domain(); var domain = chart.internal.y.domain();
expect(domain[0]).toBe(499); expect(domain[0]).toBe(499);
expect(domain[1]).toBe(511); expect(domain[1]).toBe(511);
});
}); });
it('should change axis.y.min to undefined', function () { afterAll(function(){
args.axis.y.min = undefined; args.axis.y.min = undefined;
expect(true).toBeTruthy();
}); });
}); });
describe('axis.y.max', function () { describe('axis.y.max', function () {
describe('should change axis.y.max to 1000', function () {
it('should change axis.y.max to 1000', function () { beforeAll(function(){
args.axis.y.max = 1000; args.axis.y.max = 1000;
expect(true).toBeTruthy(); });
it('should be set properly when bigger than min of data', function () {
var domain = chart.internal.y.domain();
expect(domain[0]).toBe(-89);
expect(domain[1]).toBe(1099);
});
}); });
it('should be set properly when bigger than min of data', function () { describe('should change axis.y.max to 0', function () {
var domain = chart.internal.y.domain(); beforeAll(function(){
expect(domain[0]).toBe(-89); args.axis.y.max = 0;
expect(domain[1]).toBe(1099); });
});
it('should change axis.y.max to 0', function () {
args.axis.y.max = 0;
expect(true).toBeTruthy();
});
it('should be set properly when smaller than min of data', function () { it('should be set properly when smaller than min of data', function () {
var domain = chart.internal.y.domain(); var domain = chart.internal.y.domain();
expect(domain[0]).toBe(-11); expect(domain[0]).toBe(-11);
expect(domain[1]).toBe(1); expect(domain[1]).toBe(1);
});
}); });
}); });
describe('axis.y.padding', function () { describe('axis.y.padding', function () {
it('should change axis.y.max to 1000', function () { describe('should change axis.y.max to 1000', function () {
args = { beforeAll(function(){
data: { args = {
columns: [ data: {
['data1', 10, 20, 10, 40, 15, 25], columns: [
['data2', 50, 40, 30, 45, 25, 45] ['data1', 10, 20, 10, 40, 15, 25],
] ['data2', 50, 40, 30, 45, 25, 45]
}, ]
axis: { },
y: { axis: {
padding: 200, y: {
padding: 200,
}
} }
} };
}; });
expect(true).toBeTruthy();
it('should be set properly when bigger than min of data', function () {
var domain = chart.internal.y.domain();
expect(domain[0]).toBeCloseTo(-9, -1);
expect(domain[1]).toBeCloseTo(69, -1);
});
}); });
it('should be set properly when bigger than min of data', function () {
var domain = chart.internal.y.domain();
expect(domain[0]).toBeCloseTo(-9, -1);
expect(domain[1]).toBeCloseTo(69, -1);
});
it('should change axis.y.max to 1000 with top/bottom padding', function () { describe('should change axis.y.max to 1000 with top/bottom padding', function () {
args = { beforeAll(function(){
data: { args = {
columns: [ data: {
['data1', 10, 20, 10, 40, 15, 25], columns: [
['data2', 50, 40, 30, 45, 25, 45] ['data1', 10, 20, 10, 40, 15, 25],
] ['data2', 50, 40, 30, 45, 25, 45]
}, ]
axis: { },
y: { axis: {
padding: { y: {
top: 200, padding: {
bottom: 200 top: 200,
bottom: 200
}
} }
} }
} };
}; });
expect(true).toBeTruthy();
it('should be set properly when bigger than min of data', function () {
var domain = chart.internal.y.domain();
expect(domain[0]).toBeCloseTo(-9, -1);
expect(domain[1]).toBeCloseTo(69, -1);
});
}); });
it('should be set properly when bigger than min of data', function () {
var domain = chart.internal.y.domain();
expect(domain[0]).toBeCloseTo(-9, -1);
expect(domain[1]).toBeCloseTo(69, -1);
});
}); });
}); });

301
spec/grid-spec.js

@ -9,7 +9,7 @@ describe('c3 chart grid', function () {
describe('y grid show', function () { describe('y grid show', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -28,51 +28,53 @@ describe('c3 chart grid', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('should not show y grids', function () { it('should not show y grids', function () {
expect(chart.internal.main.select('.c3-ygrids').size()).toBe(0); expect(chart.internal.main.select('.c3-ygrids').size()).toBe(0);
}); });
it('should update args to show y grids', function () { describe('with y grids', function () {
args.grid.y.show = true; beforeAll(function(){
expect(true).toBeTruthy(); args.grid.y.show = true;
}); });
it('should show y grids', function () {
var ygrids = chart.internal.main.select('.c3-ygrids');
expect(ygrids.size()).toBe(1);
expect(ygrids.selectAll('.c3-ygrid').size()).toBe(9);
});
it('should update args to show only 3 y grids', function () { it('should show y grids', function () {
args.grid.y.ticks = 3; var ygrids = chart.internal.main.select('.c3-ygrids');
expect(true).toBeTruthy(); expect(ygrids.size()).toBe(1);
expect(ygrids.selectAll('.c3-ygrid').size()).toBe(9);
});
}); });
it('should show only 3 y grids', function () { describe('with only 3 y grids', function () {
var ygrids = chart.internal.main.select('.c3-ygrids'); beforeAll(function(){
expect(ygrids.size()).toBe(1); args.grid.y.ticks = 3;
expect(ygrids.selectAll('.c3-ygrid').size()).toBe(3); });
});
it('should update args to show y grids depending on y axis ticks', function () { it('should show only 3 y grids', function () {
args.axis.y.tick.count = 5; var ygrids = chart.internal.main.select('.c3-ygrids');
expect(true).toBeTruthy(); expect(ygrids.size()).toBe(1);
expect(ygrids.selectAll('.c3-ygrid').size()).toBe(3);
});
}); });
it('should show grids depending on y axis ticks', function () { describe('with y grids depending on y axis ticks', function () {
var ygrids = chart.internal.main.select('.c3-ygrids'), beforeAll(function(){
expectedYs = []; args.axis.y.tick.count = 5;
ygrids.selectAll('.c3-ygrid').each(function (d, i) {
expectedYs[i] = +d3.select(this).attr('y1');
}); });
expect(ygrids.size()).toBe(1);
expect(ygrids.selectAll('.c3-ygrid').size()).toBe(5); it('should show grids depending on y axis ticks', function () {
chart.internal.main.select('.c3-axis-y').selectAll('.tick').each(function (d, i) { var ygrids = chart.internal.main.select('.c3-ygrids'),
var t = d3.transform(d3.select(this).attr('transform')); expectedYs = [];
expect(t.translate[1]).toBe(expectedYs[i]); ygrids.selectAll('.c3-ygrid').each(function (d, i) {
expectedYs[i] = +d3.select(this).attr('y1');
});
expect(ygrids.size()).toBe(1);
expect(ygrids.selectAll('.c3-ygrid').size()).toBe(5);
chart.internal.main.select('.c3-axis-y').selectAll('.tick').each(function (d, i) {
var t = d3.transform(d3.select(this).attr('transform'));
expect(t.translate[1]).toBe(expectedYs[i]);
});
}); });
}); });
}); });
@ -81,7 +83,7 @@ describe('c3 chart grid', function () {
describe('position', function () { describe('position', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -98,7 +100,6 @@ describe('c3 chart grid', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('should show 3 grid lines', function () { it('should show 3 grid lines', function () {
@ -127,55 +128,55 @@ describe('c3 chart grid', function () {
}); });
}); });
it('should update args', function () { describe('three gridlines', function () {
args = { beforeAll(function(){
data: { args = {
columns: [ data: {
['data1', 10, 200, 100, 400, 150, 250] columns: [
] ['data1', 10, 200, 100, 400, 150, 250]
},
axis: {
rotated: true
},
grid: {
y: {
lines: [
{value: 30, text: 'Label 30', position: 'start'},
{value: 145, text: 'Label 145', position: 'middle'},
{value: 225, text: 'Label 225'}
] ]
},
axis: {
rotated: true
},
grid: {
y: {
lines: [
{value: 30, text: 'Label 30', position: 'start'},
{value: 145, text: 'Label 145', position: 'middle'},
{value: 225, text: 'Label 225'}
]
}
} }
} };
}; });
expect(true).toBeTruthy();
});
it('should show 3 grid lines', function () { it('should show 3 grid lines', function () {
expect(chart.internal.main.selectAll('.c3-ygrid-lines .c3-ygrid-line').size()).toBe(3); expect(chart.internal.main.selectAll('.c3-ygrid-lines .c3-ygrid-line').size()).toBe(3);
}); });
it('should locate grid lines properly', function () { it('should locate grid lines properly', function () {
var lines = chart.internal.main.selectAll('.c3-ygrid-lines .c3-ygrid-line'), var lines = chart.internal.main.selectAll('.c3-ygrid-lines .c3-ygrid-line'),
expectedX1s = [75, 220, 321]; expectedX1s = [75, 220, 321];
lines.each(function (d, i) { lines.each(function (d, i) {
var x1 = d3.select(this).select('line').attr('x1'); var x1 = d3.select(this).select('line').attr('x1');
expect(x1).toBeCloseTo(expectedX1s[i], -2); expect(x1).toBeCloseTo(expectedX1s[i], -2);
});
}); });
});
it('should locate grid texts properly', function () { it('should locate grid texts properly', function () {
var lines = chart.internal.main.selectAll('.c3-ygrid-lines .c3-ygrid-line'), var lines = chart.internal.main.selectAll('.c3-ygrid-lines .c3-ygrid-line'),
expectedPositions = ['start', 'middle', 'end'], expectedPositions = ['start', 'middle', 'end'],
expectedDxs = [4, 0, -4]; expectedDxs = [4, 0, -4];
lines.each(function (d, i) { lines.each(function (d, i) {
var text = d3.select(this).select('text'), var text = d3.select(this).select('text'),
textAnchor = text.attr('text-anchor'), textAnchor = text.attr('text-anchor'),
dx = text.attr('dx'); dx = text.attr('dx');
expect(textAnchor).toBe(expectedPositions[i]); expect(textAnchor).toBe(expectedPositions[i]);
expect(+dx).toBe(expectedDxs[i]); expect(+dx).toBe(expectedDxs[i]);
});
}); });
}); });
}); });
}); });
@ -183,7 +184,7 @@ describe('c3 chart grid', function () {
describe('position', function () { describe('position', function () {
it('should have correct height', function () { beforeAll(function () { // 'should have correct height',
args = { args = {
data: { data: {
columns: [ columns: [
@ -200,7 +201,6 @@ describe('c3 chart grid', function () {
} }
}, },
}; };
expect(true).toBeTruthy();
}); });
it('should show 3 grid lines', function () { it('should show 3 grid lines', function () {
@ -229,98 +229,98 @@ describe('c3 chart grid', function () {
}); });
}); });
it('should update args', function () { describe('three grid lines', function () {
args = { beforeAll(function(){
data: { args = {
columns: [ data: {
['data1', 30, 200, 100, 400], columns: [
] ['data1', 30, 200, 100, 400],
},
axis: {
rotated: true
},
grid: {
x: {
lines: [
{value: 1, text: 'Label 1', position: 'start'},
{value: 2, text: 'Label 2', position: 'middle'},
{value: 3, text: 'Label 3'},
] ]
} },
}, axis: {
}; rotated: true
expect(true).toBeTruthy(); },
}); grid: {
x: {
lines: [
{value: 1, text: 'Label 1', position: 'start'},
{value: 2, text: 'Label 2', position: 'middle'},
{value: 3, text: 'Label 3'},
]
}
},
};
});
it('should show 3 grid lines', function () { it('should show 3 grid lines', function () {
expect(chart.internal.main.selectAll('.c3-xgrid-lines .c3-xgrid-line').size()).toBe(3); expect(chart.internal.main.selectAll('.c3-xgrid-lines .c3-xgrid-line').size()).toBe(3);
}); });
it('should locate grid lines properly', function () { it('should locate grid lines properly', function () {
var lines = chart.internal.main.selectAll('.c3-xgrid-lines .c3-xgrid-line'), var lines = chart.internal.main.selectAll('.c3-xgrid-lines .c3-xgrid-line'),
expectedY1s = [144, 283, 421]; expectedY1s = [144, 283, 421];
lines.each(function (d, i) { lines.each(function (d, i) {
var y1 = d3.select(this).select('line').attr('y1'); var y1 = d3.select(this).select('line').attr('y1');
expect(y1).toBeCloseTo(expectedY1s[i], -2); expect(y1).toBeCloseTo(expectedY1s[i], -2);
});
}); });
});
it('should locate grid texts properly', function () { it('should locate grid texts properly', function () {
var lines = chart.internal.main.selectAll('.c3-xgrid-lines .c3-xgrid-line'), var lines = chart.internal.main.selectAll('.c3-xgrid-lines .c3-xgrid-line'),
expectedPositions = ['start', 'middle', 'end'], expectedPositions = ['start', 'middle', 'end'],
expectedDxs = [4, 0, -4]; expectedDxs = [4, 0, -4];
lines.each(function (d, i) { lines.each(function (d, i) {
var text = d3.select(this).select('text'), var text = d3.select(this).select('text'),
textAnchor = text.attr('text-anchor'), textAnchor = text.attr('text-anchor'),
dx = text.attr('dx'); dx = text.attr('dx');
expect(textAnchor).toBe(expectedPositions[i]); expect(textAnchor).toBe(expectedPositions[i]);
expect(+dx).toBe(expectedDxs[i]); expect(+dx).toBe(expectedDxs[i]);
});
}); });
}); });
}); });
describe('with padding.top', function () { describe('with padding.top', function () {
it('should have correct height', function () { describe('should have correct height', function () {
args = { beforeAll(function(){
data: { args = {
columns: [ data: {
['data1', 30, 200, 100, 400], columns: [
] ['data1', 30, 200, 100, 400],
},
grid: {
x: {
lines: [
{value: 3, text: 'Label 3'}
] ]
},
grid: {
x: {
lines: [
{value: 3, text: 'Label 3'}
]
}
},
padding: {
top: 50
} }
}, };
padding: { });
top: 50
}
};
expect(true).toBeTruthy();
});
it('should show x grid lines', function () { it('should show x grid lines', function () {
var lines = chart.internal.main.select('.c3-xgrid-lines .c3-xgrid-line'), var lines = chart.internal.main.select('.c3-xgrid-lines .c3-xgrid-line'),
expectedX1 = 593, expectedX1 = 593,
expectedText = ['Label 3']; expectedText = ['Label 3'];
lines.each(function (id, i) { lines.each(function (id, i) {
var line = d3.select(this), var line = d3.select(this),
l = line.select('line'), l = line.select('line'),
t = line.select('text'); t = line.select('text');
expect(+l.attr('x1')).toBeCloseTo(expectedX1, -2); expect(+l.attr('x1')).toBeCloseTo(expectedX1, -2);
expect(t.text()).toBe(expectedText[i]); expect(t.text()).toBe(expectedText[i]);
});
}); });
}); });
}); });
describe('on category axis', function () { describe('on category axis', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
x: 'x', x: 'x',
@ -343,7 +343,6 @@ describe('c3 chart grid', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('should show x grid lines', function () { it('should show x grid lines', function () {

90
spec/interaction-spec.js

@ -11,7 +11,7 @@ describe('c3 chart interaction', function () {
describe('custom x', function () { describe('custom x', function () {
it('should generate bar chart', function () { beforeAll(function () {
args = { args = {
data: { data: {
x: 'x', x: 'x',
@ -22,7 +22,6 @@ describe('c3 chart interaction', function () {
type: 'bar' type: 'bar'
} }
}; };
expect(true).toBeTruthy();
}); });
it('should have 4 event rects properly', function () { it('should have 4 event rects properly', function () {
@ -35,34 +34,34 @@ describe('c3 chart interaction', function () {
}); });
}); });
it('should generate bar chart with only one data', function () { describe('should generate bar chart with only one data', function () {
args = { beforeAll(function(){
data: { args = {
x: 'x', data: {
columns: [ x: 'x',
['x', 0], columns: [
['data', 10] ['x', 0],
], ['data', 10]
type: 'bar' ],
} type: 'bar'
}; }
expect(true).toBeTruthy(); };
}); });
it('should have 1 event rects properly', function () { it('should have 1 event rects properly', function () {
var eventRects = d3.selectAll('.c3-event-rect'); var eventRects = d3.selectAll('.c3-event-rect');
expect(eventRects.size()).toBe(1); expect(eventRects.size()).toBe(1);
eventRects.each(function () { eventRects.each(function () {
var box = d3.select(this).node().getBoundingClientRect(); var box = d3.select(this).node().getBoundingClientRect();
expect(box.left).toBeCloseTo(40.5, -2); expect(box.left).toBeCloseTo(40.5, -2);
expect(box.width).toBeCloseTo(598, -2); expect(box.width).toBeCloseTo(598, -2);
});
}); });
}); });
}); });
describe('timeseries', function () { describe('timeseries', function () {
beforeAll(function () {
it('should generate line chart with timeseries', function () {
args = { args = {
data: { data: {
x: 'x', x: 'x',
@ -72,7 +71,6 @@ describe('c3 chart interaction', function () {
] ]
} }
}; };
expect(true).toBeTruthy();
}); });
it('should have 4 event rects properly', function () { it('should have 4 event rects properly', function () {
@ -86,31 +84,29 @@ describe('c3 chart interaction', function () {
}); });
it('should generate line chart with only 1 data timeseries', function () { describe('should generate line chart with only 1 data timeseries', function () {
args = { beforeAll(function(){
data: { args = {
x: 'x', data: {
columns: [ x: 'x',
['x', '20140101'], columns: [
['data', 10] ['x', '20140101'],
] ['data', 10]
} ]
}; }
expect(true).toBeTruthy(); };
}); });
it('should have 1 event rects properly', function () { it('should have 1 event rects properly', function () {
var eventRects = d3.selectAll('.c3-event-rect'); var eventRects = d3.selectAll('.c3-event-rect');
expect(eventRects.size()).toBe(1); expect(eventRects.size()).toBe(1);
eventRects.each(function () { eventRects.each(function () {
var box = d3.select(this).node().getBoundingClientRect(); var box = d3.select(this).node().getBoundingClientRect();
expect(box.left).toBeCloseTo(40.5, -2); expect(box.left).toBeCloseTo(40.5, -2);
expect(box.width).toBeCloseTo(598, -2); expect(box.width).toBeCloseTo(598, -2);
});
}); });
}); });
}); });
}); });
}); });

213
spec/legend-spec.js

@ -9,7 +9,7 @@ describe('c3 chart legend', function () {
describe('legend when multiple charts rendered', function () { describe('legend when multiple charts rendered', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -19,36 +19,36 @@ describe('c3 chart legend', function () {
] ]
} }
}; };
expect(true).toBeTruthy();
}); });
it('should update args with long data names', function () { describe('long data names', function () {
args = { beforeAll(function(){
data: { args = {
columns: [ data: {
['long data name 1', 30], columns: [
['long data name 2', 50], ['long data name 1', 30],
['long data name 3', 50], ['long data name 2', 50],
] ['long data name 3', 50],
} ]
}; }
expect(true).toBeTruthy(); };
}); });
it('should have properly computed legend width', function () { it('should have properly computed legend width', function () {
var expectedLeft = [148, 226, 384], var expectedLeft = [148, 226, 384],
expectedWidth = [118, 118, 108]; expectedWidth = [118, 118, 108];
d3.selectAll('.c3-legend-item').each(function (d, i) { d3.selectAll('.c3-legend-item').each(function (d, i) {
var rect = d3.select(this).node().getBoundingClientRect(); var rect = d3.select(this).node().getBoundingClientRect();
expect(rect.left).toBeCloseTo(expectedLeft[i], -2); expect(rect.left).toBeCloseTo(expectedLeft[i], -2);
expect(rect.width).toBeCloseTo(expectedWidth[i], -2); expect(rect.width).toBeCloseTo(expectedWidth[i], -2);
});
}); });
}); });
}); });
describe('legend position', function () { describe('legend position', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -57,92 +57,94 @@ describe('c3 chart legend', function () {
] ]
} }
}; };
expect(true).toBeTruthy();
}); });
it('should be located on the center of chart', function () { it('should be located on the center of chart', function () {
var box = chart.internal.legend.node().getBoundingClientRect(); var box = chart.internal.legend.node().getBoundingClientRect();
expect(box.left + box.right).toBe(640); expect(box.left + box.right).toBe(638);
}); });
}); });
describe('legend as inset', function () { describe('legend as inset', function () {
it('should change the legend to "inset" successfully', function () { describe('should change the legend to "inset" successfully', function () {
args = { beforeAll(function(){
data: { args = {
columns: [ data: {
['data1', 30, 200, 100, 400, 150, 250], columns: [
['data2', 50, 20, 10, 40, 15, 25] ['data1', 30, 200, 100, 400, 150, 250],
] ['data2', 50, 20, 10, 40, 15, 25]
}, ]
legend: { },
position: 'inset', legend: {
inset: { position: 'inset',
step: null inset: {
step: null
}
} }
} };
}; });
expect(true).toBeTruthy();
});
it('should be positioned properly', function () { it('should be positioned properly', function () {
var box = d3.select('.c3-legend-background').node().getBoundingClientRect(); var box = d3.select('.c3-legend-background').node().getBoundingClientRect();
expect(box.top).toBe(5.5); expect(box.top).toBe(5.5);
expect(box.left).toBeGreaterThan(30); expect(box.left).toBeGreaterThan(30);
}); });
it('should have automatically calculated height', function () { it('should have automatically calculated height', function () {
var box = d3.select('.c3-legend-background').node().getBoundingClientRect(); var box = d3.select('.c3-legend-background').node().getBoundingClientRect();
expect(box.height).toBe(48); expect(box.height).toBe(48);
});
}); });
it('should change the legend step to 1 successfully', function () { describe('should change the legend step to 1 successfully', function () {
args.legend.inset.step = 1; beforeAll(function(){
expect(true).toBeTruthy(); args.legend.inset.step = 1;
}); });
it('should have automatically calculated height', function () { it('should have automatically calculated height', function () {
var box = d3.select('.c3-legend-background').node().getBoundingClientRect(); var box = d3.select('.c3-legend-background').node().getBoundingClientRect();
expect(box.height).toBe(28); expect(box.height).toBe(28);
});
}); });
it('should change the legend step to 2 successfully', function () { describe('should change the legend step to 2 successfully', function () {
args.legend.inset.step = 2; beforeAll(function(){
expect(true).toBeTruthy(); args.legend.inset.step = 2;
}); });
it('should have automatically calculated height', function () { it('should have automatically calculated height', function () {
var box = d3.select('.c3-legend-background').node().getBoundingClientRect(); var box = d3.select('.c3-legend-background').node().getBoundingClientRect();
expect(box.height).toBe(48); expect(box.height).toBe(48);
});
}); });
it('should update args to have only one series', function () { describe('with only one series', function () {
args = { beforeAll(function(){
data: { args = {
columns: [ data: {
['data1', 30, 200, 100, 400, 150, 250], columns: [
] ['data1', 30, 200, 100, 400, 150, 250],
}, ]
legend: { },
position: 'inset' legend: {
} position: 'inset'
}; }
expect(true).toBeTruthy(); };
}); });
it('should locate legend properly', function () { it('should locate legend properly', function () {
var box = d3.select('.c3-legend-background').node().getBoundingClientRect(); var box = d3.select('.c3-legend-background').node().getBoundingClientRect();
expect(box.height).toBe(28); expect(box.height).toBe(28);
expect(box.width).toBeGreaterThan(64); expect(box.width).toBeGreaterThan(64);
});
}); });
}); });
describe('legend.hide', function () { describe('legend.hide', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -154,7 +156,6 @@ describe('c3 chart legend', function () {
hide: true hide: true
} }
}; };
expect(true).toBeTruthy();
}); });
it('should not show legends', function () { it('should not show legends', function () {
@ -163,31 +164,32 @@ describe('c3 chart legend', function () {
}); });
}); });
it('should update args', function () { describe('hidden legend', function () {
args = { beforeAll(function(){
data: { args = {
columns: [ data: {
['data1', 30, 200, 100, 400, 150, 250], columns: [
['data2', 130, 100, 200, 100, 250, 150] ['data1', 30, 200, 100, 400, 150, 250],
] ['data2', 130, 100, 200, 100, 250, 150]
}, ]
legend: { },
hide: 'data2' legend: {
} hide: 'data2'
}; }
expect(true).toBeTruthy(); };
}); });
it('should not show legends', function () { it('should not show legends', function () {
expect(d3.select('.c3-legend-item-data1').style('visibility')).toBe('visible'); expect(d3.select('.c3-legend-item-data1').style('visibility')).toBe('visible');
expect(d3.select('.c3-legend-item-data2').style('visibility')).toBe('hidden'); expect(d3.select('.c3-legend-item-data2').style('visibility')).toBe('hidden');
});
}); });
}); });
describe('legend.show', function () { describe('legend.show', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -199,7 +201,6 @@ describe('c3 chart legend', function () {
show: false show: false
} }
}; };
expect(true).toBeTruthy();
}); });
it('should not initially have rendered any legend items', function () { it('should not initially have rendered any legend items', function () {
@ -218,7 +219,7 @@ describe('c3 chart legend', function () {
}); });
describe('custom legend size', function() { describe('custom legend size', function() {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -235,20 +236,19 @@ describe('c3 chart legend', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('renders the legend item with the correct width and height', function () { it('renders the legend item with the correct width and height', function () {
d3.selectAll('.c3-legend-item-tile').each(function () { d3.selectAll('.c3-legend-item-tile').each(function () {
expect(d3.select(this).style('stroke-width')).toBe(args.legend.item.tile.height + 'px'); expect(d3.select(this).style('stroke-width')).toBe(args.legend.item.tile.height + 'px');
var tileWidth = d3.select(this).attr('x2') - d3.select(this).attr('x1'); var tileWidth = d3.select(this).attr('x2') - d3.select(this).attr('x1');
expect(tileWidth).toBe(args.legend.item.tile.width); expect(tileWidth).toBe(args.legend.item.tile.width);
}); });
}); });
}); });
describe('custom legend padding', function() { describe('custom legend padding', function() {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -260,14 +260,13 @@ describe('c3 chart legend', function () {
padding: 10 padding: 10
} }
}; };
expect(true).toBeTruthy();
}); });
it('renders the correct amount of padding on the legend element', function () { it('renders the correct amount of padding on the legend element', function () {
d3.selectAll('.c3-legend-item-padded1 .c3-legend-item-tile, .c3-legend-item-padded2 .c3-legend-item-tile').each(function (el, index) { d3.selectAll('.c3-legend-item-padded1 .c3-legend-item-tile, .c3-legend-item-padded2 .c3-legend-item-tile').each(function (el, index) {
var itemWidth = d3.select(this).node().parentNode.getBBox().width, var itemWidth = d3.select(this).node().parentNode.getBBox().width,
textBoxWidth = d3.select(d3.select(this).node().parentNode).select('text').node().getBBox().width, textBoxWidth = d3.select(d3.select(this).node().parentNode).select('text').node().getBBox().width,
tileWidth = 15, // default value is 10, plus 5 more for padding tileWidth = 17, // default value is 10, plus 7 more for padding @TODO verify this, seems PhantomJS@^2 adds another 1px to each side
expectedWidth = textBoxWidth + tileWidth + (index ? 0 : 10) + args.legend.padding; expectedWidth = textBoxWidth + tileWidth + (index ? 0 : 10) + args.legend.padding;
expect(itemWidth).toBe(expectedWidth); expect(itemWidth).toBe(expectedWidth);

16
spec/shape.bar-spec.js

@ -12,7 +12,7 @@ describe('c3 chart shape bar', function () {
describe('with groups', function () { describe('with groups', function () {
describe('with indexed data', function () { describe('with indexed data', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -25,7 +25,6 @@ describe('c3 chart shape bar', function () {
type: 'bar' type: 'bar'
}, },
}; };
expect(true).toBeTruthy();
}); });
it('should be stacked', function () { it('should be stacked', function () {
var expectedBottom = [275, 293, 365, 281, 395, 290]; var expectedBottom = [275, 293, 365, 281, 395, 290];
@ -37,7 +36,7 @@ describe('c3 chart shape bar', function () {
}); });
describe('with timeseries data', function () { describe('with timeseries data', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
x: 'date', x: 'date',
@ -57,7 +56,6 @@ describe('c3 chart shape bar', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('should be stacked', function () { it('should be stacked', function () {
var expectedBottom = [275, 293, 365, 281, 395, 290]; var expectedBottom = [275, 293, 365, 281, 395, 290];
@ -69,7 +67,7 @@ describe('c3 chart shape bar', function () {
}); });
describe('with category data', function () { describe('with category data', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
x: 'date', x: 'date',
@ -89,8 +87,8 @@ describe('c3 chart shape bar', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('should be stacked', function () { it('should be stacked', function () {
var expectedBottom = [275, 293, 365, 281, 395, 290]; var expectedBottom = [275, 293, 365, 281, 395, 290];
chart.internal.main.selectAll('.c3-bars-data1 .c3-bar').each(function (d, i) { chart.internal.main.selectAll('.c3-bars-data1 .c3-bar').each(function (d, i) {
@ -106,7 +104,7 @@ describe('c3 chart shape bar', function () {
describe('with normal axis', function () { describe('with normal axis', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -120,7 +118,6 @@ describe('c3 chart shape bar', function () {
rotated: false rotated: false
} }
}; };
expect(true).toBeTruthy();
}); });
it('should not be within bar', function () { it('should not be within bar', function () {
@ -151,9 +148,8 @@ describe('c3 chart shape bar', function () {
describe('with rotated axis', function () { describe('with rotated axis', function () {
it('should change the chart as axis rotated', function () { beforeAll(function () {
args.axis.rotated = true; args.axis.rotated = true;
expect(true).toBeTruthy();
}); });
it('should not be within bar', function () { it('should not be within bar', function () {

183
spec/shape.line-spec.js

@ -7,9 +7,11 @@ describe('c3 chart shape line', function () {
chart = window.initChart(chart, args, done); chart = window.initChart(chart, args, done);
}); });
var parseSvgPath = window.parseSvgPath;
describe('shape-rendering for line chart', function () { describe('shape-rendering for line chart', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -20,7 +22,15 @@ describe('c3 chart shape line', function () {
type: 'line' type: 'line'
} }
}; };
expect(true).toBeTruthy(); });
it("Should render the lines correctly", function(done) {
setTimeout(function () {
var target = chart.internal.main.select('.c3-chart-line.c3-target-data1');
var commands = parseSvgPath( target.select('.c3-line-data1').attr('d'));
expect(commands.length).toBe(6);
done();
}, 500);
}); });
it("should not have shape-rendering when it's line chart", function () { it("should not have shape-rendering when it's line chart", function () {
@ -30,84 +40,124 @@ describe('c3 chart shape line', function () {
}); });
}); });
it('should change to step chart', function () { describe('should change to step chart', function () {
args.data.type = 'step'; beforeAll(function(){
expect(true).toBeTruthy(); args.data.type = 'step';
}); });
it("should have shape-rendering = crispedges when it's step chart", function () { it("should have shape-rendering = crispedges when it's step chart", function () {
d3.selectAll('.c3-line').each(function () { d3.selectAll('.c3-line').each(function () {
var style = d3.select(this).style('shape-rendering'); var style = d3.select(this).style('shape-rendering').toLowerCase();
expect(style).toBe('crispedges'); expect(style).toBe('crispedges');
});
}); });
}); });
it('should change to spline chart', function () { describe('should change to spline chart', function () {
args.data.type = 'spline'; beforeAll(function(){
expect(true).toBeTruthy(); args.data.type = 'spline';
}); });
it('should use cardinal interpolation by default', function () { it('should use cardinal interpolation by default', function () {
expect(chart.internal.config.spline_interpolation_type).toBe('cardinal'); expect(chart.internal.config.spline_interpolation_type).toBe('cardinal');
});
}); });
}); });
describe('point.show option', function () { describe('point.show option', function () {
it('should change args to include null data', function () { describe('should change args to include null data', function () {
args = { beforeAll(function(){
data: { args = {
columns: [ data: {
['data1', 30, null, 100, 400, -150, 250], columns: [
['data2', 50, 20, 10, 40, 15, 25], ['data1', 30, null, 100, 400, -150, 250],
['data3', -150, 120, 110, 140, 115, 125] ['data2', 50, 20, 10, 40, 15, 25],
], ['data3', -150, 120, 110, 140, 115, 125]
type: 'line' ],
} type: 'line'
}; }
expect(true).toBeTruthy(); };
}); });
it('should not show the circle for null', function (done) { it('should not show the circle for null', function (done) {
setTimeout(function () { setTimeout(function () {
var target = chart.internal.main.select('.c3-chart-line.c3-target-data1'); var target = chart.internal.main.select('.c3-chart-line.c3-target-data1');
expect(+target.select('.c3-circle-0').style('opacity')).toBe(1); expect(+target.select('.c3-circle-0').style('opacity')).toBe(1);
expect(+target.select('.c3-circle-1').style('opacity')).toBe(0); expect(+target.select('.c3-circle-1').style('opacity')).toBe(0);
expect(+target.select('.c3-circle-2').style('opacity')).toBe(1); expect(+target.select('.c3-circle-2').style('opacity')).toBe(1);
done(); done();
}, 500); }, 500);
}); });
it('should change args to include null data on scatter plot', function () { it('should not draw a line segment for null data', function(done) {
args = { setTimeout(function () {
data: { var target = chart.internal.main.select('.c3-chart-line.c3-target-data1');
columns: [ var commands = parseSvgPath( target.select('.c3-line-data1').attr('d'));
['data1', 30, null, 100, 400, -150, 250], var segments = 0;
['data2', 50, 20, 10, 40, 15, 25], for(var i = 0; i < commands.length; i++) {
['data3', -150, 120, 110, 140, 115, 125] (commands[i].command === 'L') ? segments++ : null;
], }
type: 'scatter' expect(segments).toBe(3);
} done();
}; }, 500);
expect(true).toBeTruthy(); });
// it('should change args to include null data on scatter plot', function () {
// args = {
// data: {
// columns: [
// ['data1', 30, null, 100, 400, -150, 250],
// ['data2', 50, 20, 10, 40, 15, 25],
// ['data3', -150, 120, 110, 140, 115, 125]
// ],
// type: 'scatter'
// }
// };
// expect(true).toBeTruthy();
// });
// it('should not show the circle for null', function (done) {
// setTimeout(function () {
// var target = chart.internal.main.select('.c3-chart-line.c3-target-data1');
// expect(+target.select('.c3-circle-0').style('opacity')).toBe(0.5);
// expect(+target.select('.c3-circle-1').style('opacity')).toBe(0);
// expect(+target.select('.c3-circle-2').style('opacity')).toBe(0.5);
// done();
// }, 500);
// });
}); });
it('should not show the circle for null', function (done) { describe('should allow passing a function', function() {
setTimeout(function () { beforeAll(function(){
args = {
data: {
columns: [
['data1', 30, 50, 100]
],
type: 'line'
},
point: {
show: function(d) {
return d.value > 50;
}
}
};
});
it('should show point if function returns true', function() {
var target = chart.internal.main.select('.c3-chart-line.c3-target-data1'); var target = chart.internal.main.select('.c3-chart-line.c3-target-data1');
expect(+target.select('.c3-circle-0').style('opacity')).toBe(0.5); expect(+target.select('.c3-circle-0').style('opacity')).toBe(0);
expect(+target.select('.c3-circle-1').style('opacity')).toBe(0); expect(+target.select('.c3-circle-1').style('opacity')).toBe(0);
expect(+target.select('.c3-circle-2').style('opacity')).toBe(0.5); expect(+target.select('.c3-circle-2').style('opacity')).toBe(1);
done(); });
}, 500);
}); });
}); });
describe('spline.interpolation option', function () { describe('spline.interpolation option', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -123,22 +173,21 @@ describe('c3 chart shape line', function () {
} }
} }
}; };
expect(true).toBeTruthy();
}); });
it('should update interpolation function', function() { it('updates interpolation function', function() {
expect(chart.internal.getInterpolate(chart.data()[0])).toBe('monotone'); expect(chart.internal.getInterpolate(chart.data()[0])).toBe('monotone');
}); });
it('should not use a non-valid interpolation', function () { describe('should not use a non-valid interpolation', function () {
args.spline.interpolation.type = 'foo'; beforeAll(function(){
expect(true).toBeTruthy(); args.spline.interpolation.type = 'foo';
}); });
it('should use cardinal interpolation when given option is not valid', function() { it('should use cardinal interpolation when given option is not valid', function() {
expect(chart.internal.getInterpolate(chart.data()[0])).toBe('cardinal'); expect(chart.internal.getInterpolate(chart.data()[0])).toBe('cardinal');
});
}); });
}); });
}); });

50
spec/svg-helper.js

@ -0,0 +1,50 @@
/**
* Parse the d property of an SVG path into an array of drawing commands.
* @param {String} d SvgPath d attribute.]
* @return {Array} an array of drawing commands.
*/
function parseSvgPath(d) { //jshint ignore:line
'use strict';
var commands = [];
var commandTokens = ['M','L','I','H','V','C','S','Q','T','A'];
var command;
var in_x = false;
var in_y = false;
var x = '';
var y = '';
for(var i = 0; i <= d.length; i++) {
if (commandTokens.indexOf(d[i]) !== -1) {
if (in_x || in_y) {
commands.push({command: command, x: x, y: y});
x = '';
y = '';
}
command = d[i];
in_x = true;
in_y = false;
}
else {
if (d[i] === ',') {
if (in_y) {
commands.push({command: command, x: x, y: y});
x = '';
y = '';
}
in_x = !in_x;
in_y = !in_y;
}
else if (in_x) {
x += d[i];
}
else if (in_y) {
y += d[i];
}
}
}
if (d[i] !== ',' && in_y) {
commands.push({command: command, x: x, y: y});
}
return commands;
}

362
spec/tooltip-spec.js

@ -2,16 +2,20 @@ describe('c3 chart tooltip', function () {
'use strict'; 'use strict';
var chart; var chart;
var tooltipConfiguration; var tooltipConfiguration = {};
var dataOrder = 'desc';
var dataGroups;
var args = function () { var args = function () {
return { return {
data: { data: {
columns: [ columns: [
['data1', 30, 200, 100, 400, 150, 250], ['data1', 30, 200, 100, 400, 150, 250], // 1130
['data2', 50, 20, 10, 40, 15, 25], ['data2', 50, 20, 10, 40, 15, 25], // 160
['data3', 150, 120, 110, 140, 115, 125] ['data3', 150, 120, 110, 140, 115, 125] // 760
], ],
order: dataOrder,
groups: dataGroups,
}, },
tooltip: tooltipConfiguration tooltip: tooltipConfiguration
}; };
@ -19,6 +23,8 @@ describe('c3 chart tooltip', function () {
beforeEach(function (done) { beforeEach(function (done) {
chart = window.initChart(chart, args(), done); chart = window.initChart(chart, args(), done);
dataOrder = 'desc';
dataGroups = undefined;
}); });
describe('tooltip position', function () { describe('tooltip position', function () {
@ -45,9 +51,8 @@ describe('c3 chart tooltip', function () {
describe('with left margin', function () { describe('with left margin', function () {
it('should set left margin', function () { beforeAll(function () {
d3.select('#chart').style('margin-left', '300px'); d3.select('#chart').style('margin-left', '300px');
expect(true).toBeTruthy();
}); });
it('should show tooltip on proper position', function () { it('should show tooltip on proper position', function () {
@ -100,23 +105,340 @@ describe('c3 chart tooltip', function () {
}); });
describe('tooltip getTooltipContent', function () { describe('tooltip getTooltipContent', function () {
beforeAll(function () { beforeAll(function () {
tooltipConfiguration = { tooltipConfiguration = {
data_order: 'desc' data_order: 'desc'
}; };
});
it('should sort values desc', function () {
var eventRect = d3.select('.c3-event-rect-2').node();
window.setMouseEvent(chart, 'mousemove', 100, 100, eventRect);
var tooltipTable = d3.select('.c3-tooltip')[0];
var expected = ["", "c3-tooltip-name--data3",
"c3-tooltip-name--data1", "c3-tooltip-name--data2"];
var i;
for (i = 0; i < tooltipTable[0].rows.length; i++) {
expect(tooltipTable[0].rows[i].className).toBe(expected[i]);
}
});
});
describe('tooltip with data_order as desc with grouped data', function() {
beforeAll(function() {
dataOrder = 'desc';
dataGroups = [ [ 'data1', 'data2', 'data3' ]];
});
it('should display each data in descending order', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data1'); // 1130
expect(classes[2]).toBe('c3-tooltip-name--data3'); // 760
expect(classes[3]).toBe('c3-tooltip-name--data2'); // 160
});
});
describe('tooltip with data_order as asc with grouped data', function() {
beforeAll(function() {
dataOrder = 'asc';
dataGroups = [ [ 'data1', 'data2', 'data3' ]];
});
it('should display each data in ascending order', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data2'); // 160
expect(classes[2]).toBe('c3-tooltip-name--data3'); // 760
expect(classes[3]).toBe('c3-tooltip-name--data1'); // 1130
});
});
describe('tooltip with data_order as NULL with grouped data', function() {
beforeAll(function() {
dataOrder = null;
dataGroups = [ [ 'data1', 'data2', 'data3' ]];
});
it('should display each data in given order', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data1');
expect(classes[2]).toBe('c3-tooltip-name--data2');
expect(classes[3]).toBe('c3-tooltip-name--data3');
});
});
describe('tooltip with data_order as Function with grouped data', function() {
beforeAll(function() {
var order = [ 'data2', 'data1', 'data3' ];
dataOrder = function(data1, data2) {
return order.indexOf(data1.id) - order.indexOf(data2.id);
};
dataGroups = [ [ 'data1', 'data2', 'data3' ]];
}); });
it('should sort values desc', function () { it('should display each data in order given by function', function() {
var eventRect = d3.select('.c3-event-rect-2').node(); window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
window.setMouseEvent(chart, 'mousemove', 100, 100, eventRect);
var tooltipTable = d3.select('.c3-tooltip')[0]; var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
var expected = ["", "c3-tooltip-name--data3", return node.className;
"c3-tooltip-name--data1", "c3-tooltip-name--data2"]; });
var i;
for (i = 0; i < tooltipTable[0].rows.length; i++) { expect(classes[0]).toBe(''); // header
expect(tooltipTable[0].rows[i].className).toBe(expected[i]); expect(classes[1]).toBe('c3-tooltip-name--data2');
} expect(classes[2]).toBe('c3-tooltip-name--data1');
expect(classes[3]).toBe('c3-tooltip-name--data3');
});
});
describe('tooltip with data_order as Array with grouped data', function() {
beforeAll(function() {
dataOrder = [ 'data2', 'data1', 'data3' ];
dataGroups = [ [ 'data1', 'data2', 'data3' ]];
});
it('should display each data in order given by array', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data2');
expect(classes[2]).toBe('c3-tooltip-name--data1');
expect(classes[3]).toBe('c3-tooltip-name--data3');
});
});
describe('tooltip with data_order as desc with un-grouped data', function() {
beforeAll(function() {
dataOrder = 'desc';
});
it('should display each tooltip value descending order', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data3'); // 110
expect(classes[2]).toBe('c3-tooltip-name--data1'); // 100
expect(classes[3]).toBe('c3-tooltip-name--data2'); // 10
});
});
describe('tooltip with data_order as asc with un-grouped data', function() {
beforeAll(function() {
dataOrder = 'asc';
});
it('should display each tooltip value in ascending order', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data2'); // 10
expect(classes[2]).toBe('c3-tooltip-name--data1'); // 100
expect(classes[3]).toBe('c3-tooltip-name--data3'); // 110
});
});
describe('tooltip with data_order as NULL with un-grouped data', function() {
beforeAll(function() {
dataOrder = null;
});
it('should display each tooltip value in given data order', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data1');
expect(classes[2]).toBe('c3-tooltip-name--data2');
expect(classes[3]).toBe('c3-tooltip-name--data3');
});
});
describe('tooltip with data_order as Function with un-grouped data', function() {
beforeAll(function() {
var order = [ 'data2', 'data1', 'data3' ];
dataOrder = function(data1, data2) {
return order.indexOf(data1.id) - order.indexOf(data2.id);
};
});
it('should display each tooltip value in data order given by function', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data2');
expect(classes[2]).toBe('c3-tooltip-name--data1');
expect(classes[3]).toBe('c3-tooltip-name--data3');
});
});
describe('tooltip with data_order as Array with un-grouped data', function() {
beforeAll(function() {
dataOrder = [ 'data2', 'data1', 'data3' ];
});
it('should display each tooltip value in data order given by array', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data2');
expect(classes[2]).toBe('c3-tooltip-name--data1');
expect(classes[3]).toBe('c3-tooltip-name--data3');
});
});
describe('tooltip with tooltip_order as desc', function() {
beforeAll(function() {
tooltipConfiguration = {
order: 'desc'
};
// this should be ignored
dataOrder = 'asc';
dataGroups = [ [ 'data1', 'data2', 'data3' ]];
});
it('should display each tooltip value descending order', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data3'); // 110
expect(classes[2]).toBe('c3-tooltip-name--data1'); // 100
expect(classes[3]).toBe('c3-tooltip-name--data2'); // 10
});
});
describe('tooltip with tooltip_order as asc', function() {
beforeAll(function() {
tooltipConfiguration = {
order: 'asc'
};
// this should be ignored
dataOrder = 'desc';
dataGroups = [ [ 'data1', 'data2', 'data3' ]];
});
it('should display each tooltip value in ascending order', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data2'); // 10
expect(classes[2]).toBe('c3-tooltip-name--data1'); // 100
expect(classes[3]).toBe('c3-tooltip-name--data3'); // 110
});
});
describe('tooltip with tooltip_order as NULL', function() {
beforeAll(function() {
tooltipConfiguration = {
order: null
};
});
it('should display each tooltip value in given order', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data1');
expect(classes[2]).toBe('c3-tooltip-name--data2');
expect(classes[3]).toBe('c3-tooltip-name--data3');
});
});
describe('tooltip with tooltip_order as Function', function() {
beforeAll(function() {
var order = [ 'data2', 'data1', 'data3' ];
tooltipConfiguration = {
order: function(data1, data2) {
return order.indexOf(data1.id) - order.indexOf(data2.id);
}
};
});
it('should display each tooltip value in data order given by function', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data2');
expect(classes[2]).toBe('c3-tooltip-name--data1');
expect(classes[3]).toBe('c3-tooltip-name--data3');
});
});
describe('tooltip with tooltip_order as Array', function() {
beforeAll(function() {
tooltipConfiguration = {
order: [ 'data2', 'data1', 'data3' ]
};
});
it('should display each tooltip value in data order given by array', function() {
window.setMouseEvent(chart, 'mousemove', 100, 100, d3.select('.c3-event-rect-2').node());
var classes = d3.selectAll('.c3-tooltip tr')[0].map(function(node) {
return node.className;
});
expect(classes[0]).toBe(''); // header
expect(classes[1]).toBe('c3-tooltip-name--data2');
expect(classes[2]).toBe('c3-tooltip-name--data1');
expect(classes[3]).toBe('c3-tooltip-name--data3');
});
}); });
});
}); });

88
spec/type-spec.js

@ -11,7 +11,7 @@ describe('c3 chart types', function () {
describe('with data', function () { describe('with data', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -22,47 +22,47 @@ describe('c3 chart types', function () {
type: 'pie' type: 'pie'
} }
}; };
expect(true).toBeTruthy();
}); });
it('should return true', function () { it('should return true', function () {
expect(chart.internal.hasArcType()).toBeTruthy(); expect(chart.internal.hasArcType()).toBeTruthy();
}); });
it('should change chart type to "bar"', function () { describe('should change chart type to "bar"', function () {
args.data.type = 'bar'; beforeAll(function(){
expect(true).toBeTruthy(); args.data.type = 'bar';
}); });
it('should return false', function () { it('should return false', function () {
expect(chart.internal.hasArcType()).toBeFalsy(); expect(chart.internal.hasArcType()).toBeFalsy();
});
}); });
}); });
describe('with empty data', function () { describe('with empty data', function () {
it('should update args to have empty data', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [], columns: [],
type: 'pie' type: 'pie'
} }
}; };
expect(true).toBeTruthy();
}); });
it('should return true', function () { it('should return true', function () {
expect(chart.internal.hasArcType()).toBeTruthy(); expect(chart.internal.hasArcType()).toBeTruthy();
}); });
it('should change chart type to "bar"', function () { describe('should change chart type to "bar"', function () {
args.data.type = 'bar'; beforeAll(function(){
expect(true).toBeTruthy(); args.data.type = 'bar';
}); });
it('should return false', function () { it('should return false', function () {
expect(chart.internal.hasArcType()).toBeFalsy(); expect(chart.internal.hasArcType()).toBeFalsy();
});
}); });
}); });
@ -71,7 +71,7 @@ describe('c3 chart types', function () {
describe('internal.hasType', function () { describe('internal.hasType', function () {
it('should update args', function () { beforeAll(function () {
args = { args = {
data: { data: {
columns: [ columns: [
@ -82,7 +82,6 @@ describe('c3 chart types', function () {
type: 'pie' type: 'pie'
} }
}; };
expect(true).toBeTruthy();
}); });
it('should return true for "pie" type', function () { it('should return true for "pie" type', function () {
@ -97,41 +96,42 @@ describe('c3 chart types', function () {
expect(chart.internal.hasType('bar')).toBeFalsy(); expect(chart.internal.hasType('bar')).toBeFalsy();
}); });
it('should unload successfully', function () { describe('should unload successfully', function () {
chart.unload([]); beforeAll(function(){
expect(true).toBeTruthy(); chart.unload([]);
}); });
it('should return true for "pie" type even if no data', function () { it('should return true for "pie" type even if no data', function () {
expect(chart.internal.hasType('pie')).toBeTruthy(); expect(chart.internal.hasType('pie')).toBeTruthy();
}); });
it('should return false for "line" type even if no data', function () { it('should return false for "line" type even if no data', function () {
expect(chart.internal.hasType('line')).toBeFalsy(); expect(chart.internal.hasType('line')).toBeFalsy();
}); });
it('should return false for "bar" type even if no data', function () { it('should return false for "bar" type even if no data', function () {
expect(chart.internal.hasType('bar')).toBeFalsy(); expect(chart.internal.hasType('bar')).toBeFalsy();
}); });
it('should change chart type to "bar" successfully', function () { describe('should change chart type to "bar" successfully', function () {
args.data.type = 'bar'; beforeAll(function(){
expect(true).toBeTruthy(); args.data.type = 'bar';
}); });
it('should return false for "pie" type even if no data', function () { it('should return false for "pie" type even if no data', function () {
expect(chart.internal.hasType('pie')).toBeFalsy(); expect(chart.internal.hasType('pie')).toBeFalsy();
}); });
it('should return false for "line" type even if no data', function () { it('should return false for "line" type even if no data', function () {
expect(chart.internal.hasType('line')).toBeFalsy(); expect(chart.internal.hasType('line')).toBeFalsy();
}); });
it('should return true for "bar" type even if no data', function () { it('should return true for "bar" type even if no data', function () {
expect(chart.internal.hasType('bar')).toBeTruthy(); expect(chart.internal.hasType('bar')).toBeTruthy();
});
});
}); });
}); });
}); });

3
src/api.axis.js

@ -1,3 +1,6 @@
import { c3_chart_fn } from './core';
import { isValue, isDefined } from './util';
c3_chart_fn.axis = function () {}; c3_chart_fn.axis = function () {};
c3_chart_fn.axis.labels = function (labels) { c3_chart_fn.axis.labels = function (labels) {
var $$ = this.internal; var $$ = this.internal;

2
src/api.category.js

@ -1,3 +1,5 @@
import { c3_chart_fn } from './core';
c3_chart_fn.category = function (i, category) { c3_chart_fn.category = function (i, category) {
var $$ = this.internal, config = $$.config; var $$ = this.internal, config = $$.config;
if (arguments.length > 1) { if (arguments.length > 1) {

2
src/api.chart.js

@ -1,3 +1,5 @@
import { c3_chart_fn } from './core';
c3_chart_fn.resize = function (size) { c3_chart_fn.resize = function (size) {
var $$ = this.internal, config = $$.config; var $$ = this.internal, config = $$.config;
config.size_width = size ? size.width : null; config.size_width = size ? size.width : null;

2
src/api.color.js

@ -1,3 +1,5 @@
import { c3_chart_fn } from './core';
// TODO: fix // TODO: fix
c3_chart_fn.color = function (id) { c3_chart_fn.color = function (id) {
var $$ = this.internal; var $$ = this.internal;

2
src/api.data.js

@ -1,3 +1,5 @@
import { c3_chart_fn } from './core';
c3_chart_fn.data = function (targetIds) { c3_chart_fn.data = function (targetIds) {
var targets = this.internal.data.targets; var targets = this.internal.data.targets;
return typeof targetIds === 'undefined' ? targets : targets.filter(function (t) { return typeof targetIds === 'undefined' ? targets : targets.filter(function (t) {

6
src/api.flow.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_fn, c3_chart_internal_fn } from './core';
import { isValue, isDefined, diffDomain } from './util';
c3_chart_fn.flow = function (args) { c3_chart_fn.flow = function (args) {
var $$ = this.internal, var $$ = this.internal,
targets, data, notfoundIds = [], orgDataCount = $$.getMaxDataCount(), targets, data, notfoundIds = [], orgDataCount = $$.getMaxDataCount(),
@ -202,7 +206,7 @@ c3_chart_internal_fn.generateFlow = function (args) {
translateX = diffDomain(domain) / 2; translateX = diffDomain(domain) / 2;
} }
} }
} else if (flow.orgDataCount === 1 || flowStart.x === flowEnd.x) { } else if (flow.orgDataCount === 1 || (flowStart && flowStart.x) === (flowEnd && flowEnd.x)) {
translateX = $$.x(orgDomain[0]) - $$.x(domain[0]); translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
} else { } else {
if ($$.isTimeSeries()) { if ($$.isTimeSeries()) {

3
src/api.focus.js

@ -1,3 +1,6 @@
import CLASS from './class';
import { c3_chart_fn } from './core';
c3_chart_fn.focus = function (targetIds) { c3_chart_fn.focus = function (targetIds) {
var $$ = this.internal, candidates; var $$ = this.internal, candidates;

2
src/api.grid.js

@ -1,3 +1,5 @@
import { c3_chart_fn } from './core';
c3_chart_fn.xgrids = function (grids) { c3_chart_fn.xgrids = function (grids) {
var $$ = this.internal, config = $$.config; var $$ = this.internal, config = $$.config;
if (! grids) { return config.grid_x_lines; } if (! grids) { return config.grid_x_lines; }

3
src/api.group.js

@ -1,3 +1,6 @@
import { c3_chart_fn } from './core';
import { isUndefined } from './util';
c3_chart_fn.groups = function (groups) { c3_chart_fn.groups = function (groups) {
var $$ = this.internal, config = $$.config; var $$ = this.internal, config = $$.config;
if (isUndefined(groups)) { return config.data_groups; } if (isUndefined(groups)) { return config.data_groups; }

2
src/api.legend.js

@ -1,3 +1,5 @@
import { c3_chart_fn } from './core';
c3_chart_fn.legend = function () {}; c3_chart_fn.legend = function () {};
c3_chart_fn.legend.show = function (targetIds) { c3_chart_fn.legend.show = function (targetIds) {
var $$ = this.internal; var $$ = this.internal;

6
src/api.load.js

@ -1,9 +1,15 @@
import { c3_chart_fn } from './core';
c3_chart_fn.load = function (args) { c3_chart_fn.load = function (args) {
var $$ = this.internal, config = $$.config; var $$ = this.internal, config = $$.config;
// update xs if specified // update xs if specified
if (args.xs) { if (args.xs) {
$$.addXs(args.xs); $$.addXs(args.xs);
} }
// update names if exists
if ('names' in args) {
c3_chart_fn.data.names.bind(this)(args.names);
}
// update classes if exists // update classes if exists
if ('classes' in args) { if ('classes' in args) {
Object.keys(args.classes).forEach(function (id) { Object.keys(args.classes).forEach(function (id) {

3
src/api.region.js

@ -1,3 +1,6 @@
import CLASS from './class';
import { c3_chart_fn } from './core';
c3_chart_fn.regions = function (regions) { c3_chart_fn.regions = function (regions) {
var $$ = this.internal, config = $$.config; var $$ = this.internal, config = $$.config;
if (!regions) { return config.regions; } if (!regions) { return config.regions; }

4
src/api.selection.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_fn } from './core';
import { isDefined } from './util';
c3_chart_fn.selected = function (targetId) { c3_chart_fn.selected = function (targetId) {
var $$ = this.internal, d3 = $$.d3; var $$ = this.internal, d3 = $$.d3;
return d3.merge( return d3.merge(

2
src/api.show.js

@ -1,3 +1,5 @@
import { c3_chart_fn } from './core';
c3_chart_fn.show = function (targetIds, options) { c3_chart_fn.show = function (targetIds, options) {
var $$ = this.internal, targets; var $$ = this.internal, targets;

3
src/api.tooltip.js

@ -1,3 +1,6 @@
import { c3_chart_fn } from './core';
import { isValue } from './util';
c3_chart_fn.tooltip = function () {}; c3_chart_fn.tooltip = function () {};
c3_chart_fn.tooltip.show = function (args) { c3_chart_fn.tooltip.show = function (args) {
var $$ = this.internal, index, mouse; var $$ = this.internal, index, mouse;

2
src/api.transform.js

@ -1,3 +1,5 @@
import { c3_chart_fn, c3_chart_internal_fn } from './core';
c3_chart_fn.transform = function (type, targetIds) { c3_chart_fn.transform = function (type, targetIds) {
var $$ = this.internal, var $$ = this.internal,
options = ['pie', 'donut'].indexOf(type) >= 0 ? {withTransform: true} : null; options = ['pie', 'donut'].indexOf(type) >= 0 ? {withTransform: true} : null;

2
src/api.x.js

@ -1,3 +1,5 @@
import { c3_chart_fn } from './core';
c3_chart_fn.x = function (x) { c3_chart_fn.x = function (x) {
var $$ = this.internal; var $$ = this.internal;
if (arguments.length) { if (arguments.length) {

3
src/api.zoom.js

@ -1,3 +1,6 @@
import { c3_chart_fn } from './core';
import { isDefined } from './util';
c3_chart_fn.zoom = function (domain) { c3_chart_fn.zoom = function (domain) {
var $$ = this.internal; var $$ = this.internal;
if (domain) { if (domain) {

55
src/arc.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
import { isFunction } from './util';
c3_chart_internal_fn.initPie = function () { c3_chart_internal_fn.initPie = function () {
var $$ = this, d3 = $$.d3, config = $$.config; var $$ = this, d3 = $$.d3, config = $$.config;
$$.pie = d3.layout.pie().value(function (d) { $$.pie = d3.layout.pie().value(function (d) {
@ -29,7 +33,12 @@ c3_chart_internal_fn.updateArc = function () {
c3_chart_internal_fn.updateAngle = function (d) { c3_chart_internal_fn.updateAngle = function (d) {
var $$ = this, config = $$.config, var $$ = this, config = $$.config,
found = false, index = 0, found = false, index = 0,
gMin = config.gauge_min, gMax = config.gauge_max, gTic, gValue; gMin, gMax, gTic, gValue;
if (!config) {
return null;
}
$$.pie($$.filterTargetsToShow($$.data.targets)).forEach(function (t) { $$.pie($$.filterTargetsToShow($$.data.targets)).forEach(function (t) {
if (! found && t.data.id === d.data.id) { if (! found && t.data.id === d.data.id) {
found = true; found = true;
@ -45,9 +54,11 @@ c3_chart_internal_fn.updateAngle = function (d) {
d.endAngle = d.startAngle; d.endAngle = d.startAngle;
} }
if ($$.isGaugeType(d.data)) { if ($$.isGaugeType(d.data)) {
gTic = (Math.PI) / (gMax - gMin); 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); gValue = d.value < gMin ? 0 : d.value < gMax ? d.value - gMin : (gMax - gMin);
d.startAngle = -1 * (Math.PI / 2); d.startAngle = config.gauge_startingAngle;
d.endAngle = d.startAngle + gTic * gValue; d.endAngle = d.startAngle + gTic * gValue;
} }
return found ? d : null; return found ? d : null;
@ -101,8 +112,13 @@ c3_chart_internal_fn.transformForArcLabel = function (d) {
x = isNaN(c[0]) ? 0 : c[0]; x = isNaN(c[0]) ? 0 : c[0];
y = isNaN(c[1]) ? 0 : c[1]; y = isNaN(c[1]) ? 0 : c[1];
h = Math.sqrt(x * x + y * y); h = Math.sqrt(x * x + y * y);
// TODO: ratio should be an option? if ($$.hasType('donut') && config.donut_label_ratio) {
ratio = $$.radius && h ? (36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) * $$.radius / h : 0; 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) + ")"; translate = "translate(" + (x * ratio) + ',' + (y * ratio) + ")";
} }
else if (updated && hasGauge && $$.visibleTargetCount > 1) { else if (updated && hasGauge && $$.visibleTargetCount > 1) {
@ -116,7 +132,8 @@ c3_chart_internal_fn.transformForArcLabel = function (d) {
c3_chart_internal_fn.getArcRatio = function (d) { c3_chart_internal_fn.getArcRatio = function (d) {
var $$ = this, var $$ = this,
whole = $$.hasType('gauge') ? Math.PI : (Math.PI * 2); config = $$.config,
whole = Math.PI * ($$.hasType('gauge') && !config.gauge_fullCircle ? 1 : 2);
return d ? (d.endAngle - d.startAngle) / whole : null; return d ? (d.endAngle - d.startAngle) / whole : null;
}; };
@ -142,6 +159,13 @@ c3_chart_internal_fn.textForArcLabel = function (d) {
return format ? format(value, ratio, id) : $$.defaultArcValueFormat(value, ratio); return format ? format(value, ratio, id) : $$.defaultArcValueFormat(value, ratio);
}; };
c3_chart_internal_fn.textForGaugeMinMax = function (value, isMax) {
var $$ = this,
format = $$.getGaugeLabelExtents();
return format ? format(value, isMax) : value;
};
c3_chart_internal_fn.expandArc = function (targetIds) { c3_chart_internal_fn.expandArc = function (targetIds) {
var $$ = this, interval; var $$ = this, interval;
@ -241,6 +265,11 @@ c3_chart_internal_fn.getArcLabelFormat = function () {
return format; return format;
}; };
c3_chart_internal_fn.getGaugeLabelExtents = function () {
var $$ = this, config = $$.config;
return config.gauge_label_extents;
};
c3_chart_internal_fn.getArcTitle = function () { c3_chart_internal_fn.getArcTitle = function () {
var $$ = this; var $$ = this;
return $$.hasType('donut') ? $$.config.donut_title : ""; return $$.hasType('donut') ? $$.config.donut_title : "";
@ -291,7 +320,7 @@ c3_chart_internal_fn.redrawArc = function (duration, durationForExit, withTransf
.style("opacity", 0) .style("opacity", 0)
.each(function (d) { .each(function (d) {
if ($$.isGaugeType(d.data)) { if ($$.isGaugeType(d.data)) {
d.startAngle = d.endAngle = -1 * (Math.PI / 2); d.startAngle = d.endAngle = config.gauge_startingAngle;
} }
this._current = d; this._current = d;
}); });
@ -435,8 +464,8 @@ c3_chart_internal_fn.redrawArc = function (duration, durationForExit, withTransf
var d = { var d = {
data: [{value: config.gauge_max}], data: [{value: config.gauge_max}],
startAngle: -1 * (Math.PI / 2), startAngle: config.gauge_startingAngle,
endAngle: Math.PI / 2, endAngle: -1 * config.gauge_startingAngle,
index: index++ index: index++
}; };
return $$.getArc(d, true, true); return $$.getArc(d, true, true);
@ -445,13 +474,13 @@ c3_chart_internal_fn.redrawArc = function (duration, durationForExit, withTransf
.attr("dy", ".75em") .attr("dy", ".75em")
.text(config.gauge_label_show ? config.gauge_units : ''); .text(config.gauge_label_show ? config.gauge_units : '');
$$.arcs.select('.' + CLASS.chartArcsGaugeMin) $$.arcs.select('.' + CLASS.chartArcsGaugeMin)
.attr("dx", -1 * ($$.innerRadius + (($$.radius - $$.innerRadius) / 2)) + "px") .attr("dx", -1 * ($$.innerRadius + (($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2))) + "px")
.attr("dy", "1.2em") .attr("dy", "1.2em")
.text(config.gauge_label_show ? config.gauge_min : ''); .text(config.gauge_label_show ? $$.textForGaugeMinMax(config.gauge_min, false) : '');
$$.arcs.select('.' + CLASS.chartArcsGaugeMax) $$.arcs.select('.' + CLASS.chartArcsGaugeMax)
.attr("dx", $$.innerRadius + (($$.radius - $$.innerRadius) / 2) + "px") .attr("dx", $$.innerRadius + (($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2)) + "px")
.attr("dy", "1.2em") .attr("dy", "1.2em")
.text(config.gauge_label_show ? config.gauge_max : ''); .text(config.gauge_label_show ? $$.textForGaugeMinMax(config.gauge_max, true) : '');
} }
}; };
c3_chart_internal_fn.initGauge = function () { c3_chart_internal_fn.initGauge = function () {

30
src/axis.js

@ -1,4 +1,9 @@
function Axis(owner) { import CLASS from './class';
import { inherit, API } from './core';
import { isValue, isFunction, isString, isEmpty } from './util';
import c3_axis from './c3.axis';
export default function Axis(owner) {
API.call(this, owner); API.call(this, owner);
} }
@ -76,17 +81,16 @@ Axis.prototype.updateXAxisTickValues = function updateXAxisTickValues(targets, a
} }
return tickValues; return tickValues;
}; };
Axis.prototype.getYAxis = function getYAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition) { Axis.prototype.getYAxis = function getYAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) {
var axisParams = { var $$ = this.owner, config = $$.config,
withOuterTick: withOuterTick, axisParams = {
withoutTransition: withoutTransition, withOuterTick: withOuterTick,
}, withoutTransition: withoutTransition,
$$ = this.owner, tickTextRotate: withoutRotateTickText ? 0 : config.axis_y_tick_rotate
d3 = $$.d3, },
config = $$.config, axis = c3_axis($$.d3, axisParams).scale(scale).orient(orient).tickFormat(tickFormat);
axis = c3_axis(d3, axisParams).scale(scale).orient(orient).tickFormat(tickFormat);
if ($$.isTimeSeriesY()) { if ($$.isTimeSeriesY()) {
axis.ticks(d3.time[config.axis_y_tick_time_value], config.axis_y_tick_time_interval); axis.ticks($$.d3.time[config.axis_y_tick_time_value], config.axis_y_tick_time_interval);
} else { } else {
axis.tickValues(tickValues); axis.tickValues(tickValues);
} }
@ -276,10 +280,10 @@ Axis.prototype.getMaxTickWidth = function getMaxTickWidth(id, withoutRecompute)
targetsToShow = $$.filterTargetsToShow($$.data.targets); targetsToShow = $$.filterTargetsToShow($$.data.targets);
if (id === 'y') { if (id === 'y') {
scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y')); scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y'));
axis = this.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, false, true); axis = this.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, false, true, true);
} else if (id === 'y2') { } else if (id === 'y2') {
scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2')); scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2'));
axis = this.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, false, true); axis = this.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, false, true, true);
} else { } else {
scale = $$.x.copy().domain($$.getXDomain(targetsToShow)); scale = $$.x.copy().domain($$.getXDomain(targetsToShow));
axis = this.getXAxis(scale, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, false, true, true); axis = this.getXAxis(scale, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, false, true, true);

2
src/c3.axis.js

@ -3,7 +3,7 @@
// 2. ceil values of translate/x/y to int for half pixel antialiasing // 2. ceil values of translate/x/y to int for half pixel antialiasing
// 3. multiline tick text // 3. multiline tick text
var tickTextCharSize; var tickTextCharSize;
function c3_axis(d3, params) { export default function c3_axis(d3, params) {
var scale = d3.scale.linear(), orient = "bottom", innerTickSize = 6, outerTickSize, tickPadding = 3, tickValues = null, tickFormat, tickArguments; var scale = d3.scale.linear(), orient = "bottom", innerTickSize = 6, outerTickSize, tickPadding = 3, tickValues = null, tickFormat, tickArguments;
var tickOffset = 0, tickCulling = true, tickCentered; var tickOffset = 0, tickCulling = true, tickCentered;

2
src/cache.js

@ -1,3 +1,5 @@
import { c3_chart_internal_fn } from './core';
c3_chart_internal_fn.hasCaches = function (ids) { c3_chart_internal_fn.hasCaches = function (ids) {
for (var i = 0; i < ids.length; i++) { for (var i = 0; i < ids.length; i++) {
if (! (ids[i] in this.cache)) { return false; } if (! (ids[i] in this.cache)) { return false; }

2
src/category.js

@ -1,3 +1,5 @@
import { c3_chart_internal_fn } from './core';
c3_chart_internal_fn.categoryName = function (i) { c3_chart_internal_fn.categoryName = function (i) {
var config = this.config; var config = this.config;
return i < config.axis_x_categories.length ? config.axis_x_categories[i] : i; return i < config.axis_x_categories.length ? config.axis_x_categories[i] : i;

101
src/class-utils.js

@ -0,0 +1,101 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
c3_chart_internal_fn.generateClass = function (prefix, targetId) {
return " " + prefix + " " + prefix + this.getTargetSelectorSuffix(targetId);
};
c3_chart_internal_fn.classText = function (d) {
return this.generateClass(CLASS.text, d.index);
};
c3_chart_internal_fn.classTexts = function (d) {
return this.generateClass(CLASS.texts, d.id);
};
c3_chart_internal_fn.classShape = function (d) {
return this.generateClass(CLASS.shape, d.index);
};
c3_chart_internal_fn.classShapes = function (d) {
return this.generateClass(CLASS.shapes, d.id);
};
c3_chart_internal_fn.classLine = function (d) {
return this.classShape(d) + this.generateClass(CLASS.line, d.id);
};
c3_chart_internal_fn.classLines = function (d) {
return this.classShapes(d) + this.generateClass(CLASS.lines, d.id);
};
c3_chart_internal_fn.classCircle = function (d) {
return this.classShape(d) + this.generateClass(CLASS.circle, d.index);
};
c3_chart_internal_fn.classCircles = function (d) {
return this.classShapes(d) + this.generateClass(CLASS.circles, d.id);
};
c3_chart_internal_fn.classBar = function (d) {
return this.classShape(d) + this.generateClass(CLASS.bar, d.index);
};
c3_chart_internal_fn.classBars = function (d) {
return this.classShapes(d) + this.generateClass(CLASS.bars, d.id);
};
c3_chart_internal_fn.classArc = function (d) {
return this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id);
};
c3_chart_internal_fn.classArcs = function (d) {
return this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id);
};
c3_chart_internal_fn.classArea = function (d) {
return this.classShape(d) + this.generateClass(CLASS.area, d.id);
};
c3_chart_internal_fn.classAreas = function (d) {
return this.classShapes(d) + this.generateClass(CLASS.areas, d.id);
};
c3_chart_internal_fn.classRegion = function (d, i) {
return this.generateClass(CLASS.region, i) + ' ' + ('class' in d ? d['class'] : '');
};
c3_chart_internal_fn.classEvent = function (d) {
return this.generateClass(CLASS.eventRect, d.index);
};
c3_chart_internal_fn.classTarget = function (id) {
var $$ = this;
var additionalClassSuffix = $$.config.data_classes[id], additionalClass = '';
if (additionalClassSuffix) {
additionalClass = ' ' + CLASS.target + '-' + additionalClassSuffix;
}
return $$.generateClass(CLASS.target, id) + additionalClass;
};
c3_chart_internal_fn.classFocus = function (d) {
return this.classFocused(d) + this.classDefocused(d);
};
c3_chart_internal_fn.classFocused = function (d) {
return ' ' + (this.focusedTargetIds.indexOf(d.id) >= 0 ? CLASS.focused : '');
};
c3_chart_internal_fn.classDefocused = function (d) {
return ' ' + (this.defocusedTargetIds.indexOf(d.id) >= 0 ? CLASS.defocused : '');
};
c3_chart_internal_fn.classChartText = function (d) {
return CLASS.chartText + this.classTarget(d.id);
};
c3_chart_internal_fn.classChartLine = function (d) {
return CLASS.chartLine + this.classTarget(d.id);
};
c3_chart_internal_fn.classChartBar = function (d) {
return CLASS.chartBar + this.classTarget(d.id);
};
c3_chart_internal_fn.classChartArc = function (d) {
return CLASS.chartArc + this.classTarget(d.data.id);
};
c3_chart_internal_fn.getTargetSelectorSuffix = function (targetId) {
return targetId || targetId === 0 ? ('-' + targetId).replace(/[\s?!@#$%^&*()_=+,.<>'":;\[\]\/|~`{}\\]/g, '-') : '';
};
c3_chart_internal_fn.selectorTarget = function (id, prefix) {
return (prefix || '') + '.' + CLASS.target + this.getTargetSelectorSuffix(id);
};
c3_chart_internal_fn.selectorTargets = function (ids, prefix) {
var $$ = this;
ids = ids || [];
return ids.length ? ids.map(function (id) { return $$.selectorTarget(id, prefix); }) : null;
};
c3_chart_internal_fn.selectorLegend = function (id) {
return '.' + CLASS.legendItem + this.getTargetSelectorSuffix(id);
};
c3_chart_internal_fn.selectorLegends = function (ids) {
var $$ = this;
return ids && ids.length ? ids.map(function (id) { return $$.selectorLegend(id); }) : null;
};

100
src/class.js

@ -1,4 +1,4 @@
var CLASS = c3_chart_internal_fn.CLASS = { export default {
target: 'c3-target', target: 'c3-target',
chart: 'c3-chart', chart: 'c3-chart',
chartLine: 'c3-chart-line', chartLine: 'c3-chart-line',
@ -76,101 +76,3 @@ var CLASS = c3_chart_internal_fn.CLASS = {
SELECTED: '_selected_', SELECTED: '_selected_',
INCLUDED: '_included_' INCLUDED: '_included_'
}; };
c3_chart_internal_fn.generateClass = function (prefix, targetId) {
return " " + prefix + " " + prefix + this.getTargetSelectorSuffix(targetId);
};
c3_chart_internal_fn.classText = function (d) {
return this.generateClass(CLASS.text, d.index);
};
c3_chart_internal_fn.classTexts = function (d) {
return this.generateClass(CLASS.texts, d.id);
};
c3_chart_internal_fn.classShape = function (d) {
return this.generateClass(CLASS.shape, d.index);
};
c3_chart_internal_fn.classShapes = function (d) {
return this.generateClass(CLASS.shapes, d.id);
};
c3_chart_internal_fn.classLine = function (d) {
return this.classShape(d) + this.generateClass(CLASS.line, d.id);
};
c3_chart_internal_fn.classLines = function (d) {
return this.classShapes(d) + this.generateClass(CLASS.lines, d.id);
};
c3_chart_internal_fn.classCircle = function (d) {
return this.classShape(d) + this.generateClass(CLASS.circle, d.index);
};
c3_chart_internal_fn.classCircles = function (d) {
return this.classShapes(d) + this.generateClass(CLASS.circles, d.id);
};
c3_chart_internal_fn.classBar = function (d) {
return this.classShape(d) + this.generateClass(CLASS.bar, d.index);
};
c3_chart_internal_fn.classBars = function (d) {
return this.classShapes(d) + this.generateClass(CLASS.bars, d.id);
};
c3_chart_internal_fn.classArc = function (d) {
return this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id);
};
c3_chart_internal_fn.classArcs = function (d) {
return this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id);
};
c3_chart_internal_fn.classArea = function (d) {
return this.classShape(d) + this.generateClass(CLASS.area, d.id);
};
c3_chart_internal_fn.classAreas = function (d) {
return this.classShapes(d) + this.generateClass(CLASS.areas, d.id);
};
c3_chart_internal_fn.classRegion = function (d, i) {
return this.generateClass(CLASS.region, i) + ' ' + ('class' in d ? d['class'] : '');
};
c3_chart_internal_fn.classEvent = function (d) {
return this.generateClass(CLASS.eventRect, d.index);
};
c3_chart_internal_fn.classTarget = function (id) {
var $$ = this;
var additionalClassSuffix = $$.config.data_classes[id], additionalClass = '';
if (additionalClassSuffix) {
additionalClass = ' ' + CLASS.target + '-' + additionalClassSuffix;
}
return $$.generateClass(CLASS.target, id) + additionalClass;
};
c3_chart_internal_fn.classFocus = function (d) {
return this.classFocused(d) + this.classDefocused(d);
};
c3_chart_internal_fn.classFocused = function (d) {
return ' ' + (this.focusedTargetIds.indexOf(d.id) >= 0 ? CLASS.focused : '');
};
c3_chart_internal_fn.classDefocused = function (d) {
return ' ' + (this.defocusedTargetIds.indexOf(d.id) >= 0 ? CLASS.defocused : '');
};
c3_chart_internal_fn.classChartText = function (d) {
return CLASS.chartText + this.classTarget(d.id);
};
c3_chart_internal_fn.classChartLine = function (d) {
return CLASS.chartLine + this.classTarget(d.id);
};
c3_chart_internal_fn.classChartBar = function (d) {
return CLASS.chartBar + this.classTarget(d.id);
};
c3_chart_internal_fn.classChartArc = function (d) {
return CLASS.chartArc + this.classTarget(d.data.id);
};
c3_chart_internal_fn.getTargetSelectorSuffix = function (targetId) {
return targetId || targetId === 0 ? ('-' + targetId).replace(/[\s?!@#$%^&*()_=+,.<>'":;\[\]\/|~`{}\\]/g, '-') : '';
};
c3_chart_internal_fn.selectorTarget = function (id, prefix) {
return (prefix || '') + '.' + CLASS.target + this.getTargetSelectorSuffix(id);
};
c3_chart_internal_fn.selectorTargets = function (ids, prefix) {
var $$ = this;
ids = ids || [];
return ids.length ? ids.map(function (id) { return $$.selectorTarget(id, prefix); }) : null;
};
c3_chart_internal_fn.selectorLegend = function (id) {
return '.' + CLASS.legendItem + this.getTargetSelectorSuffix(id);
};
c3_chart_internal_fn.selectorLegends = function (ids) {
var $$ = this;
return ids && ids.length ? ids.map(function (id) { return $$.selectorLegend(id); }) : null;
};

2
src/clip.js

@ -1,3 +1,5 @@
import { c3_chart_internal_fn } from './core';
c3_chart_internal_fn.getClipPath = function (id) { c3_chart_internal_fn.getClipPath = function (id) {
var isIE9 = window.navigator.appVersion.toLowerCase().indexOf("msie 9.") >= 0; var isIE9 = window.navigator.appVersion.toLowerCase().indexOf("msie 9.") >= 0;
return "url(" + (isIE9 ? "" : document.URL.split('#')[0]) + "#" + id + ")"; return "url(" + (isIE9 ? "" : document.URL.split('#')[0]) + "#" + id + ")";

3
src/color.js

@ -1,3 +1,6 @@
import { c3_chart_internal_fn } from './core';
import { notEmpty } from './util';
c3_chart_internal_fn.generateColor = function () { c3_chart_internal_fn.generateColor = function () {
var $$ = this, config = $$.config, d3 = $$.d3, var $$ = this, config = $$.config, d3 = $$.d3,
colors = config.data_colors, colors = config.data_colors,

14
src/config.js

@ -1,6 +1,10 @@
import { c3_chart_internal_fn } from './core';
import { isDefined } from './util';
c3_chart_internal_fn.getDefaultConfig = function () { c3_chart_internal_fn.getDefaultConfig = function () {
var config = { var config = {
bindto: '#chart', bindto: '#chart',
svg_classname: undefined,
size_width: undefined, size_width: undefined,
size_height: undefined, size_height: undefined,
padding_left: undefined, padding_left: undefined,
@ -17,6 +21,7 @@ c3_chart_internal_fn.getDefaultConfig = function () {
zoom_onzoomend: function () {}, zoom_onzoomend: function () {},
zoom_x_min: undefined, zoom_x_min: undefined,
zoom_x_max: undefined, zoom_x_max: undefined,
interaction_brighten: true,
interaction_enabled: true, interaction_enabled: true,
onmouseover: function () {}, onmouseover: function () {},
onmouseout: function () {}, onmouseout: function () {},
@ -55,6 +60,7 @@ c3_chart_internal_fn.getDefaultConfig = function () {
data_onselected: function () {}, data_onselected: function () {},
data_onunselected: function () {}, data_onunselected: function () {},
data_url: undefined, data_url: undefined,
data_headers: undefined,
data_json: undefined, data_json: undefined,
data_rows: undefined, data_rows: undefined,
data_columns: undefined, data_columns: undefined,
@ -119,6 +125,7 @@ c3_chart_internal_fn.getDefaultConfig = function () {
axis_y_tick_format: undefined, axis_y_tick_format: undefined,
axis_y_tick_outer: true, axis_y_tick_outer: true,
axis_y_tick_values: null, axis_y_tick_values: null,
axis_y_tick_rotate: 0,
axis_y_tick_count: undefined, axis_y_tick_count: undefined,
axis_y_tick_time_value: undefined, axis_y_tick_time_value: undefined,
axis_y_tick_time_interval: undefined, axis_y_tick_time_interval: undefined,
@ -165,17 +172,22 @@ c3_chart_internal_fn.getDefaultConfig = function () {
bar_zerobased: true, bar_zerobased: true,
// area // area
area_zerobased: true, area_zerobased: true,
area_above: false,
// pie // pie
pie_label_show: true, pie_label_show: true,
pie_label_format: undefined, pie_label_format: undefined,
pie_label_threshold: 0.05, pie_label_threshold: 0.05,
pie_label_ratio: undefined,
pie_expand: {}, pie_expand: {},
pie_expand_duration: 50, pie_expand_duration: 50,
// gauge // gauge
gauge_fullCircle: false,
gauge_label_show: true, gauge_label_show: true,
gauge_label_format: undefined, gauge_label_format: undefined,
gauge_min: 0, gauge_min: 0,
gauge_max: 100, gauge_max: 100,
gauge_startingAngle: -1 * Math.PI/2,
gauge_label_extents: undefined,
gauge_units: undefined, gauge_units: undefined,
gauge_width: undefined, gauge_width: undefined,
gauge_arcs_minWidth: 5, gauge_arcs_minWidth: 5,
@ -185,6 +197,7 @@ c3_chart_internal_fn.getDefaultConfig = function () {
donut_label_show: true, donut_label_show: true,
donut_label_format: undefined, donut_label_format: undefined,
donut_label_threshold: 0.05, donut_label_threshold: 0.05,
donut_label_ratio: undefined,
donut_width: undefined, donut_width: undefined,
donut_title: "", donut_title: "",
donut_expand: {}, donut_expand: {},
@ -196,6 +209,7 @@ c3_chart_internal_fn.getDefaultConfig = function () {
// tooltip - show when mouseover on each data // tooltip - show when mouseover on each data
tooltip_show: true, tooltip_show: true,
tooltip_grouped: true, tooltip_grouped: true,
tooltip_order: undefined,
tooltip_format_title: undefined, tooltip_format_title: undefined,
tooltip_format_name: undefined, tooltip_format_name: undefined,
tooltip_format_value: undefined, tooltip_format_value: undefined,

46
src/core.js

@ -1,14 +1,18 @@
var c3 = { version: "0.4.11-rc4" }; import Axis from './axis';
import CLASS from './class';
import { isValue, isFunction, isString, isUndefined, isDefined, ceil10, asHalfPixel, diffDomain, isEmpty, notEmpty, getOption, hasValue, sanitise, getPathBox } from './util';
var c3_chart_fn, export var c3 = { version: "0.4.13" };
c3_chart_internal_fn,
c3_chart_internal_axis_fn;
function API(owner) { export var c3_chart_fn;
export var c3_chart_internal_fn;
export var c3_chart_internal_axis_fn;
export function API(owner) {
this.owner = owner; this.owner = owner;
} }
function inherit(base, derived) { export function inherit(base, derived) {
if (Object.create) { if (Object.create) {
derived.prototype = Object.create(base.prototype); derived.prototype = Object.create(base.prototype);
@ -81,7 +85,7 @@ c3_chart_internal_fn.init = function () {
$$.initParams(); $$.initParams();
if (config.data_url) { if (config.data_url) {
$$.convertUrlToData(config.data_url, config.data_mimeType, config.data_keys, $$.initWithData); $$.convertUrlToData(config.data_url, config.data_mimeType, config.data_headers, config.data_keys, $$.initWithData);
} }
else if (config.data_json) { else if (config.data_json) {
$$.initWithData($$.convertJsonToData(config.data_json, config.data_keys)); $$.initWithData($$.convertJsonToData(config.data_json, config.data_keys));
@ -253,6 +257,10 @@ c3_chart_internal_fn.initWithData = function (data) {
.on('mouseenter', function () { return config.onmouseover.call($$); }) .on('mouseenter', function () { return config.onmouseover.call($$); })
.on('mouseleave', function () { return config.onmouseout.call($$); }); .on('mouseleave', function () { return config.onmouseout.call($$); });
if ($$.config.svg_classname) {
$$.svg.attr('class', $$.config.svg_classname);
}
// Define defs // Define defs
defs = $$.svg.append("defs"); defs = $$.svg.append("defs");
$$.clipChart = $$.appendClip(defs, $$.clipId); $$.clipChart = $$.appendClip(defs, $$.clipId);
@ -416,7 +424,7 @@ c3_chart_internal_fn.updateSizes = function () {
// for arc // for arc
$$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0); $$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0);
$$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10); $$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10);
if ($$.hasType('gauge')) { if ($$.hasType('gauge') && !config.gauge_fullCircle) {
$$.arcHeight += $$.height - $$.getGaugeLabelHeight(); $$.arcHeight += $$.height - $$.getGaugeLabelHeight();
} }
if ($$.updateRadius) { $$.updateRadius(); } if ($$.updateRadius) { $$.updateRadius(); }
@ -784,7 +792,8 @@ c3_chart_internal_fn.initialOpacityForCircle = function (d) {
return d.value !== null && this.withoutFadeIn[d.id] ? this.opacityForCircle(d) : 0; return d.value !== null && this.withoutFadeIn[d.id] ? this.opacityForCircle(d) : 0;
}; };
c3_chart_internal_fn.opacityForCircle = function (d) { c3_chart_internal_fn.opacityForCircle = function (d) {
var opacity = this.config.point_show ? 1 : 0; var isPointShouldBeShown = isFunction(this.config.point_show) ? this.config.point_show(d) : this.config.point_show;
var opacity = isPointShouldBeShown ? 1 : 0;
return isValue(d.value) ? (this.isScatterType(d) ? 0.5 : opacity) : 0; return isValue(d.value) ? (this.isScatterType(d) ? 0.5 : opacity) : 0;
}; };
c3_chart_internal_fn.opacityForText = function () { c3_chart_internal_fn.opacityForText = function () {
@ -1033,6 +1042,8 @@ c3_chart_internal_fn.parseDate = function (date) {
parsedDate = date; parsedDate = date;
} else if (typeof date === 'string') { } else if (typeof date === 'string') {
parsedDate = $$.dataTimeFormat($$.config.data_xFormat).parse(date); parsedDate = $$.dataTimeFormat($$.config.data_xFormat).parse(date);
} else if (typeof date === 'object') {
parsedDate = new Date(+date);
} else if (typeof date === 'number' && !isNaN(date)) { } else if (typeof date === 'number' && !isNaN(date)) {
parsedDate = new Date(+date); parsedDate = new Date(+date);
} }
@ -1056,3 +1067,20 @@ c3_chart_internal_fn.isTabVisible = function () {
return document[hidden] ? false : true; return document[hidden] ? false : true;
}; };
c3_chart_internal_fn.isValue = isValue;
c3_chart_internal_fn.isFunction = isFunction;
c3_chart_internal_fn.isString = isString;
c3_chart_internal_fn.isUndefined = isUndefined;
c3_chart_internal_fn.isDefined = isDefined;
c3_chart_internal_fn.ceil10 = ceil10;
c3_chart_internal_fn.asHalfPixel = asHalfPixel;
c3_chart_internal_fn.diffDomain = diffDomain;
c3_chart_internal_fn.isEmpty = isEmpty;
c3_chart_internal_fn.notEmpty = notEmpty;
c3_chart_internal_fn.notEmpty = notEmpty;
c3_chart_internal_fn.getOption = getOption;
c3_chart_internal_fn.hasValue = hasValue;
c3_chart_internal_fn.sanitise = sanitise;
c3_chart_internal_fn.getPathBox = getPathBox;
c3_chart_internal_fn.CLASS = CLASS;

57
src/data.convert.js

@ -1,16 +1,26 @@
c3_chart_internal_fn.convertUrlToData = function (url, mimeType, keys, done) { import { c3_chart_internal_fn } from './core';
import { isValue, isUndefined, isDefined, notEmpty } from './util';
c3_chart_internal_fn.convertUrlToData = function (url, mimeType, headers, keys, done) {
var $$ = this, type = mimeType ? mimeType : 'csv'; var $$ = this, type = mimeType ? mimeType : 'csv';
$$.d3.xhr(url, function (error, data) { var req = $$.d3.xhr(url);
if (headers) {
Object.keys(headers).forEach(function (header) {
req.header(header, headers[header]);
});
}
req.get(function (error, data) {
var d; var d;
var dataResponse = data.response || data.responseText; // Fixes IE9 XHR issue; see #1345
if (!data) { if (!data) {
throw new Error(error.responseURL + ' ' + error.status + ' (' + error.statusText + ')'); throw new Error(error.responseURL + ' ' + error.status + ' (' + error.statusText + ')');
} }
if (type === 'json') { if (type === 'json') {
d = $$.convertJsonToData(JSON.parse(data.response), keys); d = $$.convertJsonToData(JSON.parse(dataResponse), keys);
} else if (type === 'tsv') { } else if (type === 'tsv') {
d = $$.convertTsvToData(data.response); d = $$.convertTsvToData(dataResponse);
} else { } else {
d = $$.convertCsvToData(data.response); d = $$.convertCsvToData(dataResponse);
} }
done.call($$, d); done.call($$, d);
}); });
@ -48,7 +58,10 @@ c3_chart_internal_fn.convertJsonToData = function (json, keys) {
var new_row = []; var new_row = [];
targetKeys.forEach(function (key) { targetKeys.forEach(function (key) {
// convert undefined to null because undefined data will be removed in convertDataToTargets() // convert undefined to null because undefined data will be removed in convertDataToTargets()
var v = isUndefined(o[key]) ? null : o[key]; var v = $$.findValueInJson(o, key);
if (isUndefined(v)) {
v = null;
}
new_row.push(v); new_row.push(v);
}); });
new_rows.push(new_row); new_rows.push(new_row);
@ -62,6 +75,20 @@ c3_chart_internal_fn.convertJsonToData = function (json, keys) {
} }
return data; return data;
}; };
c3_chart_internal_fn.findValueInJson = function (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;
};
c3_chart_internal_fn.convertRowsToData = function (rows) { c3_chart_internal_fn.convertRowsToData = function (rows) {
var keys = rows[0], new_row = {}, new_rows = [], i, j; var keys = rows[0], new_row = {}, new_rows = [], i, j;
for (i = 1; i < rows.length; i++) { for (i = 1; i < rows.length; i++) {
@ -140,12 +167,20 @@ c3_chart_internal_fn.convertDataToTargets = function (data, appendXs) {
id: convertedId, id: convertedId,
id_org: id, id_org: id,
values: data.map(function (d, i) { values: data.map(function (d, i) {
var xKey = $$.getXKey(id), rawX = d[xKey], x = $$.generateTargetX(rawX, id, i), var xKey = $$.getXKey(id), rawX = d[xKey],
value = d[id] !== null && !isNaN(d[id]) ? +d[id] : null; value = d[id] !== null && !isNaN(d[id]) ? +d[id] : null, x;
// use x as categories if custom x and categorized // use x as categories if custom x and categorized
if ($$.isCustomX() && $$.isCategorized() && index === 0 && rawX) { if ($$.isCustomX() && $$.isCategorized() && !isUndefined(rawX)) {
if (i === 0) { config.axis_x_categories = []; } if (index === 0 && i === 0) {
config.axis_x_categories.push(rawX); 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 // mark as x = undefined if value is undefined and filter to remove after mapped
if (isUndefined(d[id]) || $$.data.xs[id].length <= i) { if (isUndefined(d[id]) || $$.data.xs[id].length <= i) {

26
src/data.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
import { isValue, isFunction, isArray, notEmpty, hasValue } from './util';
c3_chart_internal_fn.isX = function (key) { c3_chart_internal_fn.isX = function (key) {
var $$ = this, config = $$.config; var $$ = this, config = $$.config;
return (config.data_x && key === config.data_x) || (notEmpty(config.data_xs) && hasValue(config.data_xs, key)); return (config.data_x && key === config.data_x) || (notEmpty(config.data_xs) && hasValue(config.data_xs, key));
@ -175,15 +179,23 @@ c3_chart_internal_fn.mapTargetsToUniqueXs = function (targets) {
return xs.sort(function (a, b) { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; }); return xs.sort(function (a, b) { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; });
}; };
c3_chart_internal_fn.addHiddenTargetIds = function (targetIds) { c3_chart_internal_fn.addHiddenTargetIds = function (targetIds) {
this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds); targetIds = (targetIds instanceof Array) ? targetIds : new Array(targetIds);
this.visibleTargetCount -= targetIds.length; for (var i = 0; i < targetIds.length; i++) {
if (this.hiddenTargetIds.indexOf(targetIds[i]) < 0) {
this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds[i]);
}
}
}; };
c3_chart_internal_fn.removeHiddenTargetIds = function (targetIds) { c3_chart_internal_fn.removeHiddenTargetIds = function (targetIds) {
this.hiddenTargetIds = this.hiddenTargetIds.filter(function (id) { return targetIds.indexOf(id) < 0; }); this.hiddenTargetIds = this.hiddenTargetIds.filter(function (id) { return targetIds.indexOf(id) < 0; });
this.visibleTargetCount += targetIds.length;
}; };
c3_chart_internal_fn.addHiddenLegendIds = function (targetIds) { c3_chart_internal_fn.addHiddenLegendIds = function (targetIds) {
this.hiddenLegendIds = this.hiddenLegendIds.concat(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]);
}
}
}; };
c3_chart_internal_fn.removeHiddenLegendIds = function (targetIds) { c3_chart_internal_fn.removeHiddenLegendIds = function (targetIds) {
this.hiddenLegendIds = this.hiddenLegendIds.filter(function (id) { return targetIds.indexOf(id) < 0; }); this.hiddenLegendIds = this.hiddenLegendIds.filter(function (id) { return targetIds.indexOf(id) < 0; });
@ -235,7 +247,11 @@ c3_chart_internal_fn.orderTargets = function (targets) {
}); });
} else if (isFunction(config.data_order)) { } else if (isFunction(config.data_order)) {
targets.sort(config.data_order); targets.sort(config.data_order);
} // TODO: accept name array for order } else if (isArray(config.data_order)) {
targets.sort(function (t1, t2) {
return config.data_order.indexOf(t1.id) - config.data_order.indexOf(t2.id);
});
}
return targets; return targets;
}; };
c3_chart_internal_fn.filterByX = function (targets, x) { c3_chart_internal_fn.filterByX = function (targets, x) {

5
src/data.load.js

@ -1,3 +1,6 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
c3_chart_internal_fn.load = function (targets, args) { c3_chart_internal_fn.load = function (targets, args) {
var $$ = this; var $$ = this;
if (targets) { if (targets) {
@ -39,7 +42,7 @@ c3_chart_internal_fn.loadFromArgs = function (args) {
$$.load($$.convertDataToTargets(args.data), args); $$.load($$.convertDataToTargets(args.data), args);
} }
else if (args.url) { else if (args.url) {
$$.convertUrlToData(args.url, args.mimeType, args.keys, function (data) { $$.convertUrlToData(args.url, args.mimeType, args.headers, args.keys, function (data) {
$$.load($$.convertDataToTargets(data), args); $$.load($$.convertDataToTargets(data), args);
}); });
} }

3
src/domain.js

@ -1,3 +1,6 @@
import { c3_chart_internal_fn } from './core';
import { isValue, isDefined, diffDomain, notEmpty } from './util';
c3_chart_internal_fn.getYDomainMin = function (targets) { c3_chart_internal_fn.getYDomainMin = function (targets) {
var $$ = this, config = $$.config, var $$ = this, config = $$.config,
ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets), ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets),

4
src/drag.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
import { getPathBox } from './util';
c3_chart_internal_fn.drag = function (mouse) { c3_chart_internal_fn.drag = function (mouse) {
var $$ = this, config = $$.config, main = $$.main, d3 = $$.d3; var $$ = this, config = $$.config, main = $$.main, d3 = $$.d3;
var sx, sy, mx, my, minX, maxX, minY, maxY; var sx, sy, mx, my, minX, maxX, minY, maxY;

3
src/format.js

@ -1,3 +1,6 @@
import { c3_chart_internal_fn } from './core';
import { isValue } from './util';
c3_chart_internal_fn.getYFormat = function (forArc) { c3_chart_internal_fn.getYFormat = function (forArc) {
var $$ = this, var $$ = this,
formatForY = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.yFormat, formatForY = forArc && !$$.hasType('gauge') ? $$.defaultArcValueFormat : $$.yFormat,

4
src/grid.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
import { isValue } from './util';
c3_chart_internal_fn.initGrid = function () { c3_chart_internal_fn.initGrid = function () {
var $$ = this, config = $$.config, d3 = $$.d3; var $$ = this, config = $$.config, d3 = $$.d3;
$$.grid = $$.main.append('g') $$.grid = $$.main.append('g')

4
src/head.js

@ -1,4 +0,0 @@
(function (window) {
'use strict';
/*global define, module, exports, require */

58
src/index.js

@ -0,0 +1,58 @@
import { c3 } from './core';
import './polyfill';
import './api.axis';
import './api.category';
import './api.chart';
import './api.color';
import './api.data';
import './api.flow';
import './api.focus';
import './api.grid';
import './api.group';
import './api.legend';
import './api.load';
import './api.region';
import './api.selection';
import './api.show';
import './api.tooltip';
import './api.transform';
import './api.x';
import './api.zoom';
import './arc';
import './axis';
import './c3.axis';
import './cache';
import './category';
import './class';
import './class-utils';
import './clip';
import './color';
import './config';
import './data.convert';
import './data';
import './data.load';
import './domain';
import './drag';
import './format';
import './grid';
import './interaction';
import './legend';
import './region';
import './scale';
import './selection';
import './shape.bar';
import './shape';
import './shape.line';
import './size';
import './subchart';
import './text';
import './title';
import './tooltip';
import './type';
import './ua';
import './util';
import './zoom';
export default c3;

3
src/interaction.js

@ -1,3 +1,6 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
c3_chart_internal_fn.initEventRect = function () { c3_chart_internal_fn.initEventRect = function () {
var $$ = this; var $$ = this;
$$.main.select('.' + CLASS.chart).append("g") $$.main.select('.' + CLASS.chart).append("g")

4
src/legend.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
import { isDefined, isEmpty, getOption } from './util';
c3_chart_internal_fn.initLegend = function () { c3_chart_internal_fn.initLegend = function () {
var $$ = this; var $$ = this;
$$.legendItemTextBox = {}; $$.legendItemTextBox = {};

849
src/polyfill.js

@ -1,3 +1,5 @@
/* jshint ignore:start */
// PhantomJS doesn't have support for Function.prototype.bind, which has caused confusion. Use // PhantomJS doesn't have support for Function.prototype.bind, which has caused confusion. Use
// this polyfill to avoid the confusion. // this polyfill to avoid the confusion.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Polyfill // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Polyfill
@ -23,3 +25,850 @@ if (!Function.prototype.bind) {
return fBound; return fBound;
}; };
} }
// SVGPathSeg API polyfill
// https://github.com/progers/pathseg
//
// This is a drop-in replacement for the SVGPathSeg and SVGPathSegList APIs that were removed from
// SVG2 (https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html), including the latest spec
// changes which were implemented in Firefox 43 and Chrome 46.
(function() { "use strict";
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;
}
}
}());
/* jshint ignore:end */

15
src/region.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
import { isValue } from './util';
c3_chart_internal_fn.initRegion = function () { c3_chart_internal_fn.initRegion = function () {
var $$ = this; var $$ = this;
$$.region = $$.main.append('g') $$.region = $$.main.append('g')
@ -13,16 +17,23 @@ c3_chart_internal_fn.updateRegion = function (duration) {
$$.mainRegion = $$.main.select('.' + CLASS.regions).selectAll('.' + CLASS.region) $$.mainRegion = $$.main.select('.' + CLASS.regions).selectAll('.' + CLASS.region)
.data(config.regions); .data(config.regions);
$$.mainRegion.enter().append('g') $$.mainRegion.enter().append('g')
.attr('class', $$.classRegion.bind($$))
.append('rect') .append('rect')
.style("fill-opacity", 0); .style("fill-opacity", 0);
$$.mainRegion
.attr('class', $$.classRegion.bind($$));
$$.mainRegion.exit().transition().duration(duration) $$.mainRegion.exit().transition().duration(duration)
.style("opacity", 0) .style("opacity", 0)
.remove(); .remove();
}; };
c3_chart_internal_fn.redrawRegion = function (withTransition) { c3_chart_internal_fn.redrawRegion = function (withTransition) {
var $$ = this, var $$ = this,
regions = $$.mainRegion.selectAll('rect'), regions = $$.mainRegion.selectAll('rect').each(function () {
// data is binded to g and it's not transferred to rect (child node) automatically,
// then data of each rect has to be updated manually.
// TODO: there should be more efficient way to solve this?
var parentData = $$.d3.select(this.parentNode).datum();
$$.d3.select(this).datum(parentData);
}),
x = $$.regionX.bind($$), x = $$.regionX.bind($$),
y = $$.regionY.bind($$), y = $$.regionY.bind($$),
w = $$.regionWidth.bind($$), w = $$.regionWidth.bind($$),

2
src/scale.js

@ -1,3 +1,5 @@
import { c3_chart_internal_fn } from './core';
c3_chart_internal_fn.getScale = function (min, max, forTimeseries) { c3_chart_internal_fn.getScale = function (min, max, forTimeseries) {
return (forTimeseries ? this.d3.time.scale() : this.d3.scale.linear()).range([min, max]); return (forTimeseries ? this.d3.time.scale() : this.d3.scale.linear()).range([min, max]);
}; };

15
src/selection.js

@ -1,3 +1,6 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
c3_chart_internal_fn.selectPoint = function (target, d, i) { c3_chart_internal_fn.selectPoint = function (target, d, i) {
var $$ = this, config = $$.config, var $$ = this, config = $$.config,
cx = (config.axis_rotated ? $$.circleY : $$.circleX).bind($$), cx = (config.axis_rotated ? $$.circleY : $$.circleX).bind($$),
@ -30,14 +33,18 @@ c3_chart_internal_fn.togglePoint = function (selected, target, d, i) {
c3_chart_internal_fn.selectPath = function (target, d) { c3_chart_internal_fn.selectPath = function (target, d) {
var $$ = this; var $$ = this;
$$.config.data_onselected.call($$, d, target.node()); $$.config.data_onselected.call($$, d, target.node());
target.transition().duration(100) if ($$.config.interaction_brighten) {
.style("fill", function () { return $$.d3.rgb($$.color(d)).brighter(0.75); }); target.transition().duration(100)
.style("fill", function () { return $$.d3.rgb($$.color(d)).brighter(0.75); });
}
}; };
c3_chart_internal_fn.unselectPath = function (target, d) { c3_chart_internal_fn.unselectPath = function (target, d) {
var $$ = this; var $$ = this;
$$.config.data_onunselected.call($$, d, target.node()); $$.config.data_onunselected.call($$, d, target.node());
target.transition().duration(100) if ($$.config.interaction_brighten) {
.style("fill", function () { return $$.color(d); }); target.transition().duration(100)
.style("fill", function () { return $$.color(d); });
}
}; };
c3_chart_internal_fn.togglePath = function (selected, target, d, i) { c3_chart_internal_fn.togglePath = function (selected, target, d, i) {
selected ? this.selectPath(target, d, i) : this.unselectPath(target, d, i); selected ? this.selectPath(target, d, i) : this.unselectPath(target, d, i);

6
src/shape.bar.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
import { isValue } from './util';
c3_chart_internal_fn.initBar = function () { c3_chart_internal_fn.initBar = function () {
var $$ = this; var $$ = this;
$$.main.select('.' + CLASS.chart).append("g") $$.main.select('.' + CLASS.chart).append("g")
@ -42,7 +46,7 @@ c3_chart_internal_fn.updateBar = function (durationForExit) {
}; };
c3_chart_internal_fn.redrawBar = function (drawBar, withTransition) { c3_chart_internal_fn.redrawBar = function (drawBar, withTransition) {
return [ return [
(withTransition ? this.mainBar.transition() : this.mainBar) (withTransition ? this.mainBar.transition(Math.random().toString()) : this.mainBar)
.attr('d', drawBar) .attr('d', drawBar)
.style("fill", this.color) .style("fill", this.color)
.style("opacity", 1) .style("opacity", 1)

4
src/shape.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
import { isUndefined } from './util';
c3_chart_internal_fn.getShapeIndices = function (typeFilter) { c3_chart_internal_fn.getShapeIndices = function (typeFilter) {
var $$ = this, config = $$.config, var $$ = this, config = $$.config,
indices = {}, i = 0, j, k; indices = {}, i = 0, j, k;

16
src/shape.line.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
import { isValue, isFunction, isUndefined, isDefined } from './util';
c3_chart_internal_fn.initLine = function () { c3_chart_internal_fn.initLine = function () {
var $$ = this; var $$ = this;
$$.main.select('.' + CLASS.chart).append("g") $$.main.select('.' + CLASS.chart).append("g")
@ -56,7 +60,7 @@ c3_chart_internal_fn.updateLine = function (durationForExit) {
}; };
c3_chart_internal_fn.redrawLine = function (drawLine, withTransition) { c3_chart_internal_fn.redrawLine = function (drawLine, withTransition) {
return [ return [
(withTransition ? this.mainLine.transition() : this.mainLine) (withTransition ? this.mainLine.transition(Math.random().toString()) : this.mainLine)
.attr("d", drawLine) .attr("d", drawLine)
.style("stroke", this.color) .style("stroke", this.color)
.style("opacity", 1) .style("opacity", 1)
@ -232,7 +236,7 @@ c3_chart_internal_fn.updateArea = function (durationForExit) {
}; };
c3_chart_internal_fn.redrawArea = function (drawArea, withTransition) { c3_chart_internal_fn.redrawArea = function (drawArea, withTransition) {
return [ return [
(withTransition ? this.mainArea.transition() : this.mainArea) (withTransition ? this.mainArea.transition(Math.random().toString()) : this.mainArea)
.attr("d", drawArea) .attr("d", drawArea)
.style("fill", this.color) .style("fill", this.color)
.style("opacity", this.orgAreaOpacity) .style("opacity", this.orgAreaOpacity)
@ -250,7 +254,7 @@ c3_chart_internal_fn.generateDrawArea = function (areaIndices, isSub) {
return config.data_groups.length > 0 ? getPoints(d, i)[1][1] : yScaleGetter.call($$, d.id)(d.value); 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(value0).y1(value1); 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) { if (!config.line_connectNull) {
area = area.defined(function (d) { return d.value !== null; }); area = area.defined(function (d) { return d.value !== null; });
} }
@ -315,12 +319,12 @@ c3_chart_internal_fn.updateCircle = function () {
c3_chart_internal_fn.redrawCircle = function (cx, cy, withTransition) { c3_chart_internal_fn.redrawCircle = function (cx, cy, withTransition) {
var selectedCircles = this.main.selectAll('.' + CLASS.selectedCircle); var selectedCircles = this.main.selectAll('.' + CLASS.selectedCircle);
return [ return [
(withTransition ? this.mainCircle.transition() : this.mainCircle) (withTransition ? this.mainCircle.transition(Math.random().toString()) : this.mainCircle)
.style('opacity', this.opacityForCircle.bind(this)) .style('opacity', this.opacityForCircle.bind(this))
.style("fill", this.color) .style("fill", this.color)
.attr("cx", cx) .attr("cx", cx)
.attr("cy", cy), .attr("cy", cy),
(withTransition ? selectedCircles.transition() : selectedCircles) (withTransition ? selectedCircles.transition(Math.random().toString()) : selectedCircles)
.attr("cx", cx) .attr("cx", cx)
.attr("cy", cy) .attr("cy", cy)
]; ];
@ -372,7 +376,7 @@ c3_chart_internal_fn.pointExpandedR = function (d) {
}; };
c3_chart_internal_fn.pointSelectR = function (d) { c3_chart_internal_fn.pointSelectR = function (d) {
var $$ = this, config = $$.config; var $$ = this, config = $$.config;
return config.point_select_r ? config.point_select_r : $$.pointR(d) * 4; return isFunction(config.point_select_r) ? config.point_select_r(d) : ((config.point_select_r) ? config.point_select_r : $$.pointR(d) * 4);
}; };
c3_chart_internal_fn.isWithinCircle = function (that, r) { c3_chart_internal_fn.isWithinCircle = function (that, r) {
var d3 = this.d3, var d3 = this.d3,

14
src/size.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
import { isValue, ceil10 } from './util';
c3_chart_internal_fn.getCurrentWidth = function () { c3_chart_internal_fn.getCurrentWidth = function () {
var $$ = this, config = $$.config; var $$ = this, config = $$.config;
return config.size_width ? config.size_width : $$.getParentWidth(); return config.size_width ? config.size_width : $$.getParentWidth();
@ -5,7 +9,7 @@ c3_chart_internal_fn.getCurrentWidth = function () {
c3_chart_internal_fn.getCurrentHeight = function () { c3_chart_internal_fn.getCurrentHeight = function () {
var $$ = this, config = $$.config, var $$ = this, config = $$.config,
h = config.size_height ? config.size_height : $$.getParentHeight(); h = config.size_height ? config.size_height : $$.getParentHeight();
return h > 0 ? h : 320 / ($$.hasType('gauge') ? 2 : 1); return h > 0 ? h : 320 / ($$.hasType('gauge') && !config.gauge_fullCircle ? 2 : 1);
}; };
c3_chart_internal_fn.getCurrentPaddingTop = function () { c3_chart_internal_fn.getCurrentPaddingTop = function () {
var $$ = this, var $$ = this,
@ -95,12 +99,18 @@ c3_chart_internal_fn.getHorizontalAxisHeight = function (axisId) {
var $$ = this, config = $$.config, h = 30; var $$ = this, config = $$.config, h = 30;
if (axisId === 'x' && !config.axis_x_show) { return 8; } if (axisId === 'x' && !config.axis_x_show) { return 8; }
if (axisId === 'x' && config.axis_x_height) { return config.axis_x_height; } 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 === 'y' && !config.axis_y_show) {
return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1;
}
if (axisId === 'y2' && !config.axis_y2_show) { return $$.rotated_padding_top; } if (axisId === 'y2' && !config.axis_y2_show) { return $$.rotated_padding_top; }
// Calculate x axis height when tick rotated // Calculate x axis height when tick rotated
if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) { if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) {
h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_x_tick_rotate) / 180); h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - 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 - config.axis_y_tick_rotate) / 180);
}
return h + ($$.axis.getLabelPositionById(axisId).isInner ? 0 : 10) + (axisId === 'y2' ? -10 : 0); return h + ($$.axis.getLabelPositionById(axisId).isInner ? 0 : 10) + (axisId === 'y2' ? -10 : 0);
}; };

10
src/subchart.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
import { isFunction } from './util';
c3_chart_internal_fn.initBrush = function () { c3_chart_internal_fn.initBrush = function () {
var $$ = this, d3 = $$.d3; var $$ = this, d3 = $$.d3;
$$.brush = d3.svg.brush().on("brush", function () { $$.redrawForBrush(); }); $$.brush = d3.svg.brush().on("brush", function () { $$.redrawForBrush(); });
@ -98,7 +102,7 @@ c3_chart_internal_fn.updateBarForSubchart = function (durationForExit) {
.remove(); .remove();
}; };
c3_chart_internal_fn.redrawBarForSubchart = function (drawBarOnSub, withTransition, duration) { c3_chart_internal_fn.redrawBarForSubchart = function (drawBarOnSub, withTransition, duration) {
(withTransition ? this.contextBar.transition().duration(duration) : this.contextBar) (withTransition ? this.contextBar.transition(Math.random().toString()).duration(duration) : this.contextBar)
.attr('d', drawBarOnSub) .attr('d', drawBarOnSub)
.style('opacity', 1); .style('opacity', 1);
}; };
@ -116,7 +120,7 @@ c3_chart_internal_fn.updateLineForSubchart = function (durationForExit) {
.remove(); .remove();
}; };
c3_chart_internal_fn.redrawLineForSubchart = function (drawLineOnSub, withTransition, duration) { c3_chart_internal_fn.redrawLineForSubchart = function (drawLineOnSub, withTransition, duration) {
(withTransition ? this.contextLine.transition().duration(duration) : this.contextLine) (withTransition ? this.contextLine.transition(Math.random().toString()).duration(duration) : this.contextLine)
.attr("d", drawLineOnSub) .attr("d", drawLineOnSub)
.style('opacity', 1); .style('opacity', 1);
}; };
@ -135,7 +139,7 @@ c3_chart_internal_fn.updateAreaForSubchart = function (durationForExit) {
.remove(); .remove();
}; };
c3_chart_internal_fn.redrawAreaForSubchart = function (drawAreaOnSub, withTransition, duration) { c3_chart_internal_fn.redrawAreaForSubchart = function (drawAreaOnSub, withTransition, duration) {
(withTransition ? this.contextArea.transition().duration(duration) : this.contextArea) (withTransition ? this.contextArea.transition(Math.random().toString()).duration(duration) : this.contextArea)
.attr("d", drawAreaOnSub) .attr("d", drawAreaOnSub)
.style("fill", this.color) .style("fill", this.color)
.style("opacity", this.orgAreaOpacity); .style("opacity", this.orgAreaOpacity);

9
src/tail.js

@ -1,9 +0,0 @@
if (typeof define === 'function' && define.amd) {
define("c3", ["d3"], function () { return c3; });
} else if ('undefined' !== typeof exports && 'undefined' !== typeof module) {
module.exports = c3;
} else {
window.c3 = c3;
}
})(window);

3
src/text.js

@ -1,3 +1,6 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
c3_chart_internal_fn.initText = function () { c3_chart_internal_fn.initText = function () {
var $$ = this; var $$ = this;
$$.main.select('.' + CLASS.chart).append("g") $$.main.select('.' + CLASS.chart).append("g")

2
src/title.js

@ -1,3 +1,5 @@
import { c3_chart_internal_fn } from './core';
c3_chart_internal_fn.initTitle = function () { c3_chart_internal_fn.initTitle = function () {
var $$ = this; var $$ = this;
$$.title = $$.svg.append("text") $$.title = $$.svg.append("text")

100
src/tooltip.js

@ -1,3 +1,7 @@
import CLASS from './class';
import { c3_chart_internal_fn } from './core';
import { isValue, isFunction, isArray, isString, sanitise } from './util';
c3_chart_internal_fn.initTooltip = function () { c3_chart_internal_fn.initTooltip = function () {
var $$ = this, config = $$.config, i; var $$ = this, config = $$.config, i;
$$.tooltip = $$.selectChart $$.tooltip = $$.selectChart
@ -24,44 +28,100 @@ c3_chart_internal_fn.initTooltip = function () {
.style("display", "block"); .style("display", "block");
} }
}; };
c3_chart_internal_fn.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);
};
}
};
c3_chart_internal_fn.getTooltipContent = function (d, defaultTitleFormat, defaultValueFormat, color) { c3_chart_internal_fn.getTooltipContent = function (d, defaultTitleFormat, defaultValueFormat, color) {
var $$ = this, config = $$.config, var $$ = this, config = $$.config,
titleFormat = config.tooltip_format_title || defaultTitleFormat, titleFormat = config.tooltip_format_title || defaultTitleFormat,
nameFormat = config.tooltip_format_name || function (name) { return name; }, nameFormat = config.tooltip_format_name || function (name) { return name; },
valueFormat = config.tooltip_format_value || defaultValueFormat, valueFormat = config.tooltip_format_value || defaultValueFormat,
text, i, title, value, name, bgcolor, text, i, title, value, name, bgcolor;
orderAsc = $$.isOrderAsc();
if (config.data_groups.length === 0) { var tooltipSortFunction = this.getTooltipSortFunction();
d.sort(function(a,b){ if(tooltipSortFunction) {
return orderAsc ? a.value - b.value : b.value - a.value; d.sort(tooltipSortFunction);
});
} else {
var ids = $$.orderTargets($$.data.targets).map(function (i) {
return i.id;
});
d.sort(function(a, b) {
if (a.value > 0 && b.value > 0) {
return orderAsc ? ids.indexOf(a.id) - ids.indexOf(b.id) : ids.indexOf(b.id) - ids.indexOf(a.id);
} else {
return orderAsc ? a.value - b.value : b.value - a.value;
}
});
} }
for (i = 0; i < d.length; i++) { for (i = 0; i < d.length; i++) {
if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; } if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; }
if (! text) { if (! text) {
title = titleFormat ? titleFormat(d[i].x) : d[i].x; title = sanitise(titleFormat ? titleFormat(d[i].x) : d[i].x);
text = "<table class='" + $$.CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : ""); text = "<table class='" + $$.CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
} }
value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index); value = sanitise(valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index, d));
if (value !== undefined) { if (value !== undefined) {
// Skip elements when their name is set to null // Skip elements when their name is set to null
if (d[i].name === null) { continue; } if (d[i].name === null) { continue; }
name = nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index); 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); bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
text += "<tr class='" + $$.CLASS.tooltipName + "-" + $$.getTargetSelectorSuffix(d[i].id) + "'>"; text += "<tr class='" + $$.CLASS.tooltipName + "-" + $$.getTargetSelectorSuffix(d[i].id) + "'>";

3
src/type.js

@ -1,3 +1,6 @@
import { c3_chart_internal_fn } from './core';
import { isString } from './util';
c3_chart_internal_fn.setTargetType = function (targetIds, type) { c3_chart_internal_fn.setTargetType = function (targetIds, type) {
var $$ = this, config = $$.config; var $$ = this, config = $$.config;
$$.mapToTargetIds(targetIds).forEach(function (id) { $$.mapToTargetIds(targetIds).forEach(function (id) {

2
src/ua.js

@ -1,3 +1,5 @@
import { c3_chart_internal_fn } from './core';
c3_chart_internal_fn.isSafari = function () { c3_chart_internal_fn.isSafari = function () {
var ua = window.navigator.userAgent; var ua = window.navigator.userAgent;
return ua.indexOf('Safari') >= 0 && ua.indexOf('Chrome') < 0; return ua.indexOf('Safari') >= 0 && ua.indexOf('Chrome') < 0;

98
src/util.js

@ -1,46 +1,54 @@
var isValue = c3_chart_internal_fn.isValue = function (v) { import { c3_chart_internal_fn } from './core';
export var isValue = function (v) {
return v || v === 0; return v || v === 0;
}, };
isFunction = c3_chart_internal_fn.isFunction = function (o) { export var isFunction = function (o) {
return typeof o === 'function'; return typeof o === 'function';
}, };
isString = c3_chart_internal_fn.isString = function (o) { export var isArray = function (o) {
return typeof o === 'string'; return Array.isArray(o);
}, };
isUndefined = c3_chart_internal_fn.isUndefined = function (v) { export var isString = function (o) {
return typeof v === 'undefined'; return typeof o === 'string';
}, };
isDefined = c3_chart_internal_fn.isDefined = function (v) { export var isUndefined = function (v) {
return typeof v !== 'undefined'; return typeof v === 'undefined';
}, };
ceil10 = c3_chart_internal_fn.ceil10 = function (v) { export var isDefined = function (v) {
return Math.ceil(v / 10) * 10; return typeof v !== 'undefined';
}, };
asHalfPixel = c3_chart_internal_fn.asHalfPixel = function (n) { export var ceil10 = function (v) {
return Math.ceil(n) + 0.5; return Math.ceil(v / 10) * 10;
}, };
diffDomain = c3_chart_internal_fn.diffDomain = function (d) { export var asHalfPixel = function (n) {
return d[1] - d[0]; return Math.ceil(n) + 0.5;
}, };
isEmpty = c3_chart_internal_fn.isEmpty = function (o) { export var diffDomain = function (d) {
return typeof o === 'undefined' || o === null || (isString(o) && o.length === 0) || (typeof o === 'object' && Object.keys(o).length === 0); return d[1] - d[0];
}, };
notEmpty = c3_chart_internal_fn.notEmpty = function (o) { export var isEmpty = function (o) {
return !c3_chart_internal_fn.isEmpty(o); return typeof o === 'undefined' || o === null || (isString(o) && o.length === 0) || (typeof o === 'object' && Object.keys(o).length === 0);
}, };
getOption = c3_chart_internal_fn.getOption = function (options, key, defaultValue) { export var notEmpty = function (o) {
return isDefined(options[key]) ? options[key] : defaultValue; return !c3_chart_internal_fn.isEmpty(o);
}, };
hasValue = c3_chart_internal_fn.hasValue = function (dict, value) { export var getOption = function (options, key, defaultValue) {
var found = false; return isDefined(options[key]) ? options[key] : defaultValue;
Object.keys(dict).forEach(function (key) { };
if (dict[key] === value) { found = true; } export var hasValue = function (dict, value) {
}); var found = false;
return found; Object.keys(dict).forEach(function (key) {
}, if (dict[key] === value) { found = true; }
getPathBox = c3_chart_internal_fn.getPathBox = function (path) { });
var box = path.getBoundingClientRect(), return found;
items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)], };
minX = items[0].x, minY = Math.min(items[0].y, items[1].y); export var sanitise = function (str) {
return {x: minX, y: minY, width: box.width, height: box.height}; return typeof str === 'string' ? str.replace(/</g, '&lt;').replace(/>/g, '&gt;') : str;
}; };
export var getPathBox = function (path) {
var box = path.getBoundingClientRect(),
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};
};

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save